diff options
author | Hans Goudey <h.goudey@me.com> | 2021-07-20 04:45:54 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2021-07-20 04:45:54 +0300 |
commit | 2d190d0480c7d4ef040d09088aa5392e149f1416 (patch) | |
tree | 94301a71b2db0b582ed8411dc977c4240057fb13 | |
parent | 51f6fa351d417aff102b6f819e1998a09b00b338 (diff) | |
parent | 59eb71afa1d11ab0a1d5f741debc6989ec511ff9 (diff) |
Merge branch 'master' into temp-geometry-nodes-curve-sampletemp-geometry-nodes-curve-sample
69 files changed, 2899 insertions, 1415 deletions
diff --git a/release/scripts/modules/rna_manual_reference.py b/release/scripts/modules/rna_manual_reference.py index 57fcd6f9752..f9756811bde 100644 --- a/release/scripts/modules/rna_manual_reference.py +++ b/release/scripts/modules/rna_manual_reference.py @@ -139,6 +139,7 @@ url_manual_mapping = ( ("bpy.types.fluiddomainsettings.use_resumable_cache*", "physics/fluid/type/domain/cache.html#bpy-types-fluiddomainsettings-use-resumable-cache"), ("bpy.types.fluiddomainsettings.use_spray_particles*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-use-spray-particles"), ("bpy.types.fluiddomainsettings.vector_display_type*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-vector-display-type"), + ("bpy.types.geometrynodecurveprimitivebeziersegment*", "modeling/geometry_nodes/curve_primitives/bezier_segment.html#bpy-types-geometrynodecurveprimitivebeziersegment"), ("bpy.types.linestylegeometrymodifier_perlinnoise1d*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/perlin_noise_1d.html#bpy-types-linestylegeometrymodifier-perlinnoise1d"), ("bpy.types.linestylegeometrymodifier_perlinnoise2d*", "render/freestyle/parameter_editor/line_style/modifiers/geometry/perlin_noise_2d.html#bpy-types-linestylegeometrymodifier-perlinnoise2d"), ("bpy.types.materialgpencilstyle.use_stroke_holdout*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-use-stroke-holdout"), @@ -215,6 +216,7 @@ url_manual_mapping = ( ("bpy.types.spacesequenceeditor.proxy_render_size*", "video_editing/preview/sidebar.html#bpy-types-spacesequenceeditor-proxy-render-size"), ("bpy.types.spacesequenceeditor.show_strip_offset*", "video_editing/sequencer/navigating.html#bpy-types-spacesequenceeditor-show-strip-offset"), ("bpy.types.spacesequenceeditor.show_strip_source*", "video_editing/sequencer/navigating.html#bpy-types-spacesequenceeditor-show-strip-source"), + ("bpy.types.spacespreadsheetrowfilter.column_name*", "editors/spreadsheet.html#bpy-types-spacespreadsheetrowfilter-column-name"), ("bpy.types.toolsettings.gpencil_stroke_placement*", "grease_pencil/modes/draw/stroke_placement.html#bpy-types-toolsettings-gpencil-stroke-placement"), ("bpy.types.toolsettings.use_keyframe_cycle_aware*", "editors/timeline.html#bpy-types-toolsettings-use-keyframe-cycle-aware"), ("bpy.types.toolsettings.use_keyframe_insert_auto*", "editors/timeline.html#bpy-types-toolsettings-use-keyframe-insert-auto"), @@ -233,6 +235,7 @@ url_manual_mapping = ( ("bpy.types.rendersettings.resolution_percentage*", "render/output/properties/dimensions.html#bpy-types-rendersettings-resolution-percentage"), ("bpy.types.rendersettings_simplify_gpencil_tint*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-tint"), ("bpy.types.spaceoutliner.use_filter_object_mesh*", "editors/outliner/interface.html#bpy-types-spaceoutliner-use-filter-object-mesh"), + ("bpy.types.spaceoutliner.use_filter_view_layers*", "editors/outliner/interface.html#bpy-types-spaceoutliner-use-filter-view-layers"), ("bpy.types.spacesequenceeditor.show_overexposed*", "video_editing/preview/sidebar.html#bpy-types-spacesequenceeditor-show-overexposed"), ("bpy.types.toolsettings.use_gpencil_draw_onback*", "grease_pencil/modes/draw/introduction.html#bpy-types-toolsettings-use-gpencil-draw-onback"), ("bpy.types.toolsettings.use_snap_align_rotation*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-align-rotation"), @@ -273,6 +276,8 @@ url_manual_mapping = ( ("bpy.types.spacesequenceeditor.show_safe_areas*", "video_editing/preview/introduction.html#bpy-types-spacesequenceeditor-show-safe-areas"), ("bpy.types.spacesequenceeditor.show_strip_name*", "video_editing/sequencer/navigating.html#bpy-types-spacesequenceeditor-show-strip-name"), ("bpy.types.spacespreadsheet.show_only_selected*", "editors/spreadsheet.html#bpy-types-spacespreadsheet-show-only-selected"), + ("bpy.types.spacespreadsheetrowfilter.operation*", "editors/spreadsheet.html#bpy-types-spacespreadsheetrowfilter-operation"), + ("bpy.types.spacespreadsheetrowfilter.threshold*", "editors/spreadsheet.html#bpy-types-spacespreadsheetrowfilter-threshold"), ("bpy.types.toolsettings.use_snap_grid_absolute*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-grid-absolute"), ("bpy.types.view3doverlay.show_face_orientation*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-show-face-orientation"), ("bpy.ops.object.blenderkit_material_thumbnail*", "addons/3d_view/blenderkit.html#bpy-ops-object-blenderkit-material-thumbnail"), @@ -343,6 +348,7 @@ url_manual_mapping = ( ("bpy.types.spaceoutliner.use_filter_complete*", "editors/outliner/interface.html#bpy-types-spaceoutliner-use-filter-complete"), ("bpy.types.spacesequenceeditor.show_metadata*", "video_editing/preview/introduction.html#bpy-types-spacesequenceeditor-show-metadata"), ("bpy.types.spacespreadsheet.attribute_domain*", "editors/spreadsheet.html#bpy-types-spacespreadsheet-attribute-domain"), + ("bpy.types.spacespreadsheetrowfilter.enabled*", "editors/spreadsheet.html#bpy-types-spacespreadsheetrowfilter-enabled"), ("bpy.types.spaceview3d.transform_orientation*", "editors/3dview/controls/orientation.html#bpy-types-spaceview3d-transform-orientation"), ("bpy.types.spaceview3d.use_local_collections*", "editors/3dview/sidebar.html#bpy-types-spaceview3d-use-local-collections"), ("bpy.types.toolsettings.use_snap_peel_object*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-peel-object"), @@ -350,7 +356,6 @@ url_manual_mapping = ( ("bpy.types.view3doverlay.wireframe_threshold*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-wireframe-threshold"), ("bpy.ops.object.constraint_add_with_targets*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-constraint-add-with-targets"), ("bpy.ops.object.material_slot_remove_unused*", "scene_layout/object/editing/cleanup.html#bpy-ops-object-material-slot-remove-unused"), - ("bpy.ops.object.vertex_group_copy_to_linked*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-copy-to-linked"), ("bpy.ops.outliner.collection_disable_render*", "editors/outliner/editing.html#bpy-ops-outliner-collection-disable-render"), ("bpy.types.brush.cloth_simulation_area_type*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-simulation-area-type"), ("bpy.types.brushgpencilsettings.fill_factor*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-fill-factor"), @@ -372,6 +377,7 @@ url_manual_mapping = ( ("bpy.types.fluidflowsettings.use_plane_init*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-use-plane-init"), ("bpy.types.fluidflowsettings.velocity_coord*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-velocity-coord"), ("bpy.types.fluidflowsettings.volume_density*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-volume-density"), + ("bpy.types.geometrynodecurvequadraticbezier*", "modeling/geometry_nodes/curve_primitives/quadratic_bezier.html#bpy-types-geometrynodecurvequadraticbezier"), ("bpy.types.materialgpencilstyle.show_stroke*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-show-stroke"), ("bpy.types.movietrackingcamera.focal_length*", "movie_clip/tracking/clip/sidebar/track/camera.html#bpy-types-movietrackingcamera-focal-length"), ("bpy.types.movietrackingcamera.pixel_aspect*", "movie_clip/tracking/clip/sidebar/track/camera.html#bpy-types-movietrackingcamera-pixel-aspect"), @@ -471,6 +477,7 @@ url_manual_mapping = ( ("bpy.types.geometrynodeattributecolorramp*", "modeling/geometry_nodes/attribute/attribute_color_ramp.html#bpy-types-geometrynodeattributecolorramp"), ("bpy.types.geometrynodeattributeproximity*", "modeling/geometry_nodes/attribute/attribute_proximity.html#bpy-types-geometrynodeattributeproximity"), ("bpy.types.geometrynodeattributerandomize*", "modeling/geometry_nodes/attribute/attribute_randomize.html#bpy-types-geometrynodeattributerandomize"), + ("bpy.types.geometrynodecurvequadrilateral*", "modeling/geometry_nodes/curve_primitives/quadrilateral.html#bpy-types-geometrynodecurvequadrilateral"), ("bpy.types.geometrynodeseparatecomponents*", "modeling/geometry_nodes/geometry/separate_components.html#bpy-types-geometrynodeseparatecomponents"), ("bpy.types.geometrynodesubdivisionsurface*", "modeling/geometry_nodes/mesh/subdivision_surface.html#bpy-types-geometrynodesubdivisionsurface"), ("bpy.types.imageformatsettings.color_mode*", "render/output/properties/output.html#bpy-types-imageformatsettings-color-mode"), @@ -490,7 +497,7 @@ url_manual_mapping = ( ("bpy.types.rendersettings.use_compositing*", "render/output/properties/post_processing.html#bpy-types-rendersettings-use-compositing"), ("bpy.types.rendersettings.use_placeholder*", "render/output/properties/output.html#bpy-types-rendersettings-use-placeholder"), ("bpy.types.shadernodesubsurfacescattering*", "render/shader_nodes/shader/sss.html#bpy-types-shadernodesubsurfacescattering"), - ("bpy.types.spaceclipeditor.lock_selection*", "editors/clip/display/clip_display.html#bpy-types-spaceclipeditor-lock-selection"), + ("bpy.types.spaceclipeditor.lock_selection*", "editors/clip/introduction.html#bpy-types-spaceclipeditor-lock-selection"), ("bpy.types.spacedopesheeteditor.auto_snap*", "editors/dope_sheet/editing.html#bpy-types-spacedopesheeteditor-auto-snap"), ("bpy.types.spaceoutliner.show_mode_column*", "editors/outliner/interface.html#bpy-types-spaceoutliner-show-mode-column"), ("bpy.types.spacetexteditor.use_match_case*", "editors/text_editor.html#bpy-types-spacetexteditor-use-match-case"), @@ -508,6 +515,7 @@ url_manual_mapping = ( ("bpy.ops.outliner.collection_show_inside*", "editors/outliner/editing.html#bpy-ops-outliner-collection-show-inside"), ("bpy.ops.preferences.reset_default_theme*", "editors/preferences/themes.html#bpy-ops-preferences-reset-default-theme"), ("bpy.ops.sequencer.strip_transform_clear*", "video_editing/sequencer/editing.html#bpy-ops-sequencer-strip-transform-clear"), + ("bpy.ops.spreadsheet.add_row_filter_rule*", "editors/spreadsheet.html#bpy-ops-spreadsheet-add-row-filter-rule"), ("bpy.types.animdata.action_extrapolation*", "editors/nla/sidebar.html#bpy-types-animdata-action-extrapolation"), ("bpy.types.bakesettings.max_ray_distance*", "render/cycles/baking.html#bpy-types-bakesettings-max-ray-distance"), ("bpy.types.brush.multiplane_scrape_angle*", "sculpt_paint/sculpting/tools/multiplane_scrape.html#bpy-types-brush-multiplane-scrape-angle"), @@ -695,6 +703,7 @@ url_manual_mapping = ( ("bpy.types.fmodifierfunctiongenerator*", "editors/graph_editor/fcurves/sidebar/modifiers.html#bpy-types-fmodifierfunctiongenerator"), ("bpy.types.geometrynodeattributeclamp*", "modeling/geometry_nodes/attribute/attribute_clamp.html#bpy-types-geometrynodeattributeclamp"), ("bpy.types.geometrynodecollectioninfo*", "modeling/geometry_nodes/input/collection_info.html#bpy-types-geometrynodecollectioninfo"), + ("bpy.types.geometrynodecurveendpoints*", "modeling/geometry_nodes/curve/curve_endpoints.html#bpy-types-geometrynodecurveendpoints"), ("bpy.types.geometrynodecurvesubdivide*", "modeling/geometry_nodes/curve/curve_subdivide.html#bpy-types-geometrynodecurvesubdivide"), ("bpy.types.geometrynodedeletegeometry*", "modeling/geometry_nodes/geometry/delete_geometry.html#bpy-types-geometrynodedeletegeometry"), ("bpy.types.geometrynodematerialassign*", "modeling/geometry_nodes/material/assign.html#bpy-types-geometrynodematerialassign"), @@ -765,6 +774,7 @@ url_manual_mapping = ( ("bpy.types.geometrynodecurvetopoints*", "modeling/geometry_nodes/curve/curve_to_points.html#bpy-types-geometrynodecurvetopoints"), ("bpy.types.geometrynodeinputmaterial*", "modeling/geometry_nodes/input/material.html#bpy-types-geometrynodeinputmaterial"), ("bpy.types.geometrynodemeshicosphere*", "modeling/geometry_nodes/mesh_primitives/icosphere.html#bpy-types-geometrynodemeshicosphere"), + ("bpy.types.geometrynodemeshsubdivide*", "modeling/geometry_nodes/mesh/subdivide.html#bpy-types-geometrynodemeshsubdivide"), ("bpy.types.geometrynodepointinstance*", "modeling/geometry_nodes/point/point_instance.html#bpy-types-geometrynodepointinstance"), ("bpy.types.geometrynodepointseparate*", "modeling/geometry_nodes/point/point_separate.html#bpy-types-geometrynodepointseparate"), ("bpy.types.geometrynoderesamplecurve*", "modeling/geometry_nodes/curve/resample_curve.html#bpy-types-geometrynoderesamplecurve"), @@ -795,6 +805,7 @@ url_manual_mapping = ( ("bpy.types.spline.tilt_interpolation*", "modeling/curves/properties/active_spline.html#bpy-types-spline-tilt-interpolation"), ("bpy.types.transformorientation.name*", "editors/3dview/controls/orientation.html#bpy-types-transformorientation-name"), ("bpy.types.volumedisplay.slice_depth*", "modeling/volumes/properties.html#bpy-types-volumedisplay-slice-depth"), + ("bpy.ops.clip.lock_selection_toggle*", "editors/clip/introduction.html#bpy-ops-clip-lock-selection-toggle"), ("bpy.ops.mesh.customdata_mask_clear*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-mesh-customdata-mask-clear"), ("bpy.ops.mesh.extrude_vertices_move*", "modeling/meshes/editing/vertex/extrude_vertices.html#bpy-ops-mesh-extrude-vertices-move"), ("bpy.ops.mesh.mod_weighted_strength*", "modeling/meshes/editing/mesh/normals.html#bpy-ops-mesh-mod-weighted-strength"), @@ -802,7 +813,6 @@ url_manual_mapping = ( ("bpy.ops.mesh.select_interior_faces*", "modeling/meshes/selecting/all_by_trait.html#bpy-ops-mesh-select-interior-faces"), ("bpy.ops.mesh.select_similar_region*", "modeling/meshes/selecting/similar.html#bpy-ops-mesh-select-similar-region"), ("bpy.ops.mesh.tris_convert_to_quads*", "modeling/meshes/editing/face/triangles_quads.html#bpy-ops-mesh-tris-convert-to-quads"), - ("bpy.ops.node.active_preview_toggle*", "modeling/geometry_nodes/introduction.html#bpy-ops-node-active-preview-toggle"), ("bpy.ops.object.datalayout_transfer*", "scene_layout/object/editing/link_transfer/transfer_mesh_data_layout.html#bpy-ops-object-datalayout-transfer"), ("bpy.ops.object.multires_base_apply*", "modeling/modifiers/generate/multiresolution.html#bpy-ops-object-multires-base-apply"), ("bpy.ops.object.randomize_transform*", "scene_layout/object/editing/transform/randomize.html#bpy-ops-object-randomize-transform"), @@ -872,6 +882,7 @@ url_manual_mapping = ( ("bpy.types.volumedisplay.slice_axis*", "modeling/volumes/properties.html#bpy-types-volumedisplay-slice-axis"), ("bpy.ops.anim.channels_clean_empty*", "editors/nla/editing.html#bpy-ops-anim-channels-clean-empty"), ("bpy.ops.armature.select_hierarchy*", "animation/armatures/bones/selecting.html#bpy-ops-armature-select-hierarchy"), + ("bpy.ops.armature.switch_direction*", "animation/armatures/bones/editing/switch_direction.html#bpy-ops-armature-switch-direction"), ("bpy.ops.clip.apply_solution_scale*", "movie_clip/tracking/clip/editing/reconstruction.html#bpy-ops-clip-apply-solution-scale"), ("bpy.ops.clip.set_center_principal*", "movie_clip/tracking/clip/editing/clip.html#bpy-ops-clip-set-center-principal"), ("bpy.ops.clip.setup_tracking_scene*", "movie_clip/tracking/clip/editing/clip.html#bpy-ops-clip-setup-tracking-scene"), @@ -925,7 +936,9 @@ url_manual_mapping = ( ("bpy.types.functionnodeinputstring*", "modeling/geometry_nodes/input/string.html#bpy-types-functionnodeinputstring"), ("bpy.types.functionnodeinputvector*", "modeling/geometry_nodes/input/vector.html#bpy-types-functionnodeinputvector"), ("bpy.types.functionnoderandomfloat*", "modeling/geometry_nodes/input/random_float.html#bpy-types-functionnoderandomfloat"), + ("bpy.types.geometrynodecurvecircle*", "modeling/geometry_nodes/curve_primitives/circle.html#bpy-types-geometrynodecurvecircle"), ("bpy.types.geometrynodecurvelength*", "modeling/geometry_nodes/curve/curve_length.html#bpy-types-geometrynodecurvelength"), + ("bpy.types.geometrynodecurvespiral*", "modeling/geometry_nodes/curve_primitives/spiral.html#bpy-types-geometrynodecurvespiral"), ("bpy.types.geometrynodecurvetomesh*", "modeling/geometry_nodes/curve/curve_to_mesh.html#bpy-types-geometrynodecurvetomesh"), ("bpy.types.geometrynodemeshtocurve*", "modeling/geometry_nodes/curve/mesh_to_curve.html#bpy-types-geometrynodemeshtocurve"), ("bpy.types.geometrynodepointrotate*", "modeling/geometry_nodes/point/point_rotate.html#bpy-types-geometrynodepointrotate"), @@ -989,6 +1002,7 @@ url_manual_mapping = ( ("bpy.ops.sequencer.select_handles*", "video_editing/sequencer/selecting.html#bpy-ops-sequencer-select-handles"), ("bpy.ops.uv.average_islands_scale*", "modeling/meshes/uv/editing.html#bpy-ops-uv-average-islands-scale"), ("bpy.ops.view3d.blenderkit_search*", "addons/3d_view/blenderkit.html#bpy-ops-view3d-blenderkit-search"), + ("bpy.types.armature.axes_position*", "animation/armatures/properties/display.html#bpy-types-armature-axes-position"), ("bpy.types.armature.pose_position*", "animation/armatures/properties/skeleton.html#bpy-types-armature-pose-position"), ("bpy.types.bakesettings.use_clear*", "render/cycles/baking.html#bpy-types-bakesettings-use-clear"), ("bpy.types.bone.envelope_distance*", "animation/armatures/bones/properties/deform.html#bpy-types-bone-envelope-distance"), @@ -1024,6 +1038,7 @@ url_manual_mapping = ( ("bpy.types.editbone.bbone_scalein*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-bbone-scalein"), ("bpy.types.editbone.inherit_scale*", "animation/armatures/bones/properties/relations.html#bpy-types-editbone-inherit-scale"), ("bpy.types.geometrynodeconvexhull*", "modeling/geometry_nodes/geometry/convex_hull.html#bpy-types-geometrynodeconvexhull"), + ("bpy.types.geometrynodefloattoint*", "modeling/geometry_nodes/utilities/float_to_int.html#bpy-types-geometrynodefloattoint"), ("bpy.types.geometrynodeisviewport*", "modeling/geometry_nodes/input/is_viewport.html#bpy-types-geometrynodeisviewport"), ("bpy.types.geometrynodemeshcircle*", "modeling/geometry_nodes/mesh_primitives/circle.html#bpy-types-geometrynodemeshcircle"), ("bpy.types.geometrynodeobjectinfo*", "modeling/geometry_nodes/input/object_info.html#bpy-types-geometrynodeobjectinfo"), @@ -1051,6 +1066,8 @@ url_manual_mapping = ( ("bpy.types.volumerender.step_size*", "modeling/volumes/properties.html#bpy-types-volumerender-step-size"), ("bpy.types.weightednormalmodifier*", "modeling/modifiers/modify/weighted_normal.html#bpy-types-weightednormalmodifier"), ("bpy.ops.armature.autoside_names*", "animation/armatures/bones/editing/naming.html#bpy-ops-armature-autoside-names"), + ("bpy.ops.armature.calculate_roll*", "animation/armatures/bones/editing/bone_roll.html#bpy-ops-armature-calculate-roll"), + ("bpy.ops.armature.duplicate_move*", "animation/armatures/bones/editing/duplicate.html#bpy-ops-armature-duplicate-move"), ("bpy.ops.armature.select_similar*", "animation/armatures/bones/selecting.html#bpy-ops-armature-select-similar"), ("bpy.ops.clip.create_plane_track*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-create-plane-track"), ("bpy.ops.curve.spline_weight_set*", "modeling/curves/editing/other.html#bpy-ops-curve-spline-weight-set"), @@ -1099,6 +1116,7 @@ url_manual_mapping = ( ("bpy.ops.wm.operator_cheat_sheet*", "advanced/operators.html#bpy-ops-wm-operator-cheat-sheet"), ("bpy.ops.wm.previews_batch_clear*", "files/blend/previews.html#bpy-ops-wm-previews-batch-clear"), ("bpy.ops.wm.recover_last_session*", "files/blend/open_save.html#bpy-ops-wm-recover-last-session"), + ("bpy.types.armature.display_type*", "animation/armatures/properties/display.html#bpy-types-armature-display-type"), ("bpy.types.armature.use_mirror_x*", "animation/armatures/bones/tools/tool_settings.html#bpy-types-armature-use-mirror-x"), ("bpy.types.bakesettings.normal_b*", "render/cycles/baking.html#bpy-types-bakesettings-normal-b"), ("bpy.types.bakesettings.normal_g*", "render/cycles/baking.html#bpy-types-bakesettings-normal-g"), @@ -1127,8 +1145,10 @@ url_manual_mapping = ( ("bpy.types.editbone.bbone_rollin*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-bbone-rollin"), ("bpy.types.fluideffectorsettings*", "physics/fluid/type/effector.html#bpy-types-fluideffectorsettings"), ("bpy.types.followtrackconstraint*", "animation/constraints/motion_tracking/follow_track.html#bpy-types-followtrackconstraint"), + ("bpy.types.geometrynodecurveline*", "modeling/geometry_nodes/curve_primitives/line.html#bpy-types-geometrynodecurveline"), + ("bpy.types.geometrynodecurvestar*", "modeling/geometry_nodes/curve_primitives/star.html#bpy-types-geometrynodecurvestar"), + ("bpy.types.geometrynodecurvetrim*", "modeling/geometry_nodes/curve/curve_trim.html#bpy-types-geometrynodecurvetrim"), ("bpy.types.geometrynodeedgesplit*", "modeling/geometry_nodes/mesh/edge_split.html#bpy-types-geometrynodeedgesplit"), - ("bpy.types.geometrynodesubdivide*", "modeling/geometry_nodes/mesh/subdivide.html#bpy-types-geometrynodesubdivide"), ("bpy.types.geometrynodetransform*", "modeling/geometry_nodes/geometry/transform.html#bpy-types-geometrynodetransform"), ("bpy.types.gpencilsculptsettings*", "grease_pencil/properties/index.html#bpy-types-gpencilsculptsettings"), ("bpy.types.light.cutoff_distance*", "render/eevee/lighting.html#bpy-types-light-cutoff-distance"), @@ -1247,6 +1267,8 @@ url_manual_mapping = ( ("bpy.types.volumetomeshmodifier*", "modeling/modifiers/generate/volume_to_mesh.html#bpy-types-volumetomeshmodifier"), ("bpy.types.whitebalancemodifier*", "video_editing/sequencer/sidebar/modifiers.html#bpy-types-whitebalancemodifier"), ("bpy.ops.anim.channels_ungroup*", "editors/graph_editor/channels.html#bpy-ops-anim-channels-ungroup"), + ("bpy.ops.armature.extrude_move*", "animation/armatures/bones/editing/extrude.html#bpy-ops-armature-extrude-move"), + ("bpy.ops.armature.parent_clear*", "animation/armatures/bones/editing/parenting.html#bpy-ops-armature-parent-clear"), ("bpy.ops.clip.clear_track_path*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-clear-track-path"), ("bpy.ops.clip.set_scene_frames*", "movie_clip/tracking/clip/editing/clip.html#bpy-ops-clip-set-scene-frames"), ("bpy.ops.curve.handle_type_set*", "modeling/curves/editing/control_points.html#bpy-ops-curve-handle-type-set"), @@ -1424,6 +1446,7 @@ url_manual_mapping = ( ("bpy.types.freestylelinestyle*", "render/freestyle/parameter_editor/line_style/index.html#bpy-types-freestylelinestyle"), ("bpy.types.gammacrosssequence*", "video_editing/sequencer/strips/transitions/gamma_cross.html#bpy-types-gammacrosssequence"), ("bpy.types.geometrynodeswitch*", "modeling/geometry_nodes/utilities/switch.html#bpy-types-geometrynodeswitch"), + ("bpy.types.geometrynodeviewer*", "modeling/geometry_nodes/output/viewer.html#bpy-types-geometrynodeviewer"), ("bpy.types.gpencilsculptguide*", "grease_pencil/modes/draw/guides.html#bpy-types-gpencilsculptguide"), ("bpy.types.huecorrectmodifier*", "video_editing/sequencer/sidebar/modifiers.html#bpy-types-huecorrectmodifier"), ("bpy.types.imagepaint.stencil*", "sculpt_paint/texture_paint/tool_settings/mask.html#bpy-types-imagepaint-stencil"), @@ -1462,7 +1485,9 @@ url_manual_mapping = ( ("bpy.ops.anim.channels_group*", "editors/graph_editor/channels.html#bpy-ops-anim-channels-group"), ("bpy.ops.anim.keyframe_clear*", "animation/keyframes/editing.html#bpy-ops-anim-keyframe-clear"), ("bpy.ops.armature.flip_names*", "animation/armatures/bones/editing/naming.html#bpy-ops-armature-flip-names"), + ("bpy.ops.armature.parent_set*", "animation/armatures/bones/editing/parenting.html#bpy-ops-armature-parent-set"), ("bpy.ops.armature.select_all*", "animation/armatures/bones/selecting.html#bpy-ops-armature-select-all"), + ("bpy.ops.armature.symmetrize*", "animation/armatures/bones/editing/symmetrize.html#bpy-ops-armature-symmetrize"), ("bpy.ops.clip.average_tracks*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-average-tracks"), ("bpy.ops.clip.refine_markers*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-refine-markers"), ("bpy.ops.clip.select_grouped*", "movie_clip/tracking/clip/selecting.html#bpy-ops-clip-select-grouped"), @@ -1501,6 +1526,8 @@ url_manual_mapping = ( ("bpy.ops.object.shade_smooth*", "scene_layout/object/editing/shading.html#bpy-ops-object-shade-smooth"), ("bpy.ops.object.voxel_remesh*", "modeling/meshes/retopology.html#bpy-ops-object-voxel-remesh"), ("bpy.ops.pose.armature_apply*", "animation/armatures/posing/editing/apply.html#bpy-ops-pose-armature-apply"), + ("bpy.ops.pose.group_deselect*", "animation/armatures/properties/bone_groups.html#bpy-ops-pose-group-deselect"), + ("bpy.ops.pose.group_unassign*", "animation/armatures/properties/bone_groups.html#bpy-ops-pose-group-unassign"), ("bpy.ops.pose.select_grouped*", "animation/armatures/posing/selecting.html#bpy-ops-pose-select-grouped"), ("bpy.ops.poselib.pose_remove*", "animation/armatures/posing/editing/pose_library.html#bpy-ops-poselib-pose-remove"), ("bpy.ops.poselib.pose_rename*", "animation/armatures/posing/editing/pose_library.html#bpy-ops-poselib-pose-rename"), @@ -1574,6 +1601,7 @@ url_manual_mapping = ( ("bpy.types.wireframemodifier*", "modeling/modifiers/generate/wireframe.html#bpy-types-wireframemodifier"), ("bpy.types.worldmistsettings*", "render/cycles/world_settings.html#bpy-types-worldmistsettings"), ("bpy.ops.anim.channels_move*", "editors/graph_editor/channels.html#bpy-ops-anim-channels-move"), + ("bpy.ops.armature.subdivide*", "animation/armatures/bones/editing/subdivide.html#bpy-ops-armature-subdivide"), ("bpy.ops.buttons.toggle_pin*", "editors/properties_editor.html#bpy-ops-buttons-toggle-pin"), ("bpy.ops.clip.filter_tracks*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-filter-tracks"), ("bpy.ops.clip.select_circle*", "movie_clip/tracking/clip/selecting.html#bpy-ops-clip-select-circle"), @@ -1675,6 +1703,8 @@ url_manual_mapping = ( ("bpy.types.texturenodegroup*", "editors/texture_node/types/groups.html#bpy-types-texturenodegroup"), ("bpy.types.texturenodeimage*", "editors/texture_node/types/input/image.html#bpy-types-texturenodeimage"), ("bpy.types.viewlayer.use_ao*", "render/layers/introduction.html#bpy-types-viewlayer-use-ao"), + ("bpy.ops.armature.dissolve*", "animation/armatures/bones/editing/delete.html#bpy-ops-armature-dissolve"), + ("bpy.ops.armature.separate*", "animation/armatures/bones/editing/separate_bones.html#bpy-ops-armature-separate"), ("bpy.ops.clip.clean_tracks*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-clean-tracks"), ("bpy.ops.clip.delete_track*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-delete-track"), ("bpy.ops.clip.solve_camera*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-solve-camera"), @@ -1703,6 +1733,8 @@ url_manual_mapping = ( ("bpy.ops.object.proxy_make*", "files/linked_libraries/library_proxies.html#bpy-ops-object-proxy-make"), ("bpy.ops.object.select_all*", "scene_layout/object/selecting.html#bpy-ops-object-select-all"), ("bpy.ops.object.shade_flat*", "scene_layout/object/editing/shading.html#bpy-ops-object-shade-flat"), + ("bpy.ops.pose.group_assign*", "animation/armatures/properties/bone_groups.html#bpy-ops-pose-group-assign"), + ("bpy.ops.pose.group_select*", "animation/armatures/properties/bone_groups.html#bpy-ops-pose-group-select"), ("bpy.ops.poselib.pose_move*", "animation/armatures/properties/pose_library.html#bpy-ops-poselib-pose-move"), ("bpy.ops.preferences.addon*", "editors/preferences/addons.html#bpy-ops-preferences-addon"), ("bpy.ops.scene.light_cache*", "render/eevee/render_settings/indirect_lighting.html#bpy-ops-scene-light-cache"), @@ -1872,6 +1904,7 @@ url_manual_mapping = ( ("bpy.ops.wm.owner_enable*", "interface/window_system/workspaces.html#bpy-ops-wm-owner-enable"), ("bpy.ops.wm.redraw_timer*", "advanced/operators.html#bpy-ops-wm-redraw-timer"), ("bpy.types.*light.shadow*", "render/eevee/lighting.html#bpy-types-light-shadow"), + ("bpy.types.armature.show*", "animation/armatures/properties/display.html#bpy-types-armature-show"), ("bpy.types.armaturebones*", "animation/armatures/bones/index.html#bpy-types-armaturebones"), ("bpy.types.arraymodifier*", "modeling/modifiers/generate/array.html#bpy-types-arraymodifier"), ("bpy.types.bevelmodifier*", "modeling/modifiers/generate/bevel.html#bpy-types-bevelmodifier"), @@ -1919,6 +1952,8 @@ url_manual_mapping = ( ("bpy.types.volumedisplay*", "modeling/volumes/properties.html#bpy-types-volumedisplay"), ("bpy.types.windowmanager*", "interface/index.html#bpy-types-windowmanager"), ("bpy.ops.*.select_lasso*", "interface/selecting.html#bpy-ops-select-lasso"), + ("bpy.ops.armature.align*", "animation/armatures/bones/editing/transform.html#bpy-ops-armature-align"), + ("bpy.ops.armature.split*", "animation/armatures/bones/editing/split.html#bpy-ops-armature-split"), ("bpy.ops.clip.set_plane*", "movie_clip/tracking/clip/editing/reconstruction.html#bpy-ops-clip-set-plane"), ("bpy.ops.clip.set_scale*", "movie_clip/tracking/clip/editing/reconstruction.html#bpy-ops-clip-set-scale"), ("bpy.ops.curve.decimate*", "modeling/curves/editing/curve.html#bpy-ops-curve-decimate"), @@ -1993,6 +2028,7 @@ url_manual_mapping = ( ("bpy.types.wavemodifier*", "modeling/modifiers/deform/wave.html#bpy-types-wavemodifier"), ("bpy.types.weldmodifier*", "modeling/modifiers/generate/weld.html#bpy-types-weldmodifier"), ("bpy.types.wipesequence*", "video_editing/sequencer/strips/transitions/wipe.html#bpy-types-wipesequence"), + ("bpy.ops.armature.fill*", "animation/armatures/bones/editing/fill_between_joints.html#bpy-ops-armature-fill"), ("bpy.ops.clip.prefetch*", "movie_clip/tracking/clip/editing/clip.html#bpy-ops-clip-prefetch"), ("bpy.ops.clip.set_axis*", "movie_clip/tracking/clip/editing/reconstruction.html#bpy-ops-clip-set-axis"), ("bpy.ops.file.pack_all*", "files/blend/packed_data.html#bpy-ops-file-pack-all"), @@ -2064,6 +2100,7 @@ url_manual_mapping = ( ("bpy.ops.uv.mark_seam*", "modeling/meshes/uv/unwrapping/seams.html#bpy-ops-uv-mark-seam"), ("bpy.ops.view3d.ruler*", "editors/3dview/toolbar/measure.html#bpy-ops-view3d-ruler"), ("bpy.types.areaspaces*", "interface/window_system/areas.html#bpy-types-areaspaces"), + ("bpy.types.bonegroups*", "animation/armatures/properties/bone_groups.html#bpy-types-bonegroups"), ("bpy.types.bpy_struct*", "files/data_blocks.html#bpy-types-bpy-struct"), ("bpy.types.collection*", "scene_layout/collections/collections.html#bpy-types-collection"), ("bpy.types.compositor*", "compositing/index.html#bpy-types-compositor"), diff --git a/release/scripts/startup/bl_operators/assets.py b/release/scripts/startup/bl_operators/assets.py index d2655784afd..c782cd0646e 100644 --- a/release/scripts/startup/bl_operators/assets.py +++ b/release/scripts/startup/bl_operators/assets.py @@ -18,7 +18,6 @@ # <pep8 compliant> from __future__ import annotations -from pathlib import Path import bpy from bpy.types import Operator diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index c7c5f59cab2..5e474c0c5ac 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -97,7 +97,6 @@ struct BoundBox *BKE_curve_boundbox_get(struct Object *ob); void BKE_curve_texspace_calc(struct Curve *cu); void BKE_curve_texspace_ensure(struct Curve *cu); -void BKE_curve_texspace_get(struct Curve *cu, float r_loc[3], float r_size[3]); bool BKE_curve_minmax(struct Curve *cu, bool use_radius, float min[3], float max[3]); bool BKE_curve_center_median(struct Curve *cu, float cent[3]); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 12560ebed7b..7846619577e 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -126,8 +126,8 @@ void BKE_mesh_eval_delete(struct Mesh *mesh_eval); struct Mesh *BKE_mesh_copy_for_eval(struct Mesh *source, bool reference); /* These functions construct a new Mesh, - * contrary to BKE_mesh_from_nurbs which modifies ob itself. */ -struct Mesh *BKE_mesh_new_nomain_from_curve(struct Object *ob); + * contrary to BKE_mesh_to_curve_nurblist which modifies ob itself. */ +struct Mesh *BKE_mesh_new_nomain_from_curve(const struct Object *ob); struct Mesh *BKE_mesh_new_nomain_from_curve_displist(const struct Object *ob, const struct ListBase *dispbase); @@ -143,32 +143,11 @@ int BKE_mesh_mface_index_validate(struct MFace *mface, struct Mesh *BKE_mesh_from_object(struct Object *ob); void BKE_mesh_assign_object(struct Main *bmain, struct Object *ob, struct Mesh *me); void BKE_mesh_from_metaball(struct ListBase *lb, struct Mesh *me); -int BKE_mesh_nurbs_to_mdata(struct Object *ob, - struct MVert **r_allvert, - int *r_totvert, - struct MEdge **r_alledge, - int *r_totedge, - struct MLoop **r_allloop, - struct MPoly **r_allpoly, - int *r_totloop, - int *r_totpoly); -int BKE_mesh_nurbs_displist_to_mdata(const struct Object *ob, - const struct ListBase *dispbase, - struct MVert **r_allvert, - int *r_totvert, - struct MEdge **r_alledge, - int *r_totedge, - struct MLoop **r_allloop, - struct MPoly **r_allpoly, - struct MLoopUV **r_alluv, - int *r_totloop, - int *r_totpoly); void BKE_mesh_from_nurbs_displist(struct Main *bmain, struct Object *ob, struct ListBase *dispbase, const char *obdata_name, bool temporary); -void BKE_mesh_from_nurbs(struct Main *bmain, struct Object *ob); void BKE_mesh_to_curve_nurblist(const struct Mesh *me, struct ListBase *nurblist, const int edge_users_test); diff --git a/source/blender/blenkernel/BKE_mesh_types.h b/source/blender/blenkernel/BKE_mesh_types.h index b223d3872ff..aed8c44a031 100644 --- a/source/blender/blenkernel/BKE_mesh_types.h +++ b/source/blender/blenkernel/BKE_mesh_types.h @@ -27,7 +27,6 @@ typedef enum eMeshBatchDirtyMode { BKE_MESH_BATCH_DIRTY_SELECT, BKE_MESH_BATCH_DIRTY_SELECT_PAINT, BKE_MESH_BATCH_DIRTY_SHADING, - BKE_MESH_BATCH_DIRTY_DEFORM, BKE_MESH_BATCH_DIRTY_UVEDIT_ALL, BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT, } eMeshBatchDirtyMode; diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index a16822fd7dd..4724e6dfab6 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -374,10 +374,6 @@ void BKE_object_runtime_free_data(struct Object *object); void BKE_object_batch_cache_dirty_tag(struct Object *ob); void BKE_object_data_batch_cache_dirty_tag(struct ID *object_data); -void BKE_object_data_eval_batch_cache_dirty_tag(struct Depsgraph *depsgraph, - struct ID *object_data); -void BKE_object_data_eval_batch_cache_deform_tag(struct Depsgraph *depsgraph, - struct ID *object_data); /* this function returns a superset of the scenes selection based on relationships */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 24615dd8c2b..f1369254347 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -332,16 +332,6 @@ IDTypeInfo IDType_ID_CU = { .lib_override_apply_post = NULL, }; -static int cu_isectLL(const float v1[3], - const float v2[3], - const float v3[3], - const float v4[3], - short cox, - short coy, - float *lambda, - float *mu, - float vec[3]); - /* frees editcurve entirely */ void BKE_curve_editfont_free(Curve *cu) { @@ -566,18 +556,6 @@ void BKE_curve_texspace_ensure(Curve *cu) } } -void BKE_curve_texspace_get(Curve *cu, float r_loc[3], float r_size[3]) -{ - BKE_curve_texspace_ensure(cu); - - if (r_loc) { - copy_v3_v3(r_loc, cu->loc); - } - if (r_size) { - copy_v3_v3(r_size, cu->size); - } -} - bool BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3]) { int tot = 0; diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc index 785f63a7ba2..f8a07939096 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.cc +++ b/source/blender/blenkernel/intern/gpencil_geom.cc @@ -2094,13 +2094,14 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int /** * Reduce a series of points when the distance is below a threshold. - * Special case for first and last points (both are keeped) for other points, + * Special case for first and last points (both are kept) for other points, * the merge point always is at first point. - * \param gpd: Grease pencil data-block - * \param gpf: Grease Pencil frame - * \param gps: Grease Pencil stroke - * \param threshold: Distance between points - * \param use_unselected: Set to true to analyze all stroke and not only selected points + * + * \param gpd: Grease pencil data-block. + * \param gpf: Grease Pencil frame. + * \param gps: Grease Pencil stroke. + * \param threshold: Distance between points. + * \param use_unselected: Set to true to analyze all stroke and not only selected points. */ void BKE_gpencil_stroke_merge_distance(bGPdata *gpd, bGPDframe *gpf, @@ -2276,7 +2277,7 @@ static void gpencil_generate_edgeloops(Object *ob, } /* Arrays for all edge vertices (forward and backward) that form a edge loop. - * This is reused for each edgeloop to create gpencil stroke. */ + * This is reused for each edge-loop to create gpencil stroke. */ uint *stroke = (uint *)MEM_callocN(sizeof(uint) * me->totedge * 2, __func__); uint *stroke_fw = (uint *)MEM_callocN(sizeof(uint) * me->totedge, __func__); uint *stroke_bw = (uint *)MEM_callocN(sizeof(uint) * me->totedge, __func__); @@ -2468,7 +2469,7 @@ static void make_element_name(const char *obname, const char *name, const int ma * \param scene: Original scene. * \param ob_gp: Grease pencil object to add strokes. * \param ob_mesh: Mesh to convert. - * \param angle: Limit angle to consider a edgeloop ends. + * \param angle: Limit angle to consider a edge-loop ends. * \param thickness: Thickness of the strokes. * \param offset: Offset along the normals. * \param matrix: Transformation matrix. diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index e777eb7ffe9..0e4fe91e577 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -212,54 +212,19 @@ static void make_edges_mdata_extend( } /* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */ -/* return non-zero on error */ -int BKE_mesh_nurbs_to_mdata(Object *ob, - MVert **r_allvert, - int *r_totvert, - MEdge **r_alledge, - int *r_totedge, - MLoop **r_allloop, - MPoly **r_allpoly, - int *r_totloop, - int *r_totpoly) -{ - ListBase disp = {NULL, NULL}; - - if (ob->runtime.curve_cache) { - disp = ob->runtime.curve_cache->disp; - } - - return BKE_mesh_nurbs_displist_to_mdata(ob, - &disp, - r_allvert, - r_totvert, - r_alledge, - r_totedge, - r_allloop, - r_allpoly, - NULL, - r_totloop, - r_totpoly); -} - -/* BMESH: this doesn't calculate all edges from polygons, - * only free standing edges are calculated */ - -/* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */ /* use specified dispbase */ -int BKE_mesh_nurbs_displist_to_mdata(const Object *ob, - const ListBase *dispbase, - MVert **r_allvert, - int *r_totvert, - MEdge **r_alledge, - int *r_totedge, - MLoop **r_allloop, - MPoly **r_allpoly, - MLoopUV **r_alluv, - int *r_totloop, - int *r_totpoly) +static int mesh_nurbs_displist_to_mdata(const Curve *cu, + const ListBase *dispbase, + MVert **r_allvert, + int *r_totvert, + MEdge **r_alledge, + int *r_totedge, + MLoop **r_allloop, + MPoly **r_allpoly, + MLoopUV **r_alluv, + int *r_totloop, + int *r_totpoly) { - const Curve *cu = ob->data; MVert *mvert; MPoly *mpoly; MLoop *mloop; @@ -272,7 +237,7 @@ int BKE_mesh_nurbs_displist_to_mdata(const Object *ob, /* 2d polys are filled with DL_INDEX3 displists */ (CU_DO_2DFILL(cu) == false) || /* surf polys are never filled */ - (ob->type == OB_SURF)); + BKE_curve_type_get(cu) == OB_SURF); /* count */ LISTBASE_FOREACH (const DispList *, dl, dispbase) { @@ -527,17 +492,17 @@ Mesh *BKE_mesh_new_nomain_from_curve_displist(const Object *ob, const ListBase * MLoopUV *alluv = NULL; int totvert, totedge, totloop, totpoly; - if (BKE_mesh_nurbs_displist_to_mdata(ob, - dispbase, - &allvert, - &totvert, - &alledge, - &totedge, - &allloop, - &allpoly, - &alluv, - &totloop, - &totpoly) != 0) { + if (mesh_nurbs_displist_to_mdata(ob->data, + dispbase, + &allvert, + &totvert, + &alledge, + &totedge, + &allloop, + &allpoly, + &alluv, + &totloop, + &totpoly) != 0) { /* Error initializing mdata. This often happens when curve is empty */ return BKE_mesh_new_nomain(0, 0, 0, 0, 0); } @@ -571,7 +536,7 @@ Mesh *BKE_mesh_new_nomain_from_curve_displist(const Object *ob, const ListBase * return mesh; } -Mesh *BKE_mesh_new_nomain_from_curve(Object *ob) +Mesh *BKE_mesh_new_nomain_from_curve(const Object *ob) { ListBase disp = {NULL, NULL}; @@ -589,7 +554,6 @@ void BKE_mesh_from_nurbs_displist( Object *ob1; Mesh *me_eval = (Mesh *)ob->runtime.data_eval; Mesh *me; - Curve *cu; MVert *allvert = NULL; MEdge *alledge = NULL; MLoop *allloop = NULL; @@ -597,20 +561,20 @@ void BKE_mesh_from_nurbs_displist( MPoly *allpoly = NULL; int totvert, totedge, totloop, totpoly; - cu = ob->data; + Curve *cu = ob->data; if (me_eval == NULL) { - if (BKE_mesh_nurbs_displist_to_mdata(ob, - dispbase, - &allvert, - &totvert, - &alledge, - &totedge, - &allloop, - &allpoly, - &alluv, - &totloop, - &totpoly) != 0) { + if (mesh_nurbs_displist_to_mdata(cu, + dispbase, + &allvert, + &totvert, + &alledge, + &totedge, + &allloop, + &allpoly, + &alluv, + &totloop, + &totpoly) != 0) { /* Error initializing */ return; } @@ -702,18 +666,6 @@ void BKE_mesh_from_nurbs_displist( } } -void BKE_mesh_from_nurbs(Main *bmain, Object *ob) -{ - Curve *cu = (Curve *)ob->data; - ListBase disp = {NULL, NULL}; - - if (ob->runtime.curve_cache) { - disp = ob->runtime.curve_cache->disp; - } - - BKE_mesh_from_nurbs_displist(bmain, ob, &disp, cu->id.name, false); -} - typedef struct EdgeLink { struct EdgeLink *next, *prev; void *edge; @@ -1152,8 +1104,8 @@ static Mesh *mesh_new_from_curve_type_object(Object *object) BKE_mesh_from_nurbs_displist( NULL, temp_object, &temp_object->runtime.curve_cache->disp, curve->id.name + 2, true); - /* BKE_mesh_from_nurbs changes the type to a mesh, check it worked. If it didn't the curve did - * not have any segments or otherwise would have generated an empty mesh. */ + /* BKE_mesh_from_nurbs_displist changes the type to a mesh, check it worked. If it didn't + * the curve did not have any segments or otherwise would have generated an empty mesh. */ if (temp_object->type != OB_MESH) { BKE_id_free(NULL, temp_object->data); BKE_id_free(NULL, temp_object); diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 7cdea14e9bd..7e15ac5de5d 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -388,31 +388,12 @@ void BKE_object_batch_cache_dirty_tag(Object *ob) BKE_object_data_batch_cache_dirty_tag(ob->data); } -void BKE_object_data_eval_batch_cache_dirty_tag(Depsgraph *depsgraph, ID *object_data) -{ - DEG_debug_print_eval(depsgraph, __func__, object_data->name, object_data); - BKE_object_data_batch_cache_dirty_tag(object_data); -} - -void BKE_object_data_eval_batch_cache_deform_tag(Depsgraph *depsgraph, ID *object_data) -{ - DEG_debug_print_eval(depsgraph, __func__, object_data->name, object_data); - switch (GS(object_data->name)) { - case ID_ME: - BKE_mesh_batch_cache_dirty_tag((Mesh *)object_data, BKE_MESH_BATCH_DIRTY_DEFORM); - break; - default: - /* Only mesh is currently supported. Fallback to dirty all for other datablocks types. */ - BKE_object_data_batch_cache_dirty_tag(object_data); - break; - } -} - void BKE_object_eval_uber_data(Depsgraph *depsgraph, Scene *scene, Object *ob) { DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); BLI_assert(ob->type != OB_ARMATURE); BKE_object_handle_data_update(depsgraph, scene, ob); + BKE_object_batch_cache_dirty_tag(ob); } void BKE_object_eval_ptcache_reset(Depsgraph *depsgraph, Scene *scene, Object *object) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index db1fbb56125..f2f3c5d4ca6 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -4418,12 +4418,12 @@ void psys_get_texture( if ((event & mtex->mapto) & PAMAP_TIME) { /* the first time has to set the base value for time regardless of blend mode */ - if ((setvars & MAP_PA_TIME) == 0) { + if ((setvars & PAMAP_TIME) == 0) { int flip = (mtex->timefac < 0.0f); float timefac = fabsf(mtex->timefac); ptex->time *= 1.0f - timefac; ptex->time += timefac * ((flip) ? 1.0f - value : value); - setvars |= MAP_PA_TIME; + setvars |= PAMAP_TIME; } else { ptex->time = texture_value_blend(def, ptex->time, value, mtex->timefac, blend); diff --git a/source/blender/blenlib/BLI_delaunay_2d.h b/source/blender/blenlib/BLI_delaunay_2d.h index 5a8ddfb5a92..658dcadadce 100644 --- a/source/blender/blenlib/BLI_delaunay_2d.h +++ b/source/blender/blenlib/BLI_delaunay_2d.h @@ -110,7 +110,7 @@ extern "C" { * If zero is supplied for epsilon, an internal value of 1e-8 used * instead, since this code will not work correctly if it is not allowed * to merge "too near" vertices. - * + * * Normally the output will contain mappings from outputs to inputs. * If this is not needed, set need_ids to false and the execution may be much * faster in some circumstances. @@ -250,7 +250,7 @@ template<typename Arith_t> class CDT_result { Array<vec2<Arith_t>> vert; Array<std::pair<int, int>> edge; Array<Vector<int>> face; - /* The orig vectors are only popluated if the need_ids input field is true. */ + /* The orig vectors are only populated if the need_ids input field is true. */ /** For each output vert, which input verts correspond to it? */ Array<Vector<int>> vert_orig; /** diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 3978959a425..e106643a55f 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1942,7 +1942,7 @@ static BMOpDefine bmo_inset_region_def = { }; /* - * Edgeloop Offset. + * Edge-loop Offset. * * Creates edge loops based on simple edge-outset method. */ diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 20b56ceb55f..830792a2a48 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -49,8 +49,11 @@ set(SRC COM_compositor.h COM_defines.h + intern/COM_BufferArea.h intern/COM_BufferOperation.cc intern/COM_BufferOperation.h + intern/COM_BufferRange.h + intern/COM_BuffersIterator.h intern/COM_CPUDevice.cc intern/COM_CPUDevice.h intern/COM_ChunkOrder.cc diff --git a/source/blender/compositor/COM_defines.h b/source/blender/compositor/COM_defines.h index 9f8e6f10215..0e97bafbb0b 100644 --- a/source/blender/compositor/COM_defines.h +++ b/source/blender/compositor/COM_defines.h @@ -18,6 +18,9 @@ #pragma once +#include "BLI_index_range.hh" +#include "BLI_rect.h" + namespace blender::compositor { enum class eExecutionModel { @@ -109,4 +112,24 @@ constexpr float COM_PREVIEW_SIZE = 140.f; constexpr float COM_RULE_OF_THIRDS_DIVIDER = 100.0f; constexpr float COM_BLUR_BOKEH_PIXELS = 512; +constexpr IndexRange XRange(const rcti &area) +{ + return IndexRange(area.xmin, area.xmax - area.xmin); +} + +constexpr IndexRange YRange(const rcti &area) +{ + return IndexRange(area.ymin, area.ymax - area.ymin); +} + +constexpr IndexRange XRange(const rcti *area) +{ + return XRange(*area); +} + +constexpr IndexRange YRange(const rcti *area) +{ + return YRange(*area); +} + } // namespace blender::compositor diff --git a/source/blender/compositor/intern/COM_BufferArea.h b/source/blender/compositor/intern/COM_BufferArea.h new file mode 100644 index 00000000000..621ffea5bc3 --- /dev/null +++ b/source/blender/compositor/intern/COM_BufferArea.h @@ -0,0 +1,198 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2021, Blender Foundation. + */ + +#pragma once + +#include "BLI_rect.h" + +#include <iterator> + +namespace blender::compositor { + +/* Forward declarations. */ +template<typename T> class BufferAreaIterator; + +/** + * A rectangle area of buffer elements. + */ +template<typename T> class BufferArea : rcti { + public: + using Iterator = BufferAreaIterator<T>; + using ConstIterator = BufferAreaIterator<const T>; + + private: + T *buffer_; + /* Number of elements in a buffer row. */ + int buffer_width_; + /* Buffer element stride. */ + int elem_stride_; + + public: + constexpr BufferArea() = default; + + /** + * Create a buffer area containing given rectangle area. + */ + constexpr BufferArea(T *buffer, int buffer_width, const rcti &area, int elem_stride = 1) + : rcti(area), buffer_(buffer), buffer_width_(buffer_width), elem_stride_(elem_stride) + { + } + + /** + * Create a buffer area containing whole buffer with no offsets. + */ + constexpr BufferArea(T *buffer, int buffer_width, int buffer_height, int elem_stride = 1) + : buffer_(buffer), buffer_width_(buffer_width), elem_stride_(elem_stride) + { + BLI_rcti_init(this, 0, buffer_width, 0, buffer_height); + } + + constexpr friend bool operator==(const BufferArea &a, const BufferArea &b) + { + return a.buffer_ == b.buffer_ && BLI_rcti_compare(&a, &b) && a.elem_stride_ == b.elem_stride_; + } + + constexpr const rcti &get_rect() const + { + return *this; + } + + /** + * Number of elements in a row. + */ + constexpr int width() const + { + return BLI_rcti_size_x(this); + } + + /** + * Number of elements in a column. + */ + constexpr int height() const + { + return BLI_rcti_size_y(this); + } + + constexpr Iterator begin() + { + return begin_iterator<Iterator>(); + } + + constexpr Iterator end() + { + return end_iterator<Iterator>(); + } + + constexpr ConstIterator begin() const + { + return begin_iterator<ConstIterator>(); + } + + constexpr ConstIterator end() const + { + return end_iterator<ConstIterator>(); + } + + private: + template<typename TIterator> constexpr TIterator begin_iterator() const + { + if (elem_stride_ == 0) { + /* Iterate a single element. */ + return TIterator(buffer_, 1, 1, 1); + } + + T *begin_ptr = buffer_ + (intptr_t)this->ymin * buffer_width_ * elem_stride_ + + (intptr_t)this->xmin * elem_stride_; + return TIterator(begin_ptr, buffer_width_, BLI_rcti_size_x(this), elem_stride_); + } + + template<typename TIterator> constexpr TIterator end_iterator() const + { + if (elem_stride_ == 0) { + /* Iterate a single element. */ + return TIterator(buffer_ + 1, 1, 1, 1); + } + + T *end_ptr = buffer_ + (intptr_t)(this->ymax - 1) * buffer_width_ * elem_stride_ + + (intptr_t)this->xmax * elem_stride_; + return TIterator(end_ptr, buffer_width_, BLI_rcti_size_x(this), elem_stride_); + } +}; + +template<typename T> class BufferAreaIterator { + public: + using iterator_category = std::input_iterator_tag; + using value_type = T *; + using pointer = T *const *; + using reference = T *const &; + using difference_type = std::ptrdiff_t; + + private: + int elem_stride_; + int row_stride_; + /* Stride between a row end and the next row start. */ + int rows_gap_; + T *current_; + const T *row_end_; + + public: + constexpr BufferAreaIterator() = default; + + constexpr BufferAreaIterator(T *current, int buffer_width, int area_width, int elem_stride = 1) + : elem_stride_(elem_stride), + row_stride_(buffer_width * elem_stride), + rows_gap_(row_stride_ - area_width * elem_stride), + current_(current), + row_end_(current + area_width * elem_stride) + { + } + + constexpr BufferAreaIterator &operator++() + { + current_ += elem_stride_; + if (current_ == row_end_) { + current_ += rows_gap_; + row_end_ += row_stride_; + } + return *this; + } + + constexpr BufferAreaIterator operator++(int) const + { + BufferAreaIterator copied_iterator = *this; + ++copied_iterator; + return copied_iterator; + } + + constexpr friend bool operator!=(const BufferAreaIterator &a, const BufferAreaIterator &b) + { + return a.current_ != b.current_; + } + + constexpr friend bool operator==(const BufferAreaIterator &a, const BufferAreaIterator &b) + { + return a.current_ == b.current_; + } + + constexpr T *operator*() const + { + return current_; + } +}; + +} // namespace blender::compositor diff --git a/source/blender/compositor/intern/COM_BufferRange.h b/source/blender/compositor/intern/COM_BufferRange.h new file mode 100644 index 00000000000..ffdf1f2f1e5 --- /dev/null +++ b/source/blender/compositor/intern/COM_BufferRange.h @@ -0,0 +1,171 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2021, Blender Foundation. + */ + +#pragma once + +#include "BLI_assert.h" +#include "BLI_rect.h" + +#include <iterator> + +namespace blender::compositor { + +/* Forward declarations. */ +template<typename T> class BufferRangeIterator; + +/** + * A range of buffer elements. + */ +template<typename T> class BufferRange { + public: + using Iterator = BufferRangeIterator<T>; + using ConstIterator = BufferRangeIterator<const T>; + + private: + T *start_; + /* Number of elements in the range. */ + int64_t size_; + /* Buffer element stride. */ + int elem_stride_; + + public: + constexpr BufferRange() = default; + + /** + * Create a buffer range of elements from a given element index. + */ + constexpr BufferRange(T *buffer, int64_t start_elem_index, int64_t size, int elem_stride = 1) + : start_(buffer + start_elem_index * elem_stride), size_(size), elem_stride_(elem_stride) + { + } + + constexpr friend bool operator==(const BufferRange &a, const BufferRange &b) + { + return a.start_ == b.start_ && a.size_ == b.size_ && a.elem_stride_ == b.elem_stride_; + } + + /** + * Access an element in the range. Index is relative to range start. + */ + constexpr T *operator[](int64_t index) const + { + BLI_assert(index >= 0); + BLI_assert(index < this->size()); + return start_ + index * elem_stride_; + } + + /** + * Get the number of elements in the range. + */ + constexpr int64_t size() const + { + return size_; + } + + constexpr Iterator begin() + { + return begin_iterator<Iterator>(); + } + + constexpr Iterator end() + { + return end_iterator<Iterator>(); + } + + constexpr ConstIterator begin() const + { + return begin_iterator<ConstIterator>(); + } + + constexpr ConstIterator end() const + { + return end_iterator<ConstIterator>(); + } + + private: + template<typename TIterator> constexpr TIterator begin_iterator() const + { + if (elem_stride_ == 0) { + /* Iterate a single element. */ + return TIterator(start_, 1); + } + + return TIterator(start_, elem_stride_); + } + + template<typename TIterator> constexpr TIterator end_iterator() const + { + if (elem_stride_ == 0) { + /* Iterate a single element. */ + return TIterator(start_ + 1, 1); + } + + return TIterator(start_ + size_ * elem_stride_, elem_stride_); + } +}; + +template<typename T> class BufferRangeIterator { + public: + using iterator_category = std::input_iterator_tag; + using value_type = T *; + using pointer = T *const *; + using reference = T *const &; + using difference_type = std::ptrdiff_t; + + private: + T *current_; + int elem_stride_; + + public: + constexpr BufferRangeIterator() = default; + + constexpr BufferRangeIterator(T *current, int elem_stride = 1) + : current_(current), elem_stride_(elem_stride) + { + } + + constexpr BufferRangeIterator &operator++() + { + current_ += elem_stride_; + return *this; + } + + constexpr BufferRangeIterator operator++(int) const + { + BufferRangeIterator copied_iterator = *this; + ++copied_iterator; + return copied_iterator; + } + + constexpr friend bool operator!=(const BufferRangeIterator &a, const BufferRangeIterator &b) + { + return a.current_ != b.current_; + } + + constexpr friend bool operator==(const BufferRangeIterator &a, const BufferRangeIterator &b) + { + return a.current_ == b.current_; + } + + constexpr T *operator*() const + { + return current_; + } +}; + +} // namespace blender::compositor diff --git a/source/blender/compositor/intern/COM_BuffersIterator.h b/source/blender/compositor/intern/COM_BuffersIterator.h new file mode 100644 index 00000000000..58dbd9c6f59 --- /dev/null +++ b/source/blender/compositor/intern/COM_BuffersIterator.h @@ -0,0 +1,164 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2021, Blender Foundation. + */ + +#pragma once + +#include "BLI_rect.h" +#include "BLI_vector.hh" + +namespace blender::compositor { + +/** + * Builds an iterator for simultaneously iterating an area of elements in an output buffer and any + * number of input buffers. It's not a standard C++ iterator and it does not support neither + * deference, equality or postfix increment operators. + */ +template<typename T> class BuffersIteratorBuilder { + public: + class Iterator { + const T *out_end_; + const T *out_row_end_; + int out_elem_stride_; + int out_row_stride_; + /* Stride between an output row end and the next row start. */ + int out_rows_gap_; + + struct In { + int elem_stride; + int rows_gap; + const T *in; + }; + Vector<In, 6> ins_; + + friend class BuffersIteratorBuilder; + + public: + /** + * Current output element. + */ + T *out; + + public: + /** + * Get current element from an input. + */ + const T *in(int input_index) const + { + BLI_assert(input_index < ins_.size()); + return ins_[input_index].in; + } + + int get_num_inputs() const + { + return ins_.size(); + } + + /** + * Has the end of the area been reached. + */ + bool is_end() const + { + return out >= out_end_; + } + + /** + * Go to the next element in the area. + */ + void next() + { + out += out_elem_stride_; + for (In &in : ins_) { + in.in += in.elem_stride; + } + if (out == out_row_end_) { + out += out_rows_gap_; + out_row_end_ += out_row_stride_; + for (In &in : ins_) { + in.in += in.rows_gap; + } + } + } + + Iterator &operator++() + { + this->next(); + return *this; + } + }; + + private: + Iterator iterator_; + rcti area_; + bool is_built_; + + public: + /** + * Create a buffers iterator builder to iterate given output buffer area. + * \param output: Output buffer. + * \param buffer_width: Number of elements in an output buffer row. + * \param area: Rectangle area to be iterated in all buffers. + * \param elem_stride: Output buffer element stride. + */ + BuffersIteratorBuilder(T *output, int buffer_width, const rcti &area, int elem_stride = 1) + : area_(area), is_built_(false) + { + iterator_.out_elem_stride_ = elem_stride; + iterator_.out_row_stride_ = buffer_width * elem_stride; + iterator_.out_rows_gap_ = iterator_.out_row_stride_ - BLI_rcti_size_x(&area) * elem_stride; + iterator_.out = output + (intptr_t)area.ymin * iterator_.out_row_stride_ + + (intptr_t)area.xmin * elem_stride; + iterator_.out_row_end_ = iterator_.out + (intptr_t)BLI_rcti_size_x(&area) * elem_stride; + iterator_.out_end_ = iterator_.out_row_end_ + + (intptr_t)iterator_.out_row_stride_ * (BLI_rcti_size_y(&area) - 1); + } + + /** + * Create a buffers iterator builder to iterate given output buffer with no offsets. + */ + BuffersIteratorBuilder(T *output, int buffer_width, int buffer_height, int elem_stride = 1) + : BuffersIteratorBuilder( + output, buffer_width, {0, buffer_width, 0, buffer_height}, elem_stride) + { + } + + /** + * Add an input buffer to be iterated. Its coordinates must be correlated with the output. + */ + void add_input(const T *input, int buffer_width, int elem_stride = 1) + { + BLI_assert(!is_built_); + typename Iterator::In in; + in.elem_stride = elem_stride; + in.rows_gap = buffer_width * elem_stride - BLI_rcti_size_x(&area_) * elem_stride; + in.in = input + area_.ymin * buffer_width * elem_stride + area_.xmin * elem_stride; + iterator_.ins_.append(std::move(in)); + } + + /** + * Build the iterator. + */ + BuffersIteratorBuilder::Iterator build() + { + is_built_ = true; + return iterator_; + } +}; + +template<typename T> using BuffersIterator = typename BuffersIteratorBuilder<T>::Iterator; + +} // namespace blender::compositor diff --git a/source/blender/compositor/intern/COM_Debug.cc b/source/blender/compositor/intern/COM_Debug.cc index abef4517b3e..c0460aed4a4 100644 --- a/source/blender/compositor/intern/COM_Debug.cc +++ b/source/blender/compositor/intern/COM_Debug.cc @@ -31,6 +31,8 @@ extern "C" { #include "BKE_appdir.h" #include "BKE_node.h" #include "DNA_node_types.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" } #include "COM_ExecutionSystem.h" @@ -50,7 +52,7 @@ std::string DebugInfo::m_current_node_name; std::string DebugInfo::m_current_op_name; DebugInfo::GroupStateMap DebugInfo::m_group_states; -static std::string operation_class_name(NodeOperation *op) +static std::string operation_class_name(const NodeOperation *op) { std::string full_name = typeid(*op).name(); /* Remove name-spaces. */ @@ -452,4 +454,45 @@ void DebugInfo::graphviz(const ExecutionSystem *system, StringRefNull name) } } +static std::string get_operations_export_dir() +{ + return std::string(BKE_tempdir_session()) + "COM_operations" + SEP_STR; +} + +void DebugInfo::export_operation(const NodeOperation *op, MemoryBuffer *render) +{ + ImBuf *ibuf = IMB_allocFromBuffer(nullptr, + render->getBuffer(), + render->getWidth(), + render->getHeight(), + render->get_num_channels()); + + const std::string file_name = operation_class_name(op) + "_" + std::to_string(op->get_id()) + + ".png"; + const std::string path = get_operations_export_dir() + file_name; + BLI_make_existing_file(path.c_str()); + IMB_saveiff(ibuf, path.c_str(), ibuf->flags); + IMB_freeImBuf(ibuf); +} + +void DebugInfo::delete_operation_exports() +{ + const std::string dir = get_operations_export_dir(); + if (BLI_exists(dir.c_str())) { + struct direntry *file_list; + int num_files = BLI_filelist_dir_contents(dir.c_str(), &file_list); + for (int i = 0; i < num_files; i++) { + direntry *file = &file_list[i]; + const eFileAttributes file_attrs = BLI_file_attributes(file->path); + if (file_attrs & FILE_ATTR_ANY_LINK) { + continue; + } + + if (BLI_is_file(file->path) && BLI_path_extension_check(file->path, ".png")) { + BLI_delete(file->path, false, false); + } + } + } +} + } // namespace blender::compositor diff --git a/source/blender/compositor/intern/COM_Debug.h b/source/blender/compositor/intern/COM_Debug.h index 53461e13f48..23d99c7e529 100644 --- a/source/blender/compositor/intern/COM_Debug.h +++ b/source/blender/compositor/intern/COM_Debug.h @@ -30,6 +30,9 @@ namespace blender::compositor { static constexpr bool COM_EXPORT_GRAPHVIZ = false; static constexpr bool COM_GRAPHVIZ_SHOW_NODE_NAME = false; +/* Saves operations results to image files. */ +static constexpr bool COM_EXPORT_OPERATION_BUFFERS = false; + class Node; class ExecutionSystem; class ExecutionGroup; @@ -75,6 +78,9 @@ class DebugInfo { m_group_states[execution_group] = EG_WAIT; } } + if (COM_EXPORT_OPERATION_BUFFERS) { + delete_operation_exports(); + } }; static void node_added(const Node *node) @@ -118,6 +124,14 @@ class DebugInfo { } }; + static void operation_rendered(const NodeOperation *op, MemoryBuffer *render) + { + /* Don't export constant operations as there are too many and it's rarely useful. */ + if (COM_EXPORT_OPERATION_BUFFERS && render && !render->is_a_single_elem()) { + export_operation(op, render); + } + } + static void graphviz(const ExecutionSystem *system, StringRefNull name = ""); protected: @@ -133,6 +147,9 @@ class DebugInfo { const char *name, const char *color, const char *style, char *str, int maxlen); static int graphviz_legend(char *str, int maxlen, bool has_execution_groups); static bool graphviz_system(const ExecutionSystem *system, char *str, int maxlen); + + static void export_operation(const NodeOperation *op, MemoryBuffer *render); + static void delete_operation_exports(); }; } // namespace blender::compositor diff --git a/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc b/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc index 3b0a9172871..9f6904bb306 100644 --- a/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc +++ b/source/blender/compositor/intern/COM_FullFrameExecutionModel.cc @@ -104,6 +104,7 @@ void FullFrameExecutionModel::render_operation(NodeOperation *op) op->render(op_buf, areas, input_bufs); active_buffers_.set_rendered_buffer(op, std::unique_ptr<MemoryBuffer>(op_buf)); + DebugInfo::operation_rendered(op, op_buf); operation_finished(op); } diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cc b/source/blender/compositor/intern/COM_MemoryBuffer.cc index c7bddddd0e6..f4f58146de4 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.cc +++ b/source/blender/compositor/intern/COM_MemoryBuffer.cc @@ -129,6 +129,20 @@ void MemoryBuffer::clear() memset(m_buffer, 0, buffer_len() * m_num_channels * sizeof(float)); } +BuffersIterator<float> MemoryBuffer::iterate_with(Span<MemoryBuffer *> inputs) +{ + return iterate_with(inputs, m_rect); +} + +BuffersIterator<float> MemoryBuffer::iterate_with(Span<MemoryBuffer *> inputs, const rcti &area) +{ + BuffersIteratorBuilder<float> builder(m_buffer, getWidth(), area, elem_stride); + for (MemoryBuffer *input : inputs) { + builder.add_input(input->getBuffer(), input->getWidth(), input->elem_stride); + } + return builder.build(); +} + /** * Converts a single elem buffer to a full size buffer (allocates memory for all * elements in resolution). diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h index 4ad0872b0b7..048ed4c5d6e 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.h +++ b/source/blender/compositor/intern/COM_MemoryBuffer.h @@ -18,6 +18,9 @@ #pragma once +#include "COM_BufferArea.h" +#include "COM_BufferRange.h" +#include "COM_BuffersIterator.h" #include "COM_ExecutionGroup.h" #include "COM_MemoryProxy.h" @@ -239,6 +242,32 @@ class MemoryBuffer { } /** + * Get all buffer elements as a range with no offsets. + */ + BufferRange<float> as_range() + { + return BufferRange<float>(m_buffer, 0, buffer_len(), elem_stride); + } + + BufferRange<const float> as_range() const + { + return BufferRange<const float>(m_buffer, 0, buffer_len(), elem_stride); + } + + BufferArea<float> get_buffer_area(const rcti &area) + { + return BufferArea<float>(m_buffer, getWidth(), area, elem_stride); + } + + BufferArea<const float> get_buffer_area(const rcti &area) const + { + return BufferArea<const float>(m_buffer, getWidth(), area, elem_stride); + } + + BuffersIterator<float> iterate_with(Span<MemoryBuffer *> inputs); + BuffersIterator<float> iterate_with(Span<MemoryBuffer *> inputs, const rcti &area); + + /** * \brief get the data of this MemoryBuffer * \note buffer should already be available in memory */ diff --git a/source/blender/compositor/operations/COM_BrightnessOperation.cc b/source/blender/compositor/operations/COM_BrightnessOperation.cc index 92cab47318a..7878eca2bbd 100644 --- a/source/blender/compositor/operations/COM_BrightnessOperation.cc +++ b/source/blender/compositor/operations/COM_BrightnessOperation.cc @@ -28,6 +28,7 @@ BrightnessOperation::BrightnessOperation() this->addOutputSocket(DataType::Color); this->m_inputProgram = nullptr; this->m_use_premultiply = false; + flags.can_be_constant = true; } void BrightnessOperation::setUsePremultiply(bool use_premultiply) @@ -85,6 +86,50 @@ void BrightnessOperation::executePixelSampled(float output[4], } } +void BrightnessOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) +{ + float tmp_color[4]; + for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) { + const float *in_color = it.in(0); + const float brightness = *it.in(1) / 100.0f; + const float contrast = *it.in(2); + float delta = contrast / 200.0f; + /* + * The algorithm is by Werner D. Streidt + * (http://visca.com/ffactory/archives/5-99/msg00021.html) + * Extracted of OpenCV demhist.c + */ + float a, b; + if (contrast > 0) { + a = 1.0f - delta * 2.0f; + a = 1.0f / max_ff(a, FLT_EPSILON); + b = a * (brightness - delta); + } + else { + delta *= -1; + a = max_ff(1.0f - delta * 2.0f, 0.0f); + b = a * brightness + delta; + } + const float *color; + if (this->m_use_premultiply) { + premul_to_straight_v4_v4(tmp_color, in_color); + color = tmp_color; + } + else { + color = in_color; + } + it.out[0] = a * color[0] + b; + it.out[1] = a * color[1] + b; + it.out[2] = a * color[2] + b; + it.out[3] = color[3]; + if (this->m_use_premultiply) { + straight_to_premul_v4(it.out); + } + } +} + void BrightnessOperation::deinitExecution() { this->m_inputProgram = nullptr; diff --git a/source/blender/compositor/operations/COM_BrightnessOperation.h b/source/blender/compositor/operations/COM_BrightnessOperation.h index 7c33e0b35ec..64b4fa0dbe2 100644 --- a/source/blender/compositor/operations/COM_BrightnessOperation.h +++ b/source/blender/compositor/operations/COM_BrightnessOperation.h @@ -18,11 +18,11 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedOperation.h" namespace blender::compositor { -class BrightnessOperation : public NodeOperation { +class BrightnessOperation : public MultiThreadedOperation { private: /** * Cached reference to the inputProgram @@ -52,6 +52,10 @@ class BrightnessOperation : public NodeOperation { void deinitExecution() override; void setUsePremultiply(bool use_premultiply); + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cc b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cc index c4099a6d33d..1a0d7e52b0f 100644 --- a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cc +++ b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cc @@ -1318,6 +1318,7 @@ DoubleEdgeMaskOperation::DoubleEdgeMaskOperation() this->m_adjacentOnly = false; this->m_keepInside = false; this->flags.complex = true; + is_output_rendered_ = false; } bool DoubleEdgeMaskOperation::determineDependingAreaOfInterest(rcti * /*input*/, @@ -1382,4 +1383,43 @@ void DoubleEdgeMaskOperation::deinitExecution() } } +void DoubleEdgeMaskOperation::get_area_of_interest(int UNUSED(input_idx), + const rcti &UNUSED(output_area), + rcti &r_input_area) +{ + r_input_area.xmax = this->getWidth(); + r_input_area.xmin = 0; + r_input_area.ymax = this->getHeight(); + r_input_area.ymin = 0; +} + +void DoubleEdgeMaskOperation::update_memory_buffer(MemoryBuffer *output, + const rcti &UNUSED(area), + Span<MemoryBuffer *> inputs) +{ + if (!is_output_rendered_) { + /* Ensure full buffers to work with no strides. */ + MemoryBuffer *input_inner_mask = inputs[0]; + MemoryBuffer *inner_mask = input_inner_mask->is_a_single_elem() ? input_inner_mask->inflate() : + input_inner_mask; + MemoryBuffer *input_outer_mask = inputs[1]; + MemoryBuffer *outer_mask = input_outer_mask->is_a_single_elem() ? input_outer_mask->inflate() : + input_outer_mask; + + BLI_assert(output->getWidth() == this->getWidth()); + BLI_assert(output->getHeight() == this->getHeight()); + /* TODO(manzanilla): Once tiled implementation is removed, use execution system to run + * multi-threaded where possible. */ + doDoubleEdgeMask(inner_mask->getBuffer(), outer_mask->getBuffer(), output->getBuffer()); + is_output_rendered_ = true; + + if (inner_mask != input_inner_mask) { + delete inner_mask; + } + if (outer_mask != input_outer_mask) { + delete outer_mask; + } + } +} + } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h index e956e8edc3e..45a80bbbbf0 100644 --- a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h +++ b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h @@ -18,7 +18,7 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedOperation.h" namespace blender::compositor { @@ -31,8 +31,12 @@ class DoubleEdgeMaskOperation : public NodeOperation { SocketReader *m_inputInnerMask; bool m_adjacentOnly; bool m_keepInside; + + /* TODO(manzanilla): To be removed with tiled implementation. */ float *m_cachedInstance; + bool is_output_rendered_; + public: DoubleEdgeMaskOperation(); @@ -66,6 +70,12 @@ class DoubleEdgeMaskOperation : public NodeOperation { { this->m_keepInside = keepInside; } + + void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override; + + void update_memory_buffer(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_EllipseMaskOperation.cc b/source/blender/compositor/operations/COM_EllipseMaskOperation.cc index 5a4503fecec..eb1fd98a590 100644 --- a/source/blender/compositor/operations/COM_EllipseMaskOperation.cc +++ b/source/blender/compositor/operations/COM_EllipseMaskOperation.cc @@ -20,6 +20,8 @@ #include "BLI_math.h" #include "DNA_node_types.h" +#include <functional> + namespace blender::compositor { EllipseMaskOperation::EllipseMaskOperation() @@ -114,6 +116,77 @@ void EllipseMaskOperation::executePixelSampled(float output[4], } } +void EllipseMaskOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) +{ + MaskFunc mask_func; + switch (m_maskType) { + case CMP_NODE_MASKTYPE_ADD: + mask_func = [](const bool is_inside, const float *mask, const float *value) { + return is_inside ? MAX2(mask[0], value[0]) : mask[0]; + }; + break; + case CMP_NODE_MASKTYPE_SUBTRACT: + mask_func = [](const bool is_inside, const float *mask, const float *value) { + return is_inside ? CLAMPIS(mask[0] - value[0], 0, 1) : mask[0]; + }; + break; + case CMP_NODE_MASKTYPE_MULTIPLY: + mask_func = [](const bool is_inside, const float *mask, const float *value) { + return is_inside ? mask[0] * value[0] : 0; + }; + break; + case CMP_NODE_MASKTYPE_NOT: + mask_func = [](const bool is_inside, const float *mask, const float *value) { + if (is_inside) { + return mask[0] > 0.0f ? 0.0f : value[0]; + } + return mask[0]; + }; + break; + } + apply_mask(output, area, inputs, mask_func); +} + +void EllipseMaskOperation::apply_mask(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs, + MaskFunc mask_func) +{ + const MemoryBuffer *input_mask = inputs[0]; + const MemoryBuffer *input_value = inputs[1]; + const float op_w = this->getWidth(); + const float op_h = this->getHeight(); + const float half_w = this->m_data->width / 2.0f; + const float half_h = this->m_data->height / 2.0f; + const float tx = half_w * half_w; + const float ty = half_h * half_h; + for (const int y : YRange(area)) { + const float op_ry = y / op_h; + const float dy = (op_ry - this->m_data->y) / m_aspectRatio; + float *out = output->get_elem(area.xmin, y); + const float *mask = input_mask->get_elem(area.xmin, y); + const float *value = input_value->get_elem(area.xmin, y); + for (const int x : XRange(area)) { + const float op_rx = x / op_w; + const float dx = op_rx - this->m_data->x; + const float rx = this->m_data->x + (m_cosine * dx + m_sine * dy); + const float ry = this->m_data->y + (-m_sine * dx + m_cosine * dy); + float sx = rx - this->m_data->x; + sx *= sx; + float sy = ry - this->m_data->y; + sy *= sy; + const bool inside = ((sx / tx) + (sy / ty)) < 1.0f; + out[0] = mask_func(inside, mask, value); + + mask += input_mask->elem_stride; + value += input_value->elem_stride; + out += output->elem_stride; + } + } +} + void EllipseMaskOperation::deinitExecution() { this->m_inputMask = nullptr; diff --git a/source/blender/compositor/operations/COM_EllipseMaskOperation.h b/source/blender/compositor/operations/COM_EllipseMaskOperation.h index 64afe0145cf..fba3f979d26 100644 --- a/source/blender/compositor/operations/COM_EllipseMaskOperation.h +++ b/source/blender/compositor/operations/COM_EllipseMaskOperation.h @@ -18,12 +18,14 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedOperation.h" namespace blender::compositor { -class EllipseMaskOperation : public NodeOperation { +class EllipseMaskOperation : public MultiThreadedOperation { private: + using MaskFunc = std::function<float(bool is_inside, const float *mask, const float *value)>; + /** * Cached reference to the inputProgram */ @@ -64,6 +66,16 @@ class EllipseMaskOperation : public NodeOperation { { this->m_maskType = maskType; } + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) override; + + private: + void apply_mask(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs, + MaskFunc mask_func); }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_MixOperation.cc b/source/blender/compositor/operations/COM_MixOperation.cc index 58fa09fa2a8..77ecbf60356 100644 --- a/source/blender/compositor/operations/COM_MixOperation.cc +++ b/source/blender/compositor/operations/COM_MixOperation.cc @@ -35,6 +35,7 @@ MixBaseOperation::MixBaseOperation() this->m_inputColor2Operation = nullptr; this->setUseValueAlphaMultiply(false); this->setUseClamp(false); + flags.can_be_constant = true; } void MixBaseOperation::initExecution() @@ -97,6 +98,45 @@ void MixBaseOperation::deinitExecution() this->m_inputColor2Operation = nullptr; } +void MixBaseOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) +{ + const MemoryBuffer *input_value = inputs[0]; + const MemoryBuffer *input_color1 = inputs[1]; + const MemoryBuffer *input_color2 = inputs[2]; + const int width = BLI_rcti_size_x(&area); + PixelCursor p; + p.out_stride = output->elem_stride; + p.value_stride = input_value->elem_stride; + p.color1_stride = input_color1->elem_stride; + p.color2_stride = input_color2->elem_stride; + for (const int y : YRange(area)) { + p.out = output->get_elem(area.xmin, y); + p.row_end = p.out + width * output->elem_stride; + p.value = input_value->get_elem(area.xmin, y); + p.color1 = input_color1->get_elem(area.xmin, y); + p.color2 = input_color2->get_elem(area.xmin, y); + update_memory_buffer_row(p); + } +} + +void MixBaseOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + p.out[0] = value_m * p.color1[0] + value * p.color2[0]; + p.out[1] = value_m * p.color1[1] + value * p.color2[1]; + p.out[2] = value_m * p.color1[2] + value * p.color2[2]; + p.out[3] = p.color1[3]; + p.next(); + } +} + /* ******** Mix Add Operation ******** */ void MixAddOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) @@ -121,6 +161,23 @@ void MixAddOperation::executePixelSampled(float output[4], float x, float y, Pix clampIfNeeded(output); } +void MixAddOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + p.out[0] = p.color1[0] + value * p.color2[0]; + p.out[1] = p.color1[1] + value * p.color2[1]; + p.out[2] = p.color1[2] + value * p.color2[2]; + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Blend Operation ******** */ void MixBlendOperation::executePixelSampled(float output[4], @@ -150,6 +207,24 @@ void MixBlendOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixBlendOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + float value_m = 1.0f - value; + p.out[0] = value_m * p.color1[0] + value * p.color2[0]; + p.out[1] = value_m * p.color1[1] + value * p.color2[1]; + p.out[2] = value_m * p.color1[2] + value * p.color2[2]; + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Burn Operation ******** */ void MixColorBurnOperation::executePixelSampled(float output[4], @@ -228,6 +303,48 @@ void MixColorBurnOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixColorBurnOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + + float tmp = value_m + value * p.color2[0]; + if (tmp <= 0.0f) { + p.out[0] = 0.0f; + } + else { + tmp = 1.0f - (1.0f - p.color1[0]) / tmp; + p.out[0] = CLAMPIS(tmp, 0.0f, 1.0f); + } + + tmp = value_m + value * p.color2[1]; + if (tmp <= 0.0f) { + p.out[1] = 0.0f; + } + else { + tmp = 1.0f - (1.0f - p.color1[1]) / tmp; + p.out[1] = CLAMPIS(tmp, 0.0f, 1.0f); + } + + tmp = value_m + value * p.color2[2]; + if (tmp <= 0.0f) { + p.out[2] = 0.0f; + } + else { + tmp = 1.0f - (1.0f - p.color1[2]) / tmp; + p.out[2] = CLAMPIS(tmp, 0.0f, 1.0f); + } + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Color Operation ******** */ void MixColorOperation::executePixelSampled(float output[4], @@ -268,6 +385,36 @@ void MixColorOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixColorOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + + float colH, colS, colV; + rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV); + if (colS != 0.0f) { + float rH, rS, rV; + float tmpr, tmpg, tmpb; + rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV); + hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb); + p.out[0] = (value_m * p.color1[0]) + (value * tmpr); + p.out[1] = (value_m * p.color1[1]) + (value * tmpg); + p.out[2] = (value_m * p.color1[2]) + (value * tmpb); + } + else { + copy_v3_v3(p.out, p.color1); + } + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Darken Operation ******** */ void MixDarkenOperation::executePixelSampled(float output[4], @@ -296,6 +443,24 @@ void MixDarkenOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixDarkenOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + float value_m = 1.0f - value; + p.out[0] = min_ff(p.color1[0], p.color2[0]) * value + p.color1[0] * value_m; + p.out[1] = min_ff(p.color1[1], p.color2[1]) * value + p.color1[1] * value_m; + p.out[2] = min_ff(p.color1[2], p.color2[2]) * value + p.color1[2] * value_m; + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Difference Operation ******** */ void MixDifferenceOperation::executePixelSampled(float output[4], @@ -324,6 +489,24 @@ void MixDifferenceOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixDifferenceOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + p.out[0] = value_m * p.color1[0] + value * fabsf(p.color1[0] - p.color2[0]); + p.out[1] = value_m * p.color1[1] + value * fabsf(p.color1[1] - p.color2[1]); + p.out[2] = value_m * p.color1[2] + value * fabsf(p.color1[2] - p.color2[2]); + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Difference Operation ******** */ void MixDivideOperation::executePixelSampled(float output[4], @@ -369,6 +552,41 @@ void MixDivideOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixDivideOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + + if (p.color2[0] != 0.0f) { + p.out[0] = value_m * (p.color1[0]) + value * (p.color1[0]) / p.color2[0]; + } + else { + p.out[0] = 0.0f; + } + if (p.color2[1] != 0.0f) { + p.out[1] = value_m * (p.color1[1]) + value * (p.color1[1]) / p.color2[1]; + } + else { + p.out[1] = 0.0f; + } + if (p.color2[2] != 0.0f) { + p.out[2] = value_m * (p.color1[2]) + value * (p.color1[2]) / p.color2[2]; + } + else { + p.out[2] = 0.0f; + } + + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Dodge Operation ******** */ void MixDodgeOperation::executePixelSampled(float output[4], @@ -452,6 +670,64 @@ void MixDodgeOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixDodgeOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + + float tmp; + if (p.color1[0] != 0.0f) { + tmp = 1.0f - value * p.color2[0]; + if (tmp <= 0.0f) { + p.out[0] = 1.0f; + } + else { + p.out[0] = p.color1[0] / tmp; + CLAMP_MAX(p.out[0], 1.0f); + } + } + else { + p.out[0] = 0.0f; + } + + if (p.color1[1] != 0.0f) { + tmp = 1.0f - value * p.color2[1]; + if (tmp <= 0.0f) { + p.out[1] = 1.0f; + } + else { + p.out[1] = p.color1[1] / tmp; + CLAMP_MAX(p.out[1], 1.0f); + } + } + else { + p.out[1] = 0.0f; + } + + if (p.color1[2] != 0.0f) { + tmp = 1.0f - value * p.color2[2]; + if (tmp <= 0.0f) { + p.out[2] = 1.0f; + } + else { + p.out[2] = p.color1[2] / tmp; + CLAMP_MAX(p.out[2], 1.0f); + } + } + else { + p.out[2] = 0.0f; + } + + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Glare Operation ******** */ void MixGlareOperation::executePixelSampled(float output[4], @@ -487,6 +763,33 @@ void MixGlareOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixGlareOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + const float value = p.value[0]; + /* Linear interpolation between 3 cases: + * value=-1:output=input value=0:output=input+glare value=1:output=glare + */ + float input_weight; + float glare_weight; + if (value < 0.0f) { + input_weight = 1.0f; + glare_weight = 1.0f + value; + } + else { + input_weight = 1.0f - value; + glare_weight = 1.0f; + } + p.out[0] = input_weight * MAX2(p.color1[0], 0.0f) + glare_weight * p.color2[0]; + p.out[1] = input_weight * MAX2(p.color1[1], 0.0f) + glare_weight * p.color2[1]; + p.out[2] = input_weight * MAX2(p.color1[2], 0.0f) + glare_weight * p.color2[2]; + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Hue Operation ******** */ void MixHueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) @@ -524,6 +827,36 @@ void MixHueOperation::executePixelSampled(float output[4], float x, float y, Pix clampIfNeeded(output); } +void MixHueOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + + float colH, colS, colV; + rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV); + if (colS != 0.0f) { + float rH, rS, rV; + float tmpr, tmpg, tmpb; + rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV); + hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb); + p.out[0] = value_m * p.color1[0] + value * tmpr; + p.out[1] = value_m * p.color1[1] + value * tmpg; + p.out[2] = value_m * p.color1[2] + value * tmpb; + } + else { + copy_v3_v3(p.out, p.color1); + } + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Lighten Operation ******** */ void MixLightenOperation::executePixelSampled(float output[4], @@ -570,6 +903,30 @@ void MixLightenOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixLightenOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + + float tmp = value * p.color2[0]; + p.out[0] = MAX2(tmp, p.color1[0]); + + tmp = value * p.color2[1]; + p.out[1] = MAX2(tmp, p.color1[1]); + + tmp = value * p.color2[2]; + p.out[2] = MAX2(tmp, p.color1[2]); + + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Linear Light Operation ******** */ void MixLinearLightOperation::executePixelSampled(float output[4], @@ -613,6 +970,39 @@ void MixLinearLightOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixLinearLightOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + if (p.color2[0] > 0.5f) { + p.out[0] = p.color1[0] + value * (2.0f * (p.color2[0] - 0.5f)); + } + else { + p.out[0] = p.color1[0] + value * (2.0f * (p.color2[0]) - 1.0f); + } + if (p.color2[1] > 0.5f) { + p.out[1] = p.color1[1] + value * (2.0f * (p.color2[1] - 0.5f)); + } + else { + p.out[1] = p.color1[1] + value * (2.0f * (p.color2[1]) - 1.0f); + } + if (p.color2[2] > 0.5f) { + p.out[2] = p.color1[2] + value * (2.0f * (p.color2[2] - 0.5f)); + } + else { + p.out[2] = p.color1[2] + value * (2.0f * (p.color2[2]) - 1.0f); + } + + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Multiply Operation ******** */ void MixMultiplyOperation::executePixelSampled(float output[4], @@ -641,6 +1031,25 @@ void MixMultiplyOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixMultiplyOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + p.out[0] = p.color1[0] * (value_m + value * p.color2[0]); + p.out[1] = p.color1[1] * (value_m + value * p.color2[1]); + p.out[2] = p.color1[2] * (value_m + value * p.color2[2]); + + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Overlay Operation ******** */ void MixOverlayOperation::executePixelSampled(float output[4], @@ -686,6 +1095,40 @@ void MixOverlayOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixOverlayOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + if (p.color1[0] < 0.5f) { + p.out[0] = p.color1[0] * (value_m + 2.0f * value * p.color2[0]); + } + else { + p.out[0] = 1.0f - (value_m + 2.0f * value * (1.0f - p.color2[0])) * (1.0f - p.color1[0]); + } + if (p.color1[1] < 0.5f) { + p.out[1] = p.color1[1] * (value_m + 2.0f * value * p.color2[1]); + } + else { + p.out[1] = 1.0f - (value_m + 2.0f * value * (1.0f - p.color2[1])) * (1.0f - p.color1[1]); + } + if (p.color1[2] < 0.5f) { + p.out[2] = p.color1[2] * (value_m + 2.0f * value * p.color2[2]); + } + else { + p.out[2] = 1.0f - (value_m + 2.0f * value * (1.0f - p.color2[2])) * (1.0f - p.color1[2]); + } + + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Saturation Operation ******** */ void MixSaturationOperation::executePixelSampled(float output[4], @@ -723,6 +1166,33 @@ void MixSaturationOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixSaturationOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + + float rH, rS, rV; + rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV); + if (rS != 0.0f) { + float colH, colS, colV; + rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV); + hsv_to_rgb(rH, (value_m * rS + value * colS), rV, &p.out[0], &p.out[1], &p.out[2]); + } + else { + copy_v3_v3(p.out, p.color1); + } + + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Screen Operation ******** */ void MixScreenOperation::executePixelSampled(float output[4], @@ -752,6 +1222,25 @@ void MixScreenOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixScreenOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + + p.out[0] = 1.0f - (value_m + value * (1.0f - p.color2[0])) * (1.0f - p.color1[0]); + p.out[1] = 1.0f - (value_m + value * (1.0f - p.color2[1])) * (1.0f - p.color1[1]); + p.out[2] = 1.0f - (value_m + value * (1.0f - p.color2[2])) * (1.0f - p.color1[2]); + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Soft Light Operation ******** */ void MixSoftLightOperation::executePixelSampled(float output[4], @@ -793,6 +1282,34 @@ void MixSoftLightOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixSoftLightOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + float scr, scg, scb; + + /* First calculate non-fac based Screen mix. */ + scr = 1.0f - (1.0f - p.color2[0]) * (1.0f - p.color1[0]); + scg = 1.0f - (1.0f - p.color2[1]) * (1.0f - p.color1[1]); + scb = 1.0f - (1.0f - p.color2[2]) * (1.0f - p.color1[2]); + + p.out[0] = value_m * p.color1[0] + + value * ((1.0f - p.color1[0]) * p.color2[0] * p.color1[0] + p.color1[0] * scr); + p.out[1] = value_m * p.color1[1] + + value * ((1.0f - p.color1[1]) * p.color2[1] * p.color1[1] + p.color1[1] * scg); + p.out[2] = value_m * p.color1[2] + + value * ((1.0f - p.color1[2]) * p.color2[2] * p.color1[2] + p.color1[2] * scb); + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Subtract Operation ******** */ void MixSubtractOperation::executePixelSampled(float output[4], @@ -820,6 +1337,23 @@ void MixSubtractOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixSubtractOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + p.out[0] = p.color1[0] - value * p.color2[0]; + p.out[1] = p.color1[1] - value * p.color2[1]; + p.out[2] = p.color1[2] - value * p.color2[2]; + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Value Operation ******** */ void MixValueOperation::executePixelSampled(float output[4], @@ -851,4 +1385,25 @@ void MixValueOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixValueOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + float value_m = 1.0f - value; + + float rH, rS, rV; + float colH, colS, colV; + rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV); + rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV); + hsv_to_rgb(rH, rS, (value_m * rV + value * colV), &p.out[0], &p.out[1], &p.out[2]); + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_MixOperation.h b/source/blender/compositor/operations/COM_MixOperation.h index 6c241bc5762..7ef9d78d58f 100644 --- a/source/blender/compositor/operations/COM_MixOperation.h +++ b/source/blender/compositor/operations/COM_MixOperation.h @@ -18,7 +18,7 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedOperation.h" namespace blender::compositor { @@ -27,8 +27,29 @@ namespace blender::compositor { * it assumes we are in sRGB color space. */ -class MixBaseOperation : public NodeOperation { +class MixBaseOperation : public MultiThreadedOperation { protected: + struct PixelCursor { + float *out; + const float *row_end; + const float *value; + const float *color1; + const float *color2; + int out_stride; + int value_stride; + int color1_stride; + int color2_stride; + + void next() + { + BLI_assert(out < row_end); + out += out_stride; + value += value_stride; + color1 += color1_stride; + color2 += color2_stride; + } + }; + /** * Prefetched reference to the inputProgram */ @@ -81,101 +102,165 @@ class MixBaseOperation : public NodeOperation { { this->m_useClamp = value; } + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) final; + + protected: + virtual void update_memory_buffer_row(PixelCursor &p); }; class MixAddOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixBlendOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixColorBurnOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixColorOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixDarkenOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixDifferenceOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixDivideOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixDodgeOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixGlareOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixHueOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixLightenOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixLinearLightOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixMultiplyOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixOverlayOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixSaturationOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixScreenOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixSoftLightOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixSubtractOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixValueOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_SMAAOperation.cc b/source/blender/compositor/operations/COM_SMAAOperation.cc index 3c753591ced..b078d85372d 100644 --- a/source/blender/compositor/operations/COM_SMAAOperation.cc +++ b/source/blender/compositor/operations/COM_SMAAOperation.cc @@ -19,9 +19,9 @@ */ #include "COM_SMAAOperation.h" +#include "BKE_node.h" #include "BLI_math.h" #include "COM_SMAAAreaTexture.h" -#include "BKE_node.h" extern "C" { #include "IMB_colormanagement.h" diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cc b/source/blender/compositor/operations/COM_ViewerOperation.cc index 860f56e23fa..e47396e14a1 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.cc +++ b/source/blender/compositor/operations/COM_ViewerOperation.cc @@ -191,10 +191,11 @@ void ViewerOperation::initImage() BLI_thread_unlock(LOCK_DRAW_IMAGE); } -void ViewerOperation::updateImage(rcti *rect) +void ViewerOperation::updateImage(const rcti *rect) { + float *buffer = m_outputBuffer; IMB_partial_display_buffer_update(this->m_ibuf, - this->m_outputBuffer, + buffer, nullptr, getWidth(), 0, @@ -218,4 +219,31 @@ eCompositorPriority ViewerOperation::getRenderPriority() const return eCompositorPriority::Low; } +void ViewerOperation::update_memory_buffer_partial(MemoryBuffer *UNUSED(output), + const rcti &area, + Span<MemoryBuffer *> inputs) +{ + if (!m_outputBuffer) { + return; + } + + MemoryBuffer output_buffer( + m_outputBuffer, COM_DATA_TYPE_COLOR_CHANNELS, getWidth(), getHeight()); + const MemoryBuffer *input_image = inputs[0]; + output_buffer.copy_from(input_image, area); + if (this->m_useAlphaInput) { + const MemoryBuffer *input_alpha = inputs[1]; + output_buffer.copy_from(input_alpha, area, 0, COM_DATA_TYPE_VALUE_CHANNELS, 3); + } + + if (m_depthBuffer) { + MemoryBuffer depth_buffer( + m_depthBuffer, COM_DATA_TYPE_VALUE_CHANNELS, getWidth(), getHeight()); + const MemoryBuffer *input_depth = inputs[2]; + depth_buffer.copy_from(input_depth, area); + } + + updateImage(&area); +} + } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_ViewerOperation.h b/source/blender/compositor/operations/COM_ViewerOperation.h index c0f13ff79fc..ed05a7a282d 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.h +++ b/source/blender/compositor/operations/COM_ViewerOperation.h @@ -20,15 +20,17 @@ #include "BKE_global.h" #include "BLI_rect.h" -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedOperation.h" #include "DNA_image_types.h" namespace blender::compositor { -class ViewerOperation : public NodeOperation { +class ViewerOperation : public MultiThreadedOperation { private: + /* TODO(manzanilla): To be removed together with tiled implementation. */ float *m_outputBuffer; float *m_depthBuffer; + Image *m_image; ImageUser *m_imageUser; bool m_active; @@ -125,8 +127,12 @@ class ViewerOperation : public NodeOperation { this->m_displaySettings = displaySettings; } + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) override; + private: - void updateImage(rcti *rect); + void updateImage(const rcti *rect); void initImage(); }; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index e561d0b653c..8d1074d912f 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -1496,7 +1496,7 @@ void DepsgraphNodeBuilder::build_object_data_geometry(Object *object, bool is_ob add_operation_node( &object->id, NodeType::BATCH_CACHE, - OperationCode::BATCH_UPDATE_SELECT, + OperationCode::GEOMETRY_SELECT_UPDATE, [object_cow](::Depsgraph *depsgraph) { BKE_object_select_update(depsgraph, object_cow); }); } @@ -1517,37 +1517,33 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool if (key) { build_shapekeys(key); } - - /* Geometry evaluation. */ - /* Entry operation, takes care of initialization, and some other - * relations which needs to be run prior to actual geometry evaluation. */ - op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT); - op_node->set_as_entry(); - - add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DEFORM); - + /* Nodes for result of obdata's evaluation, and geometry + * evaluation on object. */ const ID_Type id_type = GS(obdata->name); switch (id_type) { case ID_ME: { - add_operation_node(obdata, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - [obdata_cow](::Depsgraph *depsgraph) { - BKE_mesh_eval_geometry(depsgraph, (Mesh *)obdata_cow); - }); + op_node = add_operation_node(obdata, + NodeType::GEOMETRY, + OperationCode::GEOMETRY_EVAL, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_mesh_eval_geometry(depsgraph, (Mesh *)obdata_cow); + }); + op_node->set_as_entry(); break; } case ID_MB: { - add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); + op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); + op_node->set_as_entry(); break; } case ID_CU: { - add_operation_node(obdata, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - [obdata_cow](::Depsgraph *depsgraph) { - BKE_curve_eval_geometry(depsgraph, (Curve *)obdata_cow); - }); + op_node = add_operation_node(obdata, + NodeType::GEOMETRY, + OperationCode::GEOMETRY_EVAL, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_curve_eval_geometry(depsgraph, (Curve *)obdata_cow); + }); + 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; @@ -1563,41 +1559,47 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool break; } case ID_LT: { - add_operation_node(obdata, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - [obdata_cow](::Depsgraph *depsgraph) { - BKE_lattice_eval_geometry(depsgraph, (Lattice *)obdata_cow); - }); + op_node = add_operation_node(obdata, + NodeType::GEOMETRY, + OperationCode::GEOMETRY_EVAL, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_lattice_eval_geometry(depsgraph, (Lattice *)obdata_cow); + }); + op_node->set_as_entry(); break; } case ID_GD: { /* GPencil evaluation operations. */ - add_operation_node(obdata, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - [obdata_cow](::Depsgraph *depsgraph) { - BKE_gpencil_frame_active_set(depsgraph, (bGPdata *)obdata_cow); - }); + op_node = add_operation_node(obdata, + NodeType::GEOMETRY, + OperationCode::GEOMETRY_EVAL, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_gpencil_frame_active_set(depsgraph, + (bGPdata *)obdata_cow); + }); + op_node->set_as_entry(); break; } case ID_HA: { - add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); + op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); + op_node->set_as_entry(); break; } case ID_PT: { - add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); + op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); + op_node->set_as_entry(); break; } case ID_VO: { /* Volume frame update. */ - add_operation_node(obdata, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - [obdata_cow](::Depsgraph *depsgraph) { - BKE_volume_eval_geometry(depsgraph, (Volume *)obdata_cow); - }); + op_node = add_operation_node(obdata, + NodeType::GEOMETRY, + OperationCode::GEOMETRY_EVAL, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_volume_eval_geometry(depsgraph, (Volume *)obdata_cow); + }); + op_node->set_as_entry(); break; } default: @@ -1611,22 +1613,10 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool /* Batch cache. */ add_operation_node(obdata, NodeType::BATCH_CACHE, - OperationCode::BATCH_UPDATE_SELECT, + OperationCode::GEOMETRY_SELECT_UPDATE, [obdata_cow](::Depsgraph *depsgraph) { BKE_object_data_select_update(depsgraph, obdata_cow); }); - add_operation_node(obdata, - NodeType::BATCH_CACHE, - OperationCode::BATCH_UPDATE_DEFORM, - [obdata_cow](::Depsgraph *depsgraph) { - BKE_object_data_eval_batch_cache_deform_tag(depsgraph, obdata_cow); - }); - add_operation_node(obdata, - NodeType::BATCH_CACHE, - OperationCode::BATCH_UPDATE_ALL, - [obdata_cow](::Depsgraph *depsgraph) { - BKE_object_data_eval_batch_cache_dirty_tag(depsgraph, obdata_cow); - }); } void DepsgraphNodeBuilder::build_armature(bArmature *armature) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index c63b3d825a0..c7c6fafa512 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -647,7 +647,7 @@ void DepsgraphRelationBuilder::build_collection(LayerCollection *from_layer_coll /* Only create geometry relations to child objects, if they have a geometry component. */ OperationKey object_geometry_key{ - &cob->ob->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT}; + &cob->ob->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL}; if (find_node(object_geometry_key) != nullptr) { add_relation(object_geometry_key, collection_geometry_key, "Collection Geometry"); } @@ -1099,14 +1099,7 @@ void DepsgraphRelationBuilder::build_object_pointcache(Object *object) else { flag = FLAG_GEOMETRY; OperationKey geometry_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); - add_relation(point_cache_key, geometry_key, "Point Cache -> Geometry Eval"); - if (object->data) { - /* Geometry may change, so rebuild the Drawing Cache. */ - OperationKey object_data_batch_all_key( - (ID *)object->data, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_ALL); - add_relation( - point_cache_key, object_data_batch_all_key, "Point Cache -> Batch Update All"); - } + add_relation(point_cache_key, geometry_key, "Point Cache -> Geometry"); } BLI_assert(flag != -1); /* Tag that we did handle that component. */ @@ -1875,8 +1868,7 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) void DepsgraphRelationBuilder::build_particle_systems(Object *object) { TimeSourceKey time_src_key; - OperationKey obdata_ubereval_key( - &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT); + OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); OperationKey eval_init_key( &object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_INIT); OperationKey eval_done_key( @@ -2024,8 +2016,7 @@ void DepsgraphRelationBuilder::build_particle_system_visualization_object(Object { OperationKey psys_key( &object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_EVAL, psys->name); - OperationKey obdata_ubereval_key( - &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT); + OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); ComponentKey dup_ob_key(&draw_object->id, NodeType::TRANSFORM); add_relation(dup_ob_key, psys_key, "Particle Object Visualization"); if (draw_object->type == OB_MBALL) { @@ -2082,15 +2073,15 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) /* Get nodes for result of obdata's evaluation, and geometry evaluation * on object. */ ComponentKey obdata_geom_key(obdata, NodeType::GEOMETRY); - OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); + ComponentKey geom_key(&object->id, NodeType::GEOMETRY); /* Link components to each other. */ - add_relation(obdata_geom_key, obdata_ubereval_key, "Object Geometry Base Data"); - + add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data"); + OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); /* Special case: modifiers evaluation 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, NodeType::PARAMETERS, OperationCode::SCENE_EVAL); - Relation *rel = add_relation(scene_key, geom_init_key, "CoW Relation"); + Relation *rel = add_relation(scene_key, obdata_ubereval_key, "CoW Relation"); rel->flag |= RELATION_FLAG_NO_FLUSH; /* Modifiers */ if (object->modifiers.first != nullptr) { @@ -2100,13 +2091,13 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); if (mti->updateDepsgraph) { - DepsNodeHandle handle = create_node_handle(geom_init_key); + DepsNodeHandle handle = create_node_handle(obdata_ubereval_key); ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); mti->updateDepsgraph(md, &ctx); } if (BKE_object_modifier_use_time(object, md)) { TimeSourceKey time_src_key; - add_relation(time_src_key, geom_init_key, "Time Source"); + add_relation(time_src_key, obdata_ubereval_key, "Time Source"); } } } @@ -2119,13 +2110,13 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info( (GpencilModifierType)md->type); if (mti->updateDepsgraph) { - DepsNodeHandle handle = create_node_handle(geom_init_key); + DepsNodeHandle handle = create_node_handle(obdata_ubereval_key); ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); mti->updateDepsgraph(md, &ctx, graph_->mode); } if (BKE_object_modifier_gpencil_use_time(object, md)) { TimeSourceKey time_src_key; - add_relation(time_src_key, geom_init_key, "Time Source"); + add_relation(time_src_key, obdata_ubereval_key, "Time Source"); } } } @@ -2137,13 +2128,13 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) LISTBASE_FOREACH (ShaderFxData *, fx, &object->shader_fx) { const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info((ShaderFxType)fx->type); if (fxi->updateDepsgraph) { - DepsNodeHandle handle = create_node_handle(geom_init_key); + DepsNodeHandle handle = create_node_handle(obdata_ubereval_key); ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); fxi->updateDepsgraph(fx, &ctx); } if (BKE_object_shaderfx_use_time(object, fx)) { TimeSourceKey time_src_key; - add_relation(time_src_key, geom_init_key, "Time Source"); + add_relation(time_src_key, obdata_ubereval_key, "Time Source"); } } } @@ -2169,7 +2160,6 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) add_relation(mom_transform_key, mom_geom_key, "Metaball Motherball Transform -> Geometry"); } else { - ComponentKey geom_key(&object->id, NodeType::GEOMETRY); ComponentKey transform_key(&object->id, NodeType::TRANSFORM); add_relation(geom_key, mom_geom_key, "Metaball Motherball"); add_relation(transform_key, mom_geom_key, "Metaball Motherball"); @@ -2184,7 +2174,9 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) * Ideally we need to get rid of this relation. */ if (object_particles_depends_on_time(object)) { TimeSourceKey time_key; - add_relation(time_key, geom_init_key, "Legacy particle time"); + OperationKey obdata_ubereval_key( + &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); + add_relation(time_key, obdata_ubereval_key, "Legacy particle time"); } /* Object data data-block. */ build_object_data_geometry_datablock((ID *)object->data); @@ -2206,33 +2198,12 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) add_relation(final_geometry_key, synchronize_key, "Synchronize to Original"); /* Batch cache. */ OperationKey object_data_select_key( - obdata, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_SELECT); + obdata, NodeType::BATCH_CACHE, OperationCode::GEOMETRY_SELECT_UPDATE); OperationKey object_select_key( - &object->id, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_SELECT); - + &object->id, NodeType::BATCH_CACHE, OperationCode::GEOMETRY_SELECT_UPDATE); add_relation(object_data_select_key, object_select_key, "Data Selection -> Object Selection"); - add_relation(final_geometry_key, - object_select_key, - "Object Geometry -> Select Update", - RELATION_FLAG_NO_FLUSH); - - OperationKey object_data_geom_deform_key( - obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DEFORM); - OperationKey object_data_geom_init_key( - obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT); - - OperationKey object_data_batch_deform_key( - obdata, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_DEFORM); - OperationKey object_data_batch_all_key( - obdata, NodeType::BATCH_CACHE, OperationCode::BATCH_UPDATE_ALL); - - add_relation(geom_init_key, object_data_batch_all_key, "Object Geometry -> Batch Update All"); - add_relation( - object_data_geom_init_key, object_data_batch_all_key, "Data Init -> Batch Update All"); - add_relation(object_data_geom_deform_key, - object_data_batch_deform_key, - "Data Deform -> Batch Update Deform"); + geom_key, object_select_key, "Object Geometry -> Select Update", RELATION_FLAG_NO_FLUSH); } void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata) @@ -2250,13 +2221,8 @@ void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata) build_shapekeys(key); } /* Link object data evaluation node to exit operation. */ - OperationKey obdata_geom_deform_key( - obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DEFORM); - OperationKey obdata_geom_init_key(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT); OperationKey obdata_geom_eval_key(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); OperationKey obdata_geom_done_key(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE); - add_relation(obdata_geom_init_key, obdata_geom_eval_key, "ObData Init -> Geom Eval"); - add_relation(obdata_geom_deform_key, obdata_geom_eval_key, "ObData Deform -> Geom Eval"); add_relation(obdata_geom_eval_key, obdata_geom_done_key, "ObData Geom Eval Done"); /* Type-specific links. */ const ID_Type id_type = GS(obdata->name); diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 063126ff864..ab93464d09a 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -117,7 +117,7 @@ void depsgraph_select_tag_to_component_opcode(const ID *id, } else if (is_selectable_data_id_type(id_type)) { *component_type = NodeType::BATCH_CACHE; - *operation_code = OperationCode::BATCH_UPDATE_SELECT; + *operation_code = OperationCode::GEOMETRY_SELECT_UPDATE; } else { *component_type = NodeType::COPY_ON_WRITE; @@ -169,10 +169,6 @@ void depsgraph_tag_to_component_opcode(const ID *id, case ID_RECALC_GEOMETRY: depsgraph_geometry_tag_to_component(id, component_type); break; - case ID_RECALC_GEOMETRY_DEFORM: - depsgraph_geometry_tag_to_component(id, component_type); - *operation_code = OperationCode::GEOMETRY_EVAL_DEFORM; - break; case ID_RECALC_ANIMATION: *component_type = NodeType::ANIMATION; break; @@ -712,8 +708,6 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag) return "GEOMETRY"; case ID_RECALC_GEOMETRY_ALL_MODES: return "GEOMETRY_ALL_MODES"; - case ID_RECALC_GEOMETRY_DEFORM: - return "GEOMETRY_DEFORM"; case ID_RECALC_ANIMATION: return "ANIMATION"; case ID_RECALC_PSYS_REDO: diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index 2cbb0b52e34..1b24e2b7ad2 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -144,10 +144,7 @@ inline void flush_handle_component_node(IDNode *id_node, * special component where we don't want all operations to be tagged. * * TODO(sergey): Make this a more generic solution. */ - if (!ELEM(comp_node->type, - NodeType::PARTICLE_SETTINGS, - NodeType::PARTICLE_SYSTEM, - NodeType::BATCH_CACHE)) { + if (!ELEM(comp_node->type, NodeType::PARTICLE_SETTINGS, NodeType::PARTICLE_SYSTEM)) { for (OperationNode *op : comp_node->operations) { op->flag |= DEPSOP_FLAG_NEEDS_UPDATE; } diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc index d98486b83a8..c25dc6fc8d5 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.cc +++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc @@ -98,8 +98,6 @@ const char *operationCodeAsString(OperationCode opcode) /* Geometry. */ case OperationCode::GEOMETRY_EVAL_INIT: return "GEOMETRY_EVAL_INIT"; - case OperationCode::GEOMETRY_EVAL_DEFORM: - return "GEOMETRY_EVAL_DEFORM"; case OperationCode::GEOMETRY_EVAL: return "GEOMETRY_EVAL"; case OperationCode::GEOMETRY_EVAL_DONE: @@ -162,12 +160,8 @@ const char *operationCodeAsString(OperationCode opcode) case OperationCode::FILE_CACHE_UPDATE: return "FILE_CACHE_UPDATE"; /* Batch cache. */ - case OperationCode::BATCH_UPDATE_SELECT: - return "BATCH_UPDATE_SELECT"; - case OperationCode::BATCH_UPDATE_DEFORM: - return "BATCH_UPDATE_DEFORM"; - case OperationCode::BATCH_UPDATE_ALL: - return "BATCH_UPDATE_ALL"; + case OperationCode::GEOMETRY_SELECT_UPDATE: + return "GEOMETRY_SELECT_UPDATE"; /* Masks. */ case OperationCode::MASK_ANIMATION: return "MASK_ANIMATION"; diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h index b0130d03c69..a17186da941 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.h +++ b/source/blender/depsgraph/intern/node/deg_node_operation.h @@ -100,11 +100,7 @@ enum class OperationCode { /* Initialize evaluation of the geometry. Is an entry operation of geometry * component. */ GEOMETRY_EVAL_INIT, - /* Evaluate the geometry, including modifiers, and update only batches that - * are affected by deform operations. */ - GEOMETRY_EVAL_DEFORM, - /* Evaluate the geometry, including modifiers, but don't update the batch - * cache. */ + /* Evaluate the whole geometry, including modifiers. */ GEOMETRY_EVAL, /* Evaluation of geometry is completely done. */ GEOMETRY_EVAL_DONE, @@ -182,9 +178,7 @@ enum class OperationCode { WORLD_UPDATE, /* Batch caches. -------------------------------------------------------- */ - BATCH_UPDATE_SELECT, - BATCH_UPDATE_DEFORM, - BATCH_UPDATE_ALL, + GEOMETRY_SELECT_UPDATE, /* Masks. --------------------------------------------------------------- */ MASK_ANIMATION, diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 0c002ff09f2..8387fb2f43f 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -821,17 +821,6 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, eMeshBatchDirtyMode mode) mesh_batch_cache_discard_shaded_tri(cache); mesh_batch_cache_discard_uvedit(cache); break; - case BKE_MESH_BATCH_DIRTY_DEFORM: - FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) { - GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.pos_nor); - GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.lnor); - GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_pos); - GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_nor); - GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.tris); - } - batch_map = MDEPS_CREATE_MAP(vbo.pos_nor, vbo.lnor, vbo.fdots_pos, vbo.fdots_nor, ibo.tris); - mesh_batch_cache_discard_batch(cache, batch_map); - break; case BKE_MESH_BATCH_DIRTY_UVEDIT_ALL: mesh_batch_cache_discard_uvedit(cache); break; diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt index f50a5ffbb5e..7a53b54b5a4 100644 --- a/source/blender/editors/animation/CMakeLists.txt +++ b/source/blender/editors/animation/CMakeLists.txt @@ -47,6 +47,7 @@ set(SRC keyframes_draw.c keyframes_edit.c keyframes_general.c + keyframes_keylist.c keyframing.c keyingsets.c time_scrub_ui.c diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 2fcd59a1bbe..baf8adf28d0 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -48,6 +48,7 @@ #include "ED_anim_api.h" #include "ED_keyframes_draw.h" #include "ED_keyframes_edit.h" +#include "ED_keyframes_keylist.h" #include "RNA_access.h" diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c index 51a897600e1..bddd5dbff55 100644 --- a/source/blender/editors/animation/anim_motion_paths.c +++ b/source/blender/editors/animation/anim_motion_paths.c @@ -43,7 +43,7 @@ #include "GPU_vertex_buffer.h" #include "ED_anim_api.h" -#include "ED_keyframes_draw.h" +#include "ED_keyframes_keylist.h" #include "CLG_log.h" diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 06107b6fee6..4f512c9d7ca 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -24,28 +24,17 @@ /* System includes ----------------------------------------------------- */ #include <float.h> -#include <math.h> -#include <stdlib.h> -#include <string.h> - -#include "MEM_guardedalloc.h" #include "BLI_dlrbTree.h" #include "BLI_listbase.h" -#include "BLI_math.h" #include "BLI_rect.h" -#include "BLI_utildefines.h" #include "DNA_anim_types.h" -#include "DNA_brush_types.h" -#include "DNA_cachefile_types.h" #include "DNA_gpencil_types.h" #include "DNA_mask_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BKE_fcurve.h" - #include "GPU_immediate.h" #include "GPU_state.h" @@ -55,498 +44,7 @@ #include "ED_anim_api.h" #include "ED_keyframes_draw.h" - -/* *************************** Keyframe Processing *************************** */ - -/* ActKeyColumns (Keyframe Columns) ------------------------------------------ */ - -BLI_INLINE bool is_cfra_eq(float a, float b) -{ - return IS_EQT(a, b, BEZT_BINARYSEARCH_THRESH); -} - -BLI_INLINE bool is_cfra_lt(float a, float b) -{ - return (b - a) > BEZT_BINARYSEARCH_THRESH; -} - -/* Comparator callback used for ActKeyColumns and cframe float-value pointer */ -/* NOTE: this is exported to other modules that use the ActKeyColumns for finding keyframes */ -short compare_ak_cfraPtr(void *node, void *data) -{ - ActKeyColumn *ak = (ActKeyColumn *)node; - const float *cframe = data; - float val = *cframe; - - if (is_cfra_eq(val, ak->cfra)) { - return 0; - } - - if (val < ak->cfra) { - return -1; - } - return 1; -} - -/* --------------- */ - -/* Set of references to three logically adjacent keys. */ -typedef struct BezTripleChain { - /* Current keyframe. */ - BezTriple *cur; - - /* Logical neighbors. May be NULL. */ - BezTriple *prev, *next; -} BezTripleChain; - -/* Categorize the interpolation & handle type of the keyframe. */ -static eKeyframeHandleDrawOpts bezt_handle_type(BezTriple *bezt) -{ - if (bezt->h1 == HD_AUTO_ANIM && bezt->h2 == HD_AUTO_ANIM) { - return KEYFRAME_HANDLE_AUTO_CLAMP; - } - if (ELEM(bezt->h1, HD_AUTO_ANIM, HD_AUTO) && ELEM(bezt->h2, HD_AUTO_ANIM, HD_AUTO)) { - return KEYFRAME_HANDLE_AUTO; - } - if (bezt->h1 == HD_VECT && bezt->h2 == HD_VECT) { - return KEYFRAME_HANDLE_VECTOR; - } - if (ELEM(HD_FREE, bezt->h1, bezt->h2)) { - return KEYFRAME_HANDLE_FREE; - } - return KEYFRAME_HANDLE_ALIGNED; -} - -/* Determine if the keyframe is an extreme by comparing with neighbors. - * Ends of fixed-value sections and of the whole curve are also marked. - */ -static eKeyframeExtremeDrawOpts bezt_extreme_type(BezTripleChain *chain) -{ - if (chain->prev == NULL && chain->next == NULL) { - return KEYFRAME_EXTREME_NONE; - } - - /* Keyframe values for the current one and neighbors. */ - float cur_y = chain->cur->vec[1][1]; - float prev_y = cur_y, next_y = cur_y; - - if (chain->prev && !IS_EQF(cur_y, chain->prev->vec[1][1])) { - prev_y = chain->prev->vec[1][1]; - } - if (chain->next && !IS_EQF(cur_y, chain->next->vec[1][1])) { - next_y = chain->next->vec[1][1]; - } - - /* Static hold. */ - if (prev_y == cur_y && next_y == cur_y) { - return KEYFRAME_EXTREME_FLAT; - } - - /* Middle of an incline. */ - if ((prev_y < cur_y && next_y > cur_y) || (prev_y > cur_y && next_y < cur_y)) { - return KEYFRAME_EXTREME_NONE; - } - - /* Bezier handle values for the overshoot check. */ - bool l_bezier = chain->prev && chain->prev->ipo == BEZT_IPO_BEZ; - bool r_bezier = chain->next && chain->cur->ipo == BEZT_IPO_BEZ; - float handle_l = l_bezier ? chain->cur->vec[0][1] : cur_y; - float handle_r = r_bezier ? chain->cur->vec[2][1] : cur_y; - - /* Detect extremes. One of the neighbors is allowed to be equal to current. */ - if (prev_y < cur_y || next_y < cur_y) { - bool is_overshoot = (handle_l > cur_y || handle_r > cur_y); - - return KEYFRAME_EXTREME_MAX | (is_overshoot ? KEYFRAME_EXTREME_MIXED : 0); - } - - if (prev_y > cur_y || next_y > cur_y) { - bool is_overshoot = (handle_l < cur_y || handle_r < cur_y); - - return KEYFRAME_EXTREME_MIN | (is_overshoot ? KEYFRAME_EXTREME_MIXED : 0); - } - - return KEYFRAME_EXTREME_NONE; -} - -/* Comparator callback used for ActKeyColumns and BezTripleChain */ -static short compare_ak_bezt(void *node, void *data) -{ - BezTripleChain *chain = data; - - return compare_ak_cfraPtr(node, &chain->cur->vec[1][0]); -} - -/* New node callback used for building ActKeyColumns from BezTripleChain */ -static DLRBT_Node *nalloc_ak_bezt(void *data) -{ - ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn"); - BezTripleChain *chain = data; - BezTriple *bezt = chain->cur; - - /* store settings based on state of BezTriple */ - ak->cfra = bezt->vec[1][0]; - ak->sel = BEZT_ISSEL_ANY(bezt) ? SELECT : 0; - ak->key_type = BEZKEYTYPE(bezt); - ak->handle_type = bezt_handle_type(bezt); - ak->extreme_type = bezt_extreme_type(chain); - - /* count keyframes in this column */ - ak->totkey = 1; - - return (DLRBT_Node *)ak; -} - -/* Node updater callback used for building ActKeyColumns from BezTripleChain */ -static void nupdate_ak_bezt(void *node, void *data) -{ - ActKeyColumn *ak = node; - BezTripleChain *chain = data; - BezTriple *bezt = chain->cur; - - /* set selection status and 'touched' status */ - if (BEZT_ISSEL_ANY(bezt)) { - ak->sel = SELECT; - } - - /* count keyframes in this column */ - ak->totkey++; - - /* For keyframe type, 'proper' keyframes have priority over breakdowns - * (and other types for now). */ - if (BEZKEYTYPE(bezt) == BEZT_KEYTYPE_KEYFRAME) { - ak->key_type = BEZT_KEYTYPE_KEYFRAME; - } - - /* For interpolation type, select the highest value (enum is sorted). */ - ak->handle_type = MAX2(ak->handle_type, bezt_handle_type(bezt)); - - /* For extremes, detect when combining different states. */ - char new_extreme = bezt_extreme_type(chain); - - if (new_extreme != ak->extreme_type) { - /* Replace the flat status without adding mixed. */ - if (ak->extreme_type == KEYFRAME_EXTREME_FLAT) { - ak->extreme_type = new_extreme; - } - else if (new_extreme != KEYFRAME_EXTREME_FLAT) { - ak->extreme_type |= (new_extreme | KEYFRAME_EXTREME_MIXED); - } - } -} - -/* ......... */ - -/* Comparator callback used for ActKeyColumns and GPencil frame */ -static short compare_ak_gpframe(void *node, void *data) -{ - bGPDframe *gpf = (bGPDframe *)data; - - float frame = gpf->framenum; - return compare_ak_cfraPtr(node, &frame); -} - -/* New node callback used for building ActKeyColumns from GPencil frames */ -static DLRBT_Node *nalloc_ak_gpframe(void *data) -{ - ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF"); - bGPDframe *gpf = (bGPDframe *)data; - - /* store settings based on state of BezTriple */ - ak->cfra = gpf->framenum; - ak->sel = (gpf->flag & GP_FRAME_SELECT) ? SELECT : 0; - ak->key_type = gpf->key_type; - - /* count keyframes in this column */ - ak->totkey = 1; - /* Set as visible block. */ - ak->totblock = 1; - ak->block.sel = ak->sel; - ak->block.flag |= ACTKEYBLOCK_FLAG_GPENCIL; - - return (DLRBT_Node *)ak; -} - -/* Node updater callback used for building ActKeyColumns from GPencil frames */ -static void nupdate_ak_gpframe(void *node, void *data) -{ - ActKeyColumn *ak = (ActKeyColumn *)node; - bGPDframe *gpf = (bGPDframe *)data; - - /* set selection status and 'touched' status */ - if (gpf->flag & GP_FRAME_SELECT) { - ak->sel = SELECT; - } - - /* count keyframes in this column */ - ak->totkey++; - - /* for keyframe type, 'proper' keyframes have priority over breakdowns - * (and other types for now). */ - if (gpf->key_type == BEZT_KEYTYPE_KEYFRAME) { - ak->key_type = BEZT_KEYTYPE_KEYFRAME; - } -} - -/* ......... */ - -/* Comparator callback used for ActKeyColumns and GPencil frame */ -static short compare_ak_masklayshape(void *node, void *data) -{ - MaskLayerShape *masklay_shape = (MaskLayerShape *)data; - - float frame = masklay_shape->frame; - return compare_ak_cfraPtr(node, &frame); -} - -/* New node callback used for building ActKeyColumns from GPencil frames */ -static DLRBT_Node *nalloc_ak_masklayshape(void *data) -{ - ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF"); - MaskLayerShape *masklay_shape = (MaskLayerShape *)data; - - /* store settings based on state of BezTriple */ - ak->cfra = masklay_shape->frame; - ak->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? SELECT : 0; - - /* count keyframes in this column */ - ak->totkey = 1; - - return (DLRBT_Node *)ak; -} - -/* Node updater callback used for building ActKeyColumns from GPencil frames */ -static void nupdate_ak_masklayshape(void *node, void *data) -{ - ActKeyColumn *ak = (ActKeyColumn *)node; - MaskLayerShape *masklay_shape = (MaskLayerShape *)data; - - /* set selection status and 'touched' status */ - if (masklay_shape->flag & MASK_SHAPE_SELECT) { - ak->sel = SELECT; - } - - /* count keyframes in this column */ - ak->totkey++; -} - -/* --------------- */ - -/* Add the given BezTriple to the given 'list' of Keyframes */ -static void add_bezt_to_keycolumns_list(DLRBT_Tree *keys, BezTripleChain *bezt) -{ - if (ELEM(NULL, keys, bezt)) { - return; - } - - BLI_dlrbTree_add(keys, compare_ak_bezt, nalloc_ak_bezt, nupdate_ak_bezt, bezt); -} - -/* Add the given GPencil Frame to the given 'list' of Keyframes */ -static void add_gpframe_to_keycolumns_list(DLRBT_Tree *keys, bGPDframe *gpf) -{ - if (ELEM(NULL, keys, gpf)) { - return; - } - - BLI_dlrbTree_add(keys, compare_ak_gpframe, nalloc_ak_gpframe, nupdate_ak_gpframe, gpf); -} - -/* Add the given MaskLayerShape Frame to the given 'list' of Keyframes */ -static void add_masklay_to_keycolumns_list(DLRBT_Tree *keys, MaskLayerShape *masklay_shape) -{ - if (ELEM(NULL, keys, masklay_shape)) { - return; - } - - BLI_dlrbTree_add(keys, - compare_ak_masklayshape, - nalloc_ak_masklayshape, - nupdate_ak_masklayshape, - masklay_shape); -} - -/* ActKeyBlocks (Long Keyframes) ------------------------------------------ */ - -static const ActKeyBlockInfo dummy_keyblock = {0}; - -static void compute_keyblock_data(ActKeyBlockInfo *info, BezTriple *prev, BezTriple *beztn) -{ - memset(info, 0, sizeof(ActKeyBlockInfo)); - - if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD) { - /* Animator tagged a "moving hold" - * - Previous key must also be tagged as a moving hold, otherwise - * we're just dealing with the first of a pair, and we don't - * want to be creating any phantom holds... - */ - if (BEZKEYTYPE(prev) == BEZT_KEYTYPE_MOVEHOLD) { - info->flag |= ACTKEYBLOCK_FLAG_MOVING_HOLD | ACTKEYBLOCK_FLAG_ANY_HOLD; - } - } - - /* Check for same values... - * - Handles must have same central value as each other - * - Handles which control that section of the curve must be constant - */ - if (IS_EQF(beztn->vec[1][1], prev->vec[1][1])) { - bool hold; - - /* Only check handles in case of actual bezier interpolation. */ - if (prev->ipo == BEZT_IPO_BEZ) { - hold = IS_EQF(beztn->vec[1][1], beztn->vec[0][1]) && - IS_EQF(prev->vec[1][1], prev->vec[2][1]); - } - /* This interpolation type induces movement even between identical keys. */ - else { - hold = !ELEM(prev->ipo, BEZT_IPO_ELASTIC); - } - - if (hold) { - info->flag |= ACTKEYBLOCK_FLAG_STATIC_HOLD | ACTKEYBLOCK_FLAG_ANY_HOLD; - } - } - - /* Remember non-bezier interpolation info. */ - if (prev->ipo != BEZT_IPO_BEZ) { - info->flag |= ACTKEYBLOCK_FLAG_NON_BEZIER; - } - - info->sel = BEZT_ISSEL_ANY(prev) || BEZT_ISSEL_ANY(beztn); -} - -static void add_keyblock_info(ActKeyColumn *col, const ActKeyBlockInfo *block) -{ - /* New curve and block. */ - if (col->totcurve <= 1 && col->totblock == 0) { - memcpy(&col->block, block, sizeof(ActKeyBlockInfo)); - } - /* Existing curve. */ - else { - col->block.conflict |= (col->block.flag ^ block->flag); - col->block.flag |= block->flag; - col->block.sel |= block->sel; - } - - if (block->flag) { - col->totblock++; - } -} - -static void add_bezt_to_keyblocks_list(DLRBT_Tree *keys, BezTriple *bezt, int bezt_len) -{ - ActKeyColumn *col = keys->first; - - if (bezt && bezt_len >= 2) { - ActKeyBlockInfo block; - - /* Find the first key column while inserting dummy blocks. */ - for (; col != NULL && is_cfra_lt(col->cfra, bezt[0].vec[1][0]); col = col->next) { - add_keyblock_info(col, &dummy_keyblock); - } - - BLI_assert(col != NULL); - - /* Insert real blocks. */ - for (int v = 1; col != NULL && v < bezt_len; v++, bezt++) { - /* Wrong order of bezier keys: resync position. */ - if (is_cfra_lt(bezt[1].vec[1][0], bezt[0].vec[1][0])) { - /* Backtrack to find the right location. */ - if (is_cfra_lt(bezt[1].vec[1][0], col->cfra)) { - ActKeyColumn *newcol = (ActKeyColumn *)BLI_dlrbTree_search_exact( - keys, compare_ak_cfraPtr, &bezt[1].vec[1][0]); - - if (newcol != NULL) { - col = newcol; - - /* The previous keyblock is garbage too. */ - if (col->prev != NULL) { - add_keyblock_info(col->prev, &dummy_keyblock); - } - } - else { - BLI_assert(false); - } - } - - continue; - } - - /* Normal sequence */ - BLI_assert(is_cfra_eq(col->cfra, bezt[0].vec[1][0])); - - compute_keyblock_data(&block, bezt, bezt + 1); - - for (; col != NULL && is_cfra_lt(col->cfra, bezt[1].vec[1][0]); col = col->next) { - add_keyblock_info(col, &block); - } - - BLI_assert(col != NULL); - } - } - - /* Insert dummy blocks at the end. */ - for (; col != NULL; col = col->next) { - add_keyblock_info(col, &dummy_keyblock); - } -} - -/* Walk through columns and propagate blocks and totcurve. - * - * This must be called even by animation sources that don't generate - * keyblocks to keep the data structure consistent after adding columns. - */ -static void update_keyblocks(DLRBT_Tree *keys, BezTriple *bezt, int bezt_len) -{ - /* Recompute the prev/next linked list. */ - BLI_dlrbTree_linkedlist_sync(keys); - - /* Find the curve count */ - int max_curve = 0; - - LISTBASE_FOREACH (ActKeyColumn *, col, keys) { - max_curve = MAX2(max_curve, col->totcurve); - } - - /* Propagate blocks to inserted keys */ - ActKeyColumn *prev_ready = NULL; - - LISTBASE_FOREACH (ActKeyColumn *, col, keys) { - /* Pre-existing column. */ - if (col->totcurve > 0) { - prev_ready = col; - } - /* Newly inserted column, so copy block data from previous. */ - else if (prev_ready != NULL) { - col->totblock = prev_ready->totblock; - memcpy(&col->block, &prev_ready->block, sizeof(ActKeyBlockInfo)); - } - - col->totcurve = max_curve + 1; - } - - /* Add blocks on top */ - add_bezt_to_keyblocks_list(keys, bezt, bezt_len); -} - -/* --------- */ - -bool actkeyblock_is_valid(ActKeyColumn *ac) -{ - return ac != NULL && ac->next != NULL && ac->totblock > 0; -} - -/* Checks if ActKeyBlock should exist... */ -int actkeyblock_get_valid_hold(ActKeyColumn *ac) -{ - /* check that block is valid */ - if (!actkeyblock_is_valid(ac)) { - return 0; - } - - const int hold_mask = (ACTKEYBLOCK_FLAG_ANY_HOLD | ACTKEYBLOCK_FLAG_STATIC_HOLD); - return (ac->block.flag & ~ac->block.conflict) & hold_mask; -} +#include "ED_keyframes_keylist.h" /* *************************** Keyframe Drawing *************************** */ @@ -1029,257 +527,3 @@ void draw_masklay_channel(View2D *v2d, BLI_dlrbTree_free(&keys); } - -/* *************************** Keyframe List Conversions *************************** */ - -void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, int saction_flag) -{ - if (ac) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - /* get F-Curves to take keyframes from */ - filter = ANIMFILTER_DATA_VISIBLE; - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* loop through each F-Curve, grabbing the keyframes */ - for (ale = anim_data.first; ale; ale = ale->next) { - /* Why not use all #eAnim_KeyType here? - * All of the other key types are actually "summaries" themselves, - * and will just end up duplicating stuff that comes up through - * standard filtering of just F-Curves. Given the way that these work, - * there isn't really any benefit at all from including them. - Aligorith */ - - switch (ale->datatype) { - case ALE_FCURVE: - fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag); - break; - case ALE_MASKLAY: - mask_to_keylist(ac->ads, ale->data, keys); - break; - case ALE_GPFRAME: - gpl_to_keylist(ac->ads, ale->data, keys); - break; - default: - // printf("%s: datatype %d unhandled\n", __func__, ale->datatype); - break; - } - } - - ANIM_animdata_freelist(&anim_data); - } -} - -void scene_to_keylist(bDopeSheet *ads, Scene *sce, DLRBT_Tree *keys, int saction_flag) -{ - bAnimContext ac = {NULL}; - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - bAnimListElem dummychan = {NULL}; - - if (sce == NULL) { - return; - } - - /* create a dummy wrapper data to work with */ - dummychan.type = ANIMTYPE_SCENE; - dummychan.data = sce; - dummychan.id = &sce->id; - dummychan.adt = sce->adt; - - ac.ads = ads; - ac.data = &dummychan; - ac.datatype = ANIMCONT_CHANNEL; - - /* get F-Curves to take keyframes from */ - filter = ANIMFILTER_DATA_VISIBLE; /* curves only */ - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* loop through each F-Curve, grabbing the keyframes */ - for (ale = anim_data.first; ale; ale = ale->next) { - fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag); - } - - ANIM_animdata_freelist(&anim_data); -} - -void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, int saction_flag) -{ - bAnimContext ac = {NULL}; - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - bAnimListElem dummychan = {NULL}; - Base dummybase = {NULL}; - - if (ob == NULL) { - return; - } - - /* create a dummy wrapper data to work with */ - dummybase.object = ob; - - dummychan.type = ANIMTYPE_OBJECT; - dummychan.data = &dummybase; - dummychan.id = &ob->id; - dummychan.adt = ob->adt; - - ac.ads = ads; - ac.data = &dummychan; - ac.datatype = ANIMCONT_CHANNEL; - - /* get F-Curves to take keyframes from */ - filter = ANIMFILTER_DATA_VISIBLE; /* curves only */ - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* loop through each F-Curve, grabbing the keyframes */ - for (ale = anim_data.first; ale; ale = ale->next) { - fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag); - } - - ANIM_animdata_freelist(&anim_data); -} - -void cachefile_to_keylist(bDopeSheet *ads, - CacheFile *cache_file, - DLRBT_Tree *keys, - int saction_flag) -{ - if (cache_file == NULL) { - return; - } - - /* create a dummy wrapper data to work with */ - bAnimListElem dummychan = {NULL}; - dummychan.type = ANIMTYPE_DSCACHEFILE; - dummychan.data = cache_file; - dummychan.id = &cache_file->id; - dummychan.adt = cache_file->adt; - - bAnimContext ac = {NULL}; - ac.ads = ads; - ac.data = &dummychan; - ac.datatype = ANIMCONT_CHANNEL; - - /* get F-Curves to take keyframes from */ - ListBase anim_data = {NULL, NULL}; - int filter = ANIMFILTER_DATA_VISIBLE; /* curves only */ - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* loop through each F-Curve, grabbing the keyframes */ - LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) { - fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag); - } - - ANIM_animdata_freelist(&anim_data); -} - -void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, int saction_flag) -{ - if (fcu && fcu->totvert && fcu->bezt) { - /* apply NLA-mapping (if applicable) */ - if (adt) { - ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0); - } - - /* Check if the curve is cyclic. */ - bool is_cyclic = BKE_fcurve_is_cyclic(fcu) && (fcu->totvert >= 2); - bool do_extremes = (saction_flag & SACTION_SHOW_EXTREMES) != 0; - - /* loop through beztriples, making ActKeysColumns */ - BezTripleChain chain = {0}; - - for (int v = 0; v < fcu->totvert; v++) { - chain.cur = &fcu->bezt[v]; - - /* Neighbor keys, accounting for being cyclic. */ - if (do_extremes) { - chain.prev = (v > 0) ? &fcu->bezt[v - 1] : is_cyclic ? &fcu->bezt[fcu->totvert - 2] : NULL; - chain.next = (v + 1 < fcu->totvert) ? &fcu->bezt[v + 1] : is_cyclic ? &fcu->bezt[1] : NULL; - } - - add_bezt_to_keycolumns_list(keys, &chain); - } - - /* Update keyblocks. */ - update_keyblocks(keys, fcu->bezt, fcu->totvert); - - /* unapply NLA-mapping if applicable */ - if (adt) { - ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0); - } - } -} - -void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, DLRBT_Tree *keys, int saction_flag) -{ - FCurve *fcu; - - if (agrp) { - /* loop through F-Curves */ - for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next) { - fcurve_to_keylist(adt, fcu, keys, saction_flag); - } - } -} - -void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, int saction_flag) -{ - FCurve *fcu; - - if (act) { - /* loop through F-Curves */ - for (fcu = act->curves.first; fcu; fcu = fcu->next) { - fcurve_to_keylist(adt, fcu, keys, saction_flag); - } - } -} - -void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, DLRBT_Tree *keys, const bool active) -{ - bGPDlayer *gpl; - - if (gpd && keys) { - /* for now, just aggregate out all the frames, but only for visible layers */ - for (gpl = gpd->layers.last; gpl; gpl = gpl->prev) { - if ((gpl->flag & GP_LAYER_HIDE) == 0) { - if ((!active) || ((active) && (gpl->flag & GP_LAYER_SELECT))) { - gpl_to_keylist(ads, gpl, keys); - } - } - } - } -} - -void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys) -{ - bGPDframe *gpf; - - if (gpl && keys) { - /* Although the frames should already be in an ordered list, - * they are not suitable for displaying yet. */ - for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - add_gpframe_to_keycolumns_list(keys, gpf); - } - - update_keyblocks(keys, NULL, 0); - } -} - -void mask_to_keylist(bDopeSheet *UNUSED(ads), MaskLayer *masklay, DLRBT_Tree *keys) -{ - MaskLayerShape *masklay_shape; - - if (masklay && keys) { - for (masklay_shape = masklay->splines_shapes.first; masklay_shape; - masklay_shape = masklay_shape->next) { - add_masklay_to_keycolumns_list(keys, masklay_shape); - } - - update_keyblocks(keys, NULL, 0); - } -} diff --git a/source/blender/editors/animation/keyframes_keylist.c b/source/blender/editors/animation/keyframes_keylist.c new file mode 100644 index 00000000000..47ed2b56300 --- /dev/null +++ b/source/blender/editors/animation/keyframes_keylist.c @@ -0,0 +1,793 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung + * All rights reserved. + */ + +/** \file + * \ingroup edanimation + */ + +/* System includes ----------------------------------------------------- */ + +#include <float.h> +#include <math.h> +#include <stdlib.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_dlrbTree.h" +#include "BLI_listbase.h" +#include "BLI_utildefines.h" + +#include "DNA_anim_types.h" +#include "DNA_cachefile_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_mask_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "BKE_fcurve.h" + +#include "ED_anim_api.h" +#include "ED_keyframes_keylist.h" + +/* *************************** Keyframe Processing *************************** */ + +/* ActKeyColumns (Keyframe Columns) ------------------------------------------ */ + +BLI_INLINE bool is_cfra_eq(float a, float b) +{ + return IS_EQT(a, b, BEZT_BINARYSEARCH_THRESH); +} + +BLI_INLINE bool is_cfra_lt(float a, float b) +{ + return (b - a) > BEZT_BINARYSEARCH_THRESH; +} + +/* Comparator callback used for ActKeyColumns and cframe float-value pointer */ +/* NOTE: this is exported to other modules that use the ActKeyColumns for finding keyframes */ +short compare_ak_cfraPtr(void *node, void *data) +{ + ActKeyColumn *ak = (ActKeyColumn *)node; + const float *cframe = data; + float val = *cframe; + + if (is_cfra_eq(val, ak->cfra)) { + return 0; + } + + if (val < ak->cfra) { + return -1; + } + return 1; +} + +/* --------------- */ + +/* Set of references to three logically adjacent keys. */ +typedef struct BezTripleChain { + /* Current keyframe. */ + BezTriple *cur; + + /* Logical neighbors. May be NULL. */ + BezTriple *prev, *next; +} BezTripleChain; + +/* Categorize the interpolation & handle type of the keyframe. */ +static eKeyframeHandleDrawOpts bezt_handle_type(BezTriple *bezt) +{ + if (bezt->h1 == HD_AUTO_ANIM && bezt->h2 == HD_AUTO_ANIM) { + return KEYFRAME_HANDLE_AUTO_CLAMP; + } + if (ELEM(bezt->h1, HD_AUTO_ANIM, HD_AUTO) && ELEM(bezt->h2, HD_AUTO_ANIM, HD_AUTO)) { + return KEYFRAME_HANDLE_AUTO; + } + if (bezt->h1 == HD_VECT && bezt->h2 == HD_VECT) { + return KEYFRAME_HANDLE_VECTOR; + } + if (ELEM(HD_FREE, bezt->h1, bezt->h2)) { + return KEYFRAME_HANDLE_FREE; + } + return KEYFRAME_HANDLE_ALIGNED; +} + +/* Determine if the keyframe is an extreme by comparing with neighbors. + * Ends of fixed-value sections and of the whole curve are also marked. + */ +static eKeyframeExtremeDrawOpts bezt_extreme_type(BezTripleChain *chain) +{ + if (chain->prev == NULL && chain->next == NULL) { + return KEYFRAME_EXTREME_NONE; + } + + /* Keyframe values for the current one and neighbors. */ + float cur_y = chain->cur->vec[1][1]; + float prev_y = cur_y, next_y = cur_y; + + if (chain->prev && !IS_EQF(cur_y, chain->prev->vec[1][1])) { + prev_y = chain->prev->vec[1][1]; + } + if (chain->next && !IS_EQF(cur_y, chain->next->vec[1][1])) { + next_y = chain->next->vec[1][1]; + } + + /* Static hold. */ + if (prev_y == cur_y && next_y == cur_y) { + return KEYFRAME_EXTREME_FLAT; + } + + /* Middle of an incline. */ + if ((prev_y < cur_y && next_y > cur_y) || (prev_y > cur_y && next_y < cur_y)) { + return KEYFRAME_EXTREME_NONE; + } + + /* Bezier handle values for the overshoot check. */ + bool l_bezier = chain->prev && chain->prev->ipo == BEZT_IPO_BEZ; + bool r_bezier = chain->next && chain->cur->ipo == BEZT_IPO_BEZ; + float handle_l = l_bezier ? chain->cur->vec[0][1] : cur_y; + float handle_r = r_bezier ? chain->cur->vec[2][1] : cur_y; + + /* Detect extremes. One of the neighbors is allowed to be equal to current. */ + if (prev_y < cur_y || next_y < cur_y) { + bool is_overshoot = (handle_l > cur_y || handle_r > cur_y); + + return KEYFRAME_EXTREME_MAX | (is_overshoot ? KEYFRAME_EXTREME_MIXED : 0); + } + + if (prev_y > cur_y || next_y > cur_y) { + bool is_overshoot = (handle_l < cur_y || handle_r < cur_y); + + return KEYFRAME_EXTREME_MIN | (is_overshoot ? KEYFRAME_EXTREME_MIXED : 0); + } + + return KEYFRAME_EXTREME_NONE; +} + +/* Comparator callback used for ActKeyColumns and BezTripleChain */ +static short compare_ak_bezt(void *node, void *data) +{ + BezTripleChain *chain = data; + + return compare_ak_cfraPtr(node, &chain->cur->vec[1][0]); +} + +/* New node callback used for building ActKeyColumns from BezTripleChain */ +static DLRBT_Node *nalloc_ak_bezt(void *data) +{ + ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn"); + BezTripleChain *chain = data; + BezTriple *bezt = chain->cur; + + /* store settings based on state of BezTriple */ + ak->cfra = bezt->vec[1][0]; + ak->sel = BEZT_ISSEL_ANY(bezt) ? SELECT : 0; + ak->key_type = BEZKEYTYPE(bezt); + ak->handle_type = bezt_handle_type(bezt); + ak->extreme_type = bezt_extreme_type(chain); + + /* count keyframes in this column */ + ak->totkey = 1; + + return (DLRBT_Node *)ak; +} + +/* Node updater callback used for building ActKeyColumns from BezTripleChain */ +static void nupdate_ak_bezt(void *node, void *data) +{ + ActKeyColumn *ak = node; + BezTripleChain *chain = data; + BezTriple *bezt = chain->cur; + + /* set selection status and 'touched' status */ + if (BEZT_ISSEL_ANY(bezt)) { + ak->sel = SELECT; + } + + /* count keyframes in this column */ + ak->totkey++; + + /* For keyframe type, 'proper' keyframes have priority over breakdowns + * (and other types for now). */ + if (BEZKEYTYPE(bezt) == BEZT_KEYTYPE_KEYFRAME) { + ak->key_type = BEZT_KEYTYPE_KEYFRAME; + } + + /* For interpolation type, select the highest value (enum is sorted). */ + ak->handle_type = MAX2(ak->handle_type, bezt_handle_type(bezt)); + + /* For extremes, detect when combining different states. */ + char new_extreme = bezt_extreme_type(chain); + + if (new_extreme != ak->extreme_type) { + /* Replace the flat status without adding mixed. */ + if (ak->extreme_type == KEYFRAME_EXTREME_FLAT) { + ak->extreme_type = new_extreme; + } + else if (new_extreme != KEYFRAME_EXTREME_FLAT) { + ak->extreme_type |= (new_extreme | KEYFRAME_EXTREME_MIXED); + } + } +} + +/* ......... */ + +/* Comparator callback used for ActKeyColumns and GPencil frame */ +static short compare_ak_gpframe(void *node, void *data) +{ + bGPDframe *gpf = (bGPDframe *)data; + + float frame = gpf->framenum; + return compare_ak_cfraPtr(node, &frame); +} + +/* New node callback used for building ActKeyColumns from GPencil frames */ +static DLRBT_Node *nalloc_ak_gpframe(void *data) +{ + ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF"); + bGPDframe *gpf = (bGPDframe *)data; + + /* store settings based on state of BezTriple */ + ak->cfra = gpf->framenum; + ak->sel = (gpf->flag & GP_FRAME_SELECT) ? SELECT : 0; + ak->key_type = gpf->key_type; + + /* count keyframes in this column */ + ak->totkey = 1; + /* Set as visible block. */ + ak->totblock = 1; + ak->block.sel = ak->sel; + ak->block.flag |= ACTKEYBLOCK_FLAG_GPENCIL; + + return (DLRBT_Node *)ak; +} + +/* Node updater callback used for building ActKeyColumns from GPencil frames */ +static void nupdate_ak_gpframe(void *node, void *data) +{ + ActKeyColumn *ak = (ActKeyColumn *)node; + bGPDframe *gpf = (bGPDframe *)data; + + /* set selection status and 'touched' status */ + if (gpf->flag & GP_FRAME_SELECT) { + ak->sel = SELECT; + } + + /* count keyframes in this column */ + ak->totkey++; + + /* for keyframe type, 'proper' keyframes have priority over breakdowns + * (and other types for now). */ + if (gpf->key_type == BEZT_KEYTYPE_KEYFRAME) { + ak->key_type = BEZT_KEYTYPE_KEYFRAME; + } +} + +/* ......... */ + +/* Comparator callback used for ActKeyColumns and GPencil frame */ +static short compare_ak_masklayshape(void *node, void *data) +{ + MaskLayerShape *masklay_shape = (MaskLayerShape *)data; + + float frame = masklay_shape->frame; + return compare_ak_cfraPtr(node, &frame); +} + +/* New node callback used for building ActKeyColumns from GPencil frames */ +static DLRBT_Node *nalloc_ak_masklayshape(void *data) +{ + ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF"); + MaskLayerShape *masklay_shape = (MaskLayerShape *)data; + + /* store settings based on state of BezTriple */ + ak->cfra = masklay_shape->frame; + ak->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? SELECT : 0; + + /* count keyframes in this column */ + ak->totkey = 1; + + return (DLRBT_Node *)ak; +} + +/* Node updater callback used for building ActKeyColumns from GPencil frames */ +static void nupdate_ak_masklayshape(void *node, void *data) +{ + ActKeyColumn *ak = (ActKeyColumn *)node; + MaskLayerShape *masklay_shape = (MaskLayerShape *)data; + + /* set selection status and 'touched' status */ + if (masklay_shape->flag & MASK_SHAPE_SELECT) { + ak->sel = SELECT; + } + + /* count keyframes in this column */ + ak->totkey++; +} + +/* --------------- */ + +/* Add the given BezTriple to the given 'list' of Keyframes */ +static void add_bezt_to_keycolumns_list(DLRBT_Tree *keys, BezTripleChain *bezt) +{ + if (ELEM(NULL, keys, bezt)) { + return; + } + + BLI_dlrbTree_add(keys, compare_ak_bezt, nalloc_ak_bezt, nupdate_ak_bezt, bezt); +} + +/* Add the given GPencil Frame to the given 'list' of Keyframes */ +static void add_gpframe_to_keycolumns_list(DLRBT_Tree *keys, bGPDframe *gpf) +{ + if (ELEM(NULL, keys, gpf)) { + return; + } + + BLI_dlrbTree_add(keys, compare_ak_gpframe, nalloc_ak_gpframe, nupdate_ak_gpframe, gpf); +} + +/* Add the given MaskLayerShape Frame to the given 'list' of Keyframes */ +static void add_masklay_to_keycolumns_list(DLRBT_Tree *keys, MaskLayerShape *masklay_shape) +{ + if (ELEM(NULL, keys, masklay_shape)) { + return; + } + + BLI_dlrbTree_add(keys, + compare_ak_masklayshape, + nalloc_ak_masklayshape, + nupdate_ak_masklayshape, + masklay_shape); +} + +/* ActKeyBlocks (Long Keyframes) ------------------------------------------ */ + +static const ActKeyBlockInfo dummy_keyblock = {0}; + +static void compute_keyblock_data(ActKeyBlockInfo *info, BezTriple *prev, BezTriple *beztn) +{ + memset(info, 0, sizeof(ActKeyBlockInfo)); + + if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD) { + /* Animator tagged a "moving hold" + * - Previous key must also be tagged as a moving hold, otherwise + * we're just dealing with the first of a pair, and we don't + * want to be creating any phantom holds... + */ + if (BEZKEYTYPE(prev) == BEZT_KEYTYPE_MOVEHOLD) { + info->flag |= ACTKEYBLOCK_FLAG_MOVING_HOLD | ACTKEYBLOCK_FLAG_ANY_HOLD; + } + } + + /* Check for same values... + * - Handles must have same central value as each other + * - Handles which control that section of the curve must be constant + */ + if (IS_EQF(beztn->vec[1][1], prev->vec[1][1])) { + bool hold; + + /* Only check handles in case of actual bezier interpolation. */ + if (prev->ipo == BEZT_IPO_BEZ) { + hold = IS_EQF(beztn->vec[1][1], beztn->vec[0][1]) && + IS_EQF(prev->vec[1][1], prev->vec[2][1]); + } + /* This interpolation type induces movement even between identical keys. */ + else { + hold = !ELEM(prev->ipo, BEZT_IPO_ELASTIC); + } + + if (hold) { + info->flag |= ACTKEYBLOCK_FLAG_STATIC_HOLD | ACTKEYBLOCK_FLAG_ANY_HOLD; + } + } + + /* Remember non-bezier interpolation info. */ + if (prev->ipo != BEZT_IPO_BEZ) { + info->flag |= ACTKEYBLOCK_FLAG_NON_BEZIER; + } + + info->sel = BEZT_ISSEL_ANY(prev) || BEZT_ISSEL_ANY(beztn); +} + +static void add_keyblock_info(ActKeyColumn *col, const ActKeyBlockInfo *block) +{ + /* New curve and block. */ + if (col->totcurve <= 1 && col->totblock == 0) { + memcpy(&col->block, block, sizeof(ActKeyBlockInfo)); + } + /* Existing curve. */ + else { + col->block.conflict |= (col->block.flag ^ block->flag); + col->block.flag |= block->flag; + col->block.sel |= block->sel; + } + + if (block->flag) { + col->totblock++; + } +} + +static void add_bezt_to_keyblocks_list(DLRBT_Tree *keys, BezTriple *bezt, int bezt_len) +{ + ActKeyColumn *col = keys->first; + + if (bezt && bezt_len >= 2) { + ActKeyBlockInfo block; + + /* Find the first key column while inserting dummy blocks. */ + for (; col != NULL && is_cfra_lt(col->cfra, bezt[0].vec[1][0]); col = col->next) { + add_keyblock_info(col, &dummy_keyblock); + } + + BLI_assert(col != NULL); + + /* Insert real blocks. */ + for (int v = 1; col != NULL && v < bezt_len; v++, bezt++) { + /* Wrong order of bezier keys: resync position. */ + if (is_cfra_lt(bezt[1].vec[1][0], bezt[0].vec[1][0])) { + /* Backtrack to find the right location. */ + if (is_cfra_lt(bezt[1].vec[1][0], col->cfra)) { + ActKeyColumn *newcol = (ActKeyColumn *)BLI_dlrbTree_search_exact( + keys, compare_ak_cfraPtr, &bezt[1].vec[1][0]); + + if (newcol != NULL) { + col = newcol; + + /* The previous keyblock is garbage too. */ + if (col->prev != NULL) { + add_keyblock_info(col->prev, &dummy_keyblock); + } + } + else { + BLI_assert(false); + } + } + + continue; + } + + /* Normal sequence */ + BLI_assert(is_cfra_eq(col->cfra, bezt[0].vec[1][0])); + + compute_keyblock_data(&block, bezt, bezt + 1); + + for (; col != NULL && is_cfra_lt(col->cfra, bezt[1].vec[1][0]); col = col->next) { + add_keyblock_info(col, &block); + } + + BLI_assert(col != NULL); + } + } + + /* Insert dummy blocks at the end. */ + for (; col != NULL; col = col->next) { + add_keyblock_info(col, &dummy_keyblock); + } +} + +/* Walk through columns and propagate blocks and totcurve. + * + * This must be called even by animation sources that don't generate + * keyblocks to keep the data structure consistent after adding columns. + */ +static void update_keyblocks(DLRBT_Tree *keys, BezTriple *bezt, int bezt_len) +{ + /* Recompute the prev/next linked list. */ + BLI_dlrbTree_linkedlist_sync(keys); + + /* Find the curve count */ + int max_curve = 0; + + LISTBASE_FOREACH (ActKeyColumn *, col, keys) { + max_curve = MAX2(max_curve, col->totcurve); + } + + /* Propagate blocks to inserted keys */ + ActKeyColumn *prev_ready = NULL; + + LISTBASE_FOREACH (ActKeyColumn *, col, keys) { + /* Pre-existing column. */ + if (col->totcurve > 0) { + prev_ready = col; + } + /* Newly inserted column, so copy block data from previous. */ + else if (prev_ready != NULL) { + col->totblock = prev_ready->totblock; + memcpy(&col->block, &prev_ready->block, sizeof(ActKeyBlockInfo)); + } + + col->totcurve = max_curve + 1; + } + + /* Add blocks on top */ + add_bezt_to_keyblocks_list(keys, bezt, bezt_len); +} + +/* --------- */ + +bool actkeyblock_is_valid(ActKeyColumn *ac) +{ + return ac != NULL && ac->next != NULL && ac->totblock > 0; +} + +/* Checks if ActKeyBlock should exist... */ +int actkeyblock_get_valid_hold(ActKeyColumn *ac) +{ + /* check that block is valid */ + if (!actkeyblock_is_valid(ac)) { + return 0; + } + + const int hold_mask = (ACTKEYBLOCK_FLAG_ANY_HOLD | ACTKEYBLOCK_FLAG_STATIC_HOLD); + return (ac->block.flag & ~ac->block.conflict) & hold_mask; +} + +/* *************************** Keyframe List Conversions *************************** */ + +void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, int saction_flag) +{ + if (ac) { + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get F-Curves to take keyframes from */ + filter = ANIMFILTER_DATA_VISIBLE; + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* loop through each F-Curve, grabbing the keyframes */ + for (ale = anim_data.first; ale; ale = ale->next) { + /* Why not use all #eAnim_KeyType here? + * All of the other key types are actually "summaries" themselves, + * and will just end up duplicating stuff that comes up through + * standard filtering of just F-Curves. Given the way that these work, + * there isn't really any benefit at all from including them. - Aligorith */ + + switch (ale->datatype) { + case ALE_FCURVE: + fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag); + break; + case ALE_MASKLAY: + mask_to_keylist(ac->ads, ale->data, keys); + break; + case ALE_GPFRAME: + gpl_to_keylist(ac->ads, ale->data, keys); + break; + default: + // printf("%s: datatype %d unhandled\n", __func__, ale->datatype); + break; + } + } + + ANIM_animdata_freelist(&anim_data); + } +} + +void scene_to_keylist(bDopeSheet *ads, Scene *sce, DLRBT_Tree *keys, int saction_flag) +{ + bAnimContext ac = {NULL}; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + bAnimListElem dummychan = {NULL}; + + if (sce == NULL) { + return; + } + + /* create a dummy wrapper data to work with */ + dummychan.type = ANIMTYPE_SCENE; + dummychan.data = sce; + dummychan.id = &sce->id; + dummychan.adt = sce->adt; + + ac.ads = ads; + ac.data = &dummychan; + ac.datatype = ANIMCONT_CHANNEL; + + /* get F-Curves to take keyframes from */ + filter = ANIMFILTER_DATA_VISIBLE; /* curves only */ + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* loop through each F-Curve, grabbing the keyframes */ + for (ale = anim_data.first; ale; ale = ale->next) { + fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag); + } + + ANIM_animdata_freelist(&anim_data); +} + +void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, int saction_flag) +{ + bAnimContext ac = {NULL}; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + bAnimListElem dummychan = {NULL}; + Base dummybase = {NULL}; + + if (ob == NULL) { + return; + } + + /* create a dummy wrapper data to work with */ + dummybase.object = ob; + + dummychan.type = ANIMTYPE_OBJECT; + dummychan.data = &dummybase; + dummychan.id = &ob->id; + dummychan.adt = ob->adt; + + ac.ads = ads; + ac.data = &dummychan; + ac.datatype = ANIMCONT_CHANNEL; + + /* get F-Curves to take keyframes from */ + filter = ANIMFILTER_DATA_VISIBLE; /* curves only */ + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* loop through each F-Curve, grabbing the keyframes */ + for (ale = anim_data.first; ale; ale = ale->next) { + fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag); + } + + ANIM_animdata_freelist(&anim_data); +} + +void cachefile_to_keylist(bDopeSheet *ads, + CacheFile *cache_file, + DLRBT_Tree *keys, + int saction_flag) +{ + if (cache_file == NULL) { + return; + } + + /* create a dummy wrapper data to work with */ + bAnimListElem dummychan = {NULL}; + dummychan.type = ANIMTYPE_DSCACHEFILE; + dummychan.data = cache_file; + dummychan.id = &cache_file->id; + dummychan.adt = cache_file->adt; + + bAnimContext ac = {NULL}; + ac.ads = ads; + ac.data = &dummychan; + ac.datatype = ANIMCONT_CHANNEL; + + /* get F-Curves to take keyframes from */ + ListBase anim_data = {NULL, NULL}; + int filter = ANIMFILTER_DATA_VISIBLE; /* curves only */ + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* loop through each F-Curve, grabbing the keyframes */ + LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) { + fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag); + } + + ANIM_animdata_freelist(&anim_data); +} + +void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, int saction_flag) +{ + if (fcu && fcu->totvert && fcu->bezt) { + /* apply NLA-mapping (if applicable) */ + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0); + } + + /* Check if the curve is cyclic. */ + bool is_cyclic = BKE_fcurve_is_cyclic(fcu) && (fcu->totvert >= 2); + bool do_extremes = (saction_flag & SACTION_SHOW_EXTREMES) != 0; + + /* loop through beztriples, making ActKeysColumns */ + BezTripleChain chain = {0}; + + for (int v = 0; v < fcu->totvert; v++) { + chain.cur = &fcu->bezt[v]; + + /* Neighbor keys, accounting for being cyclic. */ + if (do_extremes) { + chain.prev = (v > 0) ? &fcu->bezt[v - 1] : is_cyclic ? &fcu->bezt[fcu->totvert - 2] : NULL; + chain.next = (v + 1 < fcu->totvert) ? &fcu->bezt[v + 1] : is_cyclic ? &fcu->bezt[1] : NULL; + } + + add_bezt_to_keycolumns_list(keys, &chain); + } + + /* Update keyblocks. */ + update_keyblocks(keys, fcu->bezt, fcu->totvert); + + /* unapply NLA-mapping if applicable */ + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0); + } + } +} + +void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, DLRBT_Tree *keys, int saction_flag) +{ + FCurve *fcu; + + if (agrp) { + /* loop through F-Curves */ + for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next) { + fcurve_to_keylist(adt, fcu, keys, saction_flag); + } + } +} + +void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, int saction_flag) +{ + FCurve *fcu; + + if (act) { + /* loop through F-Curves */ + for (fcu = act->curves.first; fcu; fcu = fcu->next) { + fcurve_to_keylist(adt, fcu, keys, saction_flag); + } + } +} + +void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, DLRBT_Tree *keys, const bool active) +{ + bGPDlayer *gpl; + + if (gpd && keys) { + /* for now, just aggregate out all the frames, but only for visible layers */ + for (gpl = gpd->layers.last; gpl; gpl = gpl->prev) { + if ((gpl->flag & GP_LAYER_HIDE) == 0) { + if ((!active) || ((active) && (gpl->flag & GP_LAYER_SELECT))) { + gpl_to_keylist(ads, gpl, keys); + } + } + } + } +} + +void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys) +{ + bGPDframe *gpf; + + if (gpl && keys) { + /* Although the frames should already be in an ordered list, + * they are not suitable for displaying yet. */ + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { + add_gpframe_to_keycolumns_list(keys, gpf); + } + + update_keyblocks(keys, NULL, 0); + } +} + +void mask_to_keylist(bDopeSheet *UNUSED(ads), MaskLayer *masklay, DLRBT_Tree *keys) +{ + MaskLayerShape *masklay_shape; + + if (masklay && keys) { + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; + masklay_shape = masklay_shape->next) { + add_masklay_to_keycolumns_list(keys, masklay_shape); + } + + update_keyblocks(keys, NULL, 0); + } +} diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c index df3550d5db6..cb70b2810d1 100644 --- a/source/blender/editors/armature/pose_lib.c +++ b/source/blender/editors/armature/pose_lib.c @@ -62,8 +62,8 @@ #include "ED_anim_api.h" #include "ED_armature.h" -#include "ED_keyframes_draw.h" #include "ED_keyframes_edit.h" +#include "ED_keyframes_keylist.h" #include "ED_keyframing.h" #include "ED_object.h" #include "ED_screen.h" diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index 1a1685e4a01..675af6eada9 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -77,7 +77,7 @@ #include "UI_resources.h" #include "ED_armature.h" -#include "ED_keyframes_draw.h" +#include "ED_keyframes_keylist.h" #include "ED_markers.h" #include "ED_numinput.h" #include "ED_screen.h" diff --git a/source/blender/editors/asset/CMakeLists.txt b/source/blender/editors/asset/CMakeLists.txt index a27975bc37b..fb727e686fc 100644 --- a/source/blender/editors/asset/CMakeLists.txt +++ b/source/blender/editors/asset/CMakeLists.txt @@ -34,6 +34,9 @@ set(SRC asset_list.cc asset_ops.cc asset_temp_id_consumer.cc + intern/asset_library_reference.cc + + intern/asset_library_reference.hh ) set(LIB diff --git a/source/blender/editors/asset/asset_list.cc b/source/blender/editors/asset/asset_list.cc index dd1c5f360a0..d9c1c6d862e 100644 --- a/source/blender/editors/asset/asset_list.cc +++ b/source/blender/editors/asset/asset_list.cc @@ -26,12 +26,8 @@ #include <optional> #include <string> -#include "BKE_asset.h" #include "BKE_context.h" -#include "BKE_screen.h" -#include "BLI_function_ref.hh" -#include "BLI_hash.hh" #include "BLI_map.hh" #include "BLI_path_util.h" #include "BLI_utility_mixins.hh" @@ -43,7 +39,6 @@ #include "ED_asset.h" #include "ED_fileselect.h" -#include "ED_screen.h" #include "WM_api.h" #include "WM_types.h" @@ -51,48 +46,9 @@ /* XXX uses private header of file-space. */ #include "../space_file/filelist.h" -using namespace blender; +#include "intern/asset_library_reference.hh" -/** - * Wrapper to add logic to the AssetLibraryReference DNA struct. - */ -class AssetLibraryReferenceWrapper { - const AssetLibraryReference reference_; - - public: - /* Intentionally not `explicit`, allow implicit conversion for convenience. Might have to be - * NOLINT */ - AssetLibraryReferenceWrapper(const AssetLibraryReference &reference); - ~AssetLibraryReferenceWrapper() = default; - - friend bool operator==(const AssetLibraryReferenceWrapper &a, - const AssetLibraryReferenceWrapper &b); - uint64_t hash() const; -}; - -AssetLibraryReferenceWrapper::AssetLibraryReferenceWrapper(const AssetLibraryReference &reference) - : reference_(reference) -{ -} - -bool operator==(const AssetLibraryReferenceWrapper &a, const AssetLibraryReferenceWrapper &b) -{ - return (a.reference_.type == b.reference_.type) && (a.reference_.type == ASSET_LIBRARY_CUSTOM) ? - (a.reference_.custom_library_index == b.reference_.custom_library_index) : - true; -} - -uint64_t AssetLibraryReferenceWrapper::hash() const -{ - uint64_t hash1 = DefaultHash<decltype(reference_.type)>{}(reference_.type); - if (reference_.type != ASSET_LIBRARY_CUSTOM) { - return hash1; - } - - uint64_t hash2 = DefaultHash<decltype(reference_.custom_library_index)>{}( - reference_.custom_library_index); - return hash1 ^ (hash2 * 33); /* Copied from DefaultHash for std::pair. */ -} +namespace blender::ed::asset { /* -------------------------------------------------------------------- */ /** \name Asset list API @@ -469,10 +425,14 @@ AssetListStorage::AssetListMap &AssetListStorage::global_storage() /** \} */ +} // namespace blender::ed::asset + /* -------------------------------------------------------------------- */ /** \name C-API * \{ */ +using namespace blender::ed::asset; + /** * Invoke asset list reading, potentially in a parallel job. Won't wait until the job is done, * and may return earlier. @@ -506,7 +466,6 @@ bool ED_assetlist_storage_has_list_for_library(const AssetLibraryReference *libr return AssetListStorage::lookup_list(*library_reference) != nullptr; } -/* TODO expose AssetList with an iterator? */ void ED_assetlist_iterate(const AssetLibraryReference *library_reference, AssetListIterFn fn) { AssetList *list = AssetListStorage::lookup_list(*library_reference); diff --git a/source/blender/editors/asset/intern/asset_library_reference.cc b/source/blender/editors/asset/intern/asset_library_reference.cc new file mode 100644 index 00000000000..246f304dc20 --- /dev/null +++ b/source/blender/editors/asset/intern/asset_library_reference.cc @@ -0,0 +1,46 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BLI_hash.hh" + +#include "asset_library_reference.hh" + +namespace blender::ed::asset { + +AssetLibraryReferenceWrapper::AssetLibraryReferenceWrapper(const AssetLibraryReference &reference) + : AssetLibraryReference(reference) +{ +} + +bool operator==(const AssetLibraryReferenceWrapper &a, const AssetLibraryReferenceWrapper &b) +{ + return (a.type == b.type) && (a.type == ASSET_LIBRARY_CUSTOM) ? + (a.custom_library_index == b.custom_library_index) : + true; +} + +uint64_t AssetLibraryReferenceWrapper::hash() const +{ + uint64_t hash1 = DefaultHash<decltype(type)>{}(type); + if (type != ASSET_LIBRARY_CUSTOM) { + return hash1; + } + + uint64_t hash2 = DefaultHash<decltype(custom_library_index)>{}(custom_library_index); + return hash1 ^ (hash2 * 33); /* Copied from DefaultHash for std::pair. */ +} + +} // namespace blender::ed::asset diff --git a/source/blender/editors/asset/intern/asset_library_reference.hh b/source/blender/editors/asset/intern/asset_library_reference.hh new file mode 100644 index 00000000000..7e8cb4a3472 --- /dev/null +++ b/source/blender/editors/asset/intern/asset_library_reference.hh @@ -0,0 +1,46 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup edasset + * + * Utility to extend #AssetLibraryReference with C++ functionality (operators, hash function, etc). + */ + +#pragma once + +#include <cstdint> + +#include "DNA_asset_types.h" + +namespace blender::ed::asset { + +/** + * Wrapper to add logic to the AssetLibraryReference DNA struct. + */ +class AssetLibraryReferenceWrapper : public AssetLibraryReference { + public: + /* Intentionally not `explicit`, allow implicit conversion for convenience. Might have to be + * NOLINT */ + AssetLibraryReferenceWrapper(const AssetLibraryReference &reference); + ~AssetLibraryReferenceWrapper() = default; + + friend bool operator==(const AssetLibraryReferenceWrapper &a, + const AssetLibraryReferenceWrapper &b); + uint64_t hash() const; +}; + +} // namespace blender::ed::asset diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index 2f8faf1b2bd..ac6dd7dce32 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -42,99 +42,6 @@ struct bAnimContext; struct bDopeSheet; struct bGPDlayer; -/* ****************************** Base Structs ****************************** */ - -/* Information about the stretch of time from current to the next column */ -typedef struct ActKeyBlockInfo { - /* Combination of flags from all curves. */ - short flag; - /* Mask of flags that differ between curves. */ - short conflict; - - /* Selection flag. */ - char sel; -} ActKeyBlockInfo; - -/* Keyframe Column Struct */ -typedef struct ActKeyColumn { - /* ListBase linkage */ - struct ActKeyColumn *next, *prev; - - /* sorting-tree linkage */ - /** 'children' of this node, less than and greater than it (respectively) */ - struct ActKeyColumn *left, *right; - /** parent of this node in the tree */ - struct ActKeyColumn *parent; - /** DLRB_BLACK or DLRB_RED */ - char tree_col; - - /* keyframe info */ - /** eBezTripe_KeyframeType */ - char key_type; - /** eKeyframeHandleDrawOpts */ - char handle_type; - /** eKeyframeExtremeDrawOpts */ - char extreme_type; - short sel; - float cfra; - - /* key-block info */ - ActKeyBlockInfo block; - - /* number of curves and keys in this column */ - short totcurve, totkey, totblock; -} ActKeyColumn; - -/* ActKeyBlockInfo - Flag */ -typedef enum eActKeyBlock_Hold { - /* Key block represents a moving hold */ - ACTKEYBLOCK_FLAG_MOVING_HOLD = (1 << 0), - /* Key block represents a static hold */ - ACTKEYBLOCK_FLAG_STATIC_HOLD = (1 << 1), - /* Key block represents any kind of hold */ - ACTKEYBLOCK_FLAG_ANY_HOLD = (1 << 2), - /* The curve segment uses non-bezier interpolation */ - ACTKEYBLOCK_FLAG_NON_BEZIER = (1 << 3), - /* The block is grease pencil */ - ACTKEYBLOCK_FLAG_GPENCIL = (1 << 4), -} eActKeyBlock_Flag; - -/* *********************** Keyframe Drawing ****************************** */ - -/* options for keyframe shape drawing */ -typedef enum eKeyframeShapeDrawOpts { - /* only the border */ - KEYFRAME_SHAPE_FRAME = 0, - /* only the inside filling */ - KEYFRAME_SHAPE_INSIDE, - /* the whole thing */ - KEYFRAME_SHAPE_BOTH, -} eKeyframeShapeDrawOpts; - -/* Handle type. */ -typedef enum eKeyframeHandleDrawOpts { - /* Don't draw */ - KEYFRAME_HANDLE_NONE = 0, - /* Various marks in order of increasing display priority. */ - KEYFRAME_HANDLE_AUTO_CLAMP, - KEYFRAME_HANDLE_AUTO, - KEYFRAME_HANDLE_VECTOR, - KEYFRAME_HANDLE_ALIGNED, - KEYFRAME_HANDLE_FREE, -} eKeyframeHandleDrawOpts; - -/* Extreme type. */ -typedef enum eKeyframeExtremeDrawOpts { - KEYFRAME_EXTREME_NONE = 0, - /* Minimum/maximum present. */ - KEYFRAME_EXTREME_MIN = (1 << 0), - KEYFRAME_EXTREME_MAX = (1 << 1), - /* Grouped keys have different states. */ - KEYFRAME_EXTREME_MIXED = (1 << 2), - /* Both neighbors are equal to this key. */ - KEYFRAME_EXTREME_FLAT = (1 << 3), -} eKeyframeExtremeDrawOpts; - /* draw simple diamond-shape keyframe */ /* caller should set up vertex format, bind GPU_SHADER_KEYFRAME_DIAMOND, * immBegin(GPU_PRIM_POINTS, n), then call this n times */ @@ -216,59 +123,6 @@ void draw_masklay_channel(struct View2D *v2d, float yscale_fac, int saction_flag); -/* Keydata Generation --------------- */ -/* F-Curve */ -void fcurve_to_keylist(struct AnimData *adt, - struct FCurve *fcu, - struct DLRBT_Tree *keys, - int saction_flag); -/* Action Group */ -void agroup_to_keylist(struct AnimData *adt, - struct bActionGroup *agrp, - struct DLRBT_Tree *keys, - int saction_flag); -/* Action */ -void action_to_keylist(struct AnimData *adt, - struct bAction *act, - struct DLRBT_Tree *keys, - int saction_flag); -/* Object */ -void ob_to_keylist(struct bDopeSheet *ads, - struct Object *ob, - struct DLRBT_Tree *keys, - int saction_flag); -/* Cache File */ -void cachefile_to_keylist(struct bDopeSheet *ads, - struct CacheFile *cache_file, - struct DLRBT_Tree *keys, - int saction_flag); -/* Scene */ -void scene_to_keylist(struct bDopeSheet *ads, - struct Scene *sce, - struct DLRBT_Tree *keys, - int saction_flag); -/* DopeSheet Summary */ -void summary_to_keylist(struct bAnimContext *ac, struct DLRBT_Tree *keys, int saction_flag); -/* Grease Pencil datablock summary */ -void gpencil_to_keylist(struct bDopeSheet *ads, - struct bGPdata *gpd, - struct DLRBT_Tree *keys, - const bool active); -/* Grease Pencil Layer */ -void gpl_to_keylist(struct bDopeSheet *ads, struct bGPDlayer *gpl, struct DLRBT_Tree *keys); -/* Mask */ -void mask_to_keylist(struct bDopeSheet *ads, struct MaskLayer *masklay, struct DLRBT_Tree *keys); - -/* ActKeyColumn API ---------------- */ -/* Comparator callback used for ActKeyColumns and cframe float-value pointer */ -short compare_ak_cfraPtr(void *node, void *data); - -/* Checks if ActKeyColumn has any block data */ -bool actkeyblock_is_valid(ActKeyColumn *ac); - -/* Checks if ActKeyColumn can be used as a block (i.e. drawn/used to detect "holds") */ -int actkeyblock_get_valid_hold(ActKeyColumn *ac); - #ifdef __cplusplus } #endif diff --git a/source/blender/editors/include/ED_keyframes_keylist.h b/source/blender/editors/include/ED_keyframes_keylist.h new file mode 100644 index 00000000000..14a131b5513 --- /dev/null +++ b/source/blender/editors/include/ED_keyframes_keylist.h @@ -0,0 +1,196 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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) (C) 2009 Blender Foundation, Joshua Leung + * All rights reserved. + */ + +/** \file + * \ingroup editors + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +struct AnimData; +struct CacheFile; +struct DLRBT_Tree; +struct FCurve; +struct ListBase; +struct MaskLayer; +struct Object; +struct Scene; +struct View2D; +struct bAction; +struct bActionGroup; +struct bAnimContext; +struct bDopeSheet; +struct bGPDlayer; + +/* ****************************** Base Structs ****************************** */ + +/* Information about the stretch of time from current to the next column */ +typedef struct ActKeyBlockInfo { + /* Combination of flags from all curves. */ + short flag; + /* Mask of flags that differ between curves. */ + short conflict; + + /* Selection flag. */ + char sel; +} ActKeyBlockInfo; + +/* Keyframe Column Struct */ +typedef struct ActKeyColumn { + /* ListBase linkage */ + struct ActKeyColumn *next, *prev; + + /* sorting-tree linkage */ + /** 'children' of this node, less than and greater than it (respectively) */ + struct ActKeyColumn *left, *right; + /** parent of this node in the tree */ + struct ActKeyColumn *parent; + /** DLRB_BLACK or DLRB_RED */ + char tree_col; + + /* keyframe info */ + /** eBezTripe_KeyframeType */ + char key_type; + /** eKeyframeHandleDrawOpts */ + char handle_type; + /** eKeyframeExtremeDrawOpts */ + char extreme_type; + short sel; + float cfra; + + /* key-block info */ + ActKeyBlockInfo block; + + /* number of curves and keys in this column */ + short totcurve, totkey, totblock; +} ActKeyColumn; + +/* ActKeyBlockInfo - Flag */ +typedef enum eActKeyBlock_Hold { + /* Key block represents a moving hold */ + ACTKEYBLOCK_FLAG_MOVING_HOLD = (1 << 0), + /* Key block represents a static hold */ + ACTKEYBLOCK_FLAG_STATIC_HOLD = (1 << 1), + /* Key block represents any kind of hold */ + ACTKEYBLOCK_FLAG_ANY_HOLD = (1 << 2), + /* The curve segment uses non-bezier interpolation */ + ACTKEYBLOCK_FLAG_NON_BEZIER = (1 << 3), + /* The block is grease pencil */ + ACTKEYBLOCK_FLAG_GPENCIL = (1 << 4), +} eActKeyBlock_Flag; + +/* *********************** Keyframe Drawing ****************************** */ + +/* options for keyframe shape drawing */ +typedef enum eKeyframeShapeDrawOpts { + /* only the border */ + KEYFRAME_SHAPE_FRAME = 0, + /* only the inside filling */ + KEYFRAME_SHAPE_INSIDE, + /* the whole thing */ + KEYFRAME_SHAPE_BOTH, +} eKeyframeShapeDrawOpts; + +/* Handle type. */ +typedef enum eKeyframeHandleDrawOpts { + /* Don't draw */ + KEYFRAME_HANDLE_NONE = 0, + /* Various marks in order of increasing display priority. */ + KEYFRAME_HANDLE_AUTO_CLAMP, + KEYFRAME_HANDLE_AUTO, + KEYFRAME_HANDLE_VECTOR, + KEYFRAME_HANDLE_ALIGNED, + KEYFRAME_HANDLE_FREE, +} eKeyframeHandleDrawOpts; + +/* Extreme type. */ +typedef enum eKeyframeExtremeDrawOpts { + KEYFRAME_EXTREME_NONE = 0, + /* Minimum/maximum present. */ + KEYFRAME_EXTREME_MIN = (1 << 0), + KEYFRAME_EXTREME_MAX = (1 << 1), + /* Grouped keys have different states. */ + KEYFRAME_EXTREME_MIXED = (1 << 2), + /* Both neighbors are equal to this key. */ + KEYFRAME_EXTREME_FLAT = (1 << 3), +} eKeyframeExtremeDrawOpts; + +/* ******************************* Methods ****************************** */ + +/* Key-data Generation --------------- */ + +/* F-Curve */ +void fcurve_to_keylist(struct AnimData *adt, + struct FCurve *fcu, + struct DLRBT_Tree *keys, + int saction_flag); +/* Action Group */ +void agroup_to_keylist(struct AnimData *adt, + struct bActionGroup *agrp, + struct DLRBT_Tree *keys, + int saction_flag); +/* Action */ +void action_to_keylist(struct AnimData *adt, + struct bAction *act, + struct DLRBT_Tree *keys, + int saction_flag); +/* Object */ +void ob_to_keylist(struct bDopeSheet *ads, + struct Object *ob, + struct DLRBT_Tree *keys, + int saction_flag); +/* Cache File */ +void cachefile_to_keylist(struct bDopeSheet *ads, + struct CacheFile *cache_file, + struct DLRBT_Tree *keys, + int saction_flag); +/* Scene */ +void scene_to_keylist(struct bDopeSheet *ads, + struct Scene *sce, + struct DLRBT_Tree *keys, + int saction_flag); +/* DopeSheet Summary */ +void summary_to_keylist(struct bAnimContext *ac, struct DLRBT_Tree *keys, int saction_flag); +/* Grease Pencil datablock summary */ +void gpencil_to_keylist(struct bDopeSheet *ads, + struct bGPdata *gpd, + struct DLRBT_Tree *keys, + const bool active); +/* Grease Pencil Layer */ +void gpl_to_keylist(struct bDopeSheet *ads, struct bGPDlayer *gpl, struct DLRBT_Tree *keys); +/* Mask */ +void mask_to_keylist(struct bDopeSheet *ads, struct MaskLayer *masklay, struct DLRBT_Tree *keys); + +/* ActKeyColumn API ---------------- */ +/* Comparator callback used for ActKeyColumns and cframe float-value pointer */ +short compare_ak_cfraPtr(void *node, void *data); + +/* Checks if ActKeyColumn has any block data */ +bool actkeyblock_is_valid(ActKeyColumn *ac); + +/* Checks if ActKeyColumn can be used as a block (i.e. drawn/used to detect "holds") */ +int actkeyblock_get_valid_hold(ActKeyColumn *ac); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 43ac646f053..975c86f3e71 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -66,6 +66,7 @@ #include "ED_datafiles.h" #include "ED_keyframes_draw.h" +#include "ED_keyframes_keylist.h" #include "ED_render.h" #include "UI_interface.h" diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 34e9a3f45a5..94823b92c44 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -336,7 +336,7 @@ void ED_operatormacros_mesh(void) ot = WM_operatortype_append_macro("MESH_OT_polybuild_face_at_cursor_move", "Face at Cursor Move", - "", + NULL, OPTYPE_UNDO | OPTYPE_REGISTER); WM_operatortype_macro_define(ot, "MESH_OT_polybuild_face_at_cursor"); otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); @@ -345,7 +345,7 @@ void ED_operatormacros_mesh(void) ot = WM_operatortype_append_macro("MESH_OT_polybuild_split_at_cursor_move", "Split at Cursor Move", - "", + NULL, OPTYPE_UNDO | OPTYPE_REGISTER); WM_operatortype_macro_define(ot, "MESH_OT_polybuild_split_at_cursor"); otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); @@ -354,7 +354,7 @@ void ED_operatormacros_mesh(void) ot = WM_operatortype_append_macro("MESH_OT_polybuild_transform_at_cursor_move", "Transform at Cursor Move", - "", + NULL, OPTYPE_UNDO | OPTYPE_REGISTER); WM_operatortype_macro_define(ot, "MESH_OT_polybuild_transform_at_cursor"); otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); @@ -363,7 +363,7 @@ void ED_operatormacros_mesh(void) ot = WM_operatortype_append_macro("MESH_OT_polybuild_extrude_at_cursor_move", "Extrude at Cursor Move", - "", + NULL, OPTYPE_UNDO | OPTYPE_REGISTER); WM_operatortype_macro_define(ot, "MESH_OT_polybuild_transform_at_cursor"); otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_edges_indiv"); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index ffeaf514642..3d0d856b1c5 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -71,7 +71,7 @@ #include "ED_armature.h" #include "ED_clip.h" #include "ED_image.h" -#include "ED_keyframes_draw.h" +#include "ED_keyframes_keylist.h" #include "ED_mesh.h" #include "ED_object.h" #include "ED_screen.h" diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 0d5b197ae93..59d2063ea84 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -51,8 +51,8 @@ #include "ED_anim_api.h" #include "ED_gpencil.h" -#include "ED_keyframes_draw.h" #include "ED_keyframes_edit.h" +#include "ED_keyframes_keylist.h" #include "ED_markers.h" #include "ED_mask.h" #include "ED_screen.h" diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index f9fb386095d..c96047da0c8 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -44,6 +44,7 @@ #include "ED_anim_api.h" #include "ED_keyframes_draw.h" +#include "ED_keyframes_keylist.h" #include "GPU_immediate.h" #include "GPU_immediate_util.h" diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index 383f9870714..c1ee6edfef6 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -2067,27 +2067,6 @@ static void tc_mesh_transdata_mirror_apply(TransDataContainer *tc) } } -static bool tc_mesh_is_deform_only_update(TransInfo *t, TransDataContainer *tc) -{ - if (tc->custom.type.data && - ((struct TransCustomDataMesh *)tc->custom.type.data)->cd_layer_correct) { - return false; - } - - Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(t->depsgraph, (ID *)tc->obedit->data); - Mesh *mesh_eval_cage = me_eval->edit_mesh->mesh_eval_cage; - Mesh *mesh_eval_final = me_eval->edit_mesh->mesh_eval_final; - if (mesh_eval_cage && !mesh_eval_cage->runtime.is_original) { - return false; - } - if (mesh_eval_final && mesh_eval_final != mesh_eval_cage && - !mesh_eval_final->runtime.is_original) { - return false; - } - - return me_eval->runtime.deformed_only; -} - void recalcData_mesh(TransInfo *t) { bool is_canceling = t->state == TRANS_CANCEL; @@ -2115,10 +2094,7 @@ void recalcData_mesh(TransInfo *t) tc_mesh_partial_types_calc(t, &partial_state); FOREACH_TRANS_DATA_CONTAINER (t, tc) { - const bool is_deform_only = tc_mesh_is_deform_only_update(t, tc); - - DEG_id_tag_update(tc->obedit->data, - is_deform_only ? ID_RECALC_GEOMETRY_DEFORM : ID_RECALC_GEOMETRY); + DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY); tc_mesh_partial_update(t, tc, &partial_state); } diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 2d98d756dba..41db6c290e6 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -1213,49 +1213,56 @@ static bool snap_bound_box_check_dist(const float min[3], return true; } -static void cb_mvert_co_get(const int index, const float **co, const BVHTreeFromMesh *data) +static void cb_mvert_co_get(const int index, const void *user_data, const float **r_co) { - *co = data->vert[index].co; + const BVHTreeFromMesh *data = user_data; + *r_co = data->vert[index].co; } -static void cb_bvert_co_get(const int index, const float **co, const BMEditMesh *data) +static void cb_bvert_co_get(const int index, const void *user_data, const float **r_co) { + const BMEditMesh *data = user_data; BMVert *eve = BM_vert_at_index(data->bm, index); - *co = eve->co; + *r_co = eve->co; } -static void cb_mvert_no_copy(const int index, float r_no[3], const BVHTreeFromMesh *data) +static void cb_mvert_no_copy(const int index, const void *user_data, float r_no[3]) { + const BVHTreeFromMesh *data = user_data; const MVert *vert = data->vert + index; normal_short_to_float_v3(r_no, vert->no); } -static void cb_bvert_no_copy(const int index, float r_no[3], const BMEditMesh *data) +static void cb_bvert_no_copy(const int index, const void *user_data, float r_no[3]) { + const BMEditMesh *data = user_data; BMVert *eve = BM_vert_at_index(data->bm, index); copy_v3_v3(r_no, eve->no); } -static void cb_medge_verts_get(const int index, int v_index[2], const BVHTreeFromMesh *data) +static void cb_medge_verts_get(const int index, const void *user_data, int r_v_index[2]) { + const BVHTreeFromMesh *data = user_data; const MEdge *edge = &data->edge[index]; - v_index[0] = edge->v1; - v_index[1] = edge->v2; + r_v_index[0] = edge->v1; + r_v_index[1] = edge->v2; } -static void cb_bedge_verts_get(const int index, int v_index[2], const BMEditMesh *data) +static void cb_bedge_verts_get(const int index, const void *user_data, int r_v_index[2]) { + const BMEditMesh *data = user_data; BMEdge *eed = BM_edge_at_index(data->bm, index); - v_index[0] = BM_elem_index_get(eed->v1); - v_index[1] = BM_elem_index_get(eed->v2); + r_v_index[0] = BM_elem_index_get(eed->v1); + r_v_index[1] = BM_elem_index_get(eed->v2); } -static void cb_mlooptri_edges_get(const int index, int v_index[3], const BVHTreeFromMesh *data) +static void cb_mlooptri_edges_get(const int index, const void *user_data, int r_v_index[3]) { + const BVHTreeFromMesh *data = user_data; const MEdge *medge = data->edge; const MLoop *mloop = data->loop; const MLoopTri *lt = &data->looptri[index]; @@ -1264,22 +1271,23 @@ static void cb_mlooptri_edges_get(const int index, int v_index[3], const BVHTree const uint tri_edge[2] = {mloop[lt->tri[j]].v, mloop[lt->tri[j_next]].v}; if (ELEM(ed->v1, tri_edge[0], tri_edge[1]) && ELEM(ed->v2, tri_edge[0], tri_edge[1])) { // printf("real edge found\n"); - v_index[j] = mloop[lt->tri[j]].e; + r_v_index[j] = mloop[lt->tri[j]].e; } else { - v_index[j] = -1; + r_v_index[j] = -1; } } } -static void cb_mlooptri_verts_get(const int index, int v_index[3], const BVHTreeFromMesh *data) +static void cb_mlooptri_verts_get(const int index, const void *user_data, int r_v_index[3]) { + const BVHTreeFromMesh *data = user_data; const MLoop *loop = data->loop; const MLoopTri *looptri = &data->looptri[index]; - v_index[0] = loop[looptri->tri[0]].v; - v_index[1] = loop[looptri->tri[1]].v; - v_index[2] = loop[looptri->tri[2]].v; + r_v_index[0] = loop[looptri->tri[0]].v; + r_v_index[1] = loop[looptri->tri[1]].v; + r_v_index[2] = loop[looptri->tri[2]].v; } static bool test_projected_vert_dist(const struct DistProjectedAABBPrecalc *precalc, @@ -1348,12 +1356,20 @@ static bool test_projected_edge_dist(const struct DistProjectedAABBPrecalc *prec /** \name Walk DFS * \{ */ -typedef void (*Nearest2DGetVertCoCallback)(const int index, const float **co, void *data); -typedef void (*Nearest2DGetEdgeVertsCallback)(const int index, const int v_index[2], void *data); -typedef void (*Nearest2DGetTriVertsCallback)(const int index, const int v_index[3], void *data); +typedef void (*Nearest2DGetVertCoCallback)(const int index, + const void *user_data, + const float **r_co); +typedef void (*Nearest2DGetEdgeVertsCallback)(const int index, + const void *user_data, + int r_v_index[2]); +typedef void (*Nearest2DGetTriVertsCallback)(const int index, + const void *user_data, + int r_v_index[3]); /* Equal the previous one */ -typedef void (*Nearest2DGetTriEdgesCallback)(const int index, const int e_index[3], void *data); -typedef void (*Nearest2DCopyVertNoCallback)(const int index, const float r_no[3], void *data); +typedef void (*Nearest2DGetTriEdgesCallback)(const int index, + const void *user_data, + int r_e_index[3]); +typedef void (*Nearest2DCopyVertNoCallback)(const int index, const void *user_data, float r_no[3]); typedef struct Nearest2dUserData { void *userdata; @@ -1374,18 +1390,18 @@ static void nearest2d_data_init(SnapObjectData *sod, { if (sod->type == SNAP_MESH) { r_nearest2d->userdata = &sod->treedata_mesh; - r_nearest2d->get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get; - r_nearest2d->get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get; - r_nearest2d->copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy; - r_nearest2d->get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get; - r_nearest2d->get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get; + r_nearest2d->get_vert_co = cb_mvert_co_get; + r_nearest2d->get_edge_verts_index = cb_medge_verts_get; + r_nearest2d->copy_vert_no = cb_mvert_no_copy; + r_nearest2d->get_tri_verts_index = cb_mlooptri_verts_get; + r_nearest2d->get_tri_edges_index = cb_mlooptri_edges_get; } else { BLI_assert(sod->type == SNAP_EDIT_MESH); r_nearest2d->userdata = sod->treedata_editmesh.em; - r_nearest2d->get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get; - r_nearest2d->get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get; - r_nearest2d->copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy; + r_nearest2d->get_vert_co = cb_bvert_co_get; + r_nearest2d->get_edge_verts_index = cb_bedge_verts_get; + r_nearest2d->copy_vert_no = cb_bvert_no_copy; r_nearest2d->get_tri_verts_index = NULL; r_nearest2d->get_tri_edges_index = NULL; } @@ -1404,7 +1420,7 @@ static void cb_snap_vert(void *userdata, struct Nearest2dUserData *data = userdata; const float *co; - data->get_vert_co(index, &co, data->userdata); + data->get_vert_co(index, data->userdata, &co); if (test_projected_vert_dist(precalc, clip_plane, @@ -1413,7 +1429,7 @@ static void cb_snap_vert(void *userdata, co, &nearest->dist_sq, nearest->co)) { - data->copy_vert_no(index, nearest->no, data->userdata); + data->copy_vert_no(index, data->userdata, nearest->no); nearest->index = index; } } @@ -1428,11 +1444,11 @@ static void cb_snap_edge(void *userdata, struct Nearest2dUserData *data = userdata; int vindex[2]; - data->get_edge_verts_index(index, vindex, data->userdata); + data->get_edge_verts_index(index, data->userdata, vindex); const float *v_pair[2]; - data->get_vert_co(vindex[0], &v_pair[0], data->userdata); - data->get_vert_co(vindex[1], &v_pair[1], data->userdata); + data->get_vert_co(vindex[0], data->userdata, &v_pair[0]); + data->get_vert_co(vindex[1], data->userdata, &v_pair[1]); if (test_projected_edge_dist(precalc, clip_plane, @@ -1457,7 +1473,7 @@ static void cb_snap_edge_verts(void *userdata, struct Nearest2dUserData *data = userdata; int vindex[2]; - data->get_edge_verts_index(index, vindex, data->userdata); + data->get_edge_verts_index(index, data->userdata, vindex); for (int i = 2; i--;) { if (vindex[i] == nearest->index) { @@ -1478,12 +1494,12 @@ static void cb_snap_tri_edges(void *userdata, if (data->use_backface_culling) { int vindex[3]; - data->get_tri_verts_index(index, vindex, data->userdata); + data->get_tri_verts_index(index, data->userdata, vindex); const float *t0, *t1, *t2; - data->get_vert_co(vindex[0], &t0, data->userdata); - data->get_vert_co(vindex[1], &t1, data->userdata); - data->get_vert_co(vindex[2], &t2, data->userdata); + data->get_vert_co(vindex[0], data->userdata, &t0); + data->get_vert_co(vindex[1], data->userdata, &t1); + data->get_vert_co(vindex[2], data->userdata, &t2); float dummy[3]; if (raycast_tri_backface_culling_test(precalc->ray_direction, t0, t1, t2, dummy)) { return; @@ -1491,7 +1507,7 @@ static void cb_snap_tri_edges(void *userdata, } int eindex[3]; - data->get_tri_edges_index(index, eindex, data->userdata); + data->get_tri_edges_index(index, data->userdata, eindex); for (int i = 3; i--;) { if (eindex[i] != -1) { if (eindex[i] == nearest->index) { @@ -1512,13 +1528,13 @@ static void cb_snap_tri_verts(void *userdata, struct Nearest2dUserData *data = userdata; int vindex[3]; - data->get_tri_verts_index(index, vindex, data->userdata); + data->get_tri_verts_index(index, data->userdata, vindex); if (data->use_backface_culling) { const float *t0, *t1, *t2; - data->get_vert_co(vindex[0], &t0, data->userdata); - data->get_vert_co(vindex[1], &t1, data->userdata); - data->get_vert_co(vindex[2], &t2, data->userdata); + data->get_vert_co(vindex[0], data->userdata, &t0); + data->get_vert_co(vindex[1], data->userdata, &t1); + data->get_vert_co(vindex[2], data->userdata, &t2); float dummy[3]; if (raycast_tri_backface_culling_test(precalc->ray_direction, t0, t1, t2, dummy)) { return; @@ -1693,11 +1709,11 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, sod, snapdata->view_proj == VIEW_PROJ_PERSP, use_backface_culling, &nearest2d); int vindex[2]; - nearest2d.get_edge_verts_index(*r_index, vindex, nearest2d.userdata); + nearest2d.get_edge_verts_index(*r_index, nearest2d.userdata, vindex); const float *v_pair[2]; - nearest2d.get_vert_co(vindex[0], &v_pair[0], nearest2d.userdata); - nearest2d.get_vert_co(vindex[1], &v_pair[1], nearest2d.userdata); + nearest2d.get_vert_co(vindex[0], nearest2d.userdata, &v_pair[0]); + nearest2d.get_vert_co(vindex[1], nearest2d.userdata, &v_pair[1]); struct DistProjectedAABBPrecalc neasrest_precalc; { @@ -1744,7 +1760,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, if (r_no) { float imat[4][4]; invert_m4_m4(imat, obmat); - nearest2d.copy_vert_no(vindex[v_id], r_no, nearest2d.userdata); + nearest2d.copy_vert_no(vindex[v_id], nearest2d.userdata, r_no); mul_transposed_mat3_m4_v3(imat, r_no); normalize_v3(r_no); } diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 43969bf0768..c9d652ad03d 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -621,9 +621,9 @@ typedef enum IDRecalcFlag { * When a collection gets tagged with this flag, all objects depending on the geometry and * transforms on any of the objects in the collection are updated. */ ID_RECALC_GEOMETRY = (1 << 1), - /* Same as #ID_RECALC_GEOMETRY, but instead of tagging the batch cache as `dirty_all`, just tags - what matches the deform cache. */ - ID_RECALC_GEOMETRY_DEFORM = (1 << 2), + + /* ** Animation or time changed and animation is to be re-evaluated. ** */ + ID_RECALC_ANIMATION = (1 << 2), /* ** Particle system changed. ** */ /* Only do pathcache etc. */ @@ -683,9 +683,6 @@ typedef enum IDRecalcFlag { * have to be copied on every update. */ ID_RECALC_PARAMETERS = (1 << 21), - /* ** Animation or time changed and animation is to be re-evaluated. ** */ - ID_RECALC_ANIMATION = (1 << 22), - /* Input has changed and datablock is to be reload from disk. * Applies to movie clips to inform that copy-on-written version is to be refreshed for the new * input file or for color space changes. */ diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index b7354aaa724..58c1bc6c5fd 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -295,24 +295,6 @@ typedef struct Material { #define MAP_COL (1 << 0) #define MAP_ALPHA (1 << 7) -/* pmapto */ -/* init */ -#define MAP_PA_INIT ((1 << 5) - 1) -#define MAP_PA_TIME (1 << 0) -#define MAP_PA_LIFE (1 << 1) -#define MAP_PA_DENS (1 << 2) -#define MAP_PA_SIZE (1 << 3) -#define MAP_PA_LENGTH (1 << 4) -/* reset */ -#define MAP_PA_IVEL (1 << 5) -/* physics */ -#define MAP_PA_PVEL (1 << 6) -/* path cache */ -#define MAP_PA_CLUMP (1 << 7) -#define MAP_PA_KINK (1 << 8) -#define MAP_PA_ROUGH (1 << 9) -#define MAP_PA_FREQ (1 << 10) - /* pr_type */ #define MA_FLAT 0 #define MA_SPHERE 1 diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index 2308f04c4c7..ee33e8666ec 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -54,11 +54,10 @@ typedef struct MTex { float ofs[3], size[3], rot, random_angle; char _pad0[2]; - short colormodel, pmapto, pmaptoneg; + short colormodel; short normapspace, which_output; float r, g, b, k; float def_var; - char _pad1[4]; /* common */ float colfac, varfac; diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index 057f49c0319..4895ab11618 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -711,7 +711,7 @@ void RNA_api_sequence_strip(StructRNA *srna) RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_enum(func, "split_method", seq_split_method_items, 0, "", ""); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); - /* Retirn type. */ + /* Return type. */ parm = RNA_def_pointer(func, "sequence", "Sequence", "", "Right side Sequence"); RNA_def_function_return(func, parm); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc index f7aecf72303..f9415c6d27b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc @@ -74,7 +74,7 @@ namespace blender::nodes { struct TrimLocation { /* Control point index at the start side of the trim location. */ int left_index; - /* Control point intex at the end of the trim location's segment. */ + /* Control point index at the end of the trim location's segment. */ int right_index; /* The factor between the left and right indices. */ float factor; @@ -106,8 +106,10 @@ static void linear_trim_data(const TrimLocation &start, data[size - 1] = end_data; } -/* Identical operation as #linear_trim_data, but opy data to a new MutableSpan rather than - * modifying the original data. */ +/** + * Identical operation as #linear_trim_data, but copy data to a new #MutableSpan rather than + * modifying the original data. + */ template<typename T> static void linear_trim_to_output_data(const TrimLocation &start, const TrimLocation &end, @@ -357,7 +359,7 @@ static void geo_node_curve_trim_exec(GeoNodeExecParams params) } /* Return a spline with one point instead of implicitly - * reversing the sline or switching the parameters. */ + * reversing the spline or switching the parameters. */ if (end < start) { spline.resize(1); continue; diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index a2dfaf501d6..c73dea79aac 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -1524,7 +1524,8 @@ static PyObject *list_of_lists_from_arrays(const int *array, PyDoc_STRVAR( M_Geometry_delaunay_2d_cdt_doc, - ".. function:: delaunay_2d_cdt(vert_coords, edges, faces, output_type, epsilon [,need_ids])\n" + ".. function:: delaunay_2d_cdt(vert_coords, edges, faces, output_type, epsilon, " + "need_ids=True)\n" "\n" " Computes the Constrained Delaunay Triangulation of a set of vertices,\n" " with edges and faces that must appear in the triangulation.\n" @@ -1554,7 +1555,7 @@ PyDoc_STRVAR( " :type output_type: int\\n" " :arg epsilon: For nearness tests; should not be zero\n" " :type epsilon: float\n" - " :arg need_ids: are the orig output arrays needed? (optional, default True)\n" + " :arg need_ids: are the orig output arrays needed?\n" " :type need_args: bool\n" " :return: Output tuple, (vert_coords, edges, faces, orig_verts, orig_edges, orig_faces)\n" " :rtype: (list of `mathutils.Vector`, " diff --git a/source/blender/simulation/intern/SIM_mass_spring.cpp b/source/blender/simulation/intern/SIM_mass_spring.cpp index ca01120eecb..b79731ab330 100644 --- a/source/blender/simulation/intern/SIM_mass_spring.cpp +++ b/source/blender/simulation/intern/SIM_mass_spring.cpp @@ -213,7 +213,8 @@ int SIM_cloth_solver_init(Object *UNUSED(ob), ClothModifierData *clmd) return 1; } -void SIM_mass_spring_set_implicit_vertex_mass(Implicit_Data *data, int index, float mass){ +void SIM_mass_spring_set_implicit_vertex_mass(Implicit_Data *data, int index, float mass) +{ SIM_mass_spring_set_vertex_mass(data, index, mass); } diff --git a/source/blender/windowmanager/intern/wm_operator_type.c b/source/blender/windowmanager/intern/wm_operator_type.c index e17d5a9ae70..39435721d1a 100644 --- a/source/blender/windowmanager/intern/wm_operator_type.c +++ b/source/blender/windowmanager/intern/wm_operator_type.c @@ -498,12 +498,11 @@ wmOperatorType *WM_operatortype_append_macro(const char *idname, ot->cancel = wm_macro_cancel; ot->poll = NULL; - if (!ot->description) { - /* XXX All ops should have a description but for now allow them not to. */ - ot->description = UNDOCUMENTED_OPERATOR_TIP; - } + /* XXX All ops should have a description but for now allow them not to. */ + BLI_assert((ot->description == NULL) || (ot->description[0])); - RNA_def_struct_ui_text(ot->srna, ot->name, ot->description); + 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); /* Use i18n context from rna_ext.srna if possible (py operators). */ i18n_context = ot->rna_ext.srna ? RNA_struct_translation_context(ot->rna_ext.srna) : @@ -530,16 +529,16 @@ void WM_operatortype_append_macro_ptr(void (*opfunc)(wmOperatorType *, void *), ot->cancel = wm_macro_cancel; ot->poll = NULL; - if (!ot->description) { - ot->description = UNDOCUMENTED_OPERATOR_TIP; - } + /* XXX All ops should have a description but for now allow them not to. */ + BLI_assert((ot->description == NULL) || (ot->description[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; opfunc(ot, userdata); - RNA_def_struct_ui_text(ot->srna, ot->name, ot->description); + 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); |