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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Eisel <julian@blender.org>2021-03-31 23:53:03 +0300
committerJulian Eisel <julian@blender.org>2021-03-31 23:53:03 +0300
commitc7904d2398fd4d43d15268c792aa15ea8ee538fe (patch)
tree484fd7f66ac59c82abd4aca18894f991b4935483
parent91b87d8d7fb8aec62faf00e5e0c3619d2753a92e (diff)
parent1a100d2d78c75c9a6ac015606cc16698e7775682 (diff)
Merge branch 'master' into ui-asset-view-templateui-asset-view-template
-rw-r--r--.clang-format1
-rw-r--r--.clang-tidy1
-rw-r--r--.gitignore3
-rw-r--r--CMakeLists.txt22
-rw-r--r--GNUmakefile8
-rw-r--r--build_files/build_environment/cmake/options.cmake3
-rw-r--r--build_files/cmake/platform/platform_apple.cmake13
-rw-r--r--build_files/cmake/platform/platform_win32.cmake55
-rw-r--r--build_files/windows/configure_msbuild.cmd10
-rw-r--r--build_files/windows/configure_ninja.cmd8
-rw-r--r--doc/python_api/sphinx_doc_gen.py21
-rw-r--r--extern/CMakeLists.txt4
-rw-r--r--extern/audaspace/CMakeLists.txt2
-rw-r--r--extern/audaspace/include/devices/SoftwareDevice.h1
-rw-r--r--extern/audaspace/include/devices/ThreadedDevice.h95
-rw-r--r--extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp62
-rw-r--r--extern/audaspace/plugins/pulseaudio/PulseAudioDevice.h19
-rw-r--r--extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h14
-rw-r--r--extern/audaspace/plugins/wasapi/WASAPIDevice.cpp169
-rw-r--r--extern/audaspace/plugins/wasapi/WASAPIDevice.h29
-rw-r--r--extern/audaspace/src/devices/SoftwareDevice.cpp6
-rw-r--r--extern/audaspace/src/devices/ThreadedDevice.cpp65
-rw-r--r--extern/smaa_areatex/CMakeLists.txt26
-rw-r--r--extern/smaa_areatex/README.blender5
-rw-r--r--extern/smaa_areatex/smaa_areatex.cpp1208
-rw-r--r--intern/cycles/blender/blender_image.cpp4
-rw-r--r--intern/cycles/blender/blender_image.h4
-rw-r--r--intern/cycles/blender/blender_mesh.cpp2
-rw-r--r--intern/cycles/blender/blender_volume.cpp2
-rw-r--r--intern/cycles/device/device.cpp2
-rw-r--r--intern/cycles/device/device.h2
-rw-r--r--intern/cycles/device/device_cpu.cpp1
-rw-r--r--intern/cycles/device/device_cuda.cpp1
-rw-r--r--intern/cycles/device/device_multi.cpp12
-rw-r--r--intern/cycles/device/device_opencl.cpp3
-rw-r--r--intern/cycles/device/opencl/device_opencl_impl.cpp4
-rw-r--r--intern/cycles/kernel/svm/svm_math_util.h3
-rw-r--r--intern/cycles/render/alembic.cpp24
-rw-r--r--intern/cycles/render/alembic.h16
-rw-r--r--intern/cycles/render/background.cpp8
-rw-r--r--intern/cycles/render/geometry.cpp1
-rw-r--r--intern/cycles/render/image.cpp18
-rw-r--r--intern/cycles/render/image.h12
-rw-r--r--intern/cycles/render/image_oiio.cpp4
-rw-r--r--intern/cycles/render/image_oiio.h2
-rw-r--r--intern/cycles/render/image_sky.cpp2
-rw-r--r--intern/cycles/render/image_sky.h2
-rw-r--r--intern/cycles/render/image_vdb.cpp175
-rw-r--r--intern/cycles/render/image_vdb.h3
-rw-r--r--intern/cycles/render/object.cpp4
-rw-r--r--intern/ghost/intern/GHOST_IconX11.h4
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp11
m---------release/scripts/addons0
-rw-r--r--release/scripts/modules/addon_utils.py4
-rw-r--r--release/scripts/modules/animsys_refactor.py8
-rw-r--r--release/scripts/modules/bl_rna_utils/__init__.py0
-rw-r--r--release/scripts/modules/bl_rna_utils/data_path.py91
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py1
-rw-r--r--release/scripts/startup/bl_operators/anim.py16
-rw-r--r--release/scripts/startup/bl_operators/wm.py190
-rw-r--r--release/scripts/startup/bl_ui/properties_collection.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py9
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py4
-rw-r--r--release/scripts/startup/bl_ui/space_dopesheet.py2
-rw-r--r--release/scripts/startup/bl_ui/space_graph.py5
-rw-r--r--release/scripts/startup/bl_ui/space_node.py8
-rw-r--r--release/scripts/startup/bl_ui/space_topbar.py9
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py1
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py12
-rw-r--r--release/scripts/startup/nodeitems_builtins.py32
-rw-r--r--release/scripts/templates_osl/basic_shader.osl10
-rw-r--r--release/scripts/templates_py/image_processing.py35
-rw-r--r--source/blender/blendthumb/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/BKE_action.h7
-rw-r--r--source/blender/blenkernel/BKE_armature.h2
-rw-r--r--source/blender/blenkernel/BKE_attribute.h12
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_displist.h2
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h21
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh2
-rw-r--r--source/blender/blenkernel/BKE_geometry_set_instances.hh3
-rw-r--r--source/blender/blenkernel/BKE_gpencil_geom.h16
-rw-r--r--source/blender/blenkernel/BKE_lib_override.h1
-rw-r--r--source/blender/blenkernel/BKE_node.h23
-rw-r--r--source/blender/blenkernel/BKE_node_ui_storage.hh4
-rw-r--r--source/blender/blenkernel/BKE_object.h6
-rw-r--r--source/blender/blenkernel/CMakeLists.txt7
-rw-r--r--source/blender/blenkernel/intern/action.c24
-rw-r--r--source/blender/blenkernel/intern/action_mirror.c457
-rw-r--r--source/blender/blenkernel/intern/armature_pose.cc10
-rw-r--r--source/blender/blenkernel/intern/attribute.c4
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc4
-rw-r--r--source/blender/blenkernel/intern/blendfile.c2
-rw-r--r--source/blender/blenkernel/intern/brush.c4
-rw-r--r--source/blender/blenkernel/intern/cachefile.c1
-rw-r--r--source/blender/blenkernel/intern/cryptomatte.cc3
-rw-r--r--source/blender/blenkernel/intern/curve.c17
-rw-r--r--source/blender/blenkernel/intern/displist.c13
-rw-r--r--source/blender/blenkernel/intern/fcurve.c58
-rw-r--r--source/blender/blenkernel/intern/fcurve_cache.c189
-rw-r--r--source/blender/blenkernel/intern/geometry_component_mesh.cc351
-rw-r--r--source/blender/blenkernel/intern/geometry_set.cc6
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc15
-rw-r--r--source/blender/blenkernel/intern/gpencil_geom.c553
-rw-r--r--source/blender/blenkernel/intern/lattice.c61
-rw-r--r--source/blender/blenkernel/intern/lattice_deform.c6
-rw-r--r--source/blender/blenkernel/intern/lattice_deform_test.cc1
-rw-r--r--source/blender/blenkernel/intern/lib_override.c25
-rw-r--r--source/blender/blenkernel/intern/mask.c9
-rw-r--r--source/blender/blenkernel/intern/node.cc47
-rw-r--r--source/blender/blenkernel/intern/object.c33
-rw-r--r--source/blender/blenkernel/intern/screen.c3
-rw-r--r--source/blender/blenkernel/intern/softbody.c4
-rw-r--r--source/blender/blenkernel/intern/tracking.c5
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c17
-rw-r--r--source/blender/blenlib/BLI_asan.h2
-rw-r--r--source/blender/blenlib/BLI_hash.hh27
-rw-r--r--source/blender/blenlib/BLI_set.hh2
-rw-r--r--source/blender/blenlib/BLI_user_counter.hh2
-rw-r--r--source/blender/blenlib/CMakeLists.txt1
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c7
-rw-r--r--source/blender/blenlib/intern/math_vec.cc2
-rw-r--r--source/blender/blenlib/intern/mesh_boolean.cc5
-rw-r--r--source/blender/blenlib/tests/BLI_set_test.cc4
-rw-r--r--source/blender/blenloader/intern/readfile.c9
-rw-r--r--source/blender/blenloader/intern/versioning_290.c27
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c5
-rw-r--r--source/blender/blenloader/intern/versioning_userdef.c25
-rw-r--r--source/blender/compositor/CMakeLists.txt26
-rw-r--r--source/blender/compositor/COM_compositor.h6
-rw-r--r--source/blender/compositor/COM_defines.h53
-rw-r--r--source/blender/compositor/intern/COM_CPUDevice.cc20
-rw-r--r--source/blender/compositor/intern/COM_CPUDevice.h6
-rw-r--r--source/blender/compositor/intern/COM_ChunkOrder.cc4
-rw-r--r--source/blender/compositor/intern/COM_ChunkOrder.h4
-rw-r--r--source/blender/compositor/intern/COM_ChunkOrderHotspot.cc4
-rw-r--r--source/blender/compositor/intern/COM_ChunkOrderHotspot.h4
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.cc13
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.h4
-rw-r--r--source/blender/compositor/intern/COM_Converter.cc36
-rw-r--r--source/blender/compositor/intern/COM_Converter.h7
-rw-r--r--source/blender/compositor/intern/COM_Debug.cc63
-rw-r--r--source/blender/compositor/intern/COM_Debug.h8
-rw-r--r--source/blender/compositor/intern/COM_Device.h19
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.cc169
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.h133
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.cc122
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.h22
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.cc19
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.h7
-rw-r--r--source/blender/compositor/intern/COM_MemoryProxy.cc8
-rw-r--r--source/blender/compositor/intern/COM_MemoryProxy.h21
-rw-r--r--source/blender/compositor/intern/COM_MetaData.cc4
-rw-r--r--source/blender/compositor/intern/COM_MetaData.h4
-rw-r--r--source/blender/compositor/intern/COM_Node.cc24
-rw-r--r--source/blender/compositor/intern/COM_Node.h69
-rw-r--r--source/blender/compositor/intern/COM_NodeConverter.cc4
-rw-r--r--source/blender/compositor/intern/COM_NodeConverter.h4
-rw-r--r--source/blender/compositor/intern/COM_NodeGraph.cc42
-rw-r--r--source/blender/compositor/intern/COM_NodeGraph.h17
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.cc83
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.h517
-rw-r--r--source/blender/compositor/intern/COM_NodeOperationBuilder.cc35
-rw-r--r--source/blender/compositor/intern/COM_NodeOperationBuilder.h4
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.cc22
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.h21
-rw-r--r--source/blender/compositor/intern/COM_SingleThreadedOperation.cc7
-rw-r--r--source/blender/compositor/intern/COM_SingleThreadedOperation.h17
-rw-r--r--source/blender/compositor/intern/COM_SocketReader.h153
-rw-r--r--source/blender/compositor/intern/COM_WorkPackage.cc8
-rw-r--r--source/blender/compositor/intern/COM_WorkPackage.h17
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.cc83
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.h10
-rw-r--r--source/blender/compositor/intern/COM_compositor.cc16
-rw-r--r--source/blender/compositor/nodes/COM_AlphaOverNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_AlphaOverNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_AntiAliasingNode.cc60
-rw-r--r--source/blender/compositor/nodes/COM_AntiAliasingNode.h40
-rw-r--r--source/blender/compositor/nodes/COM_BilateralBlurNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_BilateralBlurNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_BlurNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_BlurNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_BokehBlurNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_BokehBlurNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_BokehImageNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_BokehImageNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_BoxMaskNode.cc6
-rw-r--r--source/blender/compositor/nodes/COM_BoxMaskNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_BrightnessNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_BrightnessNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ChannelMatteNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ChannelMatteNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ChromaMatteNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ChromaMatteNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ColorBalanceNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ColorBalanceNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ColorCorrectionNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ColorCorrectionNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ColorCurveNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ColorCurveNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ColorExposureNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ColorExposureNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ColorMatteNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ColorMatteNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ColorNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ColorNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ColorRampNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ColorRampNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ColorSpillNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ColorSpillNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ColorToBWNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ColorToBWNode.h8
-rw-r--r--source/blender/compositor/nodes/COM_CombineColorNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_CombineColorNode.h15
-rw-r--r--source/blender/compositor/nodes/COM_CompositorNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_CompositorNode.h8
-rw-r--r--source/blender/compositor/nodes/COM_ConvertAlphaNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ConvertAlphaNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_CornerPinNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_CornerPinNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_CropNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_CropNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_CryptomatteNode.cc15
-rw-r--r--source/blender/compositor/nodes/COM_CryptomatteNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_DefocusNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_DefocusNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_DenoiseNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_DenoiseNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_DespeckleNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_DespeckleNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_DifferenceMatteNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_DifferenceMatteNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_DilateErodeNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_DilateErodeNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_DirectionalBlurNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_DirectionalBlurNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_DisplaceNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_DisplaceNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_DistanceMatteNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_DistanceMatteNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_EllipseMaskNode.cc6
-rw-r--r--source/blender/compositor/nodes/COM_EllipseMaskNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_FilterNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_FilterNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_FlipNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_FlipNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_GammaNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_GammaNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_GlareNode.cc6
-rw-r--r--source/blender/compositor/nodes/COM_GlareNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_HueSaturationValueNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_HueSaturationValueNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_IDMaskNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_IDMaskNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.cc22
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_InpaintNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_InpaintNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_InvertNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_InvertNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_KeyingNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_KeyingNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_KeyingScreenNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_KeyingScreenNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_LensDistortionNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_LensDistortionNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_LuminanceMatteNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_LuminanceMatteNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_MapRangeNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_MapRangeNode.h8
-rw-r--r--source/blender/compositor/nodes/COM_MapUVNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_MapUVNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_MapValueNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_MapValueNode.h8
-rw-r--r--source/blender/compositor/nodes/COM_MaskNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_MaskNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_MathNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_MathNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_MixNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_MixNode.h8
-rw-r--r--source/blender/compositor/nodes/COM_MovieClipNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_MovieClipNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_MovieDistortionNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_MovieDistortionNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_NormalNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_NormalNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_NormalizeNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_NormalizeNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_OutputFileNode.cc15
-rw-r--r--source/blender/compositor/nodes/COM_OutputFileNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_PixelateNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_PixelateNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_RenderLayersNode.cc13
-rw-r--r--source/blender/compositor/nodes/COM_RenderLayersNode.h6
-rw-r--r--source/blender/compositor/nodes/COM_RotateNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_RotateNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ScaleNode.cc6
-rw-r--r--source/blender/compositor/nodes/COM_ScaleNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_SeparateColorNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_SeparateColorNode.h15
-rw-r--r--source/blender/compositor/nodes/COM_SetAlphaNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_SetAlphaNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_SocketProxyNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_SocketProxyNode.h10
-rw-r--r--source/blender/compositor/nodes/COM_SplitViewerNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_SplitViewerNode.h8
-rw-r--r--source/blender/compositor/nodes/COM_Stabilize2dNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_Stabilize2dNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_SunBeamsNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_SunBeamsNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_SwitchNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_SwitchNode.h8
-rw-r--r--source/blender/compositor/nodes/COM_SwitchViewNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_SwitchViewNode.h8
-rw-r--r--source/blender/compositor/nodes/COM_TextureNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_TextureNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_TimeNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_TimeNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_TonemapNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_TonemapNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_TrackPositionNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_TrackPositionNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_TransformNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_TransformNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_TranslateNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_TranslateNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ValueNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ValueNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_VectorBlurNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_VectorBlurNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_VectorCurveNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_VectorCurveNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ViewLevelsNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ViewLevelsNode.h7
-rw-r--r--source/blender/compositor/nodes/COM_ViewerNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ViewerNode.h8
-rw-r--r--source/blender/compositor/nodes/COM_ZCombineNode.cc4
-rw-r--r--source/blender/compositor/nodes/COM_ZCombineNode.h7
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverKeyOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverKeyOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverMixedOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverMixedOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_AntiAliasOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_AntiAliasOperation.h14
-rw-r--r--source/blender/compositor/operations/COM_BilateralBlurOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_BilateralBlurOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_BlurBaseOperation.cc8
-rw-r--r--source/blender/compositor/operations/COM_BlurBaseOperation.h11
-rw-r--r--source/blender/compositor/operations/COM_BokehBlurOperation.cc27
-rw-r--r--source/blender/compositor/operations/COM_BokehBlurOperation.h19
-rw-r--r--source/blender/compositor/operations/COM_BokehImageOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_BokehImageOperation.h13
-rw-r--r--source/blender/compositor/operations/COM_BoxMaskOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_BoxMaskOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_BrightnessOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_BrightnessOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_CalculateMeanOperation.cc8
-rw-r--r--source/blender/compositor/operations/COM_CalculateMeanOperation.h14
-rw-r--r--source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.h9
-rw-r--r--source/blender/compositor/operations/COM_ChangeHSVOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ChangeHSVOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_ChannelMatteOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ChannelMatteOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_ChromaMatteOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ChromaMatteOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_ColorCorrectionOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ColorCorrectionOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_ColorCurveOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ColorCurveOperation.h16
-rw-r--r--source/blender/compositor/operations/COM_ColorExposureOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ColorExposureOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_ColorMatteOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ColorMatteOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_ColorRampOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ColorRampOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_ColorSpillOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ColorSpillOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_CompositorOperation.cc18
-rw-r--r--source/blender/compositor/operations/COM_CompositorOperation.h17
-rw-r--r--source/blender/compositor/operations/COM_ConvertColorProfileOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ConvertColorProfileOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.h11
-rw-r--r--source/blender/compositor/operations/COM_ConvertOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ConvertOperation.h50
-rw-r--r--source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_ConvolutionFilterOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_ConvolutionFilterOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_CropOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_CropOperation.h17
-rw-r--r--source/blender/compositor/operations/COM_CryptomatteOperation.cc16
-rw-r--r--source/blender/compositor/operations/COM_CryptomatteOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_CurveBaseOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_CurveBaseOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_DenoiseOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_DenoiseOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_DespeckleOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_DespeckleOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_DifferenceMatteOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_DifferenceMatteOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_DilateErodeOperation.cc12
-rw-r--r--source/blender/compositor/operations/COM_DilateErodeOperation.h44
-rw-r--r--source/blender/compositor/operations/COM_DirectionalBlurOperation.cc13
-rw-r--r--source/blender/compositor/operations/COM_DirectionalBlurOperation.h14
-rw-r--r--source/blender/compositor/operations/COM_DisplaceOperation.cc14
-rw-r--r--source/blender/compositor/operations/COM_DisplaceOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_DisplaceSimpleOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_DisplaceSimpleOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_DistanceRGBMatteOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_DistanceYCCMatteOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_DotproductOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_DotproductOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h14
-rw-r--r--source/blender/compositor/operations/COM_EllipseMaskOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_EllipseMaskOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc16
-rw-r--r--source/blender/compositor/operations/COM_FastGaussianBlurOperation.h24
-rw-r--r--source/blender/compositor/operations/COM_FlipOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_FlipOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_GammaCorrectOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_GammaCorrectOperation.h16
-rw-r--r--source/blender/compositor/operations/COM_GammaOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_GammaOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h14
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h14
-rw-r--r--source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cc10
-rw-r--r--source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h24
-rw-r--r--source/blender/compositor/operations/COM_GaussianXBlurOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_GaussianXBlurOperation.h18
-rw-r--r--source/blender/compositor/operations/COM_GaussianYBlurOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_GaussianYBlurOperation.h18
-rw-r--r--source/blender/compositor/operations/COM_GlareBaseOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_GlareBaseOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_GlareFogGlowOperation.cc21
-rw-r--r--source/blender/compositor/operations/COM_GlareFogGlowOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_GlareGhostOperation.cc10
-rw-r--r--source/blender/compositor/operations/COM_GlareGhostOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_GlareSimpleStarOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_GlareSimpleStarOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_GlareStreaksOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_GlareStreaksOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_GlareThresholdOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_GlareThresholdOperation.h13
-rw-r--r--source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_IDMaskOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_IDMaskOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_ImageOperation.cc16
-rw-r--r--source/blender/compositor/operations/COM_ImageOperation.h17
-rw-r--r--source/blender/compositor/operations/COM_InpaintOperation.cc9
-rw-r--r--source/blender/compositor/operations/COM_InpaintOperation.h14
-rw-r--r--source/blender/compositor/operations/COM_InvertOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_InvertOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_KeyingBlurOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_KeyingBlurOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_KeyingClipOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_KeyingClipOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_KeyingDespillOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_KeyingDespillOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_KeyingOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_KeyingOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_KeyingScreenOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_KeyingScreenOperation.h17
-rw-r--r--source/blender/compositor/operations/COM_LuminanceMatteOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_LuminanceMatteOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_MapRangeOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_MapRangeOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_MapUVOperation.cc10
-rw-r--r--source/blender/compositor/operations/COM_MapUVOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_MapValueOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_MapValueOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_MaskOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_MaskOperation.h16
-rw-r--r--source/blender/compositor/operations/COM_MathBaseOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_MathBaseOperation.h96
-rw-r--r--source/blender/compositor/operations/COM_MixOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_MixOperation.h51
-rw-r--r--source/blender/compositor/operations/COM_MovieClipAttributeOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_MovieClipAttributeOperation.h11
-rw-r--r--source/blender/compositor/operations/COM_MovieClipOperation.cc10
-rw-r--r--source/blender/compositor/operations/COM_MovieClipOperation.h15
-rw-r--r--source/blender/compositor/operations/COM_MovieDistortionOperation.cc8
-rw-r--r--source/blender/compositor/operations/COM_MovieDistortionOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_MultilayerImageOperation.cc12
-rw-r--r--source/blender/compositor/operations/COM_MultilayerImageOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_NormalizeOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_NormalizeOperation.h16
-rw-r--r--source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.cc17
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.h38
-rw-r--r--source/blender/compositor/operations/COM_PixelateOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_PixelateOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_PlaneCornerPinOperation.cc8
-rw-r--r--source/blender/compositor/operations/COM_PlaneCornerPinOperation.h21
-rw-r--r--source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cc8
-rw-r--r--source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h16
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackOperation.h14
-rw-r--r--source/blender/compositor/operations/COM_PreviewOperation.cc10
-rw-r--r--source/blender/compositor/operations/COM_PreviewOperation.h23
-rw-r--r--source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cc8
-rw-r--r--source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h14
-rw-r--r--source/blender/compositor/operations/COM_QualityStepHelper.cc4
-rw-r--r--source/blender/compositor/operations/COM_QualityStepHelper.h4
-rw-r--r--source/blender/compositor/operations/COM_ReadBufferOperation.cc13
-rw-r--r--source/blender/compositor/operations/COM_ReadBufferOperation.h21
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.cc12
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.h12
-rw-r--r--source/blender/compositor/operations/COM_RotateOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_RotateOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_SMAAOperation.cc868
-rw-r--r--source/blender/compositor/operations/COM_SMAAOperation.h149
-rw-r--r--source/blender/compositor/operations/COM_ScaleOperation.cc16
-rw-r--r--source/blender/compositor/operations/COM_ScaleOperation.h31
-rw-r--r--source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cc10
-rw-r--r--source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h16
-rw-r--r--source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_SetAlphaReplaceOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_SetAlphaReplaceOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_SetColorOperation.cc5
-rw-r--r--source/blender/compositor/operations/COM_SetColorOperation.h13
-rw-r--r--source/blender/compositor/operations/COM_SetSamplerOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_SetSamplerOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_SetValueOperation.cc5
-rw-r--r--source/blender/compositor/operations/COM_SetValueOperation.h14
-rw-r--r--source/blender/compositor/operations/COM_SetVectorOperation.cc5
-rw-r--r--source/blender/compositor/operations/COM_SetVectorOperation.h13
-rw-r--r--source/blender/compositor/operations/COM_SocketProxyOperation.cc9
-rw-r--r--source/blender/compositor/operations/COM_SocketProxyOperation.h26
-rw-r--r--source/blender/compositor/operations/COM_SplitOperation.cc8
-rw-r--r--source/blender/compositor/operations/COM_SplitOperation.h13
-rw-r--r--source/blender/compositor/operations/COM_SunBeamsOperation.cc14
-rw-r--r--source/blender/compositor/operations/COM_SunBeamsOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_TextureOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_TextureOperation.h15
-rw-r--r--source/blender/compositor/operations/COM_TonemapOperation.cc8
-rw-r--r--source/blender/compositor/operations/COM_TonemapOperation.h18
-rw-r--r--source/blender/compositor/operations/COM_TrackPositionOperation.cc5
-rw-r--r--source/blender/compositor/operations/COM_TrackPositionOperation.h16
-rw-r--r--source/blender/compositor/operations/COM_TranslateOperation.cc6
-rw-r--r--source/blender/compositor/operations/COM_TranslateOperation.h16
-rw-r--r--source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cc22
-rw-r--r--source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h31
-rw-r--r--source/blender/compositor/operations/COM_VectorBlurOperation.cc8
-rw-r--r--source/blender/compositor/operations/COM_VectorBlurOperation.h14
-rw-r--r--source/blender/compositor/operations/COM_VectorCurveOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_VectorCurveOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_ViewerOperation.cc12
-rw-r--r--source/blender/compositor/operations/COM_ViewerOperation.h23
-rw-r--r--source/blender/compositor/operations/COM_WrapOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_WrapOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_WriteBufferOperation.cc9
-rw-r--r--source/blender/compositor/operations/COM_WriteBufferOperation.h26
-rw-r--r--source/blender/compositor/operations/COM_ZCombineOperation.cc4
-rw-r--r--source/blender/compositor/operations/COM_ZCombineOperation.h20
-rw-r--r--source/blender/depsgraph/intern/builder/pipeline.cc2
-rw-r--r--source/blender/draw/DRW_engine.h3
-rw-r--r--source/blender/draw/engines/overlay/overlay_armature.c6
-rw-r--r--source/blender/draw/intern/draw_manager.c9
-rw-r--r--source/blender/editors/animation/keyframing.c10
-rw-r--r--source/blender/editors/armature/armature_naming.c4
-rw-r--r--source/blender/editors/armature/pose_edit.c4
-rw-r--r--source/blender/editors/armature/pose_lib.c11
-rw-r--r--source/blender/editors/armature/pose_transform.c13
-rw-r--r--source/blender/editors/armature/pose_utils.c5
-rw-r--r--source/blender/editors/curve/editcurve_paint.c9
-rw-r--r--source/blender/editors/curve/editcurve_select.c4
-rw-r--r--source/blender/editors/geometry/geometry_attributes.c6
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c335
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c24
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c30
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c3
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c50
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c14
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c12
-rw-r--r--source/blender/editors/gpencil/gpencil_trace_utils.c7
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c17
-rw-r--r--source/blender/editors/include/ED_gizmo_library.h6
-rw-r--r--source/blender/editors/include/ED_gpencil.h1
-rw-r--r--source/blender/editors/include/ED_mesh.h13
-rw-r--r--source/blender/editors/include/ED_object.h3
-rw-r--r--source/blender/editors/include/ED_view3d.h17
-rw-r--r--source/blender/editors/interface/interface.c5
-rw-r--r--source/blender/editors/interface/interface_eyedropper_color.c5
-rw-r--r--source/blender/editors/interface/interface_panel.c11
-rw-r--r--source/blender/editors/io/CMakeLists.txt15
-rw-r--r--source/blender/editors/io/io_gpencil.h45
-rw-r--r--source/blender/editors/io/io_gpencil_export.c432
-rw-r--r--source/blender/editors/io/io_gpencil_import.c195
-rw-r--r--source/blender/editors/io/io_gpencil_utils.c64
-rw-r--r--source/blender/editors/io/io_ops.c11
-rw-r--r--source/blender/editors/mask/mask_add.c40
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c2100
-rw-r--r--source/blender/editors/mesh/editmesh_path.c5
-rw-r--r--source/blender/editors/mesh/editmesh_select.c120
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c4
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c4
-rw-r--r--source/blender/editors/object/object_add.c130
-rw-r--r--source/blender/editors/object/object_data_transfer.c3
-rw-r--r--source/blender/editors/object/object_modifier.c146
-rw-r--r--source/blender/editors/object/object_transform.c7
-rw-r--r--source/blender/editors/physics/particle_edit.c16
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c15
-rw-r--r--source/blender/editors/space_file/filelist.c2
-rw-r--r--source/blender/editors/space_image/image_intern.h1
-rw-r--r--source/blender/editors/space_image/image_ops.c167
-rw-r--r--source/blender/editors/space_image/space_image.c1
-rw-r--r--source/blender/editors/space_node/drawnode.c18
-rw-r--r--source/blender/editors/space_node/node_add.c15
-rw-r--r--source/blender/editors/space_node/node_buttons.c4
-rw-r--r--source/blender/editors/space_node/node_edit.c15
-rw-r--r--source/blender/editors/space_node/node_intern.h2
-rw-r--r--source/blender/editors/space_node/node_relationships.c16
-rw-r--r--source/blender/editors/space_node/node_select.c16
-rw-r--r--source/blender/editors/space_outliner/outliner_dragdrop.c6
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c31
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c13
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_view_layer.cc8
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c41
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c21
-rw-r--r--source/blender/editors/space_sequencer/sequencer_modifier.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_proxy.c12
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c60
-rw-r--r--source/blender/editors/space_spreadsheet/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_column_layout.cc2
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc12
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c183
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_navigate.c78
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h10
-rw-r--r--source/blender/editors/space_view3d/view3d_placement.c9
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c22
-rw-r--r--source/blender/editors/transform/transform_convert.c20
-rw-r--r--source/blender/editors/transform/transform_convert_armature.c11
-rw-r--r--source/blender/editors/transform/transform_convert_cursor.c7
-rw-r--r--source/blender/editors/util/CMakeLists.txt2
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c24
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.h7
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c79
-rw-r--r--source/blender/functions/FN_cpp_type.hh6
-rw-r--r--source/blender/functions/FN_cpp_type_make.hh2
-rw-r--r--source/blender/functions/FN_multi_function.hh2
-rw-r--r--source/blender/functions/FN_multi_function_builder.hh2
-rw-r--r--source/blender/functions/FN_multi_function_data_type.hh2
-rw-r--r--source/blender/gpencil_modifiers/CMakeLists.txt9
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c19
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c2
-rw-r--r--source/blender/imbuf/intern/anim_movie.c390
-rw-r--r--source/blender/imbuf/intern/cineon/cineon_dpx.c12
-rw-r--r--source/blender/imbuf/intern/indexer.c34
-rw-r--r--source/blender/imbuf/intern/iris.c6
-rw-r--r--source/blender/imbuf/intern/metadata.c6
-rw-r--r--source/blender/imbuf/intern/radiance_hdr.c138
-rw-r--r--source/blender/imbuf/intern/tiff.c6
-rw-r--r--source/blender/io/CMakeLists.txt2
-rw-r--r--source/blender/io/gpencil/CMakeLists.txt98
-rw-r--r--source/blender/io/gpencil/gpencil_io.h92
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_base.cc396
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_base.hh118
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_capi.cc204
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_export_base.hh (renamed from source/blender/compositor/intern/COM_SocketReader.cc)23
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc311
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_export_pdf.hh67
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_export_svg.cc465
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_export_svg.hh89
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_import_base.cc83
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_import_base.hh41
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_import_svg.cc253
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_import_svg.hh56
-rw-r--r--source/blender/io/gpencil/nanosvg/nanosvg.h3313
-rw-r--r--source/blender/makesdna/DNA_ID.h74
-rw-r--r--source/blender/makesdna/DNA_armature_types.h7
-rw-r--r--source/blender/makesdna/DNA_curve_types.h2
-rw-r--r--source/blender/makesdna/DNA_node_types.h22
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h3
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h4
-rw-r--r--source/blender/makesdna/intern/dna_genfile.c5
-rw-r--r--source/blender/makesrna/RNA_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_ID.c257
-rw-r--r--source/blender/makesrna/intern/rna_access_compare_override.c4
-rw-r--r--source/blender/makesrna/intern/rna_action.c6
-rw-r--r--source/blender/makesrna/intern/rna_action_api.c24
-rw-r--r--source/blender/makesrna/intern/rna_armature.c10
-rw-r--r--source/blender/makesrna/intern/rna_attribute.c8
-rw-r--r--source/blender/makesrna/intern/rna_depsgraph.c11
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c32
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c5
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c113
-rw-r--r--source/blender/makesrna/intern/rna_object.c17
-rw-r--r--source/blender/makesrna/intern/rna_rna.c14
-rw-r--r--source/blender/makesrna/intern/rna_scene.c7
-rw-r--r--source/blender/makesrna/intern/rna_sequencer_api.c48
-rw-r--r--source/blender/makesrna/intern/rna_space.c4
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c8
-rw-r--r--source/blender/makesrna/intern/rna_wm.c103
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c6
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc44
-rw-r--r--source/blender/modifiers/intern/MOD_solidify_extrude.c2
-rw-r--r--source/blender/nodes/CMakeLists.txt7
-rw-r--r--source/blender/nodes/NOD_composite.h1
-rw-r--r--source/blender/nodes/NOD_derived_node_tree.hh5
-rw-r--r--source/blender/nodes/NOD_geometry.h4
-rw-r--r--source/blender/nodes/NOD_math_functions.hh3
-rw-r--r--source/blender/nodes/NOD_socket.h2
-rw-r--r--source/blender/nodes/NOD_static_types.h5
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_antialiasing.c65
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc278
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_map_range.cc417
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc (renamed from source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_plane.cc)30
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc15
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_point_instance.cc5
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_transform.cc28
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc6
-rw-r--r--source/blender/nodes/intern/node_socket.cc11
-rw-r--r--source/blender/nodes/intern/node_tree_multi_function.cc11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_math.cc186
-rw-r--r--source/blender/python/gpu/gpu_py_state.c25
-rw-r--r--source/blender/python/intern/CMakeLists.txt8
-rw-r--r--source/blender/python/intern/bpy_app_build_options.c14
-rw-r--r--source/blender/python/intern/bpy_rna.c2
-rw-r--r--source/blender/sequencer/CMakeLists.txt2
-rw-r--r--source/blender/sequencer/SEQ_iterator.h9
-rw-r--r--source/blender/sequencer/intern/strip_add.c2
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c8
-rw-r--r--source/creator/CMakeLists.txt51
-rw-r--r--tests/CMakeLists.txt7
-rw-r--r--tests/blender_as_python_module/CMakeLists.txt33
-rw-r--r--tests/blender_as_python_module/import_bpy.py19
-rw-r--r--tests/python/CMakeLists.txt27
-rw-r--r--tests/python/bl_blendfile_library_overrides.py103
-rw-r--r--tests/python/compositor_render_tests.py64
-rw-r--r--tests/python/operators.py90
763 files changed, 19545 insertions, 5342 deletions
diff --git a/.clang-format b/.clang-format
index 79aa893cada..9f3e37dea56 100644
--- a/.clang-format
+++ b/.clang-format
@@ -255,7 +255,6 @@ ForEachMacros:
- SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN
- SEQ_ALL_BEGIN
- - SEQ_CURRENT_BEGIN
- SURFACE_QUAD_ITER_BEGIN
- foreach
- ED_screen_areas_iter
diff --git a/.clang-tidy b/.clang-tidy
index 98fa36db790..23a541eefd1 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -43,7 +43,6 @@ Checks: >
# the windows compiler currently.
-modernize-raw-string-literal
-WarningsAsErrors: '*'
CheckOptions:
- key: modernize-use-default-member-init.UseAssignment
value: 1
diff --git a/.gitignore b/.gitignore
index b1f351255b7..96b70c2be70 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,3 +46,6 @@ Desktop.ini
# smoke simulation noise tile (generated)
waveletNoiseTile.bin
+
+# testing environment
+/Testing
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2743d2d334c..ba863cf32b6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -236,9 +236,7 @@ option(WITH_SYSTEM_AUDASPACE "Build with external audaspace library installed on
mark_as_advanced(WITH_AUDASPACE)
mark_as_advanced(WITH_SYSTEM_AUDASPACE)
-if(NOT WITH_AUDASPACE)
- set(WITH_SYSTEM_AUDASPACE OFF)
-endif()
+set_and_warn_dependency(WITH_AUDASPACE WITH_SYSTEM_AUDASPACE OFF)
option(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" ON)
if(UNIX AND NOT APPLE)
@@ -522,10 +520,10 @@ if(CMAKE_COMPILER_IS_GNUCC)
mark_as_advanced(WITH_LINKER_LLD)
endif()
-if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
- option(WITH_COMPILER_ASAN "Build and link against address sanitizer (only for Debug & RelWithDebInfo targets)." OFF)
- mark_as_advanced(WITH_COMPILER_ASAN)
+option(WITH_COMPILER_ASAN "Build and link against address sanitizer (only for Debug & RelWithDebInfo targets)." OFF)
+mark_as_advanced(WITH_COMPILER_ASAN)
+if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
if(WITH_COMPILER_ASAN)
set(_asan_defaults "\
-fsanitize=address \
@@ -704,10 +702,8 @@ if(WITH_PYTHON_MODULE AND WITH_PYTHON_INSTALL)
message(FATAL_ERROR "WITH_PYTHON_MODULE requires WITH_PYTHON_INSTALL to be OFF")
endif()
-if(NOT WITH_PYTHON)
- set(WITH_CYCLES OFF)
- set(WITH_DRACO OFF)
-endif()
+set_and_warn_dependency(WITH_PYTHON WITH_CYCLES OFF)
+set_and_warn_dependency(WITH_PYTHON WITH_DRACO OFF)
if(WITH_DRACO AND NOT WITH_PYTHON_INSTALL)
message(STATUS "WITH_DRACO requires WITH_PYTHON_INSTALL to be ON, disabling WITH_DRACO for now")
@@ -779,6 +775,7 @@ if(WITH_INSTALL_PORTABLE)
endif()
if(WITH_GHOST_SDL OR WITH_HEADLESS)
+ message(STATUS "Disabling Ghost Wayland, X11, Input IME, and OpenXR")
set(WITH_GHOST_WAYLAND OFF)
set(WITH_GHOST_X11 OFF)
set(WITH_X11_XINPUT OFF)
@@ -809,7 +806,7 @@ endif()
if(NOT WITH_CUDA_DYNLOAD)
find_package(CUDA)
if(NOT CUDA_FOUND)
- message("CUDA toolkit not found, using dynamic runtime loading of libraries instead")
+ message(STATUS "CUDA toolkit not found, using dynamic runtime loading of libraries (WITH_CUDA_DYNLOAD) instead")
set(WITH_CUDA_DYNLOAD ON)
endif()
endif()
@@ -1235,6 +1232,7 @@ if(WITH_OPENMP)
string(APPEND CMAKE_C_FLAGS " ${OpenMP_C_FLAGS}")
string(APPEND CMAKE_CXX_FLAGS " ${OpenMP_CXX_FLAGS}")
string(APPEND CMAKE_EXE_LINKER_FLAGS " ${OpenMP_LINKER_FLAGS}")
+ string(APPEND CMAKE_MODULE_LINKER_FLAGS " ${OpenMP_LINKER_FLAGS}")
else()
# Typically avoid adding flags as defines but we can't
# pass OpenMP flags to the linker for static builds, meaning
@@ -1245,6 +1243,7 @@ if(WITH_OPENMP)
find_library_static(OpenMP_LIBRARIES gomp ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES})
endif()
else()
+ message(STATUS "OpenMP not found, disabling WITH_OPENMP")
set(WITH_OPENMP OFF)
endif()
@@ -1320,6 +1319,7 @@ list(APPEND GL_DEFINITIONS -DGLEW_NO_GLU)
if(WITH_BULLET AND WITH_SYSTEM_BULLET)
find_package(Bullet)
if(NOT BULLET_FOUND)
+ message(STATUS "Bullet not found, disabling WITH_BULLET")
set(WITH_BULLET OFF)
endif()
else()
diff --git a/GNUmakefile b/GNUmakefile
index 3fe1850ca73..3f7804557aa 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -129,7 +129,10 @@ Utilities
Create a compressed archive of the source code.
* update:
- updates git and all submodules
+ Updates git and all submodules and svn.
+
+ * update_code:
+ Updates git and all submodules but not svn.
* format:
Format source code using clang (uses PATHS if passed in). For example::
@@ -522,6 +525,9 @@ icons_geom: .FORCE
update: .FORCE
$(PYTHON) ./build_files/utils/make_update.py
+update_code: .FORCE
+ $(PYTHON) ./build_files/utils/make_update.py --no-libraries
+
format: .FORCE
PATH="../lib/${OS_NCASE}_${CPU}/llvm/bin/:../lib/${OS_NCASE}_centos7_${CPU}/llvm/bin/:../lib/${OS_NCASE}/llvm/bin/:$(PATH)" \
$(PYTHON) source/tools/utils_maintenance/clang_format_paths.py $(PATHS)
diff --git a/build_files/build_environment/cmake/options.cmake b/build_files/build_environment/cmake/options.cmake
index 5091a5d9496..15ceb693ae0 100644
--- a/build_files/build_environment/cmake/options.cmake
+++ b/build_files/build_environment/cmake/options.cmake
@@ -21,7 +21,8 @@ if(WIN32)
endif()
option(WITH_WEBP "Enable building of oiio with webp support" OFF)
option(WITH_BOOST_PYTHON "Enable building of boost with python support" OFF)
-set(MAKE_THREADS 1 CACHE STRING "Number of threads to run make with")
+cmake_host_system_information(RESULT NUM_CORES QUERY NUMBER_OF_LOGICAL_CORES)
+set(MAKE_THREADS ${NUM_CORES} CACHE STRING "Number of threads to run make with")
if(NOT BUILD_MODE)
set(BUILD_MODE "Release")
diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake
index 6276032d85c..a5eee46349a 100644
--- a/build_files/cmake/platform/platform_apple.cmake
+++ b/build_files/cmake/platform/platform_apple.cmake
@@ -56,6 +56,7 @@ list(APPEND ZLIB_LIBRARIES ${BZIP2_LIBRARIES})
if(WITH_OPENAL)
find_package(OpenAL)
if(NOT OPENAL_FOUND)
+ message(WARNING "OpenAL not found, disabling WITH_OPENAL")
set(WITH_OPENAL OFF)
endif()
endif()
@@ -65,6 +66,7 @@ if(WITH_JACK)
NAMES jackmp
)
if(NOT JACK_FRAMEWORK)
+ message(STATUS "JACK not found, disabling WITH_JACK")
set(WITH_JACK OFF)
else()
set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers)
@@ -102,6 +104,7 @@ endif()
if(WITH_USD)
find_package(USD)
if(NOT USD_FOUND)
+ message(STATUS "USD not found, disabling WITH_USD")
set(WITH_USD OFF)
endif()
endif()
@@ -146,7 +149,7 @@ if(WITH_PYTHON)
set(PYTHON_INCLUDE_DIR "${_py_framework}/include/python${PYTHON_VERSION}")
set(PYTHON_EXECUTABLE "${_py_framework}/bin/python${PYTHON_VERSION}")
- set(PYTHON_LIBPATH "${_py_framework}/lib/python${PYTHON_VERSION}/config-${PYTHON_VERSION}")
+ set(PYTHON_LIBPATH "${_py_framework}/lib/python${PYTHON_VERSION}")
# set(PYTHON_LIBRARY python${PYTHON_VERSION})
# set(PYTHON_LINKFLAGS "-u _PyMac_Error -framework Python") # won't build with this enabled
@@ -308,7 +311,7 @@ if(WITH_OPENCOLORIO)
if(NOT OPENCOLORIO_FOUND)
set(WITH_OPENCOLORIO OFF)
- message(STATUS "OpenColorIO not found")
+ message(STATUS "OpenColorIO not found, disabling WITH_OPENCOLORIO")
endif()
endif()
@@ -357,7 +360,7 @@ if(WITH_CYCLES_OSL)
if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER AND OSL_SHADER_DIR)
set(OSL_FOUND TRUE)
else()
- message(STATUS "OSL not found")
+ message(WARNING "OSL not found, disabling WITH_CYCLES_OSL")
set(WITH_CYCLES_OSL OFF)
endif()
endif()
@@ -385,7 +388,7 @@ if(WITH_OPENIMAGEDENOISE)
if(NOT OPENIMAGEDENOISE_FOUND)
set(WITH_OPENIMAGEDENOISE OFF)
- message(STATUS "OpenImageDenoise not found")
+ message(STATUS "OpenImageDenoise not found, disabling WITH_OPENIMAGEDENOISE")
endif()
endif()
@@ -413,7 +416,7 @@ if(WITH_OPENMP)
set(OpenMP_LINKER_FLAGS "-L'${LIBDIR}/openmp/lib' -lomp")
# Copy libomp.dylib to allow executables like datatoc and tests to work.
- # `@executable_path/../Resources/lib/` `LC_ID_DYLIB`is added by the deps builder.
+ # `@executable_path/../Resources/lib/` `LC_ID_DYLIB` is added by the deps builder.
# For single config generator datatoc, tests etc.
execute_process(
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/Resources/lib
diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake
index acd6028e2ae..b6ec016aa95 100644
--- a/build_files/cmake/platform/platform_win32.cmake
+++ b/build_files/cmake/platform/platform_win32.cmake
@@ -149,11 +149,6 @@ add_definitions(-D_WIN32_WINNT=0x601)
include(build_files/cmake/platform/platform_win32_bundle_crt.cmake)
remove_cc_flag("/MDd" "/MD" "/Zi")
-if(WITH_WINDOWS_PDB)
- set(PDB_INFO_OVERRIDE_FLAGS "/Z7")
- set(PDB_INFO_OVERRIDE_LINKER_FLAGS "/DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO")
-endif()
-
if(MSVC_CLANG) # Clangs version of cl doesn't support all flags
string(APPEND CMAKE_CXX_FLAGS " ${CXX_WARN_FLAGS} /nologo /J /Gd /EHsc -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference ")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference")
@@ -162,6 +157,21 @@ else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP /bigobj")
endif()
+# X64 ASAN is available and usable on MSVC 16.9 preview 4 and up)
+if(WITH_COMPILER_ASAN AND MSVC AND NOT MSVC_CLANG)
+ if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.28.29828)
+ #set a flag so we don't have to do this comparison all the time
+ SET(MSVC_ASAN On)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address")
+ string(APPEND CMAKE_EXE_LINKER_FLAGS_DEBUG " /INCREMENTAL:NO")
+ string(APPEND CMAKE_SHARED_LINKER_FLAGS_DEBUG " /INCREMENTAL:NO")
+ else()
+ message("-- ASAN not supported on MSVC ${CMAKE_CXX_COMPILER_VERSION}")
+ endif()
+endif()
+
+
# C++ standards conformace (/permissive-) is available on msvc 15.5 (1912) and up
if(MSVC_VERSION GREATER 1911 AND NOT MSVC_CLANG)
string(APPEND CMAKE_CXX_FLAGS " /permissive-")
@@ -174,14 +184,41 @@ if(WITH_WINDOWS_SCCACHE AND CMAKE_VS_MSBUILD_COMMAND)
set(WITH_WINDOWS_SCCACHE Off)
endif()
+# Debug Symbol format
+# sccache # MSVC_ASAN # format # why
+# On # On # Z7 # sccache will only play nice with Z7
+# On # Off # Z7 # sccache will only play nice with Z7
+# Off # On # Zi # Asan will not play nice with Edit and Continue
+# Off # Off # ZI # Neither asan nor sscache is enabled Edit and Continue is available
+
+# Release Symbol format
+# sccache # MSVC_ASAN # format # why
+# On # On # Z7 # sccache will only play nice with Z7
+# On # Off # Z7 # sccache will only play nice with Z7
+# Off # On # Zi # Asan will not play nice with Edit and Continue
+# Off # Off # Zi # Edit and Continue disables some optimizations
+
+
if(WITH_WINDOWS_SCCACHE)
set(CMAKE_C_COMPILER_LAUNCHER sccache)
set(CMAKE_CXX_COMPILER_LAUNCHER sccache)
set(SYMBOL_FORMAT /Z7)
+ set(SYMBOL_FORMAT_RELEASE /Z7)
else()
unset(CMAKE_C_COMPILER_LAUNCHER)
unset(CMAKE_CXX_COMPILER_LAUNCHER)
- set(SYMBOL_FORMAT /ZI)
+ if(MSVC_ASAN)
+ set(SYMBOL_FORMAT /Z7)
+ set(SYMBOL_FORMAT_RELEASE /Z7)
+ else()
+ set(SYMBOL_FORMAT /ZI)
+ set(SYMBOL_FORMAT_RELEASE /Zi)
+ endif()
+endif()
+
+if(WITH_WINDOWS_PDB)
+ set(PDB_INFO_OVERRIDE_FLAGS "${SYMBOL_FORMAT_RELEASE}")
+ set(PDB_INFO_OVERRIDE_LINKER_FLAGS "/DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO")
endif()
string(APPEND CMAKE_CXX_FLAGS_DEBUG " /MDd ${SYMBOL_FORMAT}")
@@ -190,9 +227,11 @@ string(APPEND CMAKE_CXX_FLAGS_RELEASE " /MD ${PDB_INFO_OVERRIDE_FLAGS}")
string(APPEND CMAKE_C_FLAGS_RELEASE " /MD ${PDB_INFO_OVERRIDE_FLAGS}")
string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " /MD ${PDB_INFO_OVERRIDE_FLAGS}")
string(APPEND CMAKE_C_FLAGS_MINSIZEREL " /MD ${PDB_INFO_OVERRIDE_FLAGS}")
-string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " /MD ${SYMBOL_FORMAT}")
-string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " /MD ${SYMBOL_FORMAT}")
+string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " /MD ${SYMBOL_FORMAT_RELEASE}")
+string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " /MD ${SYMBOL_FORMAT_RELEASE}")
unset(SYMBOL_FORMAT)
+unset(SYMBOL_FORMAT_RELEASE)
+
# JMC is available on msvc 15.8 (1915) and up
if(MSVC_VERSION GREATER 1914 AND NOT MSVC_CLANG)
string(APPEND CMAKE_CXX_FLAGS_DEBUG " /JMC")
diff --git a/build_files/windows/configure_msbuild.cmd b/build_files/windows/configure_msbuild.cmd
index 4956f1e3ea1..be69f99a8e8 100644
--- a/build_files/windows/configure_msbuild.cmd
+++ b/build_files/windows/configure_msbuild.cmd
@@ -9,14 +9,10 @@ if "%BUILD_WITH_SCCACHE%"=="1" (
if "%WITH_CLANG%"=="1" (
set CLANG_CMAKE_ARGS=-T"llvm"
- if "%WITH_ASAN%"=="1" (
+)
+
+if "%WITH_ASAN%"=="1" (
set ASAN_CMAKE_ARGS=-DWITH_COMPILER_ASAN=On
- )
-) else (
- if "%WITH_ASAN%"=="1" (
- echo ASAN is only supported with clang.
- exit /b 1
- )
)
if "%WITH_PYDEBUG%"=="1" (
diff --git a/build_files/windows/configure_ninja.cmd b/build_files/windows/configure_ninja.cmd
index d68d94a3bcf..90085feb2bd 100644
--- a/build_files/windows/configure_ninja.cmd
+++ b/build_files/windows/configure_ninja.cmd
@@ -46,16 +46,10 @@ set LLVM_DIR=
set CFLAGS=-m64 -fmsc-version=1914
set CXXFLAGS=-m64 -fmsc-version=1914
)
- if "%WITH_ASAN%"=="1" (
- set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_COMPILER_ASAN=On
- )
)
if "%WITH_ASAN%"=="1" (
- if "%WITH_CLANG%" == "" (
- echo ASAN is only supported with clang.
- exit /b 1
- )
+ set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_COMPILER_ASAN=On
)
if NOT "%verbose%" == "" (
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index 5c6cf24a178..8be194a58a2 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -553,7 +553,7 @@ def example_extract_docstring(filepath):
line_no += 1
else:
file.close()
- return "", 0
+ return "", 0, False
for line in file:
line_no += 1
@@ -563,15 +563,17 @@ def example_extract_docstring(filepath):
text.append(line.rstrip())
line_no += 1
+ line_no_has_content = False
# Skip over blank lines so the Python code doesn't have blank lines at the top.
for line in file:
if line.strip():
+ line_no_has_content = True
break
line_no += 1
file.close()
- return "\n".join(text), line_no
+ return "\n".join(text), line_no, line_no_has_content
def title_string(text, heading_char, double=False):
@@ -590,16 +592,18 @@ def write_example_ref(ident, fw, example_id, ext="py"):
filepath = os.path.join("..", "examples", "%s.%s" % (example_id, ext))
filepath_full = os.path.join(os.path.dirname(fw.__self__.name), filepath)
- text, line_no = example_extract_docstring(filepath_full)
+ text, line_no, line_no_has_content = example_extract_docstring(filepath_full)
for line in text.split("\n"):
fw("%s\n" % (ident + line).rstrip())
fw("\n")
- fw("%s.. literalinclude:: %s\n" % (ident, filepath))
- if line_no > 0:
- fw("%s :lines: %d-\n" % (ident, line_no))
- fw("\n")
+ # Some files only contain a doc-string.
+ if line_no_has_content:
+ fw("%s.. literalinclude:: %s\n" % (ident, filepath))
+ if line_no > 0:
+ fw("%s :lines: %d-\n" % (ident, line_no))
+ fw("\n")
EXAMPLE_SET_USED.add(example_id)
else:
if bpy.app.debug:
@@ -1408,7 +1412,8 @@ def pyrna2sphinx(basepath):
else:
fw(" .. attribute:: %s\n\n" % prop.identifier)
if prop.description:
- fw(" %s\n\n" % prop.description)
+ write_indented_lines(" ", fw, prop.description, False)
+ fw("\n")
# special exception, can't use generic code here for enums
if prop.type == "enum":
diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt
index 235c2fa931a..824b2fb0e9c 100644
--- a/extern/CMakeLists.txt
+++ b/extern/CMakeLists.txt
@@ -109,3 +109,7 @@ endif()
if(WITH_MOD_FLUID)
add_subdirectory(mantaflow)
endif()
+
+if (WITH_COMPOSITOR)
+ add_subdirectory(smaa_areatex)
+endif()
diff --git a/extern/audaspace/CMakeLists.txt b/extern/audaspace/CMakeLists.txt
index fe1bf5dc742..1599c03cbad 100644
--- a/extern/audaspace/CMakeLists.txt
+++ b/extern/audaspace/CMakeLists.txt
@@ -42,6 +42,7 @@ set(SRC
src/devices/NULLDevice.cpp
src/devices/ReadDevice.cpp
src/devices/SoftwareDevice.cpp
+ src/devices/ThreadedDevice.cpp
src/Exception.cpp
src/file/File.cpp
src/file/FileManager.cpp
@@ -148,6 +149,7 @@ set(PUBLIC_HDR
include/devices/NULLDevice.h
include/devices/ReadDevice.h
include/devices/SoftwareDevice.h
+ include/devices/ThreadedDevice.h
include/Exception.h
include/file/File.h
include/file/FileManager.h
diff --git a/extern/audaspace/include/devices/SoftwareDevice.h b/extern/audaspace/include/devices/SoftwareDevice.h
index a350550048b..209be9941b1 100644
--- a/extern/audaspace/include/devices/SoftwareDevice.h
+++ b/extern/audaspace/include/devices/SoftwareDevice.h
@@ -255,6 +255,7 @@ protected:
/**
* This function tells the device, to start or pause playback.
* \param playing True if device should playback.
+ * \note This method is only called when the device is locked.
*/
virtual void playing(bool playing)=0;
diff --git a/extern/audaspace/include/devices/ThreadedDevice.h b/extern/audaspace/include/devices/ThreadedDevice.h
new file mode 100644
index 00000000000..36c2e68e36f
--- /dev/null
+++ b/extern/audaspace/include/devices/ThreadedDevice.h
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+/**
+ * @file ThreadedDevice.h
+ * @ingroup plugin
+ * The ThreadedDevice class.
+ */
+
+#include "devices/SoftwareDevice.h"
+
+#include <thread>
+
+AUD_NAMESPACE_BEGIN
+
+/**
+ * This device extends the SoftwareDevice with code for running mixing in a separate thread.
+ */
+class AUD_PLUGIN_API ThreadedDevice : public SoftwareDevice
+{
+private:
+ /**
+ * Whether there is currently playback.
+ */
+ bool m_playing;
+
+ /**
+ * Whether the current playback should stop.
+ */
+ bool m_stop;
+
+ /**
+ * The streaming thread.
+ */
+ std::thread m_thread;
+
+ /**
+ * Starts the streaming thread.
+ */
+ AUD_LOCAL void start();
+
+ /**
+ * Streaming thread main function.
+ */
+ AUD_LOCAL virtual void runMixingThread()=0;
+
+ // delete copy constructor and operator=
+ ThreadedDevice(const ThreadedDevice&) = delete;
+ ThreadedDevice& operator=(const ThreadedDevice&) = delete;
+
+protected:
+ virtual void playing(bool playing);
+
+ /**
+ * Empty default constructor. To setup the device call the function create()
+ * and to uninitialize call destroy().
+ */
+ ThreadedDevice();
+
+ /**
+ * Indicates that the mixing thread should be stopped.
+ * \return Whether the mixing thread should be stopping.
+ * \warning For thread safety, the device needs to be locked, when this method is called.
+ */
+ inline bool shouldStop() { return m_stop; }
+
+ /**
+ * This method needs to be called when the mixing thread is stopping.
+ * \warning For thread safety, the device needs to be locked, when this method is called.
+ */
+ inline void doStop() { m_stop = m_playing = false; }
+
+ /**
+ * Stops all playback and notifies the mixing thread to stop.
+ * \warning The device has to be unlocked to not run into a deadlock.
+ */
+ void stopMixingThread();
+};
+
+AUD_NAMESPACE_END
diff --git a/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp b/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp
index 0a50d5db2c7..3ffe97661d8 100644
--- a/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp
+++ b/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.cpp
@@ -27,9 +27,9 @@ void PulseAudioDevice::PulseAudio_state_callback(pa_context *context, void *data
{
PulseAudioDevice* device = (PulseAudioDevice*)data;
- device->m_state = AUD_pa_context_get_state(context);
+ std::lock_guard<ILockable> lock(*device);
- AUD_pa_threaded_mainloop_signal(device->m_mainloop, 0);
+ device->m_state = AUD_pa_context_get_state(context);
}
void PulseAudioDevice::PulseAudio_request(pa_stream *stream, size_t num_bytes, void *data)
@@ -68,29 +68,40 @@ void PulseAudioDevice::PulseAudio_underflow(pa_stream *stream, void *data)
}
}
-void PulseAudioDevice::playing(bool playing)
+void PulseAudioDevice::runMixingThread()
{
- m_playback = playing;
+ for(;;)
+ {
+ {
+ std::lock_guard<ILockable> lock(*this);
+
+ if(shouldStop())
+ {
+ AUD_pa_stream_cork(m_stream, 1, nullptr, nullptr);
+ doStop();
+ return;
+ }
+ }
+
+ if(AUD_pa_stream_is_corked(m_stream))
+ AUD_pa_stream_cork(m_stream, 0, nullptr, nullptr);
- AUD_pa_stream_cork(m_stream, playing ? 0 : 1, nullptr, nullptr);
+ AUD_pa_mainloop_iterate(m_mainloop, true, nullptr);
+ }
}
PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buffersize) :
- m_playback(false),
m_state(PA_CONTEXT_UNCONNECTED),
m_buffersize(buffersize),
m_underflows(0)
{
- m_mainloop = AUD_pa_threaded_mainloop_new();
+ m_mainloop = AUD_pa_mainloop_new();
- AUD_pa_threaded_mainloop_lock(m_mainloop);
-
- m_context = AUD_pa_context_new(AUD_pa_threaded_mainloop_get_api(m_mainloop), name.c_str());
+ m_context = AUD_pa_context_new(AUD_pa_mainloop_get_api(m_mainloop), name.c_str());
if(!m_context)
{
- AUD_pa_threaded_mainloop_unlock(m_mainloop);
- AUD_pa_threaded_mainloop_free(m_mainloop);
+ AUD_pa_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not connect to PulseAudio.");
}
@@ -99,26 +110,21 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
AUD_pa_context_connect(m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr);
- AUD_pa_threaded_mainloop_start(m_mainloop);
-
while(m_state != PA_CONTEXT_READY)
{
switch(m_state)
{
case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED:
- AUD_pa_threaded_mainloop_unlock(m_mainloop);
- AUD_pa_threaded_mainloop_stop(m_mainloop);
-
AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context);
- AUD_pa_threaded_mainloop_free(m_mainloop);
+ AUD_pa_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not connect to PulseAudio.");
break;
default:
- AUD_pa_threaded_mainloop_wait(m_mainloop);
+ AUD_pa_mainloop_iterate(m_mainloop, true, nullptr);
break;
}
}
@@ -166,13 +172,10 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
if(!m_stream)
{
- AUD_pa_threaded_mainloop_unlock(m_mainloop);
- AUD_pa_threaded_mainloop_stop(m_mainloop);
-
AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context);
- AUD_pa_threaded_mainloop_free(m_mainloop);
+ AUD_pa_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not create PulseAudio stream.");
}
@@ -188,32 +191,27 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
buffer_attr.prebuf = -1U;
buffer_attr.tlength = buffersize;
- if(AUD_pa_stream_connect_playback(m_stream, nullptr, &buffer_attr, static_cast<pa_stream_flags_t>(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr) < 0)
+ if(AUD_pa_stream_connect_playback(m_stream, nullptr, &buffer_attr, static_cast<pa_stream_flags_t>(PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr) < 0)
{
- AUD_pa_threaded_mainloop_unlock(m_mainloop);
- AUD_pa_threaded_mainloop_stop(m_mainloop);
-
AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context);
- AUD_pa_threaded_mainloop_free(m_mainloop);
+ AUD_pa_mainloop_free(m_mainloop);
AUD_THROW(DeviceException, "Could not connect PulseAudio stream.");
}
- AUD_pa_threaded_mainloop_unlock(m_mainloop);
-
create();
}
PulseAudioDevice::~PulseAudioDevice()
{
- AUD_pa_threaded_mainloop_stop(m_mainloop);
+ stopMixingThread();
AUD_pa_context_disconnect(m_context);
AUD_pa_context_unref(m_context);
- AUD_pa_threaded_mainloop_free(m_mainloop);
+ AUD_pa_mainloop_free(m_mainloop);
destroy();
}
diff --git a/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.h b/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.h
index 9efae5128b1..be34cc9032b 100644
--- a/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.h
+++ b/extern/audaspace/plugins/pulseaudio/PulseAudioDevice.h
@@ -26,7 +26,7 @@
* The PulseAudioDevice class.
*/
-#include "devices/SoftwareDevice.h"
+#include "devices/ThreadedDevice.h"
#include <pulse/pulseaudio.h>
@@ -35,15 +35,10 @@ AUD_NAMESPACE_BEGIN
/**
* This device plays back through PulseAudio, the simple direct media layer.
*/
-class AUD_PLUGIN_API PulseAudioDevice : public SoftwareDevice
+class AUD_PLUGIN_API PulseAudioDevice : public ThreadedDevice
{
private:
- /**
- * Whether there is currently playback.
- */
- volatile bool m_playback;
-
- pa_threaded_mainloop* m_mainloop;
+ pa_mainloop* m_mainloop;
pa_context* m_context;
pa_stream* m_stream;
pa_context_state_t m_state;
@@ -74,13 +69,15 @@ private:
*/
AUD_LOCAL static void PulseAudio_underflow(pa_stream* stream, void* data);
+ /**
+ * Streaming thread main function.
+ */
+ AUD_LOCAL void runMixingThread();
+
// delete copy constructor and operator=
PulseAudioDevice(const PulseAudioDevice&) = delete;
PulseAudioDevice& operator=(const PulseAudioDevice&) = delete;
-protected:
- virtual void playing(bool playing);
-
public:
/**
* Opens the PulseAudio audio device for playback.
diff --git a/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h b/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h
index 9cefbc0c7e2..4b9e1ffea2b 100644
--- a/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h
+++ b/extern/audaspace/plugins/pulseaudio/PulseAudioSymbols.h
@@ -24,18 +24,14 @@ PULSEAUDIO_SYMBOL(pa_context_unref);
PULSEAUDIO_SYMBOL(pa_stream_begin_write);
PULSEAUDIO_SYMBOL(pa_stream_connect_playback);
PULSEAUDIO_SYMBOL(pa_stream_cork);
+PULSEAUDIO_SYMBOL(pa_stream_is_corked);
PULSEAUDIO_SYMBOL(pa_stream_new);
PULSEAUDIO_SYMBOL(pa_stream_set_buffer_attr);
PULSEAUDIO_SYMBOL(pa_stream_set_underflow_callback);
PULSEAUDIO_SYMBOL(pa_stream_set_write_callback);
PULSEAUDIO_SYMBOL(pa_stream_write);
-PULSEAUDIO_SYMBOL(pa_threaded_mainloop_free);
-PULSEAUDIO_SYMBOL(pa_threaded_mainloop_get_api);
-PULSEAUDIO_SYMBOL(pa_threaded_mainloop_lock);
-PULSEAUDIO_SYMBOL(pa_threaded_mainloop_new);
-PULSEAUDIO_SYMBOL(pa_threaded_mainloop_signal);
-PULSEAUDIO_SYMBOL(pa_threaded_mainloop_start);
-PULSEAUDIO_SYMBOL(pa_threaded_mainloop_stop);
-PULSEAUDIO_SYMBOL(pa_threaded_mainloop_unlock);
-PULSEAUDIO_SYMBOL(pa_threaded_mainloop_wait);
+PULSEAUDIO_SYMBOL(pa_mainloop_free);
+PULSEAUDIO_SYMBOL(pa_mainloop_get_api);
+PULSEAUDIO_SYMBOL(pa_mainloop_new);
+PULSEAUDIO_SYMBOL(pa_mainloop_iterate);
diff --git a/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp b/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp
index 4f213dc8468..b4632ebb83e 100644
--- a/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp
+++ b/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp
@@ -31,159 +31,83 @@ template <class T> void SafeRelease(T **ppT)
}
}
-void WASAPIDevice::start()
-{
- lock();
-
- // thread is still running, we can abort stopping it
- if(m_stop)
- m_stop = false;
- // thread is not running, let's start it
- else if(!m_playing)
- {
- if(m_thread.joinable())
- m_thread.join();
-
- m_playing = true;
-
- m_thread = std::thread(&WASAPIDevice::updateStream, this);
- }
-
- unlock();
-}
-
-void WASAPIDevice::updateStream()
+void WASAPIDevice::runMixingThread()
{
UINT32 buffer_size;
+ UINT32 padding;
+ UINT32 length;
data_t* buffer;
- lock();
+ IAudioRenderClient* render_client = nullptr;
- if(FAILED(m_audio_client->GetBufferSize(&buffer_size)))
{
- m_playing = false;
- m_stop = false;
- unlock();
- return;
- }
+ std::lock_guard<ILockable> lock(*this);
- IAudioRenderClient* render_client = nullptr;
- const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
+ const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
- if(FAILED(m_audio_client->GetService(IID_IAudioRenderClient, reinterpret_cast<void**>(&render_client))))
- {
- m_playing = false;
- m_stop = false;
- unlock();
- return;
- }
+ if(FAILED(m_audio_client->GetBufferSize(&buffer_size)))
+ goto init_error;
- UINT32 padding;
+ if(FAILED(m_audio_client->GetService(IID_IAudioRenderClient, reinterpret_cast<void**>(&render_client))))
+ goto init_error;
- if(FAILED(m_audio_client->GetCurrentPadding(&padding)))
- {
- SafeRelease(&render_client);
- m_playing = false;
- m_stop = false;
- unlock();
- return;
- }
+ if(FAILED(m_audio_client->GetCurrentPadding(&padding)))
+ goto init_error;
- UINT32 length = buffer_size - padding;
+ length = buffer_size - padding;
- if(FAILED(render_client->GetBuffer(length, &buffer)))
- {
- SafeRelease(&render_client);
- m_playing = false;
- m_stop = false;
- unlock();
- return;
- }
+ if(FAILED(render_client->GetBuffer(length, &buffer)))
+ goto init_error;
- mix((data_t*)buffer, length);
+ mix((data_t*)buffer, length);
- if(FAILED(render_client->ReleaseBuffer(length, 0)))
- {
- SafeRelease(&render_client);
- m_playing = false;
- m_stop = false;
- unlock();
- return;
+ if(FAILED(render_client->ReleaseBuffer(length, 0)))
+ {
+ init_error:
+ SafeRelease(&render_client);
+ doStop();
+ return;
+ }
}
- unlock();
-
m_audio_client->Start();
auto sleepDuration = std::chrono::milliseconds(buffer_size * 1000 / int(m_specs.rate) / 2);
for(;;)
{
- lock();
-
- if(FAILED(m_audio_client->GetCurrentPadding(&padding)))
{
- m_audio_client->Stop();
- SafeRelease(&render_client);
- m_playing = false;
- m_stop = false;
- unlock();
- return;
- }
+ std::lock_guard<ILockable> lock(*this);
- length = buffer_size - padding;
+ if(FAILED(m_audio_client->GetCurrentPadding(&padding)))
+ goto stop_thread;
- if(FAILED(render_client->GetBuffer(length, &buffer)))
- {
- m_audio_client->Stop();
- SafeRelease(&render_client);
- m_playing = false;
- m_stop = false;
- unlock();
- return;
- }
+ length = buffer_size - padding;
- mix((data_t*)buffer, length);
+ if(FAILED(render_client->GetBuffer(length, &buffer)))
+ goto stop_thread;
- if(FAILED(render_client->ReleaseBuffer(length, 0)))
- {
- m_audio_client->Stop();
- SafeRelease(&render_client);
- m_playing = false;
- m_stop = false;
- unlock();
- return;
- }
+ mix((data_t*)buffer, length);
- // stop thread
- if(m_stop)
- {
- m_audio_client->Stop();
- SafeRelease(&render_client);
- m_playing = false;
- m_stop = false;
- unlock();
- return;
- }
+ if(FAILED(render_client->ReleaseBuffer(length, 0)))
+ goto stop_thread;
- unlock();
+ // stop thread
+ if(shouldStop())
+ {
+ stop_thread:
+ m_audio_client->Stop();
+ SafeRelease(&render_client);
+ doStop();
+ return;
+ }
+ }
std::this_thread::sleep_for(sleepDuration);
}
}
-void WASAPIDevice::playing(bool playing)
-{
- if((!m_playing || m_stop) && playing)
- start();
- else
- m_stop = true;
-}
-
WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
- m_playing(false),
- m_stop(false),
-
m_imm_device_enumerator(nullptr),
m_imm_device(nullptr),
m_audio_client(nullptr),
@@ -361,14 +285,7 @@ WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
WASAPIDevice::~WASAPIDevice()
{
- lock();
-
- stopAll();
-
- unlock();
-
- if(m_thread.joinable())
- m_thread.join();
+ stopMixingThread();
SafeRelease(&m_audio_client);
SafeRelease(&m_imm_device);
diff --git a/extern/audaspace/plugins/wasapi/WASAPIDevice.h b/extern/audaspace/plugins/wasapi/WASAPIDevice.h
index ae25a09c432..375f03bd255 100644
--- a/extern/audaspace/plugins/wasapi/WASAPIDevice.h
+++ b/extern/audaspace/plugins/wasapi/WASAPIDevice.h
@@ -26,7 +26,7 @@
* The WASAPIDevice class.
*/
-#include "devices/SoftwareDevice.h"
+#include "devices/ThreadedDevice.h"
#include <thread>
@@ -40,46 +40,23 @@ AUD_NAMESPACE_BEGIN
/**
* This device plays back through WASAPI, the Windows audio API.
*/
-class AUD_PLUGIN_API WASAPIDevice : public SoftwareDevice
+class AUD_PLUGIN_API WASAPIDevice : public ThreadedDevice
{
private:
- /**
- * Whether there is currently playback.
- */
- bool m_playing;
-
- /**
- * Whether the current playback should stop.
- */
- bool m_stop;
-
IMMDeviceEnumerator* m_imm_device_enumerator;
IMMDevice* m_imm_device;
IAudioClient* m_audio_client;
WAVEFORMATEXTENSIBLE m_wave_format_extensible;
/**
- * The streaming thread.
- */
- std::thread m_thread;
-
- /**
- * Starts the streaming thread.
- */
- AUD_LOCAL void start();
-
- /**
* Streaming thread main function.
*/
- AUD_LOCAL void updateStream();
+ AUD_LOCAL void runMixingThread();
// delete copy constructor and operator=
WASAPIDevice(const WASAPIDevice&) = delete;
WASAPIDevice& operator=(const WASAPIDevice&) = delete;
-protected:
- virtual void playing(bool playing);
-
public:
/**
* Opens the WASAPI audio device for playback.
diff --git a/extern/audaspace/src/devices/SoftwareDevice.cpp b/extern/audaspace/src/devices/SoftwareDevice.cpp
index c8c1c6081c2..7a2561515f4 100644
--- a/extern/audaspace/src/devices/SoftwareDevice.cpp
+++ b/extern/audaspace/src/devices/SoftwareDevice.cpp
@@ -737,7 +737,7 @@ void SoftwareDevice::mix(data_t* buffer, int length)
{
m_buffer.assureSize(length * AUD_SAMPLE_SIZE(m_specs));
- std::lock_guard<std::recursive_mutex> lock(m_mutex);
+ std::lock_guard<ILockable> lock(*this);
{
std::shared_ptr<SoftwareDevice::SoftwareHandle> sound;
@@ -880,7 +880,7 @@ std::shared_ptr<IHandle> SoftwareDevice::play(std::shared_ptr<IReader> reader, b
// play sound
std::shared_ptr<SoftwareDevice::SoftwareHandle> sound = std::shared_ptr<SoftwareDevice::SoftwareHandle>(new SoftwareDevice::SoftwareHandle(this, reader, pitch, resampler, mapper, keep));
- std::lock_guard<std::recursive_mutex> lock(m_mutex);
+ std::lock_guard<ILockable> lock(*this);
m_playingSounds.push_back(sound);
@@ -897,7 +897,7 @@ std::shared_ptr<IHandle> SoftwareDevice::play(std::shared_ptr<ISound> sound, boo
void SoftwareDevice::stopAll()
{
- std::lock_guard<std::recursive_mutex> lock(m_mutex);
+ std::lock_guard<ILockable> lock(*this);
while(!m_playingSounds.empty())
m_playingSounds.front()->stop();
diff --git a/extern/audaspace/src/devices/ThreadedDevice.cpp b/extern/audaspace/src/devices/ThreadedDevice.cpp
new file mode 100644
index 00000000000..44ceccb8a60
--- /dev/null
+++ b/extern/audaspace/src/devices/ThreadedDevice.cpp
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#include "devices/ThreadedDevice.h"
+
+#include <mutex>
+
+AUD_NAMESPACE_BEGIN
+
+void ThreadedDevice::start()
+{
+ std::lock_guard<ILockable> lock(*this);
+
+ // thread is still running, we can abort stopping it
+ if(m_stop)
+ m_stop = false;
+
+ // thread is not running, let's start it
+ else if(!m_playing)
+ {
+ if(m_thread.joinable())
+ m_thread.join();
+
+ m_playing = true;
+
+ m_thread = std::thread(&ThreadedDevice::runMixingThread, this);
+ }
+}
+
+void ThreadedDevice::playing(bool playing)
+{
+ if((!m_playing || m_stop) && playing)
+ start();
+ else
+ m_stop = true;
+}
+
+ThreadedDevice::ThreadedDevice() :
+ m_playing(false),
+ m_stop(false)
+{
+}
+
+void aud::ThreadedDevice::stopMixingThread()
+{
+ stopAll();
+
+ if(m_thread.joinable())
+ m_thread.join();
+}
+
+AUD_NAMESPACE_END
diff --git a/extern/smaa_areatex/CMakeLists.txt b/extern/smaa_areatex/CMakeLists.txt
new file mode 100644
index 00000000000..2386b0e7b79
--- /dev/null
+++ b/extern/smaa_areatex/CMakeLists.txt
@@ -0,0 +1,26 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2017, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): IRIE Shinsuke
+#
+# ***** END GPL LICENSE BLOCK *****
+
+add_executable(smaa_areatex smaa_areatex.cpp)
diff --git a/extern/smaa_areatex/README.blender b/extern/smaa_areatex/README.blender
new file mode 100644
index 00000000000..9c409142ae8
--- /dev/null
+++ b/extern/smaa_areatex/README.blender
@@ -0,0 +1,5 @@
+Project: smaa-cpp
+URL: https://github.com/iRi-E/smaa-cpp
+License: MIT
+Upstream version: 0.4.0
+Local modifications:
diff --git a/extern/smaa_areatex/smaa_areatex.cpp b/extern/smaa_areatex/smaa_areatex.cpp
new file mode 100644
index 00000000000..971706fd64d
--- /dev/null
+++ b/extern/smaa_areatex/smaa_areatex.cpp
@@ -0,0 +1,1208 @@
+/**
+ * Copyright (C) 2016-2017 IRIE Shinsuke
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * smaa_areatex.cpp version 0.4.0
+ *
+ * This is a part of smaa-cpp that is an implementation of
+ * Enhanced Subpixel Morphological Antialiasing (SMAA) written in C++.
+ *
+ * This program is C++ rewrite of AreaTex.py included in the original
+ * SMAA ditribution:
+ *
+ * https://github.com/iryoku/smaa/tree/master/Scripts
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include <cmath>
+
+/*------------------------------------------------------------------------------*/
+/* Type Definitions */
+
+class Int2;
+class Dbl2;
+
+class Int2 {
+public:
+ int x, y;
+
+ Int2() { this->x = this->y = 0; }
+ Int2(int x) { this->x = this->y = x; }
+ Int2(int x, int y) { this->x = x; this->y = y; }
+
+ operator Dbl2();
+
+ Int2 operator + (Int2 other) { return Int2(x + other.x, y + other.y); }
+ Int2 operator * (Int2 other) { return Int2(x * other.x, y * other.y); }
+};
+
+class Dbl2 {
+public:
+ double x, y;
+
+ Dbl2() { this->x = this->y = 0.0; }
+ Dbl2(double x) { this->x = this->y = x; }
+ Dbl2(double x, double y) { this->x = x; this->y = y; }
+
+ Dbl2 apply(double (* func)(double)) { return Dbl2(func(x), func(y)); }
+
+ operator Int2();
+
+ Dbl2 operator + (Dbl2 other) { return Dbl2(x + other.x, y + other.y); }
+ Dbl2 operator - (Dbl2 other) { return Dbl2(x - other.x, y - other.y); }
+ Dbl2 operator * (Dbl2 other) { return Dbl2(x * other.x, y * other.y); }
+ Dbl2 operator / (Dbl2 other) { return Dbl2(x / other.x, y / other.y); }
+ Dbl2 operator += (Dbl2 other) { return Dbl2(x += other.x, y += other.y); }
+ bool operator == (Dbl2 other) { return (x == other.x && y == other.y); }
+};
+
+Int2::operator Dbl2() { return Dbl2((double)x, (double)y); }
+Dbl2::operator Int2() { return Int2((int)x, (int)y); }
+
+/*------------------------------------------------------------------------------*/
+/* Data to Calculate Areatex */
+
+/* Texture sizes: */
+/* (it's quite possible that this is not easily configurable) */
+static const int SUBSAMPLES_ORTHO = 7;
+static const int SUBSAMPLES_DIAG = 5;
+static const int MAX_DIST_ORTHO_COMPAT = 16;
+static const int MAX_DIST_ORTHO = 20;
+static const int MAX_DIST_DIAG = 20;
+static const int TEX_SIZE_ORTHO = 80; /* 16 * 5 slots = 80 */
+static const int TEX_SIZE_DIAG = 80; /* 20 * 4 slots = 80 */
+
+/* Number of samples for calculating areas in the diagonal textures: */
+/* (diagonal areas are calculated using brute force sampling) */
+static const int SAMPLES_DIAG = 30;
+
+/* Maximum distance for smoothing u-shapes: */
+static const int SMOOTH_MAX_DISTANCE = 32;
+
+/*------------------------------------------------------------------------------*/
+/* Offset Tables */
+
+/* Offsets for subsample rendering */
+static const double subsample_offsets_ortho[SUBSAMPLES_ORTHO] = {
+ 0.0, /* 0 */
+ -0.25, /* 1 */
+ 0.25, /* 2 */
+ -0.125, /* 3 */
+ 0.125, /* 4 */
+ -0.375, /* 5 */
+ 0.375 /* 6 */
+};
+
+static const Dbl2 subsample_offsets_diag[SUBSAMPLES_DIAG] = {
+ { 0.00, 0.00}, /* 0 */
+ { 0.25, -0.25}, /* 1 */
+ {-0.25, 0.25}, /* 2 */
+ { 0.125, -0.125}, /* 3 */
+ {-0.125, 0.125} /* 4 */
+};
+
+/* Mapping offsets for placing each pattern subtexture into its place */
+enum edgesorthoIndices
+{
+ EDGESORTHO_NONE_NONE = 0,
+ EDGESORTHO_NONE_NEGA = 1,
+ EDGESORTHO_NONE_POSI = 2,
+ EDGESORTHO_NONE_BOTH = 3,
+ EDGESORTHO_NEGA_NONE = 4,
+ EDGESORTHO_NEGA_NEGA = 5,
+ EDGESORTHO_NEGA_POSI = 6,
+ EDGESORTHO_NEGA_BOTH = 7,
+ EDGESORTHO_POSI_NONE = 8,
+ EDGESORTHO_POSI_NEGA = 9,
+ EDGESORTHO_POSI_POSI = 10,
+ EDGESORTHO_POSI_BOTH = 11,
+ EDGESORTHO_BOTH_NONE = 12,
+ EDGESORTHO_BOTH_NEGA = 13,
+ EDGESORTHO_BOTH_POSI = 14,
+ EDGESORTHO_BOTH_BOTH = 15,
+};
+
+static const Int2 edgesortho_compat[16] = {
+ {0, 0}, {0, 1}, {0, 3}, {0, 4}, {1, 0}, {1, 1}, {1, 3}, {1, 4},
+ {3, 0}, {3, 1}, {3, 3}, {3, 4}, {4, 0}, {4, 1}, {4, 3}, {4, 4}
+};
+
+static const Int2 edgesortho[16] = {
+ {0, 0}, {0, 1}, {0, 2}, {0, 3}, {1, 0}, {1, 1}, {1, 2}, {1, 3},
+ {2, 0}, {2, 1}, {2, 2}, {2, 3}, {3, 0}, {3, 1}, {3, 2}, {3, 3}
+};
+
+enum edgesdiagIndices
+{
+ EDGESDIAG_NONE_NONE = 0,
+ EDGESDIAG_NONE_VERT = 1,
+ EDGESDIAG_NONE_HORZ = 2,
+ EDGESDIAG_NONE_BOTH = 3,
+ EDGESDIAG_VERT_NONE = 4,
+ EDGESDIAG_VERT_VERT = 5,
+ EDGESDIAG_VERT_HORZ = 6,
+ EDGESDIAG_VERT_BOTH = 7,
+ EDGESDIAG_HORZ_NONE = 8,
+ EDGESDIAG_HORZ_VERT = 9,
+ EDGESDIAG_HORZ_HORZ = 10,
+ EDGESDIAG_HORZ_BOTH = 11,
+ EDGESDIAG_BOTH_NONE = 12,
+ EDGESDIAG_BOTH_VERT = 13,
+ EDGESDIAG_BOTH_HORZ = 14,
+ EDGESDIAG_BOTH_BOTH = 15,
+};
+
+static const Int2 edgesdiag[16] = {
+ {0, 0}, {0, 1}, {0, 2}, {0, 3}, {1, 0}, {1, 1}, {1, 2}, {1, 3},
+ {2, 0}, {2, 1}, {2, 2}, {2, 3}, {3, 0}, {3, 1}, {3, 2}, {3, 3}
+};
+
+/*------------------------------------------------------------------------------*/
+/* Miscellaneous Utility Functions */
+
+/* Linear interpolation: */
+static Dbl2 lerp(Dbl2 a, Dbl2 b, double p)
+{
+ return a + (b - a) * Dbl2(p);
+}
+
+/* Saturates a value to [0..1] range: */
+static double saturate(double x)
+{
+ return 0.0 < x ? (x < 1.0 ? x : 1.0) : 0.0;
+}
+
+/*------------------------------------------------------------------------------*/
+/* Horizontal/Vertical Areas */
+
+class AreaOrtho {
+ double m_data[SUBSAMPLES_ORTHO][TEX_SIZE_ORTHO][TEX_SIZE_ORTHO][2];
+ bool m_compat;
+ bool m_orig_u;
+public:
+ AreaOrtho(bool compat, bool orig_u) : m_compat(compat), m_orig_u(orig_u) {}
+
+ double *getData() { return (double *)&m_data; }
+ Dbl2 getPixel(int offset_index, Int2 coords) {
+ return Dbl2(m_data[offset_index][coords.y][coords.x][0],
+ m_data[offset_index][coords.y][coords.x][1]);
+ }
+
+ void areaTex(int offset_index);
+private:
+ void putPixel(int offset_index, Int2 coords, Dbl2 pixel) {
+ m_data[offset_index][coords.y][coords.x][0] = pixel.x;
+ m_data[offset_index][coords.y][coords.x][1] = pixel.y;
+ }
+
+ Dbl2 smoothArea(double d, Dbl2 a1, Dbl2 a2);
+ Dbl2 makeQuad(int x, double d, double o);
+ Dbl2 area(Dbl2 p1, Dbl2 p2, int x);
+ Dbl2 calculate(int pattern, int left, int right, double offset);
+};
+
+/* Smoothing function for small u-patterns: */
+Dbl2 AreaOrtho::smoothArea(double d, Dbl2 a1, Dbl2 a2)
+{
+ Dbl2 b1 = (a1 * Dbl2(2.0)).apply(sqrt) * Dbl2(0.5);
+ Dbl2 b2 = (a2 * Dbl2(2.0)).apply(sqrt) * Dbl2(0.5);
+ double p = saturate(d / (double)SMOOTH_MAX_DISTANCE);
+ return lerp(b1, a1, p) + lerp(b2, a2, p);
+}
+
+/* Smoothing u-patterns by quadratic function: */
+Dbl2 AreaOrtho::makeQuad(int x, double d, double o)
+{
+ double r = (double)x;
+
+ /* fmin() below is a trick to smooth tiny u-patterns: */
+ return Dbl2(r, (1.0 - fmin(4.0, d) * r * (d - r) / (d * d)) * o);
+}
+
+/* Calculates the area under the line p1->p2, for the pixel x..x+1: */
+Dbl2 AreaOrtho::area(Dbl2 p1, Dbl2 p2, int x)
+{
+ Dbl2 d = p2 - p1;
+ double x1 = (double)x;
+ double x2 = x1 + 1.0;
+
+ if ((x1 >= p1.x && x1 < p2.x) || (x2 > p1.x && x2 <= p2.x)) { /* inside? */
+ double y1 = p1.y + (x1 - p1.x) * d.y / d.x;
+ double y2 = p1.y + (x2 - p1.x) * d.y / d.x;
+
+ if ((copysign(1.0, y1) == copysign(1.0, y2) ||
+ fabs(y1) < 1e-4 || fabs(y2) < 1e-4)) { /* trapezoid? */
+ double a = (y1 + y2) / 2.0;
+ if (a < 0.0)
+ return Dbl2(fabs(a), 0.0);
+ else
+ return Dbl2(0.0, fabs(a));
+ }
+ else { /* Then, we got two triangles: */
+ double x = p1.x - p1.y * d.x / d.y, xi;
+ double a1 = x > p1.x ? y1 * modf(x, &xi) / 2.0 : 0.0;
+ double a2 = x < p2.x ? y2 * (1.0 - modf(x, &xi)) / 2.0 : 0.0;
+ double a = fabs(a1) > fabs(a2) ? a1 : -a2;
+ if (a < 0.0)
+ return Dbl2(fabs(a1), fabs(a2));
+ else
+ return Dbl2(fabs(a2), fabs(a1));
+ }
+ }
+ else
+ return Dbl2(0.0, 0.0);
+}
+
+/* Calculates the area for a given pattern and distances to the left and to the */
+/* right, biased by an offset: */
+Dbl2 AreaOrtho::calculate(int pattern, int left, int right, double offset)
+{
+ Dbl2 a1, a2;
+
+ /*
+ * o1 |
+ * .-------´
+ * o2 |
+ *
+ * <---d--->
+ */
+ double d = (double)(left + right + 1);
+
+ double o1 = 0.5 + offset;
+ double o2 = 0.5 + offset - 1.0;
+
+ switch (pattern) {
+ case EDGESORTHO_NONE_NONE:
+ {
+ /*
+ *
+ * ------
+ *
+ */
+ return Dbl2(0.0, 0.0);
+ break;
+ }
+ case EDGESORTHO_POSI_NONE:
+ {
+ /*
+ *
+ * .------
+ * |
+ *
+ * We only offset L patterns in the crossing edge side, to make it
+ * converge with the unfiltered pattern 0 (we don't want to filter the
+ * pattern 0 to avoid artifacts).
+ */
+ if (left <= right)
+ return area(Dbl2(0.0, o2), Dbl2(d / 2.0, 0.0), left);
+ else
+ return Dbl2(0.0, 0.0);
+ break;
+ }
+ case EDGESORTHO_NONE_POSI:
+ {
+ /*
+ *
+ * ------.
+ * |
+ */
+ if (left >= right)
+ return area(Dbl2(d / 2.0, 0.0), Dbl2(d, o2), left);
+ else
+ return Dbl2(0.0, 0.0);
+ break;
+ }
+ case EDGESORTHO_POSI_POSI:
+ {
+ /*
+ *
+ * .------.
+ * | |
+ */
+ if (m_orig_u) {
+ a1 = area(Dbl2(0.0, o2), Dbl2(d / 2.0, 0.0), left);
+ a2 = area(Dbl2(d / 2.0, 0.0), Dbl2(d, o2), left);
+ return smoothArea(d, a1, a2);
+ }
+ else
+ return area(makeQuad(left, d, o2), makeQuad(left + 1, d, o2), left);
+ break;
+ }
+ case EDGESORTHO_NEGA_NONE:
+ {
+ /*
+ * |
+ * `------
+ *
+ */
+ if (left <= right)
+ return area(Dbl2(0.0, o1), Dbl2(d / 2.0, 0.0), left);
+ else
+ return Dbl2(0.0, 0.0);
+ break;
+ }
+ case EDGESORTHO_BOTH_NONE:
+ {
+ /*
+ * |
+ * +------
+ * |
+ */
+ return Dbl2(0.0, 0.0);
+ break;
+ }
+ case EDGESORTHO_NEGA_POSI:
+ {
+ /*
+ * |
+ * `------.
+ * |
+ *
+ * A problem of not offseting L patterns (see above), is that for certain
+ * max search distances, the pixels in the center of a Z pattern will
+ * detect the full Z pattern, while the pixels in the sides will detect a
+ * L pattern. To avoid discontinuities, we blend the full offsetted Z
+ * revectorization with partially offsetted L patterns.
+ */
+ if (fabs(offset) > 0.0) {
+ a1 = area(Dbl2(0.0, o1), Dbl2(d, o2), left);
+ a2 = area(Dbl2(0.0, o1), Dbl2(d / 2.0, 0.0), left);
+ a2 += area(Dbl2(d / 2.0, 0.0), Dbl2(d, o2), left);
+ return (a1 + a2) / Dbl2(2.0);
+ }
+ else
+ return area(Dbl2(0.0, o1), Dbl2(d, o2), left);
+ break;
+ }
+ case EDGESORTHO_BOTH_POSI:
+ {
+ /*
+ * |
+ * +------.
+ * | |
+ */
+ return area(Dbl2(0.0, o1), Dbl2(d, o2), left);
+ break;
+ }
+ case EDGESORTHO_NONE_NEGA:
+ {
+ /*
+ * |
+ * ------´
+ *
+ */
+ if (left >= right)
+ return area(Dbl2(d / 2.0, 0.0), Dbl2(d, o1), left);
+ else
+ return Dbl2(0.0, 0.0);
+ break;
+ }
+ case EDGESORTHO_POSI_NEGA:
+ {
+ /*
+ * |
+ * .------´
+ * |
+ */
+ if (fabs(offset) > 0.0) {
+ a1 = area(Dbl2(0.0, o2), Dbl2(d, o1), left);
+ a2 = area(Dbl2(0.0, o2), Dbl2(d / 2.0, 0.0), left);
+ a2 += area(Dbl2(d / 2.0, 0.0), Dbl2(d, o1), left);
+ return (a1 + a2) / Dbl2(2.0);
+ }
+ else
+ return area(Dbl2(0.0, o2), Dbl2(d, o1), left);
+ break;
+ }
+ case EDGESORTHO_NONE_BOTH:
+ {
+ /*
+ * |
+ * ------+
+ * |
+ */
+ return Dbl2(0.0, 0.0);
+ break;
+ }
+ case EDGESORTHO_POSI_BOTH:
+ {
+ /*
+ * |
+ * .------+
+ * | |
+ */
+ return area(Dbl2(0.0, o2), Dbl2(d, o1), left);
+ break;
+ }
+ case EDGESORTHO_NEGA_NEGA:
+ {
+ /*
+ * | |
+ * `------´
+ *
+ */
+ if (m_orig_u) {
+ a1 = area(Dbl2(0.0, o1), Dbl2(d / 2.0, 0.0), left);
+ a2 = area(Dbl2(d / 2.0, 0.0), Dbl2(d, o1), left);
+ return smoothArea(d, a1, a2);
+ }
+ else
+ return area(makeQuad(left, d, o1), makeQuad(left + 1, d, o1), left);
+ break;
+ }
+ case EDGESORTHO_BOTH_NEGA:
+ {
+ /*
+ * | |
+ * +------´
+ * |
+ */
+ return area(Dbl2(0.0, o2), Dbl2(d, o1), left);
+ break;
+ }
+ case EDGESORTHO_NEGA_BOTH:
+ {
+ /*
+ * | |
+ * `------+
+ * |
+ */
+ return area(Dbl2(0.0, o1), Dbl2(d, o2), left);
+ break;
+ }
+ case EDGESORTHO_BOTH_BOTH:
+ {
+ /*
+ * | |
+ * +------+
+ * | |
+ */
+ return Dbl2(0.0, 0.0);
+ break;
+ }
+ }
+
+ return Dbl2(0.0, 0.0);
+}
+
+/*------------------------------------------------------------------------------*/
+/* Diagonal Areas */
+
+class AreaDiag {
+ double m_data[SUBSAMPLES_DIAG][TEX_SIZE_DIAG][TEX_SIZE_DIAG][2];
+ bool m_numeric;
+ bool m_orig_u;
+public:
+ AreaDiag(bool numeric, bool orig_u) : m_numeric(numeric), m_orig_u(orig_u) {}
+
+ double *getData() { return (double *)&m_data; }
+ Dbl2 getPixel(int offset_index, Int2 coords) {
+ return Dbl2(m_data[offset_index][coords.y][coords.x][0],
+ m_data[offset_index][coords.y][coords.x][1]);
+ }
+
+ void areaTex(int offset_index);
+private:
+ void putPixel(int offset_index, Int2 coords, Dbl2 pixel) {
+ m_data[offset_index][coords.y][coords.x][0] = pixel.x;
+ m_data[offset_index][coords.y][coords.x][1] = pixel.y;
+ }
+
+ double area1(Dbl2 p1, Dbl2 p2, Int2 p);
+ Dbl2 area(Dbl2 p1, Dbl2 p2, int left);
+ Dbl2 areaTriangle(Dbl2 p1L, Dbl2 p2L, Dbl2 p1R, Dbl2 p2R, int left);
+ Dbl2 calculate(int pattern, int left, int right, Dbl2 offset);
+};
+
+/* Calculates the area under the line p1->p2 for the pixel 'p' using brute */
+/* force sampling: */
+/* (quick and dirty solution, but it works) */
+double AreaDiag::area1(Dbl2 p1, Dbl2 p2, Int2 p)
+{
+ if (p1 == p2)
+ return 1.0;
+
+ double xm = (p1.x + p2.x) / 2.0, ym = (p1.y + p2.y) / 2.0;
+ double a = p2.y - p1.y;
+ double b = p1.x - p2.x;
+ int count = 0;
+
+ for (int ix = 0; ix < SAMPLES_DIAG; ix++) {
+ double x = (double)p.x + (double)ix / (double)(SAMPLES_DIAG - 1);
+ for (int iy = 0; iy < SAMPLES_DIAG; iy++) {
+ double y = (double)p.y + (double)iy / (double)(SAMPLES_DIAG - 1);
+ if (a * (x - xm) + b * (y - ym) > 0.0) /* inside? */
+ count++;
+ }
+ }
+ return (double)count / (double)(SAMPLES_DIAG * SAMPLES_DIAG);
+}
+
+/* Calculates the area under the line p1->p2: */
+/* (includes the pixel and its opposite) */
+Dbl2 AreaDiag::area(Dbl2 p1, Dbl2 p2, int left)
+{
+ if (m_numeric) {
+ double a1 = area1(p1, p2, Int2(1, 0) + Int2(left));
+ double a2 = area1(p1, p2, Int2(1, 1) + Int2(left));
+ return Dbl2(1.0 - a1, a2);
+ }
+
+ /* Calculates the area under the line p1->p2 for the pixel 'p' analytically */
+ Dbl2 d = p2 - p1;
+ if (d.x == 0.0)
+ return Dbl2(0.0, 1.0);
+
+ double x1 = (double)(1 + left);
+ double x2 = x1 + 1.0;
+ double ymid = x1;
+ double xtop = p1.x + (ymid + 1.0 - p1.y) * d.x / d.y;
+ double xmid = p1.x + (ymid - p1.y) * d.x / d.y;
+ double xbot = p1.x + (ymid - 1.0 - p1.y) * d.x / d.y;
+
+ double y1 = p1.y + (x1 - p1.x) * d.y / d.x;
+ double y2 = p1.y + (x2 - p1.x) * d.y / d.x;
+ double fy1 = y1 - floor(y1);
+ double fy2 = y2 - floor(y2);
+ int iy1 = (int)floor(y1 - ymid);
+ int iy2 = (int)floor(y2 - ymid);
+
+ if (iy1 <= -2) {
+ if (iy2 == -1)
+ return Dbl2(1.0 - (x2 - xbot) * fy2 * 0.5, 0.0);
+ else if (iy2 == 0)
+ return Dbl2((xmid + xbot) * 0.5 - x1, (x2 - xmid) * fy2 * 0.5);
+ else if (iy2 >= 1)
+ return Dbl2((xmid + xbot) * 0.5 - x1, x2 - (xtop + xmid) * 0.5);
+ else /* iy2 < -1 */
+ return Dbl2(1.0, 0.0);
+ }
+ else if (iy1 == -1) {
+ if (iy2 == -1)
+ return Dbl2(1.0 - (fy1 + fy2) * 0.5, 0.0);
+ else if (iy2 == 0)
+ return Dbl2((xmid - x1) * (1.0 - fy1) * 0.5, (x2 - xmid) * fy2 * 0.5);
+ else if (iy2 >= 1)
+ return Dbl2((xmid - x1) * (1.0 - fy1) * 0.5, x2 - (xtop + xmid) * 0.5);
+ else /* iy2 < -1 */
+ return Dbl2(1.0 - (xbot - x1) * fy1 * 0.5, 0.0);
+ }
+ else if (iy1 == 0) {
+ if (iy2 == -1)
+ return Dbl2((x2 - xmid) * (1.0 - fy2) * 0.5, (xmid - x1) * fy1 * 0.5);
+ else if (iy2 == 0)
+ return Dbl2(0.0, (fy1 + fy2) * 0.5);
+ else if (iy2 >= 1)
+ return Dbl2(0.0, 1.0 - (xtop - x1) * (1.0 - fy1) * 0.5);
+ else /* iy2 < -1 */
+ return Dbl2(x2 - (xmid + xbot) * 0.5, (xmid - x1) * fy1 * 0.5);
+ }
+ else { /* iy1 > 0 */
+ if (iy2 == -1)
+ return Dbl2((x2 - xtop) * (1.0 - fy2) * 0.5, (xtop + xmid) * 0.5 - x1);
+ else if (iy2 == 0)
+ return Dbl2(0.0, 1.0 - (x1 - xtop) * (1.0 - fy2) * 0.5);
+ else if (iy2 >= 1)
+ return Dbl2(0.0, 1.0);
+ else /* iy2 < -1 */
+ return Dbl2(x2 - (xmid + xbot) * 0.5, (xtop + xmid) * 0.5 - x1);
+ }
+}
+
+/* Calculate u-patterns using a triangle: */
+Dbl2 AreaDiag::areaTriangle(Dbl2 p1L, Dbl2 p2L, Dbl2 p1R, Dbl2 p2R, int left)
+{
+ double x1 = (double)(1 + left);
+ double x2 = x1 + 1.0;
+
+ Dbl2 dL = p2L - p1L;
+ Dbl2 dR = p2R - p1R;
+ double xm = ((p1L.x * dL.y / dL.x - p1L.y) - (p1R.x * dR.y / dR.x - p1R.y)) / (dL.y / dL.x - dR.y / dR.x);
+
+ double y1 = (x1 < xm) ? p1L.y + (x1 - p1L.x) * dL.y / dL.x : p1R.y + (x1 - p1R.x) * dR.y / dR.x;
+ double y2 = (x2 < xm) ? p1L.y + (x2 - p1L.x) * dL.y / dL.x : p1R.y + (x2 - p1R.x) * dR.y / dR.x;
+
+ return area(Dbl2(x1, y1), Dbl2(x2, y2), left);
+}
+
+/* Calculates the area for a given pattern and distances to the left and to the */
+/* right, biased by an offset: */
+Dbl2 AreaDiag::calculate(int pattern, int left, int right, Dbl2 offset)
+{
+ Dbl2 a1, a2;
+
+ double d = (double)(left + right + 1);
+
+ /*
+ * There is some Black Magic around diagonal area calculations. Unlike
+ * orthogonal patterns, the 'null' pattern (one without crossing edges) must be
+ * filtered, and the ends of both the 'null' and L patterns are not known: L
+ * and U patterns have different endings, and we don't know what is the
+ * adjacent pattern. So, what we do is calculate a blend of both possibilites.
+ */
+ switch (pattern) {
+ case EDGESDIAG_NONE_NONE:
+ {
+ /*
+ *
+ * .-´
+ * .-´
+ * .-´
+ * .-´
+ * ´
+ *
+ */
+ a1 = area(Dbl2(1.0, 1.0), Dbl2(1.0, 1.0) + Dbl2(d), left); /* 1st possibility */
+ a2 = area(Dbl2(1.0, 0.0), Dbl2(1.0, 0.0) + Dbl2(d), left); /* 2nd possibility */
+ return (a1 + a2) / Dbl2(2.0); /* Blend them */
+ break;
+ }
+ case EDGESDIAG_VERT_NONE:
+ {
+ /*
+ *
+ * .-´
+ * .-´
+ * .-´
+ * .-´
+ * |
+ * |
+ */
+ a1 = area(Dbl2(1.0, 0.0) + offset, Dbl2(0.0, 0.0) + Dbl2(d), left);
+ a2 = area(Dbl2(1.0, 0.0) + offset, Dbl2(1.0, 0.0) + Dbl2(d), left);
+ return (a1 + a2) / Dbl2(2.0);
+ break;
+ }
+ case EDGESDIAG_NONE_HORZ:
+ {
+ /*
+ *
+ * .----
+ * .-´
+ * .-´
+ * .-´
+ * ´
+ *
+ */
+ a1 = area(Dbl2(0.0, 0.0), Dbl2(1.0, 0.0) + Dbl2(d) + offset, left);
+ a2 = area(Dbl2(1.0, 0.0), Dbl2(1.0, 0.0) + Dbl2(d) + offset, left);
+ return (a1 + a2) / Dbl2(2.0);
+ break;
+ }
+ case EDGESDIAG_VERT_HORZ:
+ {
+ /*
+ *
+ * .----
+ * .-´
+ * .-´
+ * .-´
+ * |
+ * |
+ */
+ if (m_orig_u)
+ return area(Dbl2(1.0, 0.0) + offset, Dbl2(1.0, 0.0) + Dbl2(d) + offset, left);
+ else
+ return areaTriangle(Dbl2(1.0, 0.0) + offset, Dbl2(1.0, 1.0) + Dbl2(d),
+ Dbl2(0.0, 0.0), Dbl2(1.0, 0.0) + Dbl2(d) + offset, left);
+ break;
+ }
+ case EDGESDIAG_HORZ_NONE:
+ {
+ /*
+ *
+ * .-´
+ * .-´
+ * .-´
+ * ----´
+ *
+ *
+ */
+ a1 = area(Dbl2(1.0, 1.0) + offset, Dbl2(0.0, 0.0) + Dbl2(d), left);
+ a2 = area(Dbl2(1.0, 1.0) + offset, Dbl2(1.0, 0.0) + Dbl2(d), left);
+ return (a1 + a2) / Dbl2(2.0);
+ break;
+ }
+ case EDGESDIAG_BOTH_NONE:
+ {
+ /*
+ *
+ * .-´
+ * .-´
+ * .-´
+ * --.-´
+ * |
+ * |
+ */
+ a1 = area(Dbl2(1.0, 1.0) + offset, Dbl2(0.0, 0.0) + Dbl2(d), left);
+ a2 = area(Dbl2(1.0, 0.0) + offset, Dbl2(1.0, 0.0) + Dbl2(d), left);
+ return (a1 + a2) / Dbl2(2.0);
+ break;
+ }
+ case EDGESDIAG_HORZ_HORZ:
+ {
+ /*
+ *
+ * .----
+ * .-´
+ * .-´
+ * ----´
+ *
+ *
+ */
+ return area(Dbl2(1.0, 1.0) + offset, Dbl2(1.0, 0.0) + Dbl2(d) + offset, left);
+ break;
+ }
+ case EDGESDIAG_BOTH_HORZ:
+ {
+ /*
+ *
+ * .----
+ * .-´
+ * .-´
+ * --.-´
+ * |
+ * |
+ */
+ a1 = area(Dbl2(1.0, 1.0) + offset, Dbl2(1.0, 0.0) + Dbl2(d) + offset, left);
+ a2 = area(Dbl2(1.0, 0.0) + offset, Dbl2(1.0, 0.0) + Dbl2(d) + offset, left);
+ return (a1 + a2) / Dbl2(2.0);
+ break;
+ }
+ case EDGESDIAG_NONE_VERT:
+ {
+ /*
+ * |
+ * |
+ * .-´
+ * .-´
+ * .-´
+ * ´
+ *
+ */
+ a1 = area(Dbl2(0.0, 0.0), Dbl2(1.0, 1.0) + Dbl2(d) + offset, left);
+ a2 = area(Dbl2(1.0, 0.0), Dbl2(1.0, 1.0) + Dbl2(d) + offset, left);
+ return (a1 + a2) / Dbl2(2.0);
+ break;
+ }
+ case EDGESDIAG_VERT_VERT:
+ {
+ /*
+ * |
+ * |
+ * .-´
+ * .-´
+ * .-´
+ * |
+ * |
+ */
+ return area(Dbl2(1.0, 0.0) + offset, Dbl2(1.0, 1.0) + Dbl2(d) + offset, left);
+ break;
+ }
+ case EDGESDIAG_NONE_BOTH:
+ {
+ /*
+ * |
+ * .----
+ * .-´
+ * .-´
+ * .-´
+ * ´
+ *
+ */
+ a1 = area(Dbl2(0.0, 0.0), Dbl2(1.0, 1.0) + Dbl2(d) + offset, left);
+ a2 = area(Dbl2(1.0, 0.0), Dbl2(1.0, 0.0) + Dbl2(d) + offset, left);
+ return (a1 + a2) / Dbl2(2.0);
+ break;
+ }
+ case EDGESDIAG_VERT_BOTH:
+ {
+ /*
+ * |
+ * .----
+ * .-´
+ * .-´
+ * .-´
+ * |
+ * |
+ */
+ a1 = area(Dbl2(1.0, 0.0) + offset, Dbl2(1.0, 1.0) + Dbl2(d) + offset, left);
+ a2 = area(Dbl2(1.0, 0.0) + offset, Dbl2(1.0, 0.0) + Dbl2(d) + offset, left);
+ return (a1 + a2) / Dbl2(2.0);
+ break;
+ }
+ case EDGESDIAG_HORZ_VERT:
+ {
+ /*
+ * |
+ * |
+ * .-´
+ * .-´
+ * ----´
+ *
+ *
+ */
+ if (m_orig_u)
+ return area(Dbl2(1.0, 1.0) + offset, Dbl2(1.0, 1.0) + Dbl2(d) + offset, left);
+ else
+ return areaTriangle(Dbl2(1.0, 1.0) + offset, Dbl2(2.0, 1.0) + Dbl2(d),
+ Dbl2(1.0, 0.0), Dbl2(1.0, 1.0) + Dbl2(d) + offset, left);
+ break;
+ }
+ case EDGESDIAG_BOTH_VERT:
+ {
+ /*
+ * |
+ * |
+ * .-´
+ * .-´
+ * --.-´
+ * |
+ * |
+ */
+ a1 = area(Dbl2(1.0, 1.0) + offset, Dbl2(1.0, 1.0) + Dbl2(d) + offset, left);
+ a2 = area(Dbl2(1.0, 0.0) + offset, Dbl2(1.0, 1.0) + Dbl2(d) + offset, left);
+ return (a1 + a2) / Dbl2(2.0);
+ break;
+ }
+ case EDGESDIAG_HORZ_BOTH:
+ {
+ /*
+ * |
+ * .----
+ * .-´
+ * .-´
+ * ----´
+ *
+ *
+ */
+ a1 = area(Dbl2(1.0, 1.0) + offset, Dbl2(1.0, 1.0) + Dbl2(d) + offset, left);
+ a2 = area(Dbl2(1.0, 1.0) + offset, Dbl2(1.0, 0.0) + Dbl2(d) + offset, left);
+ return (a1 + a2) / Dbl2(2.0);
+ break;
+ }
+ case EDGESDIAG_BOTH_BOTH:
+ {
+ /*
+ * |
+ * .----
+ * .-´
+ * .-´
+ * --.-´
+ * |
+ * |
+ */
+ a1 = area(Dbl2(1.0, 1.0) + offset, Dbl2(1.0, 1.0) + Dbl2(d) + offset, left);
+ a2 = area(Dbl2(1.0, 0.0) + offset, Dbl2(1.0, 0.0) + Dbl2(d) + offset, left);
+ return (a1 + a2) / Dbl2(2.0);
+ break;
+ }
+ }
+
+ return Dbl2(0.0, 0.0);
+}
+
+/*------------------------------------------------------------------------------*/
+/* Main Loops */
+
+void AreaOrtho::areaTex(int offset_index)
+{
+ double offset = subsample_offsets_ortho[offset_index];
+ int max_dist = m_compat ? MAX_DIST_ORTHO_COMPAT : MAX_DIST_ORTHO;
+
+ for (int pattern = 0; pattern < 16; pattern++) {
+ Int2 e = Int2(max_dist) * (m_compat ? edgesortho_compat : edgesortho)[pattern];
+ for (int left = 0; left < max_dist; left++) {
+ for (int right = 0; right < max_dist; right++) {
+ Dbl2 p = calculate(pattern, left * left, right * right, offset);
+ Int2 coords = e + Int2(left, right);
+
+ putPixel(offset_index, coords, p);
+ }
+ }
+ }
+ return;
+}
+
+void AreaDiag::areaTex(int offset_index)
+{
+ Dbl2 offset = subsample_offsets_diag[offset_index];
+
+ for (int pattern = 0; pattern < 16; pattern++) {
+ Int2 e = Int2(MAX_DIST_DIAG) * edgesdiag[pattern];
+ for (int left = 0; left < MAX_DIST_DIAG; left++) {
+ for (int right = 0; right < MAX_DIST_DIAG; right++) {
+ Dbl2 p = calculate(pattern, left, right, offset);
+ Int2 coords = e + Int2(left, right);
+
+ putPixel(offset_index, coords, p);
+ }
+ }
+ }
+ return;
+}
+
+/*------------------------------------------------------------------------------*/
+/* Write File to Specified Location on Disk */
+
+/* C/C++ source code (arrays of floats) */
+static void write_double_array(FILE *fp, const double *ptr, int length, const char *array_name, bool quantize)
+{
+ fprintf(fp, "static const float %s[%d] = {", array_name, length);
+
+ for (int n = 0; n < length; n++) {
+ if (n > 0)
+ fprintf(fp, ",");
+ fprintf(fp, (n % 8 != 0) ? " " : "\n\t");
+
+ if (quantize)
+ fprintf(fp, "%3d / 255.0", (int)(*(ptr++) * 255.0));
+ else
+ fprintf(fp, "%1.8lf", *(ptr++));
+ }
+
+ fprintf(fp, "\n};\n");
+}
+
+static void write_csource(AreaOrtho *ortho, AreaDiag *diag, FILE *fp, bool subsampling, bool quantize)
+{
+ fprintf(fp, "/* This file was generated by smaa_areatex.cpp */\n");
+
+ fprintf(fp, "\n/* Horizontal/Vertical Areas */\n");
+ write_double_array(fp, ortho->getData(),
+ TEX_SIZE_ORTHO * TEX_SIZE_ORTHO * 2 * (subsampling ? SUBSAMPLES_ORTHO : 1),
+ "areatex", quantize);
+
+ fprintf(fp, "\n/* Diagonal Areas */\n");
+ write_double_array(fp, diag->getData(),
+ TEX_SIZE_DIAG * TEX_SIZE_DIAG * 2 * (subsampling ? SUBSAMPLES_DIAG : 1),
+ "areatex_diag", quantize);
+}
+
+/* .tga File (RGBA 32bit uncompressed) */
+static void write_tga(AreaOrtho *ortho, AreaDiag *diag, FILE *fp, bool subsampling)
+{
+ int subsamples = subsampling ? SUBSAMPLES_ORTHO : 1;
+ unsigned char header[18] = {0, 0,
+ 2, /* uncompressed RGB */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 32, /* 32bit */
+ 8}; /* 8bit alpha, left to right, bottom to top */
+
+ /* Set width and height */
+ header[12] = (TEX_SIZE_ORTHO + TEX_SIZE_DIAG) & 0xff;
+ header[13] = ((TEX_SIZE_ORTHO + TEX_SIZE_DIAG) >> 8) & 0xff;
+ header[14] = (subsamples * TEX_SIZE_ORTHO) & 0xff;
+ header[15] = ((subsamples * TEX_SIZE_ORTHO) >> 8) & 0xff;
+
+ /* Write .tga header */
+ fwrite(header, sizeof(unsigned char), sizeof(header) / sizeof(unsigned char), fp);
+
+ /* Write pixel data */
+ for (int i = subsamples - 1; i >= 0; i--) {
+ for (int y = TEX_SIZE_ORTHO - 1; y >= 0; y--) {
+ for (int x = 0; x < TEX_SIZE_ORTHO; x++) {
+ Dbl2 p = ortho->getPixel(i, Int2(x, y));
+ fputc(0, fp); /* B */
+ fputc((unsigned char)(p.y * 255.0), fp); /* G */
+ fputc((unsigned char)(p.x * 255.0), fp); /* R */
+ fputc(0, fp); /* A */
+ }
+
+ for (int x = 0; x < TEX_SIZE_DIAG; x++) {
+ if (i < SUBSAMPLES_DIAG) {
+ Dbl2 p = diag->getPixel(i, Int2(x, y));
+ fputc(0, fp); /* B */
+ fputc((unsigned char)(p.y * 255.0), fp); /* G */
+ fputc((unsigned char)(p.x * 255.0), fp); /* R */
+ fputc(0, fp); /* A */
+ }
+ else {
+ fputc(0, fp);
+ fputc(0, fp);
+ fputc(0, fp);
+ fputc(0, fp);
+ }
+ }
+ }
+ }
+}
+
+/* .raw File (R8G8 raw data) */
+static void write_raw(AreaOrtho *ortho, AreaDiag *diag, FILE *fp, bool subsampling)
+{
+ int subsamples = subsampling ? SUBSAMPLES_ORTHO : 1;
+
+ /* Write pixel data */
+ for (int i = 0; i < subsamples; i++) {
+ for (int y = 0; y < TEX_SIZE_ORTHO; y++) {
+ for (int x = 0; x < TEX_SIZE_ORTHO; x++) {
+ Dbl2 p = ortho->getPixel(i, Int2(x, y));
+ fputc((unsigned char)(p.x * 255.0), fp); /* R */
+ fputc((unsigned char)(p.y * 255.0), fp); /* G */
+ }
+
+ for (int x = 0; x < TEX_SIZE_DIAG; x++) {
+ if (i < SUBSAMPLES_DIAG) {
+ Dbl2 p = diag->getPixel(i, Int2(x, y));
+ fputc((unsigned char)(p.x * 255.0), fp); /* R */
+ fputc((unsigned char)(p.y * 255.0), fp); /* G */
+ }
+ else {
+ fputc(0, fp);
+ fputc(0, fp);
+ }
+ }
+ }
+ }
+}
+
+static int generate_file(AreaOrtho *ortho, AreaDiag *diag, const char *path, bool subsampling, bool quantize, bool tga, bool raw)
+{
+ FILE *fp = fopen(path, tga ? "wb" : "w");
+
+ if (!fp) {
+ fprintf(stderr, "Unable to open file: %s\n", path);
+ return 1;
+ }
+
+ fprintf(stderr, "Generating %s\n", path);
+
+ if (tga)
+ write_tga(ortho, diag, fp, subsampling);
+ else if (raw)
+ write_raw(ortho, diag, fp, subsampling);
+ else
+ write_csource(ortho, diag, fp, subsampling, quantize);
+
+ fclose(fp);
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ bool subsampling = false;
+ bool quantize = false;
+ bool tga = false;
+ bool raw = false;
+ bool compat = false;
+ bool numeric = false;
+ bool orig_u = false;
+ bool help = false;
+ char *outfile = NULL;
+ int status = 0;
+
+ for (int i = 1; i < argc; i++) {
+ char *ptr = argv[i];
+ if (*ptr++ == '-' && *ptr != '\0') {
+ char c;
+ while ((c = *ptr++) != '\0') {
+ if (c == 's')
+ subsampling = true;
+ else if (c == 'q')
+ quantize = true;
+ else if (c == 't')
+ tga = true;
+ else if (c == 'r')
+ raw = true;
+ else if (c == 'c')
+ compat = true;
+ else if (c == 'n')
+ numeric = true;
+ else if (c == 'u')
+ orig_u = true;
+ else if (c == 'h')
+ help = true;
+ else {
+ fprintf(stderr, "Unknown option: -%c\n", c);
+ status = 1;
+ break;
+ }
+ }
+ }
+ else if (outfile) {
+ fprintf(stderr, "Too much file names: %s, %s\n", outfile, argv[i]);
+ status = 1;
+ }
+ else
+ outfile = argv[i];
+
+ if (status != 0)
+ break;
+ }
+
+ if (status == 0 && !help && !outfile) {
+ fprintf(stderr, "File name was not specified.\n");
+ status = 1;
+ }
+
+ if (status != 0 || help) {
+ fprintf(stderr, "Usage: %s [OPTION]... OUTFILE\n", argv[0]);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -s Calculate data for subpixel rendering\n");
+ fprintf(stderr, " -q Quantize data to 256 levels\n");
+ fprintf(stderr, " -t Write TGA image instead of C/C++ source\n");
+ fprintf(stderr, " -r Write R8G8 raw image instead of C/C++ source\n");
+ fprintf(stderr, " -c Generate compatible orthogonal data that subtexture size is 16\n");
+ fprintf(stderr, " -n Numerically calculate diagonal data using brute force sampling\n");
+ fprintf(stderr, " -u Process orthogonal / diagonal U patterns in older ways\n");
+ fprintf(stderr, " -h Print this help and exit\n");
+ fprintf(stderr, "File name OUTFILE usually should have an extension such as .c, .h, or .tga,\n");
+ fprintf(stderr, "except for a special name '-' that means standard output.\n\n");
+ fprintf(stderr, "Example:\n");
+ fprintf(stderr, " Generate TGA file exactly same as AreaTexDX10.tga bundled with the\n");
+ fprintf(stderr, " original implementation:\n\n");
+ fprintf(stderr, " $ smaa_areatex -stcnu AreaTexDX10.tga\n\n");
+ return status;
+ }
+
+ AreaOrtho *ortho = new AreaOrtho(compat, orig_u);
+ AreaDiag *diag = new AreaDiag(numeric, orig_u);
+
+ /* Calculate areatex data */
+ for (int i = 0; i < (subsampling ? SUBSAMPLES_ORTHO : 1); i++)
+ ortho->areaTex(i);
+
+ for (int i = 0; i < (subsampling ? SUBSAMPLES_DIAG : 1); i++)
+ diag->areaTex(i);
+
+ /* Generate .tga, .raw, or C/C++ source file, or write the data to stdout */
+ if (strcmp(outfile, "-") != 0)
+ status = generate_file(ortho, diag, outfile, subsampling, quantize, tga, raw);
+ else if (tga)
+ write_tga(ortho, diag, stdout, subsampling);
+ else if (raw)
+ write_raw(ortho, diag, stdout, subsampling);
+ else
+ write_csource(ortho, diag, stdout, subsampling, quantize);
+
+ delete ortho;
+ delete diag;
+
+ return status;
+}
+
+/* smaa_areatex.cpp ends here */
diff --git a/intern/cycles/blender/blender_image.cpp b/intern/cycles/blender/blender_image.cpp
index 459dc1779fb..3a9d159e461 100644
--- a/intern/cycles/blender/blender_image.cpp
+++ b/intern/cycles/blender/blender_image.cpp
@@ -29,7 +29,7 @@ BlenderImageLoader::BlenderImageLoader(BL::Image b_image, int frame)
{
}
-bool BlenderImageLoader::load_metadata(ImageMetaData &metadata)
+bool BlenderImageLoader::load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata)
{
metadata.width = b_image.size()[0];
metadata.height = b_image.size()[1];
@@ -171,7 +171,7 @@ BlenderPointDensityLoader::BlenderPointDensityLoader(BL::Depsgraph b_depsgraph,
{
}
-bool BlenderPointDensityLoader::load_metadata(ImageMetaData &metadata)
+bool BlenderPointDensityLoader::load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata)
{
metadata.channels = 4;
metadata.width = b_node.resolution();
diff --git a/intern/cycles/blender/blender_image.h b/intern/cycles/blender/blender_image.h
index b58a159a6ba..fddbbfd9c37 100644
--- a/intern/cycles/blender/blender_image.h
+++ b/intern/cycles/blender/blender_image.h
@@ -27,7 +27,7 @@ class BlenderImageLoader : public ImageLoader {
public:
BlenderImageLoader(BL::Image b_image, int frame);
- bool load_metadata(ImageMetaData &metadata) override;
+ bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override;
bool load_pixels(const ImageMetaData &metadata,
void *pixels,
const size_t pixels_size,
@@ -44,7 +44,7 @@ class BlenderPointDensityLoader : public ImageLoader {
public:
BlenderPointDensityLoader(BL::Depsgraph depsgraph, BL::ShaderNodeTexPointDensity b_node);
- bool load_metadata(ImageMetaData &metadata) override;
+ bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override;
bool load_pixels(const ImageMetaData &metadata,
void *pixels,
const size_t pixels_size,
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index c7b49354d53..11158532738 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -375,7 +375,7 @@ static void attr_create_generic(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool
case BL::Attribute::domain_POINT:
element = ATTR_ELEMENT_VERTEX;
break;
- case BL::Attribute::domain_POLYGON:
+ case BL::Attribute::domain_FACE:
element = ATTR_ELEMENT_FACE;
break;
default:
diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp
index 410f7a72cf5..0ff4de846e1 100644
--- a/intern/cycles/blender/blender_volume.cpp
+++ b/intern/cycles/blender/blender_volume.cpp
@@ -41,7 +41,7 @@ class BlenderSmokeLoader : public ImageLoader {
mesh_texture_space(b_mesh, texspace_loc, texspace_size);
}
- bool load_metadata(ImageMetaData &metadata) override
+ bool load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata) override
{
if (!b_domain) {
return false;
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 94732cd1855..ed53fbb54ae 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -619,6 +619,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
info.num = 0;
info.has_half_images = true;
+ info.has_nanovdb = true;
info.has_volume_decoupled = true;
info.has_branched_path = true;
info.has_adaptive_stop_per_sample = true;
@@ -665,6 +666,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
/* Accumulate device info. */
info.has_half_images &= device.has_half_images;
+ info.has_nanovdb &= device.has_nanovdb;
info.has_volume_decoupled &= device.has_volume_decoupled;
info.has_branched_path &= device.has_branched_path;
info.has_adaptive_stop_per_sample &= device.has_adaptive_stop_per_sample;
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index 0a731969c79..b5468248e5a 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -78,6 +78,7 @@ class DeviceInfo {
int num;
bool display_device; /* GPU is used as a display device. */
bool has_half_images; /* Support half-float textures. */
+ bool has_nanovdb; /* Support NanoVDB volumes. */
bool has_volume_decoupled; /* Decoupled volume shading. */
bool has_branched_path; /* Supports branched path tracing. */
bool has_adaptive_stop_per_sample; /* Per-sample adaptive sampling stopping. */
@@ -99,6 +100,7 @@ class DeviceInfo {
cpu_threads = 0;
display_device = false;
has_half_images = false;
+ has_nanovdb = false;
has_volume_decoupled = false;
has_branched_path = true;
has_adaptive_stop_per_sample = false;
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index e2f9c7391da..0e3c771dbc3 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -1654,6 +1654,7 @@ void device_cpu_info(vector<DeviceInfo> &devices)
info.has_adaptive_stop_per_sample = true;
info.has_osl = true;
info.has_half_images = true;
+ info.has_nanovdb = true;
info.has_profiling = true;
info.denoisers = DENOISER_NLM;
if (openimagedenoise_supported()) {
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index d9ffcceb06e..2e225ecfaf8 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -128,6 +128,7 @@ void device_cuda_info(vector<DeviceInfo> &devices)
info.num = num;
info.has_half_images = (major >= 3);
+ info.has_nanovdb = true;
info.has_volume_decoupled = false;
info.has_adaptive_stop_per_sample = false;
info.denoisers = DENOISER_NLM;
diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp
index b272e59f99d..35faadcbec5 100644
--- a/intern/cycles/device/device_multi.cpp
+++ b/intern/cycles/device/device_multi.cpp
@@ -46,10 +46,13 @@ class MultiDevice : public Device {
list<SubDevice> devices, denoising_devices;
device_ptr unique_key;
vector<vector<SubDevice *>> peer_islands;
+ bool use_denoising;
bool matching_rendering_and_denoising_devices;
MultiDevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background_)
- : Device(info, stats, profiler, background_), unique_key(1)
+ : Device(info, stats, profiler, background_),
+ unique_key(1),
+ use_denoising(!info.denoising_devices.empty())
{
foreach (DeviceInfo &subinfo, info.multi_devices) {
/* Always add CPU devices at the back since GPU devices can change
@@ -194,6 +197,7 @@ class MultiDevice : public Device {
if (!sub.device->load_kernels(requested_features))
return false;
+ use_denoising = requested_features.use_denoising;
if (requested_features.use_denoising) {
/* Only need denoising feature, everything else is unused. */
DeviceRequestedFeatures denoising_features;
@@ -400,7 +404,7 @@ class MultiDevice : public Device {
size_t existing_size = mem.device_size;
/* The tile buffers are allocated on each device (see below), so copy to all of them */
- if (strcmp(mem.name, "RenderBuffers") == 0) {
+ if (strcmp(mem.name, "RenderBuffers") == 0 && use_denoising) {
foreach (SubDevice &sub, devices) {
mem.device = sub.device;
mem.device_pointer = (existing_key) ? sub.ptr_map[existing_key] : 0;
@@ -466,7 +470,7 @@ class MultiDevice : public Device {
/* This is a hack to only allocate the tile buffers on denoising devices
* Similarly the tile buffers also need to be allocated separately on all devices so any
* overlap rendered for denoising does not interfere with each other */
- if (strcmp(mem.name, "RenderBuffers") == 0) {
+ if (strcmp(mem.name, "RenderBuffers") == 0 && use_denoising) {
vector<device_ptr> device_pointers;
device_pointers.reserve(devices.size());
@@ -518,7 +522,7 @@ class MultiDevice : public Device {
size_t existing_size = mem.device_size;
/* Free memory that was allocated for all devices (see above) on each device */
- if (strcmp(mem.name, "RenderBuffers") == 0 || mem.type == MEM_PIXELS) {
+ if (mem.type == MEM_PIXELS || (strcmp(mem.name, "RenderBuffers") == 0 && use_denoising)) {
foreach (SubDevice &sub, devices) {
mem.device = sub.device;
mem.device_pointer = sub.ptr_map[key];
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index 11376ee4883..9abb7cfb7fe 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -126,6 +126,9 @@ void device_opencl_info(vector<DeviceInfo> &devices)
/* Check OpenCL extensions */
info.has_half_images = platform_device.device_extensions.find("cl_khr_fp16") != string::npos;
+ /* Disabled for now due to apparent AMD driver bug. */
+ info.has_nanovdb = platform_name != "AMD Accelerated Parallel Processing";
+
devices.push_back(info);
num_devices++;
}
diff --git a/intern/cycles/device/opencl/device_opencl_impl.cpp b/intern/cycles/device/opencl/device_opencl_impl.cpp
index aee3b0fb64f..d378d32914c 100644
--- a/intern/cycles/device/opencl/device_opencl_impl.cpp
+++ b/intern/cycles/device/opencl/device_opencl_impl.cpp
@@ -2036,7 +2036,9 @@ string OpenCLDevice::kernel_build_options(const string *debug_src)
# endif
# ifdef WITH_NANOVDB
- build_options += "-DWITH_NANOVDB ";
+ if (info.has_nanovdb) {
+ build_options += "-DWITH_NANOVDB ";
+ }
# endif
return build_options;
diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h
index 389c44ab1da..19fb1da5a1f 100644
--- a/intern/cycles/kernel/svm/svm_math_util.h
+++ b/intern/cycles/kernel/svm/svm_math_util.h
@@ -242,12 +242,15 @@ ccl_device float3 svm_math_blackbody_color(float t)
return make_float3(4.70366907f, 0.0f, 0.0f);
}
+ /* Manually align for readability. */
+ /* clang-format off */
int i = (t >= 6365.0f) ? 5 :
(t >= 3315.0f) ? 4 :
(t >= 1902.0f) ? 3 :
(t >= 1449.0f) ? 2 :
(t >= 1167.0f) ? 1 :
0;
+ /* clang-format on */
ccl_constant float *r = blackbody_table_r[i];
ccl_constant float *g = blackbody_table_g[i];
diff --git a/intern/cycles/render/alembic.cpp b/intern/cycles/render/alembic.cpp
index 1336f81896a..c3a7b20f512 100644
--- a/intern/cycles/render/alembic.cpp
+++ b/intern/cycles/render/alembic.cpp
@@ -1407,6 +1407,15 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress)
need_data_updates = true;
}
+ /* Check if the shaders were modified. */
+ if (object->used_shaders_is_modified() && object->get_object() &&
+ object->get_object()->get_geometry()) {
+ Geometry *geometry = object->get_object()->get_geometry();
+ array<Node *> used_shaders = object->get_used_shaders();
+ geometry->set_used_shaders(used_shaders);
+ need_shader_updates = true;
+ }
+
/* Check for changes in shaders (e.g. newly requested attributes). */
foreach (Node *shader_node, object->get_used_shaders()) {
Shader *shader = static_cast<Shader *>(shader_node);
@@ -1586,6 +1595,11 @@ void AlembicProcedural::read_mesh(AlembicObject *abc_object, Abc::chrono_t frame
Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
+ /* Make sure shader ids are also updated. */
+ if (mesh->used_shaders_is_modified()) {
+ mesh->tag_shader_modified();
+ }
+
cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket());
cached_data.shader.copy_to_socket(frame_time, mesh, mesh->get_shader_socket());
@@ -1653,6 +1667,11 @@ void AlembicProcedural::read_subd(AlembicObject *abc_object, Abc::chrono_t frame
Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
+ /* Make sure shader ids are also updated. */
+ if (mesh->used_shaders_is_modified()) {
+ mesh->tag_shader_modified();
+ }
+
/* Cycles overwrites the original triangles when computing displacement, so we always have to
* repass the data if something is animated (vertices most likely) to avoid buffer overflows. */
if (!cached_data.is_constant()) {
@@ -1743,6 +1762,11 @@ void AlembicProcedural::read_curves(AlembicObject *abc_object, Abc::chrono_t fra
Hair *hair = static_cast<Hair *>(object->get_geometry());
+ /* Make sure shader ids are also updated. */
+ if (hair->used_shaders_is_modified()) {
+ hair->tag_curve_shader_modified();
+ }
+
cached_data.curve_keys.copy_to_socket(frame_time, hair, hair->get_curve_keys_socket());
cached_data.curve_radius.copy_to_socket(frame_time, hair, hair->get_curve_radius_socket());
diff --git a/intern/cycles/render/alembic.h b/intern/cycles/render/alembic.h
index d0c5856a353..3bbd10fad61 100644
--- a/intern/cycles/render/alembic.h
+++ b/intern/cycles/render/alembic.h
@@ -239,6 +239,7 @@ template<typename T> class DataStore {
{
invalidate_last_loaded_time();
data.clear();
+ index_data_map.clear();
}
void invalidate_last_loaded_time()
@@ -480,16 +481,23 @@ class AlembicProcedural : public Procedural {
* invocation, and updates the data on subsequent invocations if the frame changed. */
void generate(Scene *scene, Progress &progress);
- /* Add an object to our list of objects, and tag the socket as modified. */
- void add_object(AlembicObject *object);
-
/* Tag for an update only if something was modified. */
void tag_update(Scene *scene);
- /* Returns a pointer to an existing or a newly created AlembicObject for the given path. */
+ /* This should be called by scene exporters to request the rendering of an object located
+ * in the Alembic archive at the given path.
+ *
+ * Since we lazily load object, the function does not validate the existence of the object
+ * in the archive. If no objects with such path if found in the archive during the next call
+ * to `generate`, it will be ignored.
+ *
+ * Returns a pointer to an existing or a newly created AlembicObject for the given path. */
AlembicObject *get_or_create_object(const ustring &path);
private:
+ /* Add an object to our list of objects, and tag the socket as modified. */
+ void add_object(AlembicObject *object);
+
/* Load the data for all the objects whose data has not yet been loaded. */
void load_objects(Progress &progress);
diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp
index b3d383afae4..f0a779da012 100644
--- a/intern/cycles/render/background.cpp
+++ b/intern/cycles/render/background.cpp
@@ -130,6 +130,14 @@ void Background::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
void Background::tag_update(Scene *scene)
{
+ Shader *bg_shader = get_shader(scene);
+ if (bg_shader && bg_shader->is_modified()) {
+ /* Tag as modified to update the KernelBackground visibility information.
+ * We only tag the use_shader socket as modified as it is related to the shader
+ * and to avoid doing unnecessary updates anywhere else. */
+ tag_use_shader_modified();
+ }
+
if (ao_factor_is_modified() || use_ao_is_modified()) {
scene->integrator->tag_update(scene, Integrator::BACKGROUND_AO_MODIFIED);
}
diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp
index 124a41db21e..8b0c0d94155 100644
--- a/intern/cycles/render/geometry.cpp
+++ b/intern/cycles/render/geometry.cpp
@@ -1584,7 +1584,6 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro
dscene->tri_vnormal.tag_realloc();
dscene->tri_vindex.tag_realloc();
dscene->tri_patch.tag_realloc();
- dscene->tri_vnormal.tag_realloc();
dscene->tri_patch_uv.tag_realloc();
dscene->tri_shader.tag_realloc();
dscene->patches.tag_realloc();
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 29a95beaf7e..27f9b7df1dd 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -303,7 +303,8 @@ ImageManager::ImageManager(const DeviceInfo &info)
animation_frame = 0;
/* Set image limits */
- has_half_images = info.has_half_images;
+ features.has_half_float = info.has_half_images;
+ features.has_nanovdb = info.has_nanovdb;
}
ImageManager::~ImageManager()
@@ -347,7 +348,7 @@ void ImageManager::load_image_metadata(Image *img)
metadata = ImageMetaData();
metadata.colorspace = img->params.colorspace;
- if (img->loader->load_metadata(metadata)) {
+ if (img->loader->load_metadata(features, metadata)) {
assert(metadata.type != IMAGE_DATA_NUM_TYPES);
}
else {
@@ -356,15 +357,10 @@ void ImageManager::load_image_metadata(Image *img)
metadata.detect_colorspace();
- /* No half textures on OpenCL, use full float instead. */
- if (!has_half_images) {
- if (metadata.type == IMAGE_DATA_TYPE_HALF4) {
- metadata.type = IMAGE_DATA_TYPE_FLOAT4;
- }
- else if (metadata.type == IMAGE_DATA_TYPE_HALF) {
- metadata.type = IMAGE_DATA_TYPE_FLOAT;
- }
- }
+ assert(features.has_half_float ||
+ (metadata.type != IMAGE_DATA_TYPE_HALF4 && metadata.type != IMAGE_DATA_TYPE_HALF));
+ assert(features.has_nanovdb || (metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT ||
+ metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3));
img->need_metadata = false;
}
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index c802521db56..dede9513d5f 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -97,6 +97,13 @@ class ImageMetaData {
void detect_colorspace();
};
+/* Information about supported features that Image loaders can use. */
+class ImageDeviceFeatures {
+ public:
+ bool has_half_float;
+ bool has_nanovdb;
+};
+
/* Image loader base class, that can be subclassed to load image data
* from custom sources (file, memory, procedurally generated, etc). */
class ImageLoader {
@@ -105,7 +112,7 @@ class ImageLoader {
virtual ~ImageLoader(){};
/* Load metadata without actual image yet, should be fast. */
- virtual bool load_metadata(ImageMetaData &metadata) = 0;
+ virtual bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) = 0;
/* Load actual image contents. */
virtual bool load_pixels(const ImageMetaData &metadata,
@@ -212,7 +219,8 @@ class ImageManager {
private:
bool need_update_;
- bool has_half_images;
+
+ ImageDeviceFeatures features;
thread_mutex device_mutex;
thread_mutex images_mutex;
diff --git a/intern/cycles/render/image_oiio.cpp b/intern/cycles/render/image_oiio.cpp
index e9c87461822..4867efe6ac0 100644
--- a/intern/cycles/render/image_oiio.cpp
+++ b/intern/cycles/render/image_oiio.cpp
@@ -30,7 +30,7 @@ OIIOImageLoader::~OIIOImageLoader()
{
}
-bool OIIOImageLoader::load_metadata(ImageMetaData &metadata)
+bool OIIOImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata)
{
/* Perform preliminary checks, with meaningful logging. */
if (!path_exists(filepath.string())) {
@@ -76,7 +76,7 @@ bool OIIOImageLoader::load_metadata(ImageMetaData &metadata)
}
/* check if it's half float */
- if (spec.format == TypeDesc::HALF) {
+ if (spec.format == TypeDesc::HALF && features.has_half_float) {
is_half = true;
}
diff --git a/intern/cycles/render/image_oiio.h b/intern/cycles/render/image_oiio.h
index a234b968557..a6dbb168b65 100644
--- a/intern/cycles/render/image_oiio.h
+++ b/intern/cycles/render/image_oiio.h
@@ -26,7 +26,7 @@ class OIIOImageLoader : public ImageLoader {
OIIOImageLoader(const string &filepath);
~OIIOImageLoader();
- bool load_metadata(ImageMetaData &metadata) override;
+ bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override;
bool load_pixels(const ImageMetaData &metadata,
void *pixels,
diff --git a/intern/cycles/render/image_sky.cpp b/intern/cycles/render/image_sky.cpp
index 0560907c63e..7f9b85836f8 100644
--- a/intern/cycles/render/image_sky.cpp
+++ b/intern/cycles/render/image_sky.cpp
@@ -40,7 +40,7 @@ SkyLoader::SkyLoader(float sun_elevation,
SkyLoader::~SkyLoader(){};
-bool SkyLoader::load_metadata(ImageMetaData &metadata)
+bool SkyLoader::load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata)
{
metadata.width = 512;
metadata.height = 128;
diff --git a/intern/cycles/render/image_sky.h b/intern/cycles/render/image_sky.h
index 686f4e5b885..89ff586e7fd 100644
--- a/intern/cycles/render/image_sky.h
+++ b/intern/cycles/render/image_sky.h
@@ -34,7 +34,7 @@ class SkyLoader : public ImageLoader {
float ozone_density);
~SkyLoader();
- bool load_metadata(ImageMetaData &metadata) override;
+ bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override;
bool load_pixels(const ImageMetaData &metadata,
void *pixels,
diff --git a/intern/cycles/render/image_vdb.cpp b/intern/cycles/render/image_vdb.cpp
index 70b3de5a939..63e6214f1c8 100644
--- a/intern/cycles/render/image_vdb.cpp
+++ b/intern/cycles/render/image_vdb.cpp
@@ -34,7 +34,7 @@ VDBImageLoader::~VDBImageLoader()
{
}
-bool VDBImageLoader::load_metadata(ImageMetaData &metadata)
+bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata)
{
#ifdef WITH_OPENVDB
if (!grid) {
@@ -56,55 +56,71 @@ bool VDBImageLoader::load_metadata(ImageMetaData &metadata)
if (grid->isType<openvdb::FloatGrid>()) {
metadata.channels = 1;
# ifdef WITH_NANOVDB
- nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid));
+ if (features.has_nanovdb) {
+ nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid));
+ }
# endif
}
else if (grid->isType<openvdb::Vec3fGrid>()) {
metadata.channels = 3;
# ifdef WITH_NANOVDB
- nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid));
+ if (features.has_nanovdb) {
+ nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid));
+ }
# endif
}
else if (grid->isType<openvdb::BoolGrid>()) {
metadata.channels = 1;
# ifdef WITH_NANOVDB
- nanogrid = nanovdb::openToNanoVDB(
- openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid)));
+ if (features.has_nanovdb) {
+ nanogrid = nanovdb::openToNanoVDB(
+ openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid)));
+ }
# endif
}
else if (grid->isType<openvdb::DoubleGrid>()) {
metadata.channels = 1;
# ifdef WITH_NANOVDB
- nanogrid = nanovdb::openToNanoVDB(
- openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid)));
+ if (features.has_nanovdb) {
+ nanogrid = nanovdb::openToNanoVDB(
+ openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid)));
+ }
# endif
}
else if (grid->isType<openvdb::Int32Grid>()) {
metadata.channels = 1;
# ifdef WITH_NANOVDB
- nanogrid = nanovdb::openToNanoVDB(
- openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid)));
+ if (features.has_nanovdb) {
+ nanogrid = nanovdb::openToNanoVDB(
+ openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid)));
+ }
# endif
}
else if (grid->isType<openvdb::Int64Grid>()) {
metadata.channels = 1;
# ifdef WITH_NANOVDB
- nanogrid = nanovdb::openToNanoVDB(
- openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid)));
+ if (features.has_nanovdb) {
+ nanogrid = nanovdb::openToNanoVDB(
+ openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid)));
+ }
# endif
}
else if (grid->isType<openvdb::Vec3IGrid>()) {
metadata.channels = 3;
# ifdef WITH_NANOVDB
- nanogrid = nanovdb::openToNanoVDB(
- openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid)));
+ if (features.has_nanovdb) {
+ nanogrid = nanovdb::openToNanoVDB(
+ openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid)));
+ }
# endif
}
else if (grid->isType<openvdb::Vec3dGrid>()) {
metadata.channels = 3;
# ifdef WITH_NANOVDB
- nanogrid = nanovdb::openToNanoVDB(
- openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid)));
+ if (features.has_nanovdb) {
+ nanogrid = nanovdb::openToNanoVDB(
+ openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid)));
+ }
# endif
}
else if (grid->isType<openvdb::MaskGrid>()) {
@@ -118,21 +134,25 @@ bool VDBImageLoader::load_metadata(ImageMetaData &metadata)
}
# ifdef WITH_NANOVDB
- metadata.byte_size = nanogrid.size();
- if (metadata.channels == 1) {
- metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT;
- }
- else {
- metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT3;
- }
-# else
- if (metadata.channels == 1) {
- metadata.type = IMAGE_DATA_TYPE_FLOAT;
- }
- else {
- metadata.type = IMAGE_DATA_TYPE_FLOAT4;
+ if (nanogrid) {
+ metadata.byte_size = nanogrid.size();
+ if (metadata.channels == 1) {
+ metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT;
+ }
+ else {
+ metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT3;
+ }
}
+ else
# endif
+ {
+ if (metadata.channels == 1) {
+ metadata.type = IMAGE_DATA_TYPE_FLOAT;
+ }
+ else {
+ metadata.type = IMAGE_DATA_TYPE_FLOAT4;
+ }
+ }
/* Set transform from object space to voxel index. */
openvdb::math::Mat4f grid_matrix = grid->transform().baseMap()->getAffineMap()->getMat4();
@@ -143,13 +163,18 @@ bool VDBImageLoader::load_metadata(ImageMetaData &metadata)
}
}
+ Transform texture_to_index;
# ifdef WITH_NANOVDB
- Transform texture_to_index = transform_identity();
-# else
- openvdb::Coord min = bbox.min();
- Transform texture_to_index = transform_translate(min.x(), min.y(), min.z()) *
- transform_scale(dim.x(), dim.y(), dim.z());
+ if (nanogrid) {
+ texture_to_index = transform_identity();
+ }
+ else
# endif
+ {
+ openvdb::Coord min = bbox.min();
+ texture_to_index = transform_translate(min.x(), min.y(), min.z()) *
+ transform_scale(dim.x(), dim.y(), dim.z());
+ }
metadata.transform_3d = transform_inverse(index_to_object * texture_to_index);
metadata.use_transform_3d = true;
@@ -165,48 +190,52 @@ bool VDBImageLoader::load_pixels(const ImageMetaData &, void *pixels, const size
{
#ifdef WITH_OPENVDB
# ifdef WITH_NANOVDB
- memcpy(pixels, nanogrid.data(), nanogrid.size());
-# else
- if (grid->isType<openvdb::FloatGrid>()) {
- openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid), dense);
- }
- else if (grid->isType<openvdb::Vec3fGrid>()) {
- openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
- bbox, (openvdb::Vec3f *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid), dense);
- }
- else if (grid->isType<openvdb::BoolGrid>()) {
- openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid), dense);
- }
- else if (grid->isType<openvdb::DoubleGrid>()) {
- openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid), dense);
- }
- else if (grid->isType<openvdb::Int32Grid>()) {
- openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid), dense);
- }
- else if (grid->isType<openvdb::Int64Grid>()) {
- openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid), dense);
- }
- else if (grid->isType<openvdb::Vec3IGrid>()) {
- openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
- bbox, (openvdb::Vec3f *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid), dense);
- }
- else if (grid->isType<openvdb::Vec3dGrid>()) {
- openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
- bbox, (openvdb::Vec3f *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid), dense);
- }
- else if (grid->isType<openvdb::MaskGrid>()) {
- openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
- openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid), dense);
+ if (nanogrid) {
+ memcpy(pixels, nanogrid.data(), nanogrid.size());
}
+ else
# endif
+ {
+ if (grid->isType<openvdb::FloatGrid>()) {
+ openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid), dense);
+ }
+ else if (grid->isType<openvdb::Vec3fGrid>()) {
+ openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
+ bbox, (openvdb::Vec3f *)pixels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid), dense);
+ }
+ else if (grid->isType<openvdb::BoolGrid>()) {
+ openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid), dense);
+ }
+ else if (grid->isType<openvdb::DoubleGrid>()) {
+ openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid), dense);
+ }
+ else if (grid->isType<openvdb::Int32Grid>()) {
+ openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid), dense);
+ }
+ else if (grid->isType<openvdb::Int64Grid>()) {
+ openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid), dense);
+ }
+ else if (grid->isType<openvdb::Vec3IGrid>()) {
+ openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
+ bbox, (openvdb::Vec3f *)pixels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid), dense);
+ }
+ else if (grid->isType<openvdb::Vec3dGrid>()) {
+ openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
+ bbox, (openvdb::Vec3f *)pixels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid), dense);
+ }
+ else if (grid->isType<openvdb::MaskGrid>()) {
+ openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid), dense);
+ }
+ }
return true;
#else
(void)pixels;
diff --git a/intern/cycles/render/image_vdb.h b/intern/cycles/render/image_vdb.h
index 71d10cc39f5..763196f2a15 100644
--- a/intern/cycles/render/image_vdb.h
+++ b/intern/cycles/render/image_vdb.h
@@ -33,7 +33,8 @@ class VDBImageLoader : public ImageLoader {
VDBImageLoader(const string &grid_name);
~VDBImageLoader();
- virtual bool load_metadata(ImageMetaData &metadata) override;
+ virtual bool load_metadata(const ImageDeviceFeatures &features,
+ ImageMetaData &metadata) override;
virtual bool load_pixels(const ImageMetaData &metadata,
void *pixels,
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 52f63685aeb..8b3ac31cf8b 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -153,10 +153,6 @@ void Object::update_motion()
void Object::compute_bounds(bool motion_blur)
{
- if (!is_modified() && !geometry->is_modified()) {
- return;
- }
-
BoundBox mbounds = geometry->bounds;
if (motion_blur && use_motion()) {
diff --git a/intern/ghost/intern/GHOST_IconX11.h b/intern/ghost/intern/GHOST_IconX11.h
index 615a7dae6b5..403d611b71d 100644
--- a/intern/ghost/intern/GHOST_IconX11.h
+++ b/intern/ghost/intern/GHOST_IconX11.h
@@ -24,7 +24,8 @@
#pragma once
-/*
+/**
+ * \code{.py}
* import bpy
* import textwrap
*
@@ -42,6 +43,7 @@
* print("%d,%d," % (w, h))
* text = ", ".join(["0x%x" % p for p in pixels])
* print(textwrap.fill(text, width=120), end=",\n")
+ * \endcode
*/
/**
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 70901954df2..28ce1381562 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -533,11 +533,18 @@ GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state)
wp.showCmd = SW_SHOWMAXIMIZED;
wp.ptMaxPosition.x = 0;
wp.ptMaxPosition.y = 0;
- style &= ~WS_CAPTION;
+ style &= ~(WS_CAPTION | WS_MAXIMIZE);
break;
case GHOST_kWindowStateNormal:
default:
- wp.showCmd = SW_SHOWNORMAL;
+ if (curstate == GHOST_kWindowStateFullScreen &&
+ m_normal_state == GHOST_kWindowStateMaximized) {
+ wp.showCmd = SW_SHOWMAXIMIZED;
+ m_normal_state = GHOST_kWindowStateNormal;
+ }
+ else {
+ wp.showCmd = SW_SHOWNORMAL;
+ }
break;
}
::SetWindowLongPtr(m_hWnd, GWL_STYLE, style);
diff --git a/release/scripts/addons b/release/scripts/addons
-Subproject bcd08a9506d33bdd7358201031b04d041ef22d9
+Subproject 63492d3d0334e1827f611f8fe5a931f3ccbddfc
diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py
index 83bed69d8d2..387691f9f05 100644
--- a/release/scripts/modules/addon_utils.py
+++ b/release/scripts/modules/addon_utils.py
@@ -349,6 +349,10 @@ def enable(module_name, *, default_set=False, persistent=False, handle_error=Non
# 1) try import
try:
mod = __import__(module_name)
+ if mod.__file__ is None:
+ # This can happen when the addon has been removed but there are
+ # residual `.pyc` files left behind.
+ raise ImportError(name=module_name)
mod.__time__ = os.path.getmtime(mod.__file__)
mod.__addon_enabled__ = False
except Exception as ex:
diff --git a/release/scripts/modules/animsys_refactor.py b/release/scripts/modules/animsys_refactor.py
index 97e8a8dd144..fd4952e2a53 100644
--- a/release/scripts/modules/animsys_refactor.py
+++ b/release/scripts/modules/animsys_refactor.py
@@ -32,12 +32,6 @@ import bpy
IS_TESTING = False
-def drepr(string):
- # is there a less crappy way to do this in python?, re.escape also escapes
- # single quotes strings so can't use it.
- return '"%s"' % repr(string)[1:-1].replace("\"", "\\\"").replace("\\'", "'")
-
-
def classes_recursive(base_type, clss=None):
if clss is None:
clss = [base_type]
@@ -66,7 +60,7 @@ class DataPathBuilder:
if type(key) is int:
str_value = '[%d]' % key
elif type(key) is str:
- str_value = '[%s]' % drepr(key)
+ str_value = '["%s"]' % bpy.utils.escape_identifier(key)
else:
raise Exception("unsupported accessor %r of type %r (internal error)" % (key, type(key)))
return DataPathBuilder(self.data_path + (str_value, ))
diff --git a/release/scripts/modules/bl_rna_utils/__init__.py b/release/scripts/modules/bl_rna_utils/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/release/scripts/modules/bl_rna_utils/__init__.py
diff --git a/release/scripts/modules/bl_rna_utils/data_path.py b/release/scripts/modules/bl_rna_utils/data_path.py
new file mode 100644
index 00000000000..42942b7a295
--- /dev/null
+++ b/release/scripts/modules/bl_rna_utils/data_path.py
@@ -0,0 +1,91 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+__all__ = (
+ "property_definition_from_data_path",
+ "decompose_data_path",
+)
+
+class _TokenizeDataPath:
+ """
+ Class to split up tokens of a data-path.
+
+ Note that almost all access generates new objects with additional paths,
+ with the exception of iteration which is the intended way to access the resulting data."""
+ __slots__ = (
+ "data_path",
+ )
+
+ def __init__(self, attrs):
+ self.data_path = attrs
+
+ def __getattr__(self, attr):
+ return _TokenizeDataPath(self.data_path + ((".%s" % attr),))
+
+ def __getitem__(self, key):
+ return _TokenizeDataPath(self.data_path + (("[%r]" % (key,)),))
+
+ def __call__(self, *args, **kw):
+ value_str = ", ".join([
+ val for val in (
+ ", ".join(repr(value) for value in args),
+ ", ".join(["%s=%r" % (key, value) for key, value in kw.items()]),
+ ) if val])
+ return _TokenizeDataPath(self.data_path + ('(%s)' % value_str, ))
+
+ def __iter__(self):
+ return iter(self.data_path)
+
+
+def decompose_data_path(data_path):
+ """
+ Return the components of a data path split into a list.
+ """
+ ns = {"base": _TokenizeDataPath(())}
+ return list(eval("base" + data_path, ns, ns))
+
+
+def property_definition_from_data_path(base, data_path):
+ """
+ Return an RNA property definition from an object and a data path.
+
+ In Blender this is often used with ``context`` as the base and a
+ path that it references, for example ``.space_data.lock_camera``.
+ """
+ data = decompose_data_path(data_path)
+ while data and (not data[-1].startswith(".")):
+ data.pop()
+
+ if (not data) or (not data[-1].startswith(".")) or (len(data) < 2):
+ return None
+
+ data_path_head = "".join(data[:-1])
+ data_path_tail = data[-1]
+
+ value_head = eval("base" + data_path_head)
+ value_head_rna = getattr(value_head, "bl_rna", None)
+ if value_head_rna is None:
+ return None
+
+ value_tail = value_head.bl_rna.properties.get(data_path_tail[1:])
+ if not value_tail:
+ return None
+
+ return value_tail
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 2fb0e9a0bea..68e273f2244 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -1694,6 +1694,7 @@ def km_image(params):
("image.view_all", {"type": 'HOME', "value": 'PRESS', "shift": True},
{"properties": [("fit_view", True)]}),
("image.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
+ ("image.view_cursor_center", {"type": 'C', "value": 'PRESS', "shift": True}, None),
("image.view_pan", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None),
("image.view_pan", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True}, None),
("image.view_pan", {"type": 'TRACKPADPAN', "value": 'ANY'}, None),
diff --git a/release/scripts/startup/bl_operators/anim.py b/release/scripts/startup/bl_operators/anim.py
index 8ec9bececc5..81a28964389 100644
--- a/release/scripts/startup/bl_operators/anim.py
+++ b/release/scripts/startup/bl_operators/anim.py
@@ -355,7 +355,8 @@ class UpdateAnimatedTransformConstraint(Operator):
use_convert_to_radians: BoolProperty(
name="Convert to Radians",
- description="Convert fcurves/drivers affecting rotations to radians (Warning: use this only once!)",
+ description="Convert f-curves/drivers affecting rotations to radians.\n"
+ "Warning: Use this only once",
default=True,
)
@@ -430,22 +431,9 @@ class UpdateAnimatedTransformConstraint(Operator):
return {'FINISHED'}
-class ANIM_OT_show_group_colors_deprecated(Operator):
- """This option moved to Preferences > Animation"""
-
- bl_idname = "anim.show_group_colors_deprecated"
- bl_label = "Show Group Colors"
- bl_options = {'REGISTER'}
-
- @classmethod
- def poll(cls, _context):
- return False
-
-
classes = (
ANIM_OT_keying_set_export,
NLA_OT_bake,
ClearUselessActions,
UpdateAnimatedTransformConstraint,
- ANIM_OT_show_group_colors_deprecated,
)
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 2f97942faa4..35826cea860 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -95,6 +95,76 @@ def context_path_validate(context, data_path):
return value
+def context_path_to_rna_property(context, data_path):
+ from bl_rna_utils.data_path import property_definition_from_data_path
+ rna_prop = property_definition_from_data_path(context, "." + data_path)
+ if rna_prop is not None:
+ return rna_prop
+ return None
+
+
+def context_path_decompose(data_path):
+ # Decompose a data_path into 3 components:
+ # base_path, prop_attr, prop_item, where:
+ # `"foo.bar["baz"].fiz().bob.buz[10][2]"`, returns...
+ # `("foo.bar["baz"].fiz().bob", "buz", "[10][2]")`
+ #
+ # This is useful as we often want the base and the property, ignoring any item access.
+ # Note that item access includes function calls since these aren't properties.
+ #
+ # Note that the `.` is removed from the start of the first and second values,
+ # this is done because `.attr` isn't convenient to use as an argument,
+ # also the convention is not to include this within the data paths or the operator logic for `bpy.ops.wm.*`.
+ from bl_rna_utils.data_path import decompose_data_path
+ path_split = decompose_data_path("." + data_path)
+
+ # Find the last property that isn't a function call.
+ value_prev = ""
+ i = len(path_split)
+ while (i := i - 1) >= 0:
+ value = path_split[i]
+ if value.startswith("."):
+ if not value_prev.startswith("("):
+ break
+ value_prev = value
+
+ if i != -1:
+ base_path = "".join(path_split[:i])
+ prop_attr = path_split[i]
+ prop_item = "".join(path_split[i + 1:])
+
+ if base_path:
+ assert(base_path.startswith("."))
+ base_path= base_path[1:]
+ if prop_attr:
+ assert(prop_attr.startswith("."))
+ prop_attr = prop_attr[1:]
+ else:
+ # If there are no properties, everything is an item.
+ # Note that should not happen in practice with values which are added onto `context`,
+ # include since it's correct to account for this case and not doing so will create a confusing exception.
+ base_path = ""
+ prop_attr = ""
+ prop_item = "".join(path_split)
+
+ return (base_path, prop_attr, prop_item)
+
+
+def description_from_data_path(base, data_path, *, prefix, value=Ellipsis):
+ if context_path_validate(base, data_path) is Ellipsis:
+ return None
+
+ if (
+ (rna_prop := context_path_to_rna_property(base, data_path)) and
+ (description := rna_prop.description)
+ ):
+ description = "%s: %s" % (prefix, description)
+ if value != Ellipsis:
+ description = "%s\n%s: %s" % (description, iface_("Value"), str(value))
+ return description
+ return None
+
+
def operator_value_is_undo(value):
if value in {None, Ellipsis}:
return False
@@ -120,12 +190,9 @@ def operator_value_is_undo(value):
def operator_path_is_undo(context, data_path):
- # note that if we have data paths that use strings this could fail
- # luckily we don't do this!
- #
- # When we can't find the data owner assume no undo is needed.
- data_path_head = data_path.rpartition(".")[0]
+ data_path_head, _, _ = context_path_decompose(data_path)
+ # When we can't find the data owner assume no undo is needed.
if not data_path_head:
return False
@@ -168,6 +235,10 @@ class WM_OT_context_set_boolean(Operator):
default=True,
)
+ @classmethod
+ def description(cls, context, props):
+ return description_from_data_path(context, props.data_path, prefix=iface_("Assign"), value=props.value)
+
execute = execute_context_assign
@@ -185,6 +256,10 @@ class WM_OT_context_set_int(Operator): # same as enum
)
relative: rna_relative_prop
+ @classmethod
+ def description(cls, context, props):
+ return description_from_data_path(context, props.data_path, prefix="Assign", value=props.value)
+
execute = execute_context_assign
@@ -201,6 +276,10 @@ class WM_OT_context_scale_float(Operator):
default=1.0,
)
+ @classmethod
+ def description(cls, context, props):
+ return description_from_data_path(context, props.data_path, prefix=iface_("Scale"), value=props.value)
+
def execute(self, context):
data_path = self.data_path
if context_path_validate(context, data_path) is Ellipsis:
@@ -235,6 +314,10 @@ class WM_OT_context_scale_int(Operator):
options={'SKIP_SAVE'},
)
+ @classmethod
+ def description(cls, context, props):
+ return description_from_data_path(context, props.data_path, prefix=iface_("Scale"), value=props.value)
+
def execute(self, context):
data_path = self.data_path
if context_path_validate(context, data_path) is Ellipsis:
@@ -274,6 +357,10 @@ class WM_OT_context_set_float(Operator): # same as enum
)
relative: rna_relative_prop
+ @classmethod
+ def description(cls, context, props):
+ return description_from_data_path(context, props.data_path, prefix="Assign", value=props.value)
+
execute = execute_context_assign
@@ -290,6 +377,10 @@ class WM_OT_context_set_string(Operator): # same as enum
maxlen=1024,
)
+ @classmethod
+ def description(cls, context, props):
+ return description_from_data_path(context, props.data_path, prefix=iface_("Assign"), value=props.value)
+
execute = execute_context_assign
@@ -306,6 +397,10 @@ class WM_OT_context_set_enum(Operator):
maxlen=1024,
)
+ @classmethod
+ def description(cls, context, props):
+ return description_from_data_path(context, props.data_path, prefix=iface_("Assign"), value=props.value)
+
execute = execute_context_assign
@@ -322,6 +417,10 @@ class WM_OT_context_set_value(Operator):
maxlen=1024,
)
+ @classmethod
+ def description(cls, context, props):
+ return description_from_data_path(context, props.data_path, prefix=iface_("Assign"), value=props.value)
+
def execute(self, context):
data_path = self.data_path
if context_path_validate(context, data_path) is Ellipsis:
@@ -339,6 +438,13 @@ class WM_OT_context_toggle(Operator):
data_path: rna_path_prop
module: rna_module_prop
+ @classmethod
+ def description(cls, context, props):
+ # Currently unsupported, it might be possible to extract this.
+ if props.module:
+ return None
+ return description_from_data_path(context, props.data_path, prefix=iface_("Toggle"))
+
def execute(self, context):
data_path = self.data_path
@@ -375,6 +481,11 @@ class WM_OT_context_toggle_enum(Operator):
maxlen=1024,
)
+ @classmethod
+ def description(cls, context, props):
+ value = "(%r, %r)" % (props.value_1, props.value_2)
+ return description_from_data_path(context, props.data_path, prefix=iface_("Toggle"), value=value)
+
def execute(self, context):
data_path = self.data_path
@@ -406,6 +517,10 @@ class WM_OT_context_cycle_int(Operator):
reverse: rna_reverse_prop
wrap: rna_wrap_prop
+ @classmethod
+ def description(cls, context, props):
+ return description_from_data_path(context, props.data_path, prefix=iface_("Cycle"))
+
def execute(self, context):
data_path = self.data_path
value = context_path_validate(context, data_path)
@@ -442,6 +557,10 @@ class WM_OT_context_cycle_enum(Operator):
reverse: rna_reverse_prop
wrap: rna_wrap_prop
+ @classmethod
+ def description(cls, context, props):
+ return description_from_data_path(context, props.data_path, prefix=iface_("Cycle"))
+
def execute(self, context):
data_path = self.data_path
value = context_path_validate(context, data_path)
@@ -450,22 +569,11 @@ class WM_OT_context_cycle_enum(Operator):
orig_value = value
- # Have to get rna enum values
- rna_struct_str, rna_prop_str = data_path.rsplit('.', 1)
- i = rna_prop_str.find('[')
-
- # just in case we get "context.foo.bar[0]"
- if i != -1:
- rna_prop_str = rna_prop_str[0:i]
-
- rna_struct = eval("context.%s.rna_type" % rna_struct_str)
-
- rna_prop = rna_struct.properties[rna_prop_str]
-
+ rna_prop = context_path_to_rna_property(context, data_path)
if type(rna_prop) != bpy.types.EnumProperty:
raise Exception("expected an enum property")
- enums = rna_struct.properties[rna_prop_str].enum_items.keys()
+ enums = rna_prop.enum_items.keys()
orig_index = enums.index(orig_value)
# Have the info we need, advance to the next item.
@@ -498,6 +606,10 @@ class WM_OT_context_cycle_array(Operator):
data_path: rna_path_prop
reverse: rna_reverse_prop
+ @classmethod
+ def description(cls, context, props):
+ return description_from_data_path(context, props.data_path, prefix=iface_("Cycle"))
+
def execute(self, context):
data_path = self.data_path
value = context_path_validate(context, data_path)
@@ -523,6 +635,10 @@ class WM_OT_context_menu_enum(Operator):
data_path: rna_path_prop
+ @classmethod
+ def description(cls, context, props):
+ return description_from_data_path(context, props.data_path, prefix=iface_("Menu"))
+
def execute(self, context):
data_path = self.data_path
value = context_path_validate(context, data_path)
@@ -530,15 +646,15 @@ class WM_OT_context_menu_enum(Operator):
if value is Ellipsis:
return {'PASS_THROUGH'}
- base_path, prop_string = data_path.rsplit(".", 1)
+ base_path, prop_attr, _ = context_path_decompose(data_path)
value_base = context_path_validate(context, base_path)
- prop = value_base.bl_rna.properties[prop_string]
+ rna_prop = context_path_to_rna_property(context, data_path)
def draw_cb(self, context):
layout = self.layout
- layout.prop(value_base, prop_string, expand=True)
+ layout.prop(value_base, prop_attr, expand=True)
- context.window_manager.popup_menu(draw_func=draw_cb, title=prop.name, icon=prop.icon)
+ context.window_manager.popup_menu(draw_func=draw_cb, title=rna_prop.name, icon=rna_prop.icon)
return {'FINISHED'}
@@ -550,6 +666,10 @@ class WM_OT_context_pie_enum(Operator):
data_path: rna_path_prop
+ @classmethod
+ def description(cls, context, props):
+ return description_from_data_path(context, props.data_path, prefix=iface_("Pie Menu"))
+
def invoke(self, context, event):
wm = context.window_manager
data_path = self.data_path
@@ -558,15 +678,15 @@ class WM_OT_context_pie_enum(Operator):
if value is Ellipsis:
return {'PASS_THROUGH'}
- base_path, prop_string = data_path.rsplit(".", 1)
+ base_path, prop_attr, _ = context_path_decompose(data_path)
value_base = context_path_validate(context, base_path)
- prop = value_base.bl_rna.properties[prop_string]
+ rna_prop = context_path_to_rna_property(context, data_path)
def draw_cb(self, context):
layout = self.layout
- layout.prop(value_base, prop_string, expand=True)
+ layout.prop(value_base, prop_attr, expand=True)
- wm.popup_menu_pie(draw_func=draw_cb, title=prop.name, icon=prop.icon, event=event)
+ wm.popup_menu_pie(draw_func=draw_cb, title=rna_prop.name, icon=rna_prop.icon, event=event)
return {'FINISHED'}
@@ -587,11 +707,15 @@ class WM_OT_operator_pie_enum(Operator):
maxlen=1024,
)
+ @classmethod
+ def description(cls, context, props):
+ return description_from_data_path(context, props.data_path, prefix=iface_("Pie Menu"))
+
def invoke(self, context, event):
wm = context.window_manager
data_path = self.data_path
- prop_string = self.prop_string
+ prop_attr = self.prop_string
# same as eval("bpy.ops." + data_path)
op_mod_str, ob_id_str = data_path.split(".", 1)
@@ -607,7 +731,7 @@ class WM_OT_operator_pie_enum(Operator):
def draw_cb(self, context):
layout = self.layout
pie = layout.menu_pie()
- pie.operator_enum(data_path, prop_string)
+ pie.operator_enum(data_path, prop_attr)
wm.popup_menu_pie(draw_func=draw_cb, title=op_rna.name, event=event)
@@ -631,17 +755,17 @@ class WM_OT_context_set_id(Operator):
value = self.value
data_path = self.data_path
- # match the pointer type from the target property to bpy.data.*
+ # Match the pointer type from the target property to `bpy.data.*`
# so we lookup the correct list.
- data_path_base, data_path_prop = data_path.rsplit(".", 1)
- data_prop_rna = eval("context.%s" % data_path_base).rna_type.properties[data_path_prop]
- data_prop_rna_type = data_prop_rna.fixed_type
+
+ rna_prop = context_path_to_rna_property(context, data_path)
+ rna_prop_fixed_type = rna_prop.fixed_type
id_iter = None
for prop in bpy.data.rna_type.properties:
if prop.rna_type.identifier == "CollectionProperty":
- if prop.fixed_type == data_prop_rna_type:
+ if prop.fixed_type == rna_prop_fixed_type:
id_iter = prop.identifier
break
diff --git a/release/scripts/startup/bl_ui/properties_collection.py b/release/scripts/startup/bl_ui/properties_collection.py
index 186314f9591..c5c35121135 100644
--- a/release/scripts/startup/bl_ui/properties_collection.py
+++ b/release/scripts/startup/bl_ui/properties_collection.py
@@ -77,6 +77,7 @@ class COLLECTION_PT_instancing(CollectionButtonsPanel, Panel):
class COLLECTION_PT_lineart_collection(CollectionButtonsPanel, Panel):
bl_label = "Line Art"
+ bl_order = 10
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index 4cdcab45926..87572fcd438 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -86,12 +86,19 @@ class DATA_PT_display(ArmatureButtonsPanel, Panel):
col = layout.column(heading="Show")
col.prop(arm, "show_names", text="Names")
- col.prop(arm, "show_axes", text="Axes")
col.prop(arm, "show_bone_custom_shapes", text="Shapes")
col.prop(arm, "show_group_colors", text="Group Colors")
+
if ob:
col.prop(ob, "show_in_front", text="In Front")
+ col = layout.column(align=False, heading="Axes")
+ row = col.row(align=True)
+ row.prop(arm, "show_axes", text="")
+ sub = row.row(align=True)
+ sub.active = arm.show_axes
+ sub.prop(arm, "axes_position", text="Position")
+
class DATA_MT_bone_group_context_menu(Menu):
bl_label = "Bone Group Specials"
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index d85078d4ec2..aca7ba3c5ad 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -277,6 +277,7 @@ class MATERIAL_PT_viewport(MaterialButtonsPanel, Panel):
class MATERIAL_PT_lineart(MaterialButtonsPanel, Panel):
bl_label = "Line Art"
bl_options = {'DEFAULT_CLOSED'}
+ bl_order = 10
@classmethod
def poll(cls, context):
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index b74100aa570..033e6196323 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -311,6 +311,7 @@ class OBJECT_PT_instancing_size(ObjectButtonsPanel, Panel):
class OBJECT_PT_lineart(ObjectButtonsPanel, Panel):
bl_label = "Line Art"
bl_options = {'DEFAULT_CLOSED'}
+ bl_order = 10
@classmethod
def poll(cls, context):
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index 82f43790d72..4ddb4953fbd 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -74,10 +74,6 @@ class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
- row = layout.row(align=True)
- row.alignment = 'LEFT'
- row.label(text="Enable physics for:")
-
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
obj = context.object
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py
index 84f83559da6..e7893b8c448 100644
--- a/release/scripts/startup/bl_ui/space_dopesheet.py
+++ b/release/scripts/startup/bl_ui/space_dopesheet.py
@@ -348,8 +348,6 @@ class DOPESHEET_MT_view(Menu):
col.active = context.space_data.mode != 'SHAPEKEY'
col.prop(st, "show_sliders")
- if bpy.app.version < (2, 93):
- layout.operator("anim.show_group_colors_deprecated", icon='CHECKBOX_HLT')
layout.prop(st, "show_interpolation")
layout.prop(st, "show_extremes")
layout.prop(st, "use_auto_merge_keyframes")
diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py
index 9ba3bd8f8cc..f8521592dd9 100644
--- a/release/scripts/startup/bl_ui/space_graph.py
+++ b/release/scripts/startup/bl_ui/space_graph.py
@@ -18,7 +18,6 @@
# <pep8 compliant>
-import bpy
from bpy.types import Header, Menu, Panel
from bl_ui.space_dopesheet import (
DopesheetFilterPopoverBase,
@@ -120,10 +119,6 @@ class GRAPH_MT_view(Menu):
layout.prop(st, "use_realtime_update")
layout.prop(st, "show_cursor")
layout.prop(st, "show_sliders")
-
- if bpy.app.version < (2, 93):
- layout.operator("anim.show_group_colors_deprecated", icon='CHECKBOX_HLT')
-
layout.prop(st, "use_auto_merge_keyframes")
if st.mode != 'DRIVERS':
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index a85dd70e8f4..d8cfa9dcc82 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -481,7 +481,7 @@ class NODE_MT_context_menu(Menu):
class NODE_PT_active_node_generic(Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
- bl_category = "Item"
+ bl_category = "Node"
bl_label = "Node"
@classmethod
@@ -499,7 +499,7 @@ class NODE_PT_active_node_generic(Panel):
class NODE_PT_active_node_color(Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
- bl_category = "Item"
+ bl_category = "Node"
bl_label = "Color"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = 'NODE_PT_active_node_generic'
@@ -529,7 +529,7 @@ class NODE_PT_active_node_color(Panel):
class NODE_PT_active_node_properties(Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
- bl_category = "Item"
+ bl_category = "Node"
bl_label = "Properties"
bl_options = {'DEFAULT_CLOSED'}
@@ -570,7 +570,7 @@ class NODE_PT_active_node_properties(Panel):
class NODE_PT_texture_mapping(Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
- bl_category = "Item"
+ bl_category = "Node"
bl_label = "Texture Mapping"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
index 7219922c379..adab0b0c88a 100644
--- a/release/scripts/startup/bl_ui/space_topbar.py
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -469,6 +469,8 @@ class TOPBAR_MT_file_import(Menu):
if bpy.app.build_options.alembic:
self.layout.operator("wm.alembic_import", text="Alembic (.abc)")
+ self.layout.operator("wm.gpencil_import_svg", text="SVG as Grease Pencil")
+
class TOPBAR_MT_file_export(Menu):
bl_idname = "TOPBAR_MT_file_export"
@@ -485,6 +487,13 @@ class TOPBAR_MT_file_export(Menu):
self.layout.operator(
"wm.usd_export", text="Universal Scene Description (.usd, .usdc, .usda)")
+ # Pugixml lib dependency
+ if bpy.app.build_options.pugixml:
+ self.layout.operator("wm.gpencil_export_svg", text="Grease Pencil as SVG")
+ # Haru lib dependency
+ if bpy.app.build_options.haru:
+ self.layout.operator("wm.gpencil_export_pdf", text="Grease Pencil as PDF")
+
class TOPBAR_MT_file_external_data(Menu):
bl_label = "External Data"
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 96695ff1be5..f44cf23fb58 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -2244,6 +2244,7 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
({"property": "use_switch_object_operator"}, "T80402"),
({"property": "use_sculpt_tools_tilt"}, "T82877"),
({"property": "use_asset_browser"}, ("project/profile/124/", "Milestone 1")),
+ ({"property": "use_override_templates"}, ("T73318", "Milestone 4")),
),
)
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 72baa5331bf..831fc06eda5 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -622,9 +622,15 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
@classmethod
def poll(cls, context):
- settings = cls.paint_settings(context)
- return (settings and settings.brush and
- (context.sculpt_object or context.image_paint_object or context.vertex_paint_object))
+ if (
+ (settings := cls.paint_settings(context)) and
+ (brush := settings.brush)
+ ):
+ if context.sculpt_object or context.vertex_paint_object:
+ return True
+ elif context.image_paint_object:
+ return (brush.image_tool == 'DRAW')
+ return False
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index febb31af188..7e887caf3f2 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -368,6 +368,7 @@ compositor_node_categories = [
NodeItem("CompositorNodePixelate"),
NodeItem("CompositorNodeSunBeams"),
NodeItem("CompositorNodeDenoise"),
+ NodeItem("CompositorNodeAntiAliasing"),
]),
CompositorNodeCategory("CMP_OP_VECTOR", "Vector", items=[
NodeItem("CompositorNodeNormal"),
@@ -484,6 +485,7 @@ geometry_node_categories = [
GeometryNodeCategory("GEO_ATTRIBUTE", "Attribute", items=[
NodeItem("GeometryNodeAttributeRandomize"),
NodeItem("GeometryNodeAttributeMath"),
+ NodeItem("GeometryNodeAttributeClamp"),
NodeItem("GeometryNodeAttributeCompare"),
NodeItem("GeometryNodeAttributeConvert"),
NodeItem("GeometryNodeAttributeFill"),
@@ -495,6 +497,7 @@ geometry_node_categories = [
NodeItem("GeometryNodeAttributeCombineXYZ"),
NodeItem("GeometryNodeAttributeSeparateXYZ"),
NodeItem("GeometryNodeAttributeRemove"),
+ NodeItem("GeometryNodeAttributeMapRange"),
]),
GeometryNodeCategory("GEO_COLOR", "Color", items=[
NodeItem("ShaderNodeValToRGB"),
@@ -520,7 +523,16 @@ geometry_node_categories = [
NodeItem("GeometryNodeEdgeSplit"),
NodeItem("GeometryNodeSubdivisionSurface"),
NodeItem("GeometryNodeSubdivide"),
-
+ ]),
+ GeometryNodeCategory("GEO_PRIMITIVES", "Mesh Primitives", items=[
+ NodeItem("GeometryNodeMeshCircle"),
+ NodeItem("GeometryNodeMeshCone"),
+ NodeItem("GeometryNodeMeshCube"),
+ NodeItem("GeometryNodeMeshCylinder"),
+ NodeItem("GeometryNodeMeshGrid"),
+ NodeItem("GeometryNodeMeshIcoSphere"),
+ NodeItem("GeometryNodeMeshLine"),
+ NodeItem("GeometryNodeMeshUVSphere"),
]),
GeometryNodeCategory("GEO_POINT", "Point", items=[
NodeItem("GeometryNodePointDistribute"),
@@ -531,20 +543,6 @@ geometry_node_categories = [
NodeItem("GeometryNodeRotatePoints"),
NodeItem("GeometryNodeAlignRotationToVector"),
]),
- GeometryNodeCategory("GEO_VOLUME", "Volume", items=[
- NodeItem("GeometryNodePointsToVolume"),
- NodeItem("GeometryNodeVolumeToMesh"),
- ]),
- GeometryNodeCategory("GEO_PRIMITIVES", "Mesh Primitives", items=[
- NodeItem("GeometryNodeMeshCube"),
- NodeItem("GeometryNodeMeshCircle"),
- NodeItem("GeometryNodeMeshUVSphere"),
- NodeItem("GeometryNodeMeshIcoSphere"),
- NodeItem("GeometryNodeMeshCylinder"),
- NodeItem("GeometryNodeMeshCone"),
- NodeItem("GeometryNodeMeshLine"),
- NodeItem("GeometryNodeMeshPlane"),
- ]),
GeometryNodeCategory("GEO_UTILITIES", "Utilities", items=[
NodeItem("ShaderNodeMapRange"),
NodeItem("ShaderNodeClamp"),
@@ -558,6 +556,10 @@ geometry_node_categories = [
NodeItem("ShaderNodeVectorMath"),
NodeItem("ShaderNodeVectorRotate"),
]),
+ GeometryNodeCategory("GEO_VOLUME", "Volume", items=[
+ NodeItem("GeometryNodePointsToVolume"),
+ NodeItem("GeometryNodeVolumeToMesh"),
+ ]),
GeometryNodeCategory("GEO_GROUP", "Group", items=node_group_items),
GeometryNodeCategory("GEO_LAYOUT", "Layout", items=[
NodeItem("NodeFrame"),
diff --git a/release/scripts/templates_osl/basic_shader.osl b/release/scripts/templates_osl/basic_shader.osl
new file mode 100644
index 00000000000..3c5240a1bbd
--- /dev/null
+++ b/release/scripts/templates_osl/basic_shader.osl
@@ -0,0 +1,10 @@
+shader basic_shader(
+ float in_float = 1.0,
+ color in_color = color(1.0, 1.0, 1.0),
+ output float out_float = 0.0,
+ output color out_color = color(0.0, 0.0, 0.0)
+ )
+{
+ out_float = in_float * 2.0;
+ out_color = in_color * 2.0;
+}
diff --git a/release/scripts/templates_py/image_processing.py b/release/scripts/templates_py/image_processing.py
new file mode 100644
index 00000000000..2392faf440c
--- /dev/null
+++ b/release/scripts/templates_py/image_processing.py
@@ -0,0 +1,35 @@
+# This sample shows the an efficient way of doing image processing
+# over Blender's images using Python.
+
+import bpy
+import numpy as np
+
+
+input_image_name = "Image"
+output_image_name = "NewImage"
+
+# Retrieve input image.
+input_image = bpy.data.images[input_image_name]
+w, h = input_image.size
+
+# Allocate a numpy array to manipulate pixel data.
+pixel_data = np.zeros((w, h, 4), 'f')
+
+# Fast copy of pixel data from bpy.data to numpy array.
+input_image.pixels.foreach_get(pixel_data.ravel())
+
+# Do whatever image processing you want using numpy here:
+# Example 1: Inverse red green and blue channels.
+pixel_data[:,:,:3] = 1.0 - pixel_data[:,:,:3]
+# Example 2: Change gamma on the red channel.
+pixel_data[:,:,0] = np.power(pixel_data[:,:,0], 1.5)
+
+# Create output image.
+if output_image_name in bpy.data.images:
+ output_image = bpy.data.images[output_image_name]
+else:
+ output_image = bpy.data.images.new(output_image_name, width=w, height=h)
+
+# Copy of pixel data from numpy array back to the output image.
+output_image.pixels.foreach_set(pixel_data.ravel())
+output_image.update()
diff --git a/source/blender/blendthumb/CMakeLists.txt b/source/blender/blendthumb/CMakeLists.txt
index cb121cb9c8d..b42ca284ecb 100644
--- a/source/blender/blendthumb/CMakeLists.txt
+++ b/source/blender/blendthumb/CMakeLists.txt
@@ -31,6 +31,7 @@ set(SRC
string(APPEND CMAKE_SHARED_LINKER_FLAGS_DEBUG " /nodefaultlib:MSVCRT.lib")
add_library(BlendThumb SHARED ${SRC})
+setup_platform_linker_flags(BlendThumb)
target_link_libraries(BlendThumb ${ZLIB_LIBRARIES})
install(
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 717cfa607ad..e27cb2be8ee 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -188,10 +188,6 @@ void BKE_pose_itasc_init(struct bItasc *itasc);
/* Checks if a bone is part of an IK chain or not */
bool BKE_pose_channel_in_IK_chain(struct Object *ob, struct bPoseChannel *pchan);
-/* clears BONE_UNKEYED flags for frame changing */
-// XXX to be deprecated for a more general solution in animsys...
-void framechange_poses_clear_unkeyed(struct Main *bmain);
-
/* Bone Groups API --------------------- */
/* Adds a new bone-group */
@@ -227,6 +223,9 @@ void BKE_pose_blend_read_data(struct BlendDataReader *reader, struct bPose *pose
void BKE_pose_blend_read_lib(struct BlendLibReader *reader, struct Object *ob, struct bPose *pose);
void BKE_pose_blend_read_expand(struct BlendExpander *expander, struct bPose *pose);
+/* action_mirror.c */
+void BKE_action_flip_with_pose(struct bAction *act, struct Object *ob_arm);
+
#ifdef __cplusplus
};
#endif
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index a0ba1415b41..0bd817f0da1 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -342,6 +342,8 @@ void BKE_pchan_bbone_deform_segment_index(const struct bPoseChannel *pchan,
#define PBONE_SELECTABLE(arm, bone) \
(PBONE_VISIBLE(arm, bone) && !((bone)->flag & BONE_UNSELECTABLE))
+#define PBONE_SELECTED(arm, bone) (((bone)->flag & BONE_SELECTED) & PBONE_VISIBLE(arm, bone))
+
/* context.selected_pose_bones */
#define FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN(_ob, _pchan) \
for (bPoseChannel *_pchan = (_ob)->pose->chanbase.first; _pchan; _pchan = _pchan->next) { \
diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h
index a98bfd1e3df..30a595dba8e 100644
--- a/source/blender/blenkernel/BKE_attribute.h
+++ b/source/blender/blenkernel/BKE_attribute.h
@@ -39,12 +39,12 @@ struct ReportList;
/* Attribute.domain */
typedef enum AttributeDomain {
- ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */
- ATTR_DOMAIN_POINT = 0, /* Mesh, Hair or PointCloud Point */
- ATTR_DOMAIN_EDGE = 1, /* Mesh Edge */
- ATTR_DOMAIN_CORNER = 2, /* Mesh Corner */
- ATTR_DOMAIN_POLYGON = 3, /* Mesh Polygon */
- ATTR_DOMAIN_CURVE = 4, /* Hair Curve */
+ ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */
+ ATTR_DOMAIN_POINT = 0, /* Mesh, Hair or PointCloud Point */
+ ATTR_DOMAIN_EDGE = 1, /* Mesh Edge */
+ ATTR_DOMAIN_CORNER = 2, /* Mesh Corner */
+ ATTR_DOMAIN_FACE = 3, /* Mesh Face */
+ ATTR_DOMAIN_CURVE = 4, /* Hair Curve */
ATTR_DOMAIN_NUM
} AttributeDomain;
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index c9585430ae2..0fcc2fe8f46 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 14
+#define BLENDER_FILE_SUBVERSION 15
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index 05e60d38487..1883cebe203 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -75,8 +75,6 @@ typedef struct DispList {
int *index;
int charidx;
int totindex; /* indexed array drawing surfaces */
-
- unsigned int *bevel_split; /* BLI_bitmap */
} DispList;
void BKE_displist_copy(struct ListBase *lbn, struct ListBase *lb);
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 4569e68ea4a..589d1839dd4 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -232,6 +232,19 @@ int BKE_fcurve_bezt_binarysearch_index(struct BezTriple array[],
int arraylen,
bool *r_replace);
+/* fcurve_cache.c */
+/* Cached f-curve look-ups, use when this needs to be done many times. */
+struct FCurvePathCache;
+struct FCurvePathCache *BKE_fcurve_pathcache_create(ListBase *list);
+void BKE_fcurve_pathcache_destroy(struct FCurvePathCache *fcache);
+struct FCurve *BKE_fcurve_pathcache_find(struct FCurvePathCache *fcache,
+ const char rna_path[],
+ const int array_index);
+int BKE_fcurve_pathcache_find_array(struct FCurvePathCache *fcache,
+ const char *rna_path,
+ struct FCurve **fcurve_result,
+ int fcurve_result_len);
+
/* get the time extents for F-Curve */
bool BKE_fcurve_calc_range(
struct FCurve *fcu, float *min, float *max, const bool do_sel_only, const bool do_min_length);
@@ -245,6 +258,14 @@ bool BKE_fcurve_calc_bounds(struct FCurve *fcu,
const bool do_sel_only,
const bool include_handles);
+float *BKE_fcurves_calc_keyed_frames_ex(struct FCurve **fcurve_array,
+ const int fcurve_array_len,
+ const float interval,
+ int *r_frames_len);
+float *BKE_fcurves_calc_keyed_frames(struct FCurve **fcurve_array,
+ const int fcurve_array_len,
+ int *r_frames_len);
+
void BKE_fcurve_active_keyframe_set(struct FCurve *fcu, const struct BezTriple *active_bezt);
int BKE_fcurve_active_keyframe_index(const struct FCurve *fcu);
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 8cc37a3e711..4454669b59a 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -313,6 +313,8 @@ struct GeometrySet {
friend bool operator==(const GeometrySet &a, const GeometrySet &b);
uint64_t hash() const;
+ void clear();
+
/* Utility methods for creation. */
static GeometrySet create_with_mesh(
Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
diff --git a/source/blender/blenkernel/BKE_geometry_set_instances.hh b/source/blender/blenkernel/BKE_geometry_set_instances.hh
index 16c28e32e3c..c372fdff049 100644
--- a/source/blender/blenkernel/BKE_geometry_set_instances.hh
+++ b/source/blender/blenkernel/BKE_geometry_set_instances.hh
@@ -39,7 +39,8 @@ struct GeometryInstanceGroup {
Vector<float4x4> transforms;
};
-Vector<GeometryInstanceGroup> geometry_set_gather_instances(const GeometrySet &geometry_set);
+void geometry_set_gather_instances(const GeometrySet &geometry_set,
+ Vector<GeometryInstanceGroup> &r_instance_groups);
GeometrySet geometry_set_realize_mesh_for_modifier(const GeometrySet &geometry_set);
GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set);
diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h
index 89a794f2df3..a9bd0a524c4 100644
--- a/source/blender/blenkernel/BKE_gpencil_geom.h
+++ b/source/blender/blenkernel/BKE_gpencil_geom.h
@@ -27,10 +27,10 @@
extern "C" {
#endif
-struct BoundBox;
struct Depsgraph;
struct Main;
struct Object;
+struct RegionView3D;
struct Scene;
struct bGPDcurve;
struct bGPDframe;
@@ -173,6 +173,20 @@ void BKE_gpencil_stroke_uniform_subdivide(struct bGPdata *gpd,
const uint32_t target_number,
const bool select);
+void BKE_gpencil_stroke_to_view_space(struct RegionView3D *rv3d,
+ struct bGPDstroke *gps,
+ const float diff_mat[4][4]);
+void BKE_gpencil_stroke_from_view_space(struct RegionView3D *rv3d,
+ struct bGPDstroke *gps,
+ const float diff_mat[4][4]);
+struct bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d,
+ struct bGPdata *gpd,
+ const struct bGPDlayer *gpl,
+ struct bGPDstroke *gps,
+ const int subdivisions,
+ const float diff_mat[4][4]);
+float BKE_gpencil_stroke_average_pressure_get(struct bGPDstroke *gps);
+bool BKE_gpencil_stroke_is_pressure_constant(struct bGPDstroke *gps);
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h
index f69580d38be..0750a3332a8 100644
--- a/source/blender/blenkernel/BKE_lib_override.h
+++ b/source/blender/blenkernel/BKE_lib_override.h
@@ -74,6 +74,7 @@ bool BKE_lib_override_library_create(struct Main *bmain,
struct ViewLayer *view_layer,
struct ID *id_root,
struct ID *id_reference);
+bool BKE_lib_override_library_template_create(struct ID *id);
bool BKE_lib_override_library_proxy_convert(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer,
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 71f188a2de1..42ed026cb01 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -483,14 +483,14 @@ void ntreeBlendReadExpand(struct BlendExpander *expander, struct bNodeTree *ntre
/** \name Node Tree Interface
* \{ */
struct bNodeSocket *ntreeFindSocketInterface(struct bNodeTree *ntree,
- int in_out,
+ eNodeSocketInOut in_out,
const char *identifier);
struct bNodeSocket *ntreeAddSocketInterface(struct bNodeTree *ntree,
- int in_out,
+ eNodeSocketInOut in_out,
const char *idname,
const char *name);
struct bNodeSocket *ntreeInsertSocketInterface(struct bNodeTree *ntree,
- int in_out,
+ eNodeSocketInOut in_out,
const char *idname,
struct bNodeSocket *next_sock,
const char *name);
@@ -556,30 +556,32 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype);
} \
((void)0)
-struct bNodeSocket *nodeFindSocket(const struct bNode *node, int in_out, const char *identifier);
+struct bNodeSocket *nodeFindSocket(const struct bNode *node,
+ eNodeSocketInOut in_out,
+ const char *identifier);
struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree,
struct bNode *node,
- int in_out,
+ eNodeSocketInOut in_out,
const char *idname,
const char *identifier,
const char *name);
struct bNodeSocket *nodeInsertSocket(struct bNodeTree *ntree,
struct bNode *node,
- int in_out,
+ eNodeSocketInOut in_out,
const char *idname,
struct bNodeSocket *next_sock,
const char *identifier,
const char *name);
struct bNodeSocket *nodeAddStaticSocket(struct bNodeTree *ntree,
struct bNode *node,
- int in_out,
+ eNodeSocketInOut in_out,
int type,
int subtype,
const char *identifier,
const char *name);
struct bNodeSocket *nodeInsertStaticSocket(struct bNodeTree *ntree,
struct bNode *node,
- int in_out,
+ eNodeSocketInOut in_out,
int type,
int subtype,
struct bNodeSocket *next_sock,
@@ -1188,6 +1190,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *localtree,
#define CMP_NODE_TRACKPOS 271
#define CMP_NODE_INPAINT 272
#define CMP_NODE_DESPECKLE 273
+#define CMP_NODE_ANTIALIASING 274
#define CMP_NODE_GLARE 301
#define CMP_NODE_TONEMAP 302
@@ -1393,7 +1396,9 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_MESH_PRIMITIVE_ICO_SPHERE 1036
#define GEO_NODE_MESH_PRIMITIVE_CONE 1037
#define GEO_NODE_MESH_PRIMITIVE_LINE 1038
-#define GEO_NODE_MESH_PRIMITIVE_PLANE 1039
+#define GEO_NODE_MESH_PRIMITIVE_GRID 1039
+#define GEO_NODE_ATTRIBUTE_MAP_RANGE 1040
+#define GEO_NODE_ATTRIBUTE_CLAMP 1041
/** \} */
diff --git a/source/blender/blenkernel/BKE_node_ui_storage.hh b/source/blender/blenkernel/BKE_node_ui_storage.hh
index a8fdbec1e8c..aa7e5180b03 100644
--- a/source/blender/blenkernel/BKE_node_ui_storage.hh
+++ b/source/blender/blenkernel/BKE_node_ui_storage.hh
@@ -58,9 +58,7 @@ class NodeTreeEvaluationContext {
uint64_t hash() const
{
- const uint64_t hash1 = blender::DefaultHash<std::string>{}(object_name_);
- const uint64_t hash2 = BLI_session_uuid_hash_uint64(&modifier_session_uuid_);
- return hash1 ^ (hash2 * 33); /* Copied from DefaultHash for std::pair. */
+ return blender::get_default_hash_2(object_name_, modifier_session_uuid_);
}
friend bool operator==(const NodeTreeEvaluationContext &a, const NodeTreeEvaluationContext &b)
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 12c40e891c9..0c2c6313dde 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -336,6 +336,12 @@ struct Mesh *BKE_object_get_evaluated_mesh(struct Object *object);
struct Mesh *BKE_object_get_pre_modified_mesh(struct Object *object);
struct Mesh *BKE_object_get_original_mesh(struct Object *object);
+/* Lattice accessors.
+ * These functions return either the regular lattice, or the edit-mode lattice,
+ * whichever is currently in use. */
+struct Lattice *BKE_object_get_lattice(const struct Object *object);
+struct Lattice *BKE_object_get_evaluated_lattice(const struct Object *object);
+
int BKE_object_insert_ptcache(struct Object *ob);
void BKE_object_delete_ptcache(struct Object *ob, int index);
struct KeyBlock *BKE_object_shapekey_insert(struct Main *bmain,
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 310ac6c4903..8fbf49b31d4 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -69,6 +69,7 @@ set(SRC
intern/CCGSubSurf_util.c
intern/DerivedMesh.cc
intern/action.c
+ intern/action_mirror.c
intern/addon.c
intern/anim_data.c
intern/anim_path.c
@@ -126,6 +127,7 @@ set(SRC
intern/editmesh_tangent.c
intern/effect.c
intern/fcurve.c
+ intern/fcurve_cache.c
intern/fcurve_driver.c
intern/fluid.c
intern/fmodifier.c
@@ -385,6 +387,7 @@ set(SRC
BKE_multires.h
BKE_nla.h
BKE_node.h
+ BKE_node_ui_storage.hh
BKE_object.h
BKE_object_deform.h
BKE_object_facemap.h
@@ -434,10 +437,10 @@ set(SRC
nla_private.h
particle_private.h
tracking_private.h
- intern/attribute_access_intern.hh
intern/CCGSubSurf.h
intern/CCGSubSurf_inline.h
intern/CCGSubSurf_intern.h
+ intern/attribute_access_intern.hh
intern/data_transfer_intern.h
intern/lib_intern.h
intern/multires_inline.h
@@ -742,7 +745,7 @@ if(WITH_GMP)
list(APPEND INC_SYS
${GMP_INCLUDE_DIRS}
)
- endif()
+endif()
# # Warnings as errors, this is too strict!
# if(MSVC)
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index f9c2a4e53ad..0b38e2d9f75 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -1316,30 +1316,6 @@ void BKE_pose_tag_update_constraint_flags(bPose *pose)
pose->flag |= POSE_CONSTRAINTS_NEED_UPDATE_FLAGS;
}
-/* Clears all BONE_UNKEYED flags for every pose channel in every pose
- * This should only be called on frame changing, when it is acceptable to
- * do this. Otherwise, these flags should not get cleared as poses may get lost.
- */
-void framechange_poses_clear_unkeyed(Main *bmain)
-{
- Object *ob;
- bPose *pose;
- bPoseChannel *pchan;
-
- /* This needs to be done for each object that has a pose */
- /* TODO: proxies may/may not be correctly handled here... (this needs checking) */
- for (ob = bmain->objects.first; ob; ob = ob->id.next) {
- /* we only need to do this on objects with a pose */
- if ((pose = ob->pose)) {
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone) {
- pchan->bone->flag &= ~BONE_UNKEYED;
- }
- }
- }
- }
-}
-
/* ************************** Bone Groups ************************** */
/* Adds a new bone-group (name may be NULL) */
diff --git a/source/blender/blenkernel/intern/action_mirror.c b/source/blender/blenkernel/intern/action_mirror.c
new file mode 100644
index 00000000000..c975d2bfb9c
--- /dev/null
+++ b/source/blender/blenkernel/intern/action_mirror.c
@@ -0,0 +1,457 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup bke
+ *
+ * Mirror/Symmetry functions applying to actions.
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_string_utils.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_fcurve.h"
+
+#include "DEG_depsgraph.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Flip the Action (Armature/Pose Objects)
+ *
+ * This flips the action using the rest pose (not the evaluated pose).
+ *
+ * Details:
+ *
+ * - Key-frames are modified in-place, creating new key-frames is not yet supported.
+ * That could be useful if a user for example only has 2x rotation channels set.
+ * In practice users typically keyframe all rotation channels or none.
+ *
+ * - F-curve modifiers are disabled for evaluation,
+ * so the values written back to the keyframes don't include modifier offsets.
+ *
+ * - Sub-frame key-frames aren't supported,
+ * this could be added if needed without much trouble.
+ *
+ * - F-curves must have a #FCurve.bezt array (sampled curves aren't supported).
+ * \{ */
+
+/**
+ * This structure is created for each pose channels F-curve,
+ * an action be evaluated and stored in `fcurve_eval`,
+ * with the mirrored values written into `bezt_array`.
+ *
+ * Store F-curve evaluated values, constructed with a sorted array of rounded keyed-frames,
+ * passed to #action_flip_pchan_cache_init.
+ */
+struct FCurve_KeyCache {
+ /**
+ * When NULL, ignore this channel.
+ */
+ FCurve *fcurve;
+ /**
+ * Cached evaluated F-curve values (without modifiers).
+ */
+ float *fcurve_eval;
+ /**
+ * Cached #FCurve.bezt values, NULL when no key-frame exists on this frame.
+ *
+ * \note The case where two keyframes round to the same frame isn't supported.
+ * In this case only the first will be used.
+ */
+ BezTriple **bezt_array;
+};
+
+/**
+ * Assign `fkc` path, using a `path` lookup for a single value.
+ */
+static void action_flip_pchan_cache_fcurve_assign_value(struct FCurve_KeyCache *fkc,
+ int index,
+ const char *path,
+ struct FCurvePathCache *fcache)
+{
+ FCurve *fcu = BKE_fcurve_pathcache_find(fcache, path, index);
+ if (fcu && fcu->bezt) {
+ fkc->fcurve = fcu;
+ }
+}
+
+/**
+ * Assign #FCurve_KeyCache.fcurve path, using a `path` lookup for an array.
+ */
+static void action_flip_pchan_cache_fcurve_assign_array(struct FCurve_KeyCache *fkc,
+ int fkc_len,
+ const char *path,
+ struct FCurvePathCache *fcache)
+{
+ FCurve **fcurves = alloca(sizeof(*fcurves) * fkc_len);
+ if (BKE_fcurve_pathcache_find_array(fcache, path, fcurves, fkc_len)) {
+ for (int i = 0; i < fkc_len; i++) {
+ if (fcurves[i] && fcurves[i]->bezt) {
+ fkc[i].fcurve = fcurves[i];
+ }
+ }
+ }
+}
+
+/**
+ * Fill in pose channel cache for each frame in `keyed_frames`.
+ *
+ * \param keyed_frames: An array of keyed_frames to evaluate,
+ * note that each frame is rounded to the nearest int.
+ * \param keyed_frames_len: The length of the `keyed_frames` array.
+ */
+static void action_flip_pchan_cache_init(struct FCurve_KeyCache *fkc,
+ const float *keyed_frames,
+ int keyed_frames_len)
+{
+ BLI_assert(fkc->fcurve != NULL);
+
+ /* Cache the F-curve values for `keyed_frames`. */
+ const int fcurve_flag = fkc->fcurve->flag;
+ fkc->fcurve->flag |= FCURVE_MOD_OFF;
+ fkc->fcurve_eval = MEM_mallocN(sizeof(float) * keyed_frames_len, __func__);
+ for (int frame_index = 0; frame_index < keyed_frames_len; frame_index++) {
+ const float evaltime = keyed_frames[frame_index];
+ fkc->fcurve_eval[frame_index] = evaluate_fcurve_only_curve(fkc->fcurve, evaltime);
+ }
+ fkc->fcurve->flag = fcurve_flag;
+
+ /* Cache the #BezTriple for `keyed_frames`, or leave as NULL. */
+ fkc->bezt_array = MEM_mallocN(sizeof(*fkc->bezt_array) * keyed_frames_len, __func__);
+ BezTriple *bezt = fkc->fcurve->bezt;
+ BezTriple *bezt_end = fkc->fcurve->bezt + fkc->fcurve->totvert;
+
+ int frame_index = 0;
+ while (frame_index < keyed_frames_len) {
+ const float evaltime = keyed_frames[frame_index];
+ const float bezt_time = roundf(bezt->vec[1][0]);
+ if (bezt_time > evaltime) {
+ fkc->bezt_array[frame_index++] = NULL;
+ }
+ else {
+ if (bezt_time == evaltime) {
+ fkc->bezt_array[frame_index++] = bezt;
+ }
+ bezt++;
+ if (bezt == bezt_end) {
+ break;
+ }
+ }
+ }
+ /* Clear remaining unset keyed_frames (if-any). */
+ while (frame_index < keyed_frames_len) {
+ fkc->bezt_array[frame_index++] = NULL;
+ }
+}
+
+/**
+ */
+static void action_flip_pchan(Object *ob_arm,
+ const bPoseChannel *pchan,
+ struct FCurvePathCache *fcache)
+{
+ /* Begin F-Curve pose channel value extraction. */
+ /* Use a fixed buffer size as it's known this can only be at most:
+ * `pose.bones["{MAXBONENAME}"].rotation_quaternion`. */
+ char path_xform[256];
+ char pchan_name_esc[sizeof(((bActionChannel *)NULL)->name) * 2];
+ BLI_str_escape(pchan_name_esc, pchan->name, sizeof(pchan_name_esc));
+ const int path_xform_prefix_len = SNPRINTF(path_xform, "pose.bones[\"%s\"]", pchan_name_esc);
+ char *path_xform_suffix = path_xform + path_xform_prefix_len;
+ const int path_xform_suffix_len = sizeof(path_xform) - path_xform_prefix_len;
+
+ /* Lookup and assign all available #FCurve channels,
+ * unavailable channels are left NULL. */
+
+ /**
+ * Structure to store transformation F-curves corresponding to a pose bones transformation.
+ * Match struct member names from #bPoseChannel so macros avoid repetition.
+ *
+ * \note There is no need to read values unless they influence the 4x4 transform matrix,
+ * and no need to write values back unless they would be changed by a modified matrix.
+ * So `rotmode` needs to be read, but doesn't need to be written back to.
+ *
+ * Most bendy-bone settings don't need to be included either, flipping their RNA paths is enough.
+ * Although the X/Y settings could make sense to transform, in practice it would only
+ * work well if the rotation happened to swap X/Y alignment, leave this for now.
+ */
+ struct {
+ struct FCurve_KeyCache loc[3], eul[3], quat[4], rotAxis[3], rotAngle, size[3], rotmode;
+ } fkc_pchan = {{{NULL}}};
+
+#define FCURVE_ASSIGN_VALUE(id, path_test_suffix, index) \
+ BLI_strncpy(path_xform_suffix, path_test_suffix, path_xform_suffix_len); \
+ action_flip_pchan_cache_fcurve_assign_value(&fkc_pchan.id, index, path_xform, fcache)
+
+#define FCURVE_ASSIGN_ARRAY(id, path_test_suffix) \
+ BLI_strncpy(path_xform_suffix, path_test_suffix, path_xform_suffix_len); \
+ action_flip_pchan_cache_fcurve_assign_array( \
+ fkc_pchan.id, ARRAY_SIZE(fkc_pchan.id), path_xform, fcache)
+
+ FCURVE_ASSIGN_ARRAY(loc, ".location");
+ FCURVE_ASSIGN_ARRAY(eul, ".rotation_euler");
+ FCURVE_ASSIGN_ARRAY(quat, ".rotation_quaternion");
+ FCURVE_ASSIGN_ARRAY(rotAxis, ".rotation_axis_angle");
+ FCURVE_ASSIGN_VALUE(rotAngle, ".rotation_axis_angle", 3);
+ FCURVE_ASSIGN_ARRAY(size, ".scale");
+ FCURVE_ASSIGN_VALUE(rotmode, ".rotation_mode", 0);
+
+#undef FCURVE_ASSIGN_VALUE
+#undef FCURVE_ASSIGN_ARRAY
+
+ /* Array of F-curves, for convenient access. */
+#define FCURVE_CHANNEL_LEN (sizeof(fkc_pchan) / sizeof(struct FCurve_KeyCache))
+ FCurve *fcurve_array[FCURVE_CHANNEL_LEN];
+ int fcurve_array_len = 0;
+
+ for (int chan = 0; chan < FCURVE_CHANNEL_LEN; chan++) {
+ struct FCurve_KeyCache *fkc = (struct FCurve_KeyCache *)(&fkc_pchan) + chan;
+ if (fkc->fcurve != NULL) {
+ fcurve_array[fcurve_array_len++] = fkc->fcurve;
+ }
+ }
+
+ /* If this pose has no transform channels, there is nothing to do. */
+ if (fcurve_array_len == 0) {
+ return;
+ }
+
+ /* Calculate an array of frames used by any of the key-frames in `fcurve_array`. */
+ int keyed_frames_len;
+ const float *keyed_frames = BKE_fcurves_calc_keyed_frames(
+ fcurve_array, fcurve_array_len, &keyed_frames_len);
+
+ /* Initialize the pose channel curve cache from the F-curve. */
+ for (int chan = 0; chan < FCURVE_CHANNEL_LEN; chan++) {
+ struct FCurve_KeyCache *fkc = (struct FCurve_KeyCache *)(&fkc_pchan) + chan;
+ if (fkc->fcurve == NULL) {
+ continue;
+ }
+ action_flip_pchan_cache_init(fkc, keyed_frames, keyed_frames_len);
+ }
+
+ /* X-axis flipping matrix. */
+ float flip_mtx[4][4];
+ unit_m4(flip_mtx);
+ flip_mtx[0][0] = -1;
+
+ bPoseChannel *pchan_flip = NULL;
+ char pchan_name_flip[MAXBONENAME];
+ BLI_string_flip_side_name(pchan_name_flip, pchan->name, false, sizeof(pchan_name_flip));
+ if (!STREQ(pchan_name_flip, pchan->name)) {
+ pchan_flip = BKE_pose_channel_find_name(ob_arm->pose, pchan_name_flip);
+ }
+
+ float arm_mat_inv[4][4];
+ invert_m4_m4(arm_mat_inv, pchan_flip ? pchan_flip->bone->arm_mat : pchan->bone->arm_mat);
+
+ /* Now flip the transformation & write it back to the F-curves in `fkc_pchan`. */
+
+ for (int frame_index = 0; frame_index < keyed_frames_len; frame_index++) {
+
+ /* Temporary pose channel to write values into,
+ * using the `fkc_pchan` values, falling back to the values in the pose channel. */
+ bPoseChannel pchan_temp = *pchan;
+
+ /* Load the values into the channel. */
+#define READ_VALUE_FLT(id) \
+ if (fkc_pchan.id.fcurve_eval != NULL) { \
+ pchan_temp.id = fkc_pchan.id.fcurve_eval[frame_index]; \
+ } \
+ ((void)0)
+
+#define READ_VALUE_INT(id) \
+ if (fkc_pchan.id.fcurve_eval != NULL) { \
+ pchan_temp.id = floorf(fkc_pchan.id.fcurve_eval[frame_index] + 0.5f); \
+ } \
+ ((void)0)
+
+#define READ_ARRAY_FLT(id) \
+ for (int i = 0; i < ARRAY_SIZE(pchan_temp.id); i++) { \
+ READ_VALUE_FLT(id[i]); \
+ } \
+ ((void)0)
+
+ READ_ARRAY_FLT(loc);
+ READ_ARRAY_FLT(eul);
+ READ_ARRAY_FLT(quat);
+ READ_ARRAY_FLT(rotAxis);
+ READ_VALUE_FLT(rotAngle);
+ READ_ARRAY_FLT(size);
+ READ_VALUE_INT(rotmode);
+
+#undef READ_ARRAY_FLT
+#undef READ_VALUE_FLT
+#undef READ_VALUE_INT
+
+ float chan_mat[4][4];
+ BKE_pchan_to_mat4(&pchan_temp, chan_mat);
+
+ /* Move to the pose-space. */
+ mul_m4_m4m4(chan_mat, pchan->bone->arm_mat, chan_mat);
+
+ /* Flip the matrix. */
+ mul_m4_m4m4(chan_mat, chan_mat, flip_mtx);
+ mul_m4_m4m4(chan_mat, flip_mtx, chan_mat);
+
+ /* Move back to bone-space space, using the flipped bone if it exists. */
+ mul_m4_m4m4(chan_mat, arm_mat_inv, chan_mat);
+
+ BKE_pchan_apply_mat4(&pchan_temp, chan_mat, false);
+
+ /* Write the values back to the F-curves. */
+#define WRITE_VALUE_FLT(id) \
+ if (fkc_pchan.id.fcurve_eval != NULL) { \
+ BezTriple *bezt = fkc_pchan.id.bezt_array[frame_index]; \
+ if (bezt != NULL) { \
+ const float delta = pchan_temp.id - bezt->vec[1][1]; \
+ bezt->vec[0][1] += delta; \
+ bezt->vec[1][1] += delta; \
+ bezt->vec[2][1] += delta; \
+ } \
+ } \
+ ((void)0)
+
+#define WRITE_ARRAY_FLT(id) \
+ for (int i = 0; i < ARRAY_SIZE(pchan_temp.id); i++) { \
+ WRITE_VALUE_FLT(id[i]); \
+ } \
+ ((void)0)
+
+ /* Write the values back the the F-curves. */
+ WRITE_ARRAY_FLT(loc);
+ WRITE_ARRAY_FLT(eul);
+ WRITE_ARRAY_FLT(quat);
+ WRITE_ARRAY_FLT(rotAxis);
+ WRITE_VALUE_FLT(rotAngle);
+ WRITE_ARRAY_FLT(size);
+ /* No need to write back 'rotmode' as it can't be transformed. */
+
+#undef WRITE_ARRAY_FLT
+#undef WRITE_VALUE_FLT
+ }
+
+ /* Recalculate handles. */
+ for (int i = 0; i < fcurve_array_len; i++) {
+ calchandles_fcurve_ex(fcurve_array[i], 0);
+ }
+
+ MEM_freeN((void *)keyed_frames);
+
+ for (int chan = 0; chan < FCURVE_CHANNEL_LEN; chan++) {
+ struct FCurve_KeyCache *fkc = (struct FCurve_KeyCache *)(&fkc_pchan) + chan;
+ if (fkc->fcurve_eval) {
+ MEM_freeN(fkc->fcurve_eval);
+ }
+ if (fkc->bezt_array) {
+ MEM_freeN(fkc->bezt_array);
+ }
+ }
+}
+
+/**
+ * Swap all RNA paths left/right.
+ */
+static void action_flip_pchan_rna_paths(struct bAction *act)
+{
+ const char *path_pose_prefix = "pose.bones[\"";
+ const int path_pose_prefix_len = strlen(path_pose_prefix);
+
+ /* Tag curves that have renamed f-curves. */
+ LISTBASE_FOREACH (bActionGroup *, agrp, &act->groups) {
+ agrp->flag &= ~AGRP_TEMP;
+ }
+
+ LISTBASE_FOREACH (FCurve *, fcu, &act->curves) {
+ if (!STRPREFIX(fcu->rna_path, path_pose_prefix)) {
+ continue;
+ }
+
+ const char *name_esc = fcu->rna_path + path_pose_prefix_len;
+ const char *name_esc_end = BLI_str_escape_find_quote(name_esc);
+
+ /* While unlikely, an RNA path could be malformed. */
+ if (UNLIKELY(name_esc_end == NULL)) {
+ continue;
+ }
+
+ char name[MAXBONENAME];
+ const size_t name_esc_len = (size_t)(name_esc_end - name_esc);
+ const size_t name_len = BLI_str_unescape(name, name_esc, name_esc_len);
+
+ /* While unlikely, data paths could be constructed that have longer names than
+ * are currently supported. */
+ if (UNLIKELY(name_len >= sizeof(name))) {
+ continue;
+ }
+
+ /* When the flipped name differs, perform the rename. */
+ char name_flip[MAXBONENAME];
+ BLI_string_flip_side_name(name_flip, name, false, sizeof(name_flip));
+ if (!STREQ(name_flip, name)) {
+ char name_flip_esc[MAXBONENAME * 2];
+ BLI_str_escape(name_flip_esc, name_flip, sizeof(name_flip_esc));
+ char *path_flip = BLI_sprintfN("pose.bones[\"%s%s", name_flip_esc, name_esc_end);
+ MEM_freeN(fcu->rna_path);
+ fcu->rna_path = path_flip;
+
+ if (fcu->grp != NULL) {
+ fcu->grp->flag |= AGRP_TEMP;
+ }
+ }
+ }
+
+ /* Rename tagged groups. */
+ LISTBASE_FOREACH (bActionGroup *, agrp, &act->groups) {
+ if ((agrp->flag & AGRP_TEMP) == 0) {
+ continue;
+ }
+ agrp->flag &= ~AGRP_TEMP;
+ char name_flip[MAXBONENAME];
+ BLI_string_flip_side_name(name_flip, agrp->name, false, sizeof(name_flip));
+ if (!STREQ(name_flip, agrp->name)) {
+ STRNCPY(agrp->name, name_flip);
+ }
+ }
+}
+
+void BKE_action_flip_with_pose(struct bAction *act, struct Object *ob_arm)
+{
+ struct FCurvePathCache *fcache = BKE_fcurve_pathcache_create(&act->curves);
+ int i;
+ LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &ob_arm->pose->chanbase, i) {
+ action_flip_pchan(ob_arm, pchan, fcache);
+ }
+ BKE_fcurve_pathcache_destroy(fcache);
+
+ action_flip_pchan_rna_paths(act);
+
+ DEG_id_tag_update(&act->id, ID_RECALC_COPY_ON_WRITE);
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/armature_pose.cc b/source/blender/blenkernel/intern/armature_pose.cc
index bb371b16c42..ca11692372b 100644
--- a/source/blender/blenkernel/intern/armature_pose.cc
+++ b/source/blender/blenkernel/intern/armature_pose.cc
@@ -39,7 +39,7 @@ namespace {
using BoneNameSet = blender::Set<std::string>;
// Forward declarations.
-BoneNameSet pose_apply_find_selected_bones(const bPose *pose);
+BoneNameSet pose_apply_find_selected_bones(const bArmature *armature, const bPose *pose);
void pose_apply_disable_fcurves_for_unselected_bones(bAction *action,
const BoneNameSet &selected_bone_names);
void pose_apply_restore_fcurves(bAction *action);
@@ -54,7 +54,8 @@ void BKE_pose_apply_action(struct Object *ob,
return;
}
- const BoneNameSet selected_bone_names = pose_apply_find_selected_bones(pose);
+ const bArmature *armature = (bArmature *)ob->data;
+ const BoneNameSet selected_bone_names = pose_apply_find_selected_bones(armature, pose);
const bool limit_to_selected_bones = !selected_bone_names.is_empty();
if (limit_to_selected_bones) {
@@ -74,15 +75,14 @@ void BKE_pose_apply_action(struct Object *ob,
}
namespace {
-BoneNameSet pose_apply_find_selected_bones(const bPose *pose)
+BoneNameSet pose_apply_find_selected_bones(const bArmature *armature, const bPose *pose)
{
BoneNameSet selected_bone_names;
bool all_bones_selected = true;
bool no_bones_selected = true;
LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
- const bool is_selected = (pchan->bone->flag & BONE_SELECTED) != 0 &&
- (pchan->bone->flag & BONE_HIDDEN_P) == 0;
+ const bool is_selected = PBONE_SELECTED(armature, pchan->bone);
all_bones_selected &= is_selected;
no_bones_selected &= !is_selected;
diff --git a/source/blender/blenkernel/intern/attribute.c b/source/blender/blenkernel/intern/attribute.c
index d8fd3a19303..5db45471f0a 100644
--- a/source/blender/blenkernel/intern/attribute.c
+++ b/source/blender/blenkernel/intern/attribute.c
@@ -69,8 +69,8 @@ static void get_domains(ID *id, DomainInfo info[ATTR_DOMAIN_NUM])
info[ATTR_DOMAIN_EDGE].length = mesh->totedge;
info[ATTR_DOMAIN_CORNER].customdata = &mesh->ldata;
info[ATTR_DOMAIN_CORNER].length = mesh->totloop;
- info[ATTR_DOMAIN_POLYGON].customdata = &mesh->pdata;
- info[ATTR_DOMAIN_POLYGON].length = mesh->totpoly;
+ info[ATTR_DOMAIN_FACE].customdata = &mesh->pdata;
+ info[ATTR_DOMAIN_FACE].length = mesh->totpoly;
break;
}
case ID_HA: {
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index 6a8ceb467e7..52f89ca302b 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -331,7 +331,7 @@ static int attribute_domain_priority(const AttributeDomain domain)
case ATTR_DOMAIN_CURVE:
return 0;
#endif
- case ATTR_DOMAIN_POLYGON:
+ case ATTR_DOMAIN_FACE:
return 1;
case ATTR_DOMAIN_EDGE:
return 2;
@@ -893,7 +893,7 @@ ReadAttributePtr GeometryComponent::attribute_try_get_for_read(
return {};
}
- if (attribute->domain() != domain) {
+ if (domain != ATTR_DOMAIN_AUTO && attribute->domain() != domain) {
attribute = this->attribute_try_adapt_domain(std::move(attribute), domain);
if (!attribute) {
return {};
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index efbf19c7381..a61e7a2d1d8 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -400,6 +400,8 @@ static void setup_app_data(bContext *C,
bmain,
curscene,
bfd->cur_view_layer ? bfd->cur_view_layer : BKE_view_layer_default_view(curscene));
+ /* We need to rebuild some of the deleted override rules (for UI feedback purpose). */
+ BKE_lib_override_library_main_operations_create(bmain, true);
}
}
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 13ba1957a32..ef567044282 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -574,8 +574,8 @@ bool BKE_brush_delete(Main *bmain, Brush *brush)
if (brush->id.tag & LIB_TAG_INDIRECT) {
return false;
}
- if (BKE_library_ID_is_indirectly_used(bmain, brush) && ID_REAL_USERS(brush) <= 1 &&
- ID_EXTRA_USERS(brush) == 0) {
+ if (ID_REAL_USERS(brush) <= 1 && ID_EXTRA_USERS(brush) == 0 &&
+ BKE_library_ID_is_indirectly_used(bmain, brush)) {
return false;
}
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index d233022fd3f..feae033337d 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -99,6 +99,7 @@ static void cache_file_blend_write(BlendWriter *writer, ID *id, const void *id_a
cache_file->handle_readers = NULL;
BLO_write_id_struct(writer, CacheFile, id_address, &cache_file->id);
+ BKE_id_blend_write(writer, &cache_file->id);
if (cache_file->adt) {
BKE_animdata_blend_write(writer, cache_file->adt);
diff --git a/source/blender/blenkernel/intern/cryptomatte.cc b/source/blender/blenkernel/intern/cryptomatte.cc
index 6c7b3d82c3b..895f06da5fe 100644
--- a/source/blender/blenkernel/intern/cryptomatte.cc
+++ b/source/blender/blenkernel/intern/cryptomatte.cc
@@ -433,6 +433,9 @@ static bool from_manifest(CryptomatteLayer &layer, blender::StringRefNull manife
}
const int quoted_hash_len = quoted_string_len_(ref);
+ if (quoted_hash_len < 2) {
+ return false;
+ }
const int hash_len = quoted_hash_len - 2;
CryptomatteHash hash = CryptomatteHash::from_hex_encoded(ref.substr(1, hash_len));
ref = ref.drop_prefix(quoted_hash_len);
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index f3551c98f07..b0ea9b0f0d3 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -2756,7 +2756,6 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
bevp->tilt = bp->tilt;
bevp->radius = bp->radius;
bevp->weight = bp->weight;
- bevp->split_tag = true;
bp++;
if (seglen != NULL && len != 0) {
*seglen = len_v3v3(bevp->vec, bp->vec);
@@ -2828,7 +2827,6 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
bevp->tilt = prevbezt->tilt;
bevp->radius = prevbezt->radius;
bevp->weight = prevbezt->weight;
- bevp->split_tag = true;
bevp->dupe_tag = false;
bevp++;
bl->nr++;
@@ -2879,21 +2877,6 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
sizeof(BevPoint));
}
- /* indicate with handlecodes double points */
- if (prevbezt->h1 == prevbezt->h2) {
- if (ELEM(prevbezt->h1, 0, HD_VECT)) {
- bevp->split_tag = true;
- }
- }
- else {
- if (ELEM(prevbezt->h1, 0, HD_VECT)) {
- bevp->split_tag = true;
- }
- else if (ELEM(prevbezt->h2, 0, HD_VECT)) {
- bevp->split_tag = true;
- }
- }
-
/* seglen */
if (seglen != NULL) {
*seglen = 0;
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index d4581991566..829f9a94b66 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -74,9 +74,6 @@ void BKE_displist_elem_free(DispList *dl)
if (dl->index) {
MEM_freeN(dl->index);
}
- if (dl->bevel_split) {
- MEM_freeN(dl->bevel_split);
- }
MEM_freeN(dl);
}
}
@@ -137,10 +134,6 @@ void BKE_displist_copy(ListBase *lbn, ListBase *lb)
dln->verts = MEM_dupallocN(dl->verts);
dln->nors = MEM_dupallocN(dl->nors);
dln->index = MEM_dupallocN(dl->index);
-
- if (dl->bevel_split) {
- dln->bevel_split = MEM_dupallocN(dl->bevel_split);
- }
}
}
@@ -1609,8 +1602,6 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
/* CU_2D conflicts with R_NOPUNOFLIP */
dl->rt = nu->flag & ~CU_2D;
- dl->bevel_split = BLI_BITMAP_NEW(steps, "bevel_split");
-
/* for each point of poly make a bevel piece */
BevPoint *bevp_first = bl->bevpoints;
BevPoint *bevp_last = &bl->bevpoints[bl->nr - 1];
@@ -1659,10 +1650,6 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
}
}
- if (bevp->split_tag) {
- BLI_BITMAP_ENABLE(dl->bevel_split, a);
- }
-
/* rotate bevel piece and write in data */
if ((a == 0) && (bevp != bevp_last)) {
rotateBevelPiece(
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 8e1fa9732ea..010ab09bb31 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -35,7 +35,9 @@
#include "BLI_blenlib.h"
#include "BLI_easing.h"
+#include "BLI_ghash.h"
#include "BLI_math.h"
+#include "BLI_sort_utils.h"
#include "BKE_anim_data.h"
#include "BKE_animsys.h"
@@ -290,6 +292,12 @@ FCurve *BKE_fcurve_find(ListBase *list, const char rna_path[], const int array_i
return NULL;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name FCurve Iteration
+ * \{ */
+
/* Quick way to loop over all fcurves of a given 'path'. */
FCurve *BKE_fcurve_iter_step(FCurve *fcu_iter, const char rna_path[])
{
@@ -829,6 +837,56 @@ bool BKE_fcurve_calc_range(
return foundvert;
}
+/**
+ * Return an array of keyed frames, rounded to `interval`.
+ *
+ * \param interval: Set to 1.0 to round to whole keyframes, 0.5 for in-between key-frames, etc.
+ *
+ * \note An interval of zero could be supported (this implies no rounding at all),
+ * however this risks very small differences in float values being treated as separate keyframes.
+ */
+float *BKE_fcurves_calc_keyed_frames_ex(FCurve **fcurve_array,
+ int fcurve_array_len,
+ const float interval,
+ int *r_frames_len)
+{
+ /* Use `1e-3f` as the smallest possible value since these are converted to integers
+ * and we can be sure `MAXFRAME / 1e-3f < INT_MAX` as it's around half the size. */
+ const double interval_db = max_ff(interval, 1e-3f);
+ GSet *frames_unique = BLI_gset_int_new(__func__);
+ for (int fcurve_index = 0; fcurve_index < fcurve_array_len; fcurve_index++) {
+ const FCurve *fcu = fcurve_array[fcurve_index];
+ for (int i = 0; i < fcu->totvert; i++) {
+ const BezTriple *bezt = &fcu->bezt[i];
+ const double value = round((double)bezt->vec[1][0] / interval_db);
+ BLI_assert(value > INT_MIN && value < INT_MAX);
+ BLI_gset_add(frames_unique, POINTER_FROM_INT((int)value));
+ }
+ }
+
+ const size_t frames_len = BLI_gset_len(frames_unique);
+ float *frames = MEM_mallocN(sizeof(*frames) * frames_len, __func__);
+
+ GSetIterator gs_iter;
+ int i = 0;
+ GSET_ITER_INDEX (gs_iter, frames_unique, i) {
+ const int value = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
+ frames[i] = (double)value * interval_db;
+ }
+ BLI_gset_free(frames_unique, NULL);
+
+ qsort(frames, frames_len, sizeof(*frames), BLI_sortutil_cmp_float);
+ *r_frames_len = frames_len;
+ return frames;
+}
+
+float *BKE_fcurves_calc_keyed_frames(FCurve **fcurve_array,
+ int fcurve_array_len,
+ int *r_frames_len)
+{
+ return BKE_fcurves_calc_keyed_frames_ex(fcurve_array, fcurve_array_len, 1.0f, r_frames_len);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/intern/fcurve_cache.c b/source/blender/blenkernel/intern/fcurve_cache.c
new file mode 100644
index 00000000000..8142b871edd
--- /dev/null
+++ b/source/blender/blenkernel/intern/fcurve_cache.c
@@ -0,0 +1,189 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup bke
+ *
+ * Cache F-Curve look-ups.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_anim_types.h"
+
+#include "BLI_ghash.h"
+#include "BLI_listbase.h"
+
+#include "BKE_fcurve.h"
+
+/* -------------------------------------------------------------------- */
+/** \name F-Curve Path Cache
+ *
+ * Cache for finding curves by RNA path & array index.
+ * \{ */
+
+struct FCurvePathCache_Span {
+ /** Index in the #FCurvePathCache.fcurve_array indicating the start of the span. */
+ uint index;
+ /** Number of items in the span in #FCurvePathCache.fcurve_array that share an RNA path. */
+ uint len;
+};
+
+struct FCurvePathCache {
+ /** All curves sorted by (#FCurve.rna_path, #FCurve.array_index) */
+ FCurve **fcurve_array;
+ uint fcurve_array_len;
+ /** Storage for values of `span_from_rna_path`. */
+ struct FCurvePathCache_Span *span_table;
+ /** Map `FCurve.rna_path` to elements in #FCurvePathCache.span_table */
+ GHash *span_from_rna_path;
+};
+
+/**
+ * #qsort callback for an #FCurve array.
+ */
+static int fcurve_cmp_for_cache(const void *fcu_a_p, const void *fcu_b_p)
+{
+ const FCurve *fcu_a = *((const FCurve **)fcu_a_p);
+ const FCurve *fcu_b = *((const FCurve **)fcu_b_p);
+ const int cmp = strcmp(fcu_a->rna_path, fcu_b->rna_path);
+ if (cmp != 0) {
+ return cmp;
+ }
+ if (fcu_a->array_index < fcu_b->array_index) {
+ return -1;
+ }
+ if (fcu_a->array_index > fcu_b->array_index) {
+ return 1;
+ }
+ return 0;
+}
+
+struct FCurvePathCache *BKE_fcurve_pathcache_create(ListBase *list)
+{
+ const uint fcurve_array_len = BLI_listbase_count(list);
+ FCurve **fcurve_array = MEM_mallocN(sizeof(*fcurve_array) * fcurve_array_len, __func__);
+ uint i;
+ LISTBASE_FOREACH_INDEX (FCurve *, fcu, list, i) {
+ fcurve_array[i] = fcu;
+ }
+ qsort(fcurve_array, fcurve_array_len, sizeof(FCurve *), fcurve_cmp_for_cache);
+
+ /* Allow for the case no F-curves share an RNA-path, otherwise this is over-allocated.
+ * Although in practice it's likely to only be 3-4x as large as is needed
+ * (with transform channels for e.g.). */
+ struct FCurvePathCache_Span *span_table = MEM_mallocN(sizeof(*span_table) * fcurve_array_len,
+ __func__);
+
+ /* May over reserve, harmless. */
+ GHash *span_from_rna_path = BLI_ghash_str_new_ex(__func__, fcurve_array_len);
+ uint span_index = 0;
+ i = 0;
+ while (i < fcurve_array_len) {
+ uint i_end;
+ for (i_end = i + 1; i_end < fcurve_array_len; i_end++) {
+ /* As the indices are sorted, we know a decrease means a new RNA path is found. */
+ if (fcurve_array[i]->array_index > fcurve_array[i_end]->array_index) {
+ BLI_assert(!STREQ(fcurve_array[i]->rna_path, fcurve_array[i_end]->rna_path));
+ break;
+ }
+ if (!STREQ(fcurve_array[i]->rna_path, fcurve_array[i_end]->rna_path)) {
+ break;
+ }
+ }
+
+ struct FCurvePathCache_Span *span = &span_table[span_index++];
+ span->index = i;
+ span->len = i_end - i;
+ BLI_ghash_insert(span_from_rna_path, fcurve_array[i]->rna_path, span);
+ i = i_end;
+ }
+
+ struct FCurvePathCache *fcache = MEM_callocN(sizeof(struct FCurvePathCache), __func__);
+ fcache->fcurve_array = fcurve_array;
+ fcache->fcurve_array_len = fcurve_array_len;
+ fcache->span_table = span_table;
+ fcache->span_from_rna_path = span_from_rna_path;
+
+ return fcache;
+}
+
+void BKE_fcurve_pathcache_destroy(struct FCurvePathCache *fcache)
+{
+ MEM_freeN(fcache->fcurve_array);
+ MEM_freeN(fcache->span_table);
+ BLI_ghash_free(fcache->span_from_rna_path, NULL, NULL);
+ MEM_freeN(fcache);
+}
+
+FCurve *BKE_fcurve_pathcache_find(struct FCurvePathCache *fcache,
+ const char *rna_path,
+ const int array_index)
+{
+ const struct FCurvePathCache_Span *span = BLI_ghash_lookup(fcache->span_from_rna_path, rna_path);
+ if (span == NULL) {
+ return NULL;
+ }
+
+ FCurve **fcurve = fcache->fcurve_array + span->index;
+ const uint len = span->len;
+ for (int i = 0; i < len; i++) {
+ if (fcurve[i]->array_index == array_index) {
+ return fcurve[i];
+ }
+ /* As these are sorted, early exit. */
+ if (fcurve[i]->array_index > array_index) {
+ break;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Fill in an array of F-Curve, leave NULL when not found.
+ *
+ * \return The number of F-Curves found.
+ */
+int BKE_fcurve_pathcache_find_array(struct FCurvePathCache *fcache,
+ const char *rna_path,
+ FCurve **fcurve_result,
+ int fcurve_result_len)
+{
+ memset(fcurve_result, 0x0, sizeof(*fcurve_result) * fcurve_result_len);
+
+ const struct FCurvePathCache_Span *span = BLI_ghash_lookup(fcache->span_from_rna_path, rna_path);
+ if (span == NULL) {
+ return 0;
+ }
+
+ int found = 0;
+ FCurve **fcurve = fcache->fcurve_array + span->index;
+ const uint len = span->len;
+ for (int i = 0; i < len; i++) {
+ /* As these are sorted, early exit. */
+ if ((uint)fcurve[i]->array_index > (uint)fcurve_result_len) {
+ break;
+ }
+ fcurve_result[fcurve[i]->array_index] = fcurve[i];
+ found += 1;
+ }
+ return found;
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc
index d7cdc8ad880..27756e3cbed 100644
--- a/source/blender/blenkernel/intern/geometry_component_mesh.cc
+++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc
@@ -175,7 +175,7 @@ int MeshComponent::attribute_domain_size(const AttributeDomain domain) const
return mesh_->totvert;
case ATTR_DOMAIN_EDGE:
return mesh_->totedge;
- case ATTR_DOMAIN_POLYGON:
+ case ATTR_DOMAIN_FACE:
return mesh_->totpoly;
default:
break;
@@ -259,9 +259,9 @@ static ReadAttributePtr adapt_mesh_domain_point_to_corner(const Mesh &mesh,
* only some values are required.
*/
template<typename T>
-static void adapt_mesh_domain_corner_to_polygon_impl(const Mesh &mesh,
- Span<T> old_values,
- MutableSpan<T> r_values)
+static void adapt_mesh_domain_corner_to_face_impl(const Mesh &mesh,
+ Span<T> old_values,
+ MutableSpan<T> r_values)
{
BLI_assert(r_values.size() == mesh.totpoly);
attribute_math::DefaultMixer<T> mixer(r_values);
@@ -277,8 +277,8 @@ static void adapt_mesh_domain_corner_to_polygon_impl(const Mesh &mesh,
mixer.finalize();
}
-static ReadAttributePtr adapt_mesh_domain_corner_to_polygon(const Mesh &mesh,
- ReadAttributePtr attribute)
+static ReadAttributePtr adapt_mesh_domain_corner_to_face(const Mesh &mesh,
+ ReadAttributePtr attribute)
{
ReadAttributePtr new_attribute;
const CustomDataType data_type = attribute->custom_data_type();
@@ -286,7 +286,7 @@ static ReadAttributePtr adapt_mesh_domain_corner_to_polygon(const Mesh &mesh,
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totpoly);
- adapt_mesh_domain_corner_to_polygon_impl<T>(mesh, attribute->get_span<T>(), values);
+ adapt_mesh_domain_corner_to_face_impl<T>(mesh, attribute->get_span<T>(), values);
new_attribute = std::make_unique<OwnedArrayReadAttribute<T>>(ATTR_DOMAIN_POINT,
std::move(values));
}
@@ -336,9 +336,9 @@ static ReadAttributePtr adapt_mesh_domain_corner_to_edge(const Mesh &mesh,
}
template<typename T>
-void adapt_mesh_domain_polygon_to_point_impl(const Mesh &mesh,
- Span<T> old_values,
- MutableSpan<T> r_values)
+void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh,
+ Span<T> old_values,
+ MutableSpan<T> r_values)
{
BLI_assert(r_values.size() == mesh.totvert);
attribute_math::DefaultMixer<T> mixer(r_values);
@@ -356,8 +356,8 @@ void adapt_mesh_domain_polygon_to_point_impl(const Mesh &mesh,
mixer.finalize();
}
-static ReadAttributePtr adapt_mesh_domain_polygon_to_point(const Mesh &mesh,
- ReadAttributePtr attribute)
+static ReadAttributePtr adapt_mesh_domain_face_to_point(const Mesh &mesh,
+ ReadAttributePtr attribute)
{
ReadAttributePtr new_attribute;
const CustomDataType data_type = attribute->custom_data_type();
@@ -365,7 +365,7 @@ static ReadAttributePtr adapt_mesh_domain_polygon_to_point(const Mesh &mesh,
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totvert);
- adapt_mesh_domain_polygon_to_point_impl<T>(mesh, attribute->get_span<T>(), values);
+ adapt_mesh_domain_face_to_point_impl<T>(mesh, attribute->get_span<T>(), values);
new_attribute = std::make_unique<OwnedArrayReadAttribute<T>>(ATTR_DOMAIN_POINT,
std::move(values));
}
@@ -374,9 +374,9 @@ static ReadAttributePtr adapt_mesh_domain_polygon_to_point(const Mesh &mesh,
}
template<typename T>
-void adapt_mesh_domain_polygon_to_corner_impl(const Mesh &mesh,
- const Span<T> old_values,
- MutableSpan<T> r_values)
+void adapt_mesh_domain_face_to_corner_impl(const Mesh &mesh,
+ const Span<T> old_values,
+ MutableSpan<T> r_values)
{
BLI_assert(r_values.size() == mesh.totloop);
@@ -387,8 +387,8 @@ void adapt_mesh_domain_polygon_to_corner_impl(const Mesh &mesh,
}
}
-static ReadAttributePtr adapt_mesh_domain_polygon_to_corner(const Mesh &mesh,
- ReadAttributePtr attribute)
+static ReadAttributePtr adapt_mesh_domain_face_to_corner(const Mesh &mesh,
+ ReadAttributePtr attribute)
{
ReadAttributePtr new_attribute;
const CustomDataType data_type = attribute->custom_data_type();
@@ -396,7 +396,7 @@ static ReadAttributePtr adapt_mesh_domain_polygon_to_corner(const Mesh &mesh,
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totloop);
- adapt_mesh_domain_polygon_to_corner_impl<T>(mesh, attribute->get_span<T>(), values);
+ adapt_mesh_domain_face_to_corner_impl<T>(mesh, attribute->get_span<T>(), values);
new_attribute = std::make_unique<OwnedArrayReadAttribute<T>>(ATTR_DOMAIN_POINT,
std::move(values));
}
@@ -405,9 +405,9 @@ static ReadAttributePtr adapt_mesh_domain_polygon_to_corner(const Mesh &mesh,
}
template<typename T>
-void adapt_mesh_domain_polygon_to_edge_impl(const Mesh &mesh,
- const Span<T> old_values,
- MutableSpan<T> r_values)
+void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh,
+ const Span<T> old_values,
+ MutableSpan<T> r_values)
{
BLI_assert(r_values.size() == mesh.totedge);
attribute_math::DefaultMixer<T> mixer(r_values);
@@ -423,8 +423,8 @@ void adapt_mesh_domain_polygon_to_edge_impl(const Mesh &mesh,
mixer.finalize();
}
-static ReadAttributePtr adapt_mesh_domain_polygon_to_edge(const Mesh &mesh,
- ReadAttributePtr attribute)
+static ReadAttributePtr adapt_mesh_domain_face_to_edge(const Mesh &mesh,
+ ReadAttributePtr attribute)
{
ReadAttributePtr new_attribute;
const CustomDataType data_type = attribute->custom_data_type();
@@ -432,7 +432,7 @@ static ReadAttributePtr adapt_mesh_domain_polygon_to_edge(const Mesh &mesh,
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totedge);
- adapt_mesh_domain_polygon_to_edge_impl<T>(mesh, attribute->get_span<T>(), values);
+ adapt_mesh_domain_face_to_edge_impl<T>(mesh, attribute->get_span<T>(), values);
new_attribute = std::make_unique<OwnedArrayReadAttribute<T>>(ATTR_DOMAIN_POINT,
std::move(values));
}
@@ -446,9 +446,9 @@ static ReadAttributePtr adapt_mesh_domain_polygon_to_edge(const Mesh &mesh,
* only some values are required.
*/
template<typename T>
-static void adapt_mesh_domain_point_to_polygon_impl(const Mesh &mesh,
- const Span<T> old_values,
- MutableSpan<T> r_values)
+static void adapt_mesh_domain_point_to_face_impl(const Mesh &mesh,
+ const Span<T> old_values,
+ MutableSpan<T> r_values)
{
BLI_assert(r_values.size() == mesh.totpoly);
attribute_math::DefaultMixer<T> mixer(r_values);
@@ -464,8 +464,8 @@ static void adapt_mesh_domain_point_to_polygon_impl(const Mesh &mesh,
mixer.finalize();
}
-static ReadAttributePtr adapt_mesh_domain_point_to_polygon(const Mesh &mesh,
- ReadAttributePtr attribute)
+static ReadAttributePtr adapt_mesh_domain_point_to_face(const Mesh &mesh,
+ ReadAttributePtr attribute)
{
ReadAttributePtr new_attribute;
const CustomDataType data_type = attribute->custom_data_type();
@@ -473,7 +473,7 @@ static ReadAttributePtr adapt_mesh_domain_point_to_polygon(const Mesh &mesh,
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totpoly);
- adapt_mesh_domain_point_to_polygon_impl<T>(mesh, attribute->get_span<T>(), values);
+ adapt_mesh_domain_point_to_face_impl<T>(mesh, attribute->get_span<T>(), values);
new_attribute = std::make_unique<OwnedArrayReadAttribute<T>>(ATTR_DOMAIN_POINT,
std::move(values));
}
@@ -531,7 +531,7 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
for (const int poly_index : IndexRange(mesh.totpoly)) {
const MPoly &poly = mesh.mpoly[poly_index];
- /* For every corner, mix the values from the adjacent edges on the polygon. */
+ /* For every corner, mix the values from the adjacent edges on the face. */
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const int loop_index_prev = (loop_index - 1) % poly.totloop;
const MLoop &loop = mesh.mloop[loop_index];
@@ -602,9 +602,9 @@ static ReadAttributePtr adapt_mesh_domain_edge_to_point(const Mesh &mesh,
* only some values are required.
*/
template<typename T>
-static void adapt_mesh_domain_edge_to_polygon_impl(const Mesh &mesh,
- const Span<T> old_values,
- MutableSpan<T> r_values)
+static void adapt_mesh_domain_edge_to_face_impl(const Mesh &mesh,
+ const Span<T> old_values,
+ MutableSpan<T> r_values)
{
BLI_assert(r_values.size() == mesh.totpoly);
attribute_math::DefaultMixer<T> mixer(r_values);
@@ -620,8 +620,8 @@ static void adapt_mesh_domain_edge_to_polygon_impl(const Mesh &mesh,
mixer.finalize();
}
-static ReadAttributePtr adapt_mesh_domain_edge_to_polygon(const Mesh &mesh,
- ReadAttributePtr attribute)
+static ReadAttributePtr adapt_mesh_domain_edge_to_face(const Mesh &mesh,
+ ReadAttributePtr attribute)
{
ReadAttributePtr new_attribute;
const CustomDataType data_type = attribute->custom_data_type();
@@ -629,7 +629,7 @@ static ReadAttributePtr adapt_mesh_domain_edge_to_polygon(const Mesh &mesh,
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
Array<T> values(mesh.totpoly);
- adapt_mesh_domain_edge_to_polygon_impl<T>(mesh, attribute->get_span<T>(), values);
+ adapt_mesh_domain_edge_to_face_impl<T>(mesh, attribute->get_span<T>(), values);
new_attribute = std::make_unique<OwnedArrayReadAttribute<T>>(ATTR_DOMAIN_POINT,
std::move(values));
}
@@ -658,8 +658,8 @@ ReadAttributePtr MeshComponent::attribute_try_adapt_domain(ReadAttributePtr attr
switch (new_domain) {
case ATTR_DOMAIN_POINT:
return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, std::move(attribute));
- case ATTR_DOMAIN_POLYGON:
- return blender::bke::adapt_mesh_domain_corner_to_polygon(*mesh_, std::move(attribute));
+ case ATTR_DOMAIN_FACE:
+ return blender::bke::adapt_mesh_domain_corner_to_face(*mesh_, std::move(attribute));
case ATTR_DOMAIN_EDGE:
return blender::bke::adapt_mesh_domain_corner_to_edge(*mesh_, std::move(attribute));
default:
@@ -672,8 +672,8 @@ ReadAttributePtr MeshComponent::attribute_try_adapt_domain(ReadAttributePtr attr
switch (new_domain) {
case ATTR_DOMAIN_CORNER:
return blender::bke::adapt_mesh_domain_point_to_corner(*mesh_, std::move(attribute));
- case ATTR_DOMAIN_POLYGON:
- return blender::bke::adapt_mesh_domain_point_to_polygon(*mesh_, std::move(attribute));
+ case ATTR_DOMAIN_FACE:
+ return blender::bke::adapt_mesh_domain_point_to_face(*mesh_, std::move(attribute));
case ATTR_DOMAIN_EDGE:
return blender::bke::adapt_mesh_domain_point_to_edge(*mesh_, std::move(attribute));
default:
@@ -682,14 +682,14 @@ ReadAttributePtr MeshComponent::attribute_try_adapt_domain(ReadAttributePtr attr
}
break;
}
- case ATTR_DOMAIN_POLYGON: {
+ case ATTR_DOMAIN_FACE: {
switch (new_domain) {
case ATTR_DOMAIN_POINT:
- return blender::bke::adapt_mesh_domain_polygon_to_point(*mesh_, std::move(attribute));
+ return blender::bke::adapt_mesh_domain_face_to_point(*mesh_, std::move(attribute));
case ATTR_DOMAIN_CORNER:
- return blender::bke::adapt_mesh_domain_polygon_to_corner(*mesh_, std::move(attribute));
+ return blender::bke::adapt_mesh_domain_face_to_corner(*mesh_, std::move(attribute));
case ATTR_DOMAIN_EDGE:
- return blender::bke::adapt_mesh_domain_polygon_to_edge(*mesh_, std::move(attribute));
+ return blender::bke::adapt_mesh_domain_face_to_edge(*mesh_, std::move(attribute));
default:
break;
}
@@ -701,8 +701,8 @@ ReadAttributePtr MeshComponent::attribute_try_adapt_domain(ReadAttributePtr attr
return blender::bke::adapt_mesh_domain_edge_to_corner(*mesh_, std::move(attribute));
case ATTR_DOMAIN_POINT:
return blender::bke::adapt_mesh_domain_edge_to_point(*mesh_, std::move(attribute));
- case ATTR_DOMAIN_POLYGON:
- return blender::bke::adapt_mesh_domain_edge_to_polygon(*mesh_, std::move(attribute));
+ case ATTR_DOMAIN_FACE:
+ return blender::bke::adapt_mesh_domain_edge_to_face(*mesh_, std::move(attribute));
default:
BLI_assert(false);
break;
@@ -733,28 +733,35 @@ static const Mesh *get_mesh_from_component_for_read(const GeometryComponent &com
namespace blender::bke {
-static float3 get_vertex_position(const MVert &vert)
+template<typename StructT,
+ typename ElemT,
+ ElemT (*GetFunc)(const StructT &),
+ AttributeDomain Domain>
+static ReadAttributePtr make_derived_read_attribute(const void *data, const int domain_size)
{
- return float3(vert.co);
+ return std::make_unique<DerivedArrayReadAttribute<StructT, ElemT, GetFunc>>(
+ Domain, Span<StructT>((const StructT *)data, domain_size));
}
-static void set_vertex_position(MVert &vert, const float3 &position)
+template<typename StructT,
+ typename ElemT,
+ ElemT (*GetFunc)(const StructT &),
+ void (*SetFunc)(StructT &, const ElemT &),
+ AttributeDomain Domain>
+static WriteAttributePtr make_derived_write_attribute(void *data, const int domain_size)
{
- copy_v3_v3(vert.co, position);
+ return std::make_unique<DerivedArrayWriteAttribute<StructT, ElemT, GetFunc, SetFunc>>(
+ Domain, MutableSpan<StructT>((StructT *)data, domain_size));
}
-static ReadAttributePtr make_vertex_position_read_attribute(const void *data,
- const int domain_size)
+static float3 get_vertex_position(const MVert &vert)
{
- return std::make_unique<DerivedArrayReadAttribute<MVert, float3, get_vertex_position>>(
- ATTR_DOMAIN_POINT, Span<MVert>((const MVert *)data, domain_size));
+ return float3(vert.co);
}
-static WriteAttributePtr make_vertex_position_write_attribute(void *data, const int domain_size)
+static void set_vertex_position(MVert &vert, const float3 &position)
{
- return std::make_unique<
- DerivedArrayWriteAttribute<MVert, float3, get_vertex_position, set_vertex_position>>(
- ATTR_DOMAIN_POINT, MutableSpan<MVert>((MVert *)data, domain_size));
+ copy_v3_v3(vert.co, position);
}
static void tag_normals_dirty_when_writing_position(GeometryComponent &component)
@@ -775,19 +782,6 @@ static void set_material_index(MPoly &mpoly, const int &index)
mpoly.mat_nr = static_cast<short>(std::clamp(index, 0, SHRT_MAX));
}
-static ReadAttributePtr make_material_index_read_attribute(const void *data, const int domain_size)
-{
- return std::make_unique<DerivedArrayReadAttribute<MPoly, int, get_material_index>>(
- ATTR_DOMAIN_POLYGON, Span<MPoly>((const MPoly *)data, domain_size));
-}
-
-static WriteAttributePtr make_material_index_write_attribute(void *data, const int domain_size)
-{
- return std::make_unique<
- DerivedArrayWriteAttribute<MPoly, int, get_material_index, set_material_index>>(
- ATTR_DOMAIN_POLYGON, MutableSpan<MPoly>((MPoly *)data, domain_size));
-}
-
static bool get_shade_smooth(const MPoly &mpoly)
{
return mpoly.flag & ME_SMOOTH;
@@ -798,19 +792,6 @@ static void set_shade_smooth(MPoly &mpoly, const bool &value)
SET_FLAG_FROM_TEST(mpoly.flag, value, ME_SMOOTH);
}
-static ReadAttributePtr make_shade_smooth_read_attribute(const void *data, const int domain_size)
-{
- return std::make_unique<DerivedArrayReadAttribute<MPoly, bool, get_shade_smooth>>(
- ATTR_DOMAIN_POLYGON, Span<MPoly>((const MPoly *)data, domain_size));
-}
-
-static WriteAttributePtr make_shade_smooth_write_attribute(void *data, const int domain_size)
-{
- return std::make_unique<
- DerivedArrayWriteAttribute<MPoly, bool, get_shade_smooth, set_shade_smooth>>(
- ATTR_DOMAIN_POLYGON, MutableSpan<MPoly>((MPoly *)data, domain_size));
-}
-
static float2 get_loop_uv(const MLoopUV &uv)
{
return float2(uv.uv);
@@ -821,18 +802,6 @@ static void set_loop_uv(MLoopUV &uv, const float2 &co)
copy_v2_v2(uv.uv, co);
}
-static ReadAttributePtr make_uvs_read_attribute(const void *data, const int domain_size)
-{
- return std::make_unique<DerivedArrayReadAttribute<MLoopUV, float2, get_loop_uv>>(
- ATTR_DOMAIN_CORNER, Span((const MLoopUV *)data, domain_size));
-}
-
-static WriteAttributePtr make_uvs_write_attribute(void *data, const int domain_size)
-{
- return std::make_unique<DerivedArrayWriteAttribute<MLoopUV, float2, get_loop_uv, set_loop_uv>>(
- ATTR_DOMAIN_CORNER, MutableSpan((MLoopUV *)data, domain_size));
-}
-
static Color4f get_loop_color(const MLoopCol &col)
{
Color4f value;
@@ -845,19 +814,6 @@ static void set_loop_color(MLoopCol &col, const Color4f &value)
rgba_float_to_uchar(&col.r, value);
}
-static ReadAttributePtr make_vertex_color_read_attribute(const void *data, const int domain_size)
-{
- return std::make_unique<DerivedArrayReadAttribute<MLoopCol, Color4f, get_loop_color>>(
- ATTR_DOMAIN_CORNER, Span((const MLoopCol *)data, domain_size));
-}
-
-static WriteAttributePtr make_vertex_color_write_attribute(void *data, const int domain_size)
-{
- return std::make_unique<
- DerivedArrayWriteAttribute<MLoopCol, Color4f, get_loop_color, set_loop_color>>(
- ATTR_DOMAIN_CORNER, MutableSpan((MLoopCol *)data, domain_size));
-}
-
static float get_crease(const MEdge &edge)
{
return edge.crease / 255.0f;
@@ -868,18 +824,6 @@ static void set_crease(MEdge &edge, const float &value)
edge.crease = round_fl_to_uchar_clamp(value * 255.0f);
}
-static ReadAttributePtr make_crease_read_attribute(const void *data, const int domain_size)
-{
- return std::make_unique<DerivedArrayReadAttribute<MEdge, float, get_crease>>(
- ATTR_DOMAIN_EDGE, Span((const MEdge *)data, domain_size));
-}
-
-static WriteAttributePtr make_crease_write_attribute(void *data, const int domain_size)
-{
- return std::make_unique<DerivedArrayWriteAttribute<MEdge, float, get_crease, set_crease>>(
- ATTR_DOMAIN_EDGE, MutableSpan((MEdge *)data, domain_size));
-}
-
class VertexWeightWriteAttribute final : public WriteAttribute {
private:
MDeformVert *dverts_;
@@ -1049,7 +993,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
public:
NormalAttributeProvider()
: BuiltinAttributeProvider(
- "normal", ATTR_DOMAIN_POLYGON, CD_PROP_FLOAT3, NonCreatable, Readonly, NonDeletable)
+ "normal", ATTR_DOMAIN_FACE, CD_PROP_FLOAT3, NonCreatable, Readonly, NonDeletable)
{
}
@@ -1067,7 +1011,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
const void *data = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
return std::make_unique<ArrayReadAttribute<float3>>(
- ATTR_DOMAIN_POLYGON, Span<float3>((const float3 *)data, mesh->totpoly));
+ ATTR_DOMAIN_FACE, Span<float3>((const float3 *)data, mesh->totpoly));
}
Array<float3> normals(mesh->totpoly);
@@ -1076,8 +1020,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
BKE_mesh_calc_poly_normal(poly, &mesh->mloop[poly->loopstart], mesh->mvert, normals[i]);
}
- return std::make_unique<OwnedArrayReadAttribute<float3>>(ATTR_DOMAIN_POLYGON,
- std::move(normals));
+ return std::make_unique<OwnedArrayReadAttribute<float3>>(ATTR_DOMAIN_FACE, std::move(normals));
}
WriteAttributePtr try_get_for_write(GeometryComponent &UNUSED(component)) const final
@@ -1097,7 +1040,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
bool exists(const GeometryComponent &component) const final
{
- return component.attribute_domain_size(ATTR_DOMAIN_POLYGON) != 0;
+ return component.attribute_domain_size(ATTR_DOMAIN_FACE) != 0;
}
};
@@ -1134,82 +1077,104 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
static CustomDataAccessInfo edge_access = {MAKE_MUTABLE_CUSTOM_DATA_GETTER(edata),
MAKE_CONST_CUSTOM_DATA_GETTER(edata),
update_custom_data_pointers};
- static CustomDataAccessInfo polygon_access = {MAKE_MUTABLE_CUSTOM_DATA_GETTER(pdata),
- MAKE_CONST_CUSTOM_DATA_GETTER(pdata),
- update_custom_data_pointers};
+ static CustomDataAccessInfo face_access = {MAKE_MUTABLE_CUSTOM_DATA_GETTER(pdata),
+ MAKE_CONST_CUSTOM_DATA_GETTER(pdata),
+ update_custom_data_pointers};
#undef MAKE_CONST_CUSTOM_DATA_GETTER
#undef MAKE_MUTABLE_CUSTOM_DATA_GETTER
- static BuiltinCustomDataLayerProvider position("position",
- ATTR_DOMAIN_POINT,
- CD_PROP_FLOAT3,
- CD_MVERT,
- BuiltinAttributeProvider::NonCreatable,
- BuiltinAttributeProvider::Writable,
- BuiltinAttributeProvider::NonDeletable,
- point_access,
- make_vertex_position_read_attribute,
- make_vertex_position_write_attribute,
- tag_normals_dirty_when_writing_position);
+ static BuiltinCustomDataLayerProvider position(
+ "position",
+ ATTR_DOMAIN_POINT,
+ CD_PROP_FLOAT3,
+ CD_MVERT,
+ BuiltinAttributeProvider::NonCreatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::NonDeletable,
+ point_access,
+ make_derived_read_attribute<MVert, float3, get_vertex_position, ATTR_DOMAIN_POINT>,
+ make_derived_write_attribute<MVert,
+ float3,
+ get_vertex_position,
+ set_vertex_position,
+ ATTR_DOMAIN_POINT>,
+ tag_normals_dirty_when_writing_position);
static NormalAttributeProvider normal;
- static BuiltinCustomDataLayerProvider material_index("material_index",
- ATTR_DOMAIN_POLYGON,
- CD_PROP_INT32,
- CD_MPOLY,
- BuiltinAttributeProvider::NonCreatable,
- BuiltinAttributeProvider::Writable,
- BuiltinAttributeProvider::NonDeletable,
- polygon_access,
- make_material_index_read_attribute,
- make_material_index_write_attribute,
- nullptr);
-
- static BuiltinCustomDataLayerProvider shade_smooth("shade_smooth",
- ATTR_DOMAIN_POLYGON,
- CD_PROP_BOOL,
- CD_MPOLY,
- BuiltinAttributeProvider::NonCreatable,
- BuiltinAttributeProvider::Writable,
- BuiltinAttributeProvider::NonDeletable,
- polygon_access,
- make_shade_smooth_read_attribute,
- make_shade_smooth_write_attribute,
- nullptr);
-
- static BuiltinCustomDataLayerProvider crease("crease",
- ATTR_DOMAIN_EDGE,
- CD_PROP_FLOAT,
- CD_MEDGE,
- BuiltinAttributeProvider::NonCreatable,
- BuiltinAttributeProvider::Writable,
- BuiltinAttributeProvider::NonDeletable,
- edge_access,
- make_crease_read_attribute,
- make_crease_write_attribute,
- nullptr);
-
- static NamedLegacyCustomDataProvider uvs(ATTR_DOMAIN_CORNER,
- CD_PROP_FLOAT2,
- CD_MLOOPUV,
- corner_access,
- make_uvs_read_attribute,
- make_uvs_write_attribute);
-
- static NamedLegacyCustomDataProvider vertex_colors(ATTR_DOMAIN_CORNER,
- CD_PROP_COLOR,
- CD_MLOOPCOL,
- corner_access,
- make_vertex_color_read_attribute,
- make_vertex_color_write_attribute);
+ static BuiltinCustomDataLayerProvider material_index(
+ "material_index",
+ ATTR_DOMAIN_FACE,
+ CD_PROP_INT32,
+ CD_MPOLY,
+ BuiltinAttributeProvider::NonCreatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::NonDeletable,
+ face_access,
+ make_derived_read_attribute<MPoly, int, get_material_index, ATTR_DOMAIN_FACE>,
+ make_derived_write_attribute<MPoly,
+ int,
+ get_material_index,
+ set_material_index,
+ ATTR_DOMAIN_FACE>,
+ nullptr);
+
+ static BuiltinCustomDataLayerProvider shade_smooth(
+ "shade_smooth",
+ ATTR_DOMAIN_FACE,
+ CD_PROP_BOOL,
+ CD_MPOLY,
+ BuiltinAttributeProvider::NonCreatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::NonDeletable,
+ face_access,
+ make_derived_read_attribute<MPoly, bool, get_shade_smooth, ATTR_DOMAIN_FACE>,
+ make_derived_write_attribute<MPoly,
+ bool,
+ get_shade_smooth,
+ set_shade_smooth,
+ ATTR_DOMAIN_FACE>,
+ nullptr);
+
+ static BuiltinCustomDataLayerProvider crease(
+ "crease",
+ ATTR_DOMAIN_EDGE,
+ CD_PROP_FLOAT,
+ CD_MEDGE,
+ BuiltinAttributeProvider::NonCreatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::NonDeletable,
+ edge_access,
+ make_derived_read_attribute<MEdge, float, get_crease, ATTR_DOMAIN_EDGE>,
+ make_derived_write_attribute<MEdge, float, get_crease, set_crease, ATTR_DOMAIN_EDGE>,
+ nullptr);
+
+ static NamedLegacyCustomDataProvider uvs(
+ ATTR_DOMAIN_CORNER,
+ CD_PROP_FLOAT2,
+ CD_MLOOPUV,
+ corner_access,
+ make_derived_read_attribute<MLoopUV, float2, get_loop_uv, ATTR_DOMAIN_CORNER>,
+ make_derived_write_attribute<MLoopUV, float2, get_loop_uv, set_loop_uv, ATTR_DOMAIN_CORNER>);
+
+ static NamedLegacyCustomDataProvider vertex_colors(
+ ATTR_DOMAIN_CORNER,
+ CD_PROP_COLOR,
+ CD_MLOOPCOL,
+ corner_access,
+ make_derived_read_attribute<MLoopCol, Color4f, get_loop_color, ATTR_DOMAIN_CORNER>,
+ make_derived_write_attribute<MLoopCol,
+ Color4f,
+ get_loop_color,
+ set_loop_color,
+ ATTR_DOMAIN_CORNER>);
static VertexGroupsAttributeProvider vertex_groups;
static CustomDataAttributeProvider corner_custom_data(ATTR_DOMAIN_CORNER, corner_access);
static CustomDataAttributeProvider point_custom_data(ATTR_DOMAIN_POINT, point_access);
static CustomDataAttributeProvider edge_custom_data(ATTR_DOMAIN_EDGE, edge_access);
- static CustomDataAttributeProvider polygon_custom_data(ATTR_DOMAIN_POLYGON, polygon_access);
+ static CustomDataAttributeProvider face_custom_data(ATTR_DOMAIN_FACE, face_access);
return ComponentAttributeProviders({&position, &material_index, &shade_smooth, &normal, &crease},
{&uvs,
@@ -1218,7 +1183,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
&vertex_groups,
&point_custom_data,
&edge_custom_data,
- &polygon_custom_data});
+ &face_custom_data});
}
} // namespace blender::bke
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index a09c3f5f3d3..9f57fcfb2ba 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -205,6 +205,12 @@ uint64_t GeometrySet::hash() const
return reinterpret_cast<uint64_t>(this);
}
+/* Remove all geometry components from the geometry set. */
+void GeometrySet::clear()
+{
+ components_.clear();
+}
+
/* Returns a read-only mesh or null. */
const Mesh *GeometrySet::get_mesh_for_read() const
{
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index 24a402ac545..10c88a47416 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -153,16 +153,13 @@ static void geometry_set_collect_recursive(const GeometrySet &geometry_set,
*
* \note This doesn't extract instances from the "dupli" system for non-geometry-nodes instances.
*/
-Vector<GeometryInstanceGroup> geometry_set_gather_instances(const GeometrySet &geometry_set)
+void geometry_set_gather_instances(const GeometrySet &geometry_set,
+ Vector<GeometryInstanceGroup> &r_instance_groups)
{
- Vector<GeometryInstanceGroup> result_vector;
-
float4x4 unit_transform;
unit_m4(unit_transform.values);
- geometry_set_collect_recursive(geometry_set, unit_transform, result_vector);
-
- return result_vector;
+ geometry_set_collect_recursive(geometry_set, unit_transform, r_instance_groups);
}
void gather_attribute_info(Map<std::string, AttributeKind> &attributes,
@@ -436,7 +433,8 @@ GeometrySet geometry_set_realize_mesh_for_modifier(const GeometrySet &geometry_s
}
GeometrySet new_geometry_set = geometry_set;
- Vector<GeometryInstanceGroup> set_groups = geometry_set_gather_instances(geometry_set);
+ Vector<GeometryInstanceGroup> set_groups;
+ geometry_set_gather_instances(geometry_set, set_groups);
join_instance_groups_mesh(set_groups, true, new_geometry_set);
/* Remove all instances, even though some might contain other non-mesh data. We can't really
* keep only non-mesh instances in general. */
@@ -454,7 +452,8 @@ GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set)
GeometrySet new_geometry_set;
- Vector<GeometryInstanceGroup> set_groups = geometry_set_gather_instances(geometry_set);
+ Vector<GeometryInstanceGroup> set_groups;
+ geometry_set_gather_instances(geometry_set, set_groups);
join_instance_groups_mesh(set_groups, false, new_geometry_set);
join_instance_groups_pointcloud(set_groups, new_geometry_set);
join_instance_groups_volume(set_groups, new_geometry_set);
diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c
index 8c4882854d1..27c2d9e146b 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.c
+++ b/source/blender/blenkernel/intern/gpencil_geom.c
@@ -46,9 +46,11 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
#include "BLT_translation.h"
+#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_curve.h"
@@ -3460,4 +3462,555 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd,
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
+/**
+ * Stroke to view space
+ * Transforms a stroke to view space. This allows for manipulations in 2D but also easy conversion
+ * back to 3D.
+ * Note: also takes care of parent space transform
+ */
+void BKE_gpencil_stroke_to_view_space(RegionView3D *rv3d,
+ bGPDstroke *gps,
+ const float diff_mat[4][4])
+{
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ /* Point to parent space. */
+ mul_v3_m4v3(&pt->x, diff_mat, &pt->x);
+ /* point to view space */
+ mul_m4_v3(rv3d->viewmat, &pt->x);
+ }
+}
+
+/**
+ * Stroke from view space
+ * Transforms a stroke from view space back to world space. Inverse of
+ * BKE_gpencil_stroke_to_view_space
+ * Note: also takes care of parent space transform
+ */
+void BKE_gpencil_stroke_from_view_space(RegionView3D *rv3d,
+ bGPDstroke *gps,
+ const float diff_mat[4][4])
+{
+ float inverse_diff_mat[4][4];
+ invert_m4_m4(inverse_diff_mat, diff_mat);
+
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ mul_v3_m4v3(&pt->x, rv3d->viewinv, &pt->x);
+ mul_m4_v3(inverse_diff_mat, &pt->x);
+ }
+}
+
+/* ----------------------------------------------------------------------------- */
+/* Stroke to perimeter */
+
+typedef struct tPerimeterPoint {
+ struct tPerimeterPoint *next, *prev;
+ float x, y, z;
+} tPerimeterPoint;
+
+static tPerimeterPoint *new_perimeter_point(const float pt[3])
+{
+ tPerimeterPoint *new_pt = MEM_callocN(sizeof(tPerimeterPoint), __func__);
+ copy_v3_v3(&new_pt->x, pt);
+ return new_pt;
+}
+
+static int generate_arc_from_point_to_point(ListBase *list,
+ tPerimeterPoint *from,
+ tPerimeterPoint *to,
+ float center_pt[3],
+ int subdivisions,
+ bool clockwise)
+{
+ float vec_from[2];
+ float vec_to[2];
+ sub_v2_v2v2(vec_from, &from->x, center_pt);
+ sub_v2_v2v2(vec_to, &to->x, center_pt);
+ if (is_zero_v2(vec_from) || is_zero_v2(vec_to)) {
+ return 0;
+ }
+
+ float dot = dot_v2v2(vec_from, vec_to);
+ float det = cross_v2v2(vec_from, vec_to);
+ float angle = clockwise ? M_PI - atan2f(-det, -dot) : atan2f(-det, -dot) + M_PI;
+
+ /* Number of points is 2^(n+1) + 1 on half a circle (n=subdivisions)
+ * so we multiply by (angle / pi) to get the right amount of
+ * points to insert. */
+ int num_points = (int)(((1 << (subdivisions + 1)) - 1) * (angle / M_PI));
+ if (num_points > 0) {
+ float angle_incr = angle / (float)num_points;
+
+ float vec_p[3];
+ float vec_t[3];
+ float tmp_angle;
+ tPerimeterPoint *last_point;
+ if (clockwise) {
+ last_point = to;
+ copy_v2_v2(vec_t, vec_to);
+ }
+ else {
+ last_point = from;
+ copy_v2_v2(vec_t, vec_from);
+ }
+
+ for (int i = 0; i < num_points - 1; i++) {
+ tmp_angle = (i + 1) * angle_incr;
+
+ rotate_v2_v2fl(vec_p, vec_t, tmp_angle);
+ add_v2_v2(vec_p, center_pt);
+ vec_p[2] = center_pt[2];
+
+ tPerimeterPoint *new_point = new_perimeter_point(vec_p);
+ if (clockwise) {
+ BLI_insertlinkbefore(list, last_point, new_point);
+ }
+ else {
+ BLI_insertlinkafter(list, last_point, new_point);
+ }
+
+ last_point = new_point;
+ }
+
+ return num_points - 1;
+ }
+
+ return 0;
+}
+
+static int generate_semi_circle_from_point_to_point(ListBase *list,
+ tPerimeterPoint *from,
+ tPerimeterPoint *to,
+ int subdivisions)
+{
+ int num_points = (1 << (subdivisions + 1)) + 1;
+ float center_pt[3];
+ interp_v3_v3v3(center_pt, &from->x, &to->x, 0.5f);
+
+ float vec_center[2];
+ sub_v2_v2v2(vec_center, &from->x, center_pt);
+ if (is_zero_v2(vec_center)) {
+ return 0;
+ }
+
+ float vec_p[3];
+ float angle_incr = M_PI / ((float)num_points - 1);
+
+ tPerimeterPoint *last_point = from;
+ for (int i = 1; i < num_points; i++) {
+ float angle = i * angle_incr;
+
+ /* Rotate vector around point to get perimeter points. */
+ rotate_v2_v2fl(vec_p, vec_center, angle);
+ add_v2_v2(vec_p, center_pt);
+ vec_p[2] = center_pt[2];
+
+ tPerimeterPoint *new_point = new_perimeter_point(vec_p);
+ BLI_insertlinkafter(list, last_point, new_point);
+
+ last_point = new_point;
+ }
+
+ return num_points - 1;
+}
+
+static int generate_perimeter_cap(const float point[4],
+ const float other_point[4],
+ float radius,
+ ListBase *list,
+ int subdivisions,
+ short cap_type)
+{
+ float cap_vec[2];
+ sub_v2_v2v2(cap_vec, other_point, point);
+ normalize_v2(cap_vec);
+
+ float cap_nvec[2];
+ if (is_zero_v2(cap_vec)) {
+ cap_nvec[0] = 0;
+ cap_nvec[1] = radius;
+ }
+ else {
+ cap_nvec[0] = -cap_vec[1];
+ cap_nvec[1] = cap_vec[0];
+ mul_v2_fl(cap_nvec, radius);
+ }
+ float cap_nvec_inv[2];
+ negate_v2_v2(cap_nvec_inv, cap_nvec);
+
+ float vec_perimeter[3];
+ copy_v3_v3(vec_perimeter, point);
+ add_v2_v2(vec_perimeter, cap_nvec);
+
+ float vec_perimeter_inv[3];
+ copy_v3_v3(vec_perimeter_inv, point);
+ add_v2_v2(vec_perimeter_inv, cap_nvec_inv);
+
+ tPerimeterPoint *p_pt = new_perimeter_point(vec_perimeter);
+ tPerimeterPoint *p_pt_inv = new_perimeter_point(vec_perimeter_inv);
+
+ BLI_addtail(list, p_pt);
+ BLI_addtail(list, p_pt_inv);
+
+ int num_points = 0;
+ if (cap_type == GP_STROKE_CAP_ROUND) {
+ num_points += generate_semi_circle_from_point_to_point(list, p_pt, p_pt_inv, subdivisions);
+ }
+
+ return num_points + 2;
+}
+
+/**
+ * Calculate the perimeter (outline) of a stroke as list of tPerimeterPoint.
+ * \param subdivisions: Number of subdivisions for the start and end caps
+ * \return: list of tPerimeterPoint
+ */
+static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd,
+ const bGPDlayer *gpl,
+ const bGPDstroke *gps,
+ int subdivisions,
+ int *r_num_perimeter_points)
+{
+ /* sanity check */
+ if (gps->totpoints < 1) {
+ return NULL;
+ }
+
+ float defaultpixsize = 1000.0f / gpd->pixfactor;
+ float stroke_radius = ((gps->thickness + gpl->line_change) / defaultpixsize) / 2.0f;
+
+ ListBase *perimeter_right_side = MEM_callocN(sizeof(ListBase), __func__);
+ ListBase *perimeter_left_side = MEM_callocN(sizeof(ListBase), __func__);
+ int num_perimeter_points = 0;
+
+ bGPDspoint *first = &gps->points[0];
+ bGPDspoint *last = &gps->points[gps->totpoints - 1];
+
+ float first_radius = stroke_radius * first->pressure;
+ float last_radius = stroke_radius * last->pressure;
+
+ bGPDspoint *first_next;
+ bGPDspoint *last_prev;
+ if (gps->totpoints > 1) {
+ first_next = &gps->points[1];
+ last_prev = &gps->points[gps->totpoints - 2];
+ }
+ else {
+ first_next = first;
+ last_prev = last;
+ }
+
+ float first_pt[3];
+ float last_pt[3];
+ float first_next_pt[3];
+ float last_prev_pt[3];
+ copy_v3_v3(first_pt, &first->x);
+ copy_v3_v3(last_pt, &last->x);
+ copy_v3_v3(first_next_pt, &first_next->x);
+ copy_v3_v3(last_prev_pt, &last_prev->x);
+
+ /* Edge-case if single point. */
+ if (gps->totpoints == 1) {
+ first_next_pt[0] += 1.0f;
+ last_prev_pt[0] -= 1.0f;
+ }
+
+ /* generate points for start cap */
+ num_perimeter_points += generate_perimeter_cap(
+ first_pt, first_next_pt, first_radius, perimeter_right_side, subdivisions, gps->caps[0]);
+
+ /* generate perimeter points */
+ float curr_pt[3], next_pt[3], prev_pt[3];
+ float vec_next[2], vec_prev[2];
+ float nvec_next[2], nvec_prev[2];
+ float nvec_next_pt[3], nvec_prev_pt[3];
+ float vec_tangent[2];
+
+ float vec_miter_left[2], vec_miter_right[2];
+ float miter_left_pt[3], miter_right_pt[3];
+
+ for (int i = 1; i < gps->totpoints - 1; i++) {
+ bGPDspoint *curr = &gps->points[i];
+ bGPDspoint *prev = &gps->points[i - 1];
+ bGPDspoint *next = &gps->points[i + 1];
+ float radius = stroke_radius * curr->pressure;
+
+ copy_v3_v3(curr_pt, &curr->x);
+ copy_v3_v3(next_pt, &next->x);
+ copy_v3_v3(prev_pt, &prev->x);
+
+ sub_v2_v2v2(vec_prev, curr_pt, prev_pt);
+ sub_v2_v2v2(vec_next, next_pt, curr_pt);
+ float prev_length = len_v2(vec_prev);
+ float next_length = len_v2(vec_next);
+
+ if (normalize_v2(vec_prev) == 0.0f) {
+ vec_prev[0] = 1.0f;
+ vec_prev[1] = 0.0f;
+ }
+ if (normalize_v2(vec_next) == 0.0f) {
+ vec_next[0] = 1.0f;
+ vec_next[1] = 0.0f;
+ }
+
+ nvec_prev[0] = -vec_prev[1];
+ nvec_prev[1] = vec_prev[0];
+
+ nvec_next[0] = -vec_next[1];
+ nvec_next[1] = vec_next[0];
+
+ add_v2_v2v2(vec_tangent, vec_prev, vec_next);
+ if (normalize_v2(vec_tangent) == 0.0f) {
+ copy_v2_v2(vec_tangent, nvec_prev);
+ }
+
+ vec_miter_left[0] = -vec_tangent[1];
+ vec_miter_left[1] = vec_tangent[0];
+
+ /* calculate miter length */
+ float an1 = dot_v2v2(vec_miter_left, nvec_prev);
+ if (an1 == 0.0f) {
+ an1 = 1.0f;
+ }
+ float miter_length = radius / an1;
+ if (miter_length <= 0.0f) {
+ miter_length = 0.01f;
+ }
+
+ normalize_v2_length(vec_miter_left, miter_length);
+
+ copy_v2_v2(vec_miter_right, vec_miter_left);
+ negate_v2(vec_miter_right);
+
+ float angle = dot_v2v2(vec_next, nvec_prev);
+ /* Add two points if angle is close to being straight. */
+ if (fabsf(angle) < 0.0001f) {
+ normalize_v2_length(nvec_prev, radius);
+ normalize_v2_length(nvec_next, radius);
+
+ copy_v3_v3(nvec_prev_pt, curr_pt);
+ add_v2_v2(nvec_prev_pt, nvec_prev);
+
+ copy_v3_v3(nvec_next_pt, curr_pt);
+ negate_v2(nvec_next);
+ add_v2_v2(nvec_next_pt, nvec_next);
+
+ tPerimeterPoint *normal_prev = new_perimeter_point(nvec_prev_pt);
+ tPerimeterPoint *normal_next = new_perimeter_point(nvec_next_pt);
+
+ BLI_addtail(perimeter_left_side, normal_prev);
+ BLI_addtail(perimeter_right_side, normal_next);
+ num_perimeter_points += 2;
+ }
+ else {
+ /* bend to the left */
+ if (angle < 0.0f) {
+ normalize_v2_length(nvec_prev, radius);
+ normalize_v2_length(nvec_next, radius);
+
+ copy_v3_v3(nvec_prev_pt, curr_pt);
+ add_v2_v2(nvec_prev_pt, nvec_prev);
+
+ copy_v3_v3(nvec_next_pt, curr_pt);
+ add_v2_v2(nvec_next_pt, nvec_next);
+
+ tPerimeterPoint *normal_prev = new_perimeter_point(nvec_prev_pt);
+ tPerimeterPoint *normal_next = new_perimeter_point(nvec_next_pt);
+
+ BLI_addtail(perimeter_left_side, normal_prev);
+ BLI_addtail(perimeter_left_side, normal_next);
+ num_perimeter_points += 2;
+
+ num_perimeter_points += generate_arc_from_point_to_point(
+ perimeter_left_side, normal_prev, normal_next, curr_pt, subdivisions, true);
+
+ if (miter_length < prev_length && miter_length < next_length) {
+ copy_v3_v3(miter_right_pt, curr_pt);
+ add_v2_v2(miter_right_pt, vec_miter_right);
+ }
+ else {
+ copy_v3_v3(miter_right_pt, curr_pt);
+ negate_v2(nvec_next);
+ add_v2_v2(miter_right_pt, nvec_next);
+ }
+
+ tPerimeterPoint *miter_right = new_perimeter_point(miter_right_pt);
+ BLI_addtail(perimeter_right_side, miter_right);
+ num_perimeter_points++;
+ }
+ /* bend to the right */
+ else {
+ normalize_v2_length(nvec_prev, -radius);
+ normalize_v2_length(nvec_next, -radius);
+
+ copy_v3_v3(nvec_prev_pt, curr_pt);
+ add_v2_v2(nvec_prev_pt, nvec_prev);
+
+ copy_v3_v3(nvec_next_pt, curr_pt);
+ add_v2_v2(nvec_next_pt, nvec_next);
+
+ tPerimeterPoint *normal_prev = new_perimeter_point(nvec_prev_pt);
+ tPerimeterPoint *normal_next = new_perimeter_point(nvec_next_pt);
+
+ BLI_addtail(perimeter_right_side, normal_prev);
+ BLI_addtail(perimeter_right_side, normal_next);
+ num_perimeter_points += 2;
+
+ num_perimeter_points += generate_arc_from_point_to_point(
+ perimeter_right_side, normal_prev, normal_next, curr_pt, subdivisions, false);
+
+ if (miter_length < prev_length && miter_length < next_length) {
+ copy_v3_v3(miter_left_pt, curr_pt);
+ add_v2_v2(miter_left_pt, vec_miter_left);
+ }
+ else {
+ copy_v3_v3(miter_left_pt, curr_pt);
+ negate_v2(nvec_prev);
+ add_v2_v2(miter_left_pt, nvec_prev);
+ }
+
+ tPerimeterPoint *miter_left = new_perimeter_point(miter_left_pt);
+ BLI_addtail(perimeter_left_side, miter_left);
+ num_perimeter_points++;
+ }
+ }
+ }
+
+ /* generate points for end cap */
+ num_perimeter_points += generate_perimeter_cap(
+ last_pt, last_prev_pt, last_radius, perimeter_right_side, subdivisions, gps->caps[1]);
+
+ /* merge both sides to one list */
+ BLI_listbase_reverse(perimeter_right_side);
+ BLI_movelisttolist(perimeter_left_side,
+ perimeter_right_side); // perimeter_left_side contains entire list
+ ListBase *perimeter_list = perimeter_left_side;
+
+ /* close by creating a point close to the first (make a small gap) */
+ float close_pt[3];
+ tPerimeterPoint *close_first = (tPerimeterPoint *)perimeter_list->first;
+ tPerimeterPoint *close_last = (tPerimeterPoint *)perimeter_list->last;
+ interp_v3_v3v3(close_pt, &close_last->x, &close_first->x, 0.99f);
+
+ if (compare_v3v3(close_pt, &close_first->x, FLT_EPSILON) == false) {
+ tPerimeterPoint *close_p_pt = new_perimeter_point(close_pt);
+ BLI_addtail(perimeter_list, close_p_pt);
+ num_perimeter_points++;
+ }
+
+ /* free temp data */
+ BLI_freelistN(perimeter_right_side);
+ MEM_freeN(perimeter_right_side);
+
+ *r_num_perimeter_points = num_perimeter_points;
+ return perimeter_list;
+}
+
+/**
+ * Calculates the perimeter of a stroke projected from the view and
+ * returns it as a new stroke.
+ * \param subdivisions: Number of subdivisions for the start and end caps
+ * \return: bGPDstroke pointer to stroke perimeter
+ */
+bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d,
+ bGPdata *gpd,
+ const bGPDlayer *gpl,
+ bGPDstroke *gps,
+ const int subdivisions,
+ const float diff_mat[4][4])
+{
+ if (gps->totpoints == 0) {
+ return NULL;
+ }
+ bGPDstroke *gps_temp = BKE_gpencil_stroke_duplicate(gps, true, false);
+ const bool cyclic = ((gps_temp->flag & GP_STROKE_CYCLIC) != 0);
+
+ /* If Cyclic, add a new point. */
+ if (cyclic && (gps_temp->totpoints > 1)) {
+ gps_temp->totpoints++;
+ gps_temp->points = MEM_recallocN(gps_temp->points,
+ sizeof(*gps_temp->points) * gps_temp->totpoints);
+ bGPDspoint *pt_src = &gps_temp->points[0];
+ bGPDspoint *pt_dst = &gps_temp->points[gps_temp->totpoints - 1];
+ copy_v3_v3(&pt_dst->x, &pt_src->x);
+ pt_dst->pressure = pt_src->pressure;
+ pt_dst->strength = pt_src->strength;
+ pt_dst->uv_fac = 1.0f;
+ pt_dst->uv_rot = 0;
+ }
+
+ BKE_gpencil_stroke_to_view_space(rv3d, gps_temp, diff_mat);
+ int num_perimeter_points = 0;
+ ListBase *perimeter_points = gpencil_stroke_perimeter_ex(
+ gpd, gpl, gps_temp, subdivisions, &num_perimeter_points);
+
+ if (num_perimeter_points == 0) {
+ return NULL;
+ }
+
+ /* Create new stroke. */
+ bGPDstroke *perimeter_stroke = BKE_gpencil_stroke_new(gps_temp->mat_nr, num_perimeter_points, 1);
+
+ int i = 0;
+ LISTBASE_FOREACH_INDEX (tPerimeterPoint *, curr, perimeter_points, i) {
+ bGPDspoint *pt = &perimeter_stroke->points[i];
+
+ copy_v3_v3(&pt->x, &curr->x);
+ pt->pressure = 0.0f;
+ pt->strength = 1.0f;
+
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+
+ BKE_gpencil_stroke_from_view_space(rv3d, perimeter_stroke, diff_mat);
+
+ /* Free temp data. */
+ BLI_freelistN(perimeter_points);
+ MEM_freeN(perimeter_points);
+
+ /* Triangles cache needs to be recalculated. */
+ BKE_gpencil_stroke_geometry_update(gpd, perimeter_stroke);
+
+ perimeter_stroke->flag |= GP_STROKE_SELECT | GP_STROKE_CYCLIC;
+
+ BKE_gpencil_free_stroke(gps_temp);
+
+ return perimeter_stroke;
+}
+
+/** Get average pressure. */
+float BKE_gpencil_stroke_average_pressure_get(bGPDstroke *gps)
+{
+
+ if (gps->totpoints == 1) {
+ return gps->points[0].pressure;
+ }
+
+ float tot = 0.0f;
+ for (int i = 0; i < gps->totpoints; i++) {
+ const bGPDspoint *pt = &gps->points[i];
+ tot += pt->pressure;
+ }
+
+ return tot / (float)gps->totpoints;
+}
+
+/** Check if the thickness of the stroke is constant. */
+bool BKE_gpencil_stroke_is_pressure_constant(bGPDstroke *gps)
+{
+ if (gps->totpoints == 1) {
+ return true;
+ }
+
+ const float first_pressure = gps->points[0].pressure;
+ for (int i = 0; i < gps->totpoints; i++) {
+ const bGPDspoint *pt = &gps->points[i];
+ if (pt->pressure != first_pressure) {
+ return false;
+ }
+ }
+
+ return true;
+}
/** \} */
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 7c451051727..48104e72825 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -540,10 +540,12 @@ void BKE_lattice_vert_coords_apply(Lattice *lt, const float (*vert_coords)[3])
void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, Scene *scene, Object *ob)
{
+ BKE_object_free_derived_caches(ob);
+ if (ob->runtime.curve_cache == NULL) {
+ ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for lattice");
+ }
+
Lattice *lt = ob->data;
- /* Get vertex coordinates from the original copy;
- * otherwise we get already-modified coordinates. */
- Object *ob_orig = DEG_get_original_object(ob);
VirtualModifierData virtualModifierData;
ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData);
float(*vert_coords)[3] = NULL;
@@ -551,13 +553,6 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, Scene *scene, Objec
const bool is_editmode = (lt->editlatt != NULL);
const ModifierEvalContext mectx = {depsgraph, ob, 0};
- if (ob->runtime.curve_cache) {
- BKE_displist_free(&ob->runtime.curve_cache->disp);
- }
- else {
- ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for lattice");
- }
-
for (; md; md = md->next) {
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
@@ -577,49 +572,33 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, Scene *scene, Objec
continue;
}
- if (!vert_coords) {
- Lattice *lt_orig = ob_orig->data;
- if (lt_orig->editlatt) {
- lt_orig = lt_orig->editlatt->latt;
- }
- vert_coords = BKE_lattice_vert_coords_alloc(lt_orig, &numVerts);
+ if (vert_coords == NULL) {
+ /* Get either the edit-mode or regular lattice, whichever is in use now. */
+ const Lattice *effective_lattice = BKE_object_get_lattice(ob);
+ vert_coords = BKE_lattice_vert_coords_alloc(effective_lattice, &numVerts);
}
+
mti->deformVerts(md, &mectx, NULL, vert_coords, numVerts);
}
- if (ob->id.tag & LIB_TAG_COPIED_ON_WRITE) {
- if (vert_coords) {
- BKE_lattice_vert_coords_apply(ob->data, vert_coords);
- MEM_freeN(vert_coords);
- }
+ if (vert_coords == NULL) {
+ return;
}
- else {
- /* Displist won't do anything; this is just for posterity's sake until we remove it. */
- if (!vert_coords) {
- Lattice *lt_orig = ob_orig->data;
- if (lt_orig->editlatt) {
- lt_orig = lt_orig->editlatt->latt;
- }
- vert_coords = BKE_lattice_vert_coords_alloc(lt_orig, &numVerts);
- }
-
- DispList *dl = MEM_callocN(sizeof(*dl), "lt_dl");
- dl->type = DL_VERTS;
- dl->parts = 1;
- dl->nr = numVerts;
- dl->verts = (float *)vert_coords;
- BLI_addtail(&ob->runtime.curve_cache->disp, dl);
+ Lattice *lt_eval = BKE_object_get_evaluated_lattice(ob);
+ if (lt_eval == NULL) {
+ BKE_id_copy_ex(NULL, &lt->id, (ID **)&lt_eval, LIB_ID_COPY_LOCALIZE);
+ BKE_object_eval_assign_data(ob, &lt_eval->id, true);
}
+
+ BKE_lattice_vert_coords_apply(lt_eval, vert_coords);
+ MEM_freeN(vert_coords);
}
struct MDeformVert *BKE_lattice_deform_verts_get(const struct Object *oblatt)
{
- Lattice *lt = (Lattice *)oblatt->data;
BLI_assert(oblatt->type == OB_LATTICE);
- if (lt->editlatt) {
- lt = lt->editlatt->latt;
- }
+ Lattice *lt = BKE_object_get_lattice(oblatt);
return lt->dvert;
}
diff --git a/source/blender/blenkernel/intern/lattice_deform.c b/source/blender/blenkernel/intern/lattice_deform.c
index 2651042939f..4a926ee3d96 100644
--- a/source/blender/blenkernel/intern/lattice_deform.c
+++ b/source/blender/blenkernel/intern/lattice_deform.c
@@ -47,6 +47,7 @@
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_modifier.h"
+#include "BKE_object.h"
#include "BKE_deform.h"
@@ -69,7 +70,7 @@ typedef struct LatticeDeformData {
LatticeDeformData *BKE_lattice_deform_data_create(const Object *oblatt, const Object *ob)
{
/* we make an array with all differences */
- Lattice *lt = oblatt->data;
+ Lattice *lt = BKE_object_get_lattice(oblatt);
BPoint *bp;
DispList *dl = oblatt->runtime.curve_cache ?
BKE_displist_find(&oblatt->runtime.curve_cache->disp, DL_VERTS) :
@@ -83,9 +84,6 @@ LatticeDeformData *BKE_lattice_deform_data_create(const Object *oblatt, const Ob
float latmat[4][4];
LatticeDeformData *lattice_deform_data;
- if (lt->editlatt) {
- lt = lt->editlatt->latt;
- }
bp = lt->def;
const int32_t num_points = lt->pntsu * lt->pntsv * lt->pntsw;
diff --git a/source/blender/blenkernel/intern/lattice_deform_test.cc b/source/blender/blenkernel/intern/lattice_deform_test.cc
index f08d0349598..a7cd5c36ec2 100644
--- a/source/blender/blenkernel/intern/lattice_deform_test.cc
+++ b/source/blender/blenkernel/intern/lattice_deform_test.cc
@@ -51,6 +51,7 @@ static void test_lattice_deform_init(LatticeDeformTestContext *ctx,
ctx->coords[index][2] = (rng->get_float() - 0.5f) * 10;
}
IDType_ID_LT.init_data(&ctx->lattice.id);
+ strcpy(ctx->lattice.id.name, "LTLattice");
IDType_ID_OB.init_data(&ctx->ob_lattice.id);
ctx->ob_lattice.type = OB_LATTICE;
ctx->ob_lattice.data = &ctx->lattice;
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 8b23acdde9b..ebe8043d41d 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -118,7 +118,7 @@ IDOverrideLibrary *BKE_lib_override_library_init(ID *local_id, ID *reference_id)
/** Shalow or deep copy of a whole override from \a src_id to \a dst_id. */
void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id, const bool do_full_copy)
{
- BLI_assert(ID_IS_OVERRIDE_LIBRARY(src_id));
+ BLI_assert(ID_IS_OVERRIDE_LIBRARY(src_id) || ID_IS_OVERRIDE_LIBRARY_TEMPLATE(src_id));
if (dst_id->override_library != NULL) {
if (src_id->override_library == NULL) {
@@ -437,6 +437,10 @@ static bool lib_override_hierarchy_dependencies_recursive_tag(LibOverrideGroupTa
}
/* We only consider IDs from the same library. */
ID *to_id = *to_id_entry->id_pointer.to;
+ if (!ID_IS_LINKED(to_id) && !ID_IS_OVERRIDE_LIBRARY(to_id)) {
+ /* Pure local data is a barrier of dependency in override cases. */
+ continue;
+ }
if (to_id != NULL && to_id->lib == id->lib) {
LibOverrideGroupTagData sub_data = *data;
sub_data.id_root = to_id;
@@ -812,10 +816,29 @@ bool BKE_lib_override_library_create(
BKE_main_id_clear_newpoins(bmain);
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+ /* We need to rebuild some of the deleted override rules (for UI feedback purpose). */
+ BKE_lib_override_library_main_operations_create(bmain, true);
+
return success;
}
/**
+ * Create a library override template.
+ */
+bool BKE_lib_override_library_template_create(struct ID *id)
+{
+ if (ID_IS_LINKED(id)) {
+ return false;
+ }
+ if (ID_IS_OVERRIDE_LIBRARY(id)) {
+ return false;
+ }
+
+ BKE_lib_override_library_init(id, NULL);
+ return true;
+}
+
+/**
* Convert a given proxy object into a library override.
*
* \note This is a thin wrapper around \a BKE_lib_override_library_create, only extra work is to
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 3a3ad9ef051..a3f122115d8 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -1893,10 +1893,17 @@ static void interp_weights_uv_v2_calc(float r_uv[2],
const float pt_a[2],
const float pt_b[2])
{
+ const float segment_len = len_v2v2(pt_a, pt_b);
+ if (segment_len == 0.0f) {
+ r_uv[0] = 1.0f;
+ r_uv[1] = 0.0f;
+ return;
+ }
+
float pt_on_line[2];
r_uv[0] = closest_to_line_v2(pt_on_line, pt, pt_a, pt_b);
- r_uv[1] = (len_v2v2(pt_on_line, pt) / len_v2v2(pt_a, pt_b)) *
+ r_uv[1] = (len_v2v2(pt_on_line, pt) / segment_len) *
/* This line only sets the sign. */
((line_point_side_v2(pt_a, pt_b, pt) < 0.0f) ? -1.0f : 1.0f);
}
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index d06e4030117..315ff40289d 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -778,6 +778,13 @@ static void lib_link_node_socket(BlendLibReader *reader, Library *lib, bNodeSock
{
IDP_BlendReadLib(reader, sock->prop);
+ /* This can happen for all socket types when a file is saved in an older version of Blender than
+ * it was originally created in (T86298). Some socket types still require a default value. The
+ * default value of those sockets will be created in `ntreeSetTypes`. */
+ if (sock->default_value == nullptr) {
+ return;
+ }
+
switch ((eNodeSocketDatatype)sock->type) {
case SOCK_OBJECT: {
bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value;
@@ -1364,7 +1371,9 @@ GHashIterator *nodeSocketTypeGetIterator(void)
return BLI_ghashIterator_new(nodesockettypes_hash);
}
-struct bNodeSocket *nodeFindSocket(const bNode *node, int in_out, const char *identifier)
+struct bNodeSocket *nodeFindSocket(const bNode *node,
+ eNodeSocketInOut in_out,
+ const char *identifier)
{
const ListBase *sockets = (in_out == SOCK_IN) ? &node->inputs : &node->outputs;
LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
@@ -1521,7 +1530,7 @@ void nodeModifySocketType(
bNodeSocket *nodeAddSocket(bNodeTree *ntree,
bNode *node,
- int in_out,
+ eNodeSocketInOut in_out,
const char *idname,
const char *identifier,
const char *name)
@@ -1543,7 +1552,7 @@ bNodeSocket *nodeAddSocket(bNodeTree *ntree,
bNodeSocket *nodeInsertSocket(bNodeTree *ntree,
bNode *node,
- int in_out,
+ eNodeSocketInOut in_out,
const char *idname,
bNodeSocket *next_sock,
const char *identifier,
@@ -1704,7 +1713,7 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype)
bNodeSocket *nodeAddStaticSocket(bNodeTree *ntree,
bNode *node,
- int in_out,
+ eNodeSocketInOut in_out,
int type,
int subtype,
const char *identifier,
@@ -1724,7 +1733,7 @@ bNodeSocket *nodeAddStaticSocket(bNodeTree *ntree,
bNodeSocket *nodeInsertStaticSocket(bNodeTree *ntree,
bNode *node,
- int in_out,
+ eNodeSocketInOut in_out,
int type,
int subtype,
bNodeSocket *next_sock,
@@ -3220,7 +3229,7 @@ void ntreeLocalMerge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree)
/* ************ NODE TREE INTERFACE *************** */
static bNodeSocket *make_socket_interface(bNodeTree *ntree,
- int in_out,
+ eNodeSocketInOut in_out,
const char *idname,
const char *name)
{
@@ -3256,7 +3265,9 @@ static bNodeSocket *make_socket_interface(bNodeTree *ntree,
return sock;
}
-bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree, int in_out, const char *identifier)
+bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree,
+ eNodeSocketInOut in_out,
+ const char *identifier)
{
ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs;
LISTBASE_FOREACH (bNodeSocket *, iosock, sockets) {
@@ -3268,7 +3279,7 @@ bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree, int in_out, const char *
}
bNodeSocket *ntreeAddSocketInterface(bNodeTree *ntree,
- int in_out,
+ eNodeSocketInOut in_out,
const char *idname,
const char *name)
{
@@ -3284,8 +3295,11 @@ bNodeSocket *ntreeAddSocketInterface(bNodeTree *ntree,
return iosock;
}
-bNodeSocket *ntreeInsertSocketInterface(
- bNodeTree *ntree, int in_out, const char *idname, bNodeSocket *next_sock, const char *name)
+bNodeSocket *ntreeInsertSocketInterface(bNodeTree *ntree,
+ eNodeSocketInOut in_out,
+ const char *idname,
+ bNodeSocket *next_sock,
+ const char *name)
{
bNodeSocket *iosock = make_socket_interface(ntree, in_out, idname, name);
if (in_out == SOCK_IN) {
@@ -3304,7 +3318,7 @@ struct bNodeSocket *ntreeAddSocketInterfaceFromSocket(bNodeTree *ntree,
bNodeSocket *from_sock)
{
bNodeSocket *iosock = ntreeAddSocketInterface(
- ntree, from_sock->in_out, from_sock->idname, from_sock->name);
+ ntree, static_cast<eNodeSocketInOut>(from_sock->in_out), from_sock->idname, from_sock->name);
if (iosock) {
if (iosock->typeinfo->interface_from_socket) {
iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
@@ -3319,7 +3333,11 @@ struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(bNodeTree *ntree,
bNodeSocket *from_sock)
{
bNodeSocket *iosock = ntreeInsertSocketInterface(
- ntree, from_sock->in_out, from_sock->idname, next_sock, from_sock->name);
+ ntree,
+ static_cast<eNodeSocketInOut>(from_sock->in_out),
+ from_sock->idname,
+ next_sock,
+ from_sock->name);
if (iosock) {
if (iosock->typeinfo->interface_from_socket) {
iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
@@ -4693,6 +4711,7 @@ static void registerCompositNodes()
register_node_type_cmp_defocus();
register_node_type_cmp_sunbeams();
register_node_type_cmp_denoise();
+ register_node_type_cmp_antialiasing();
register_node_type_cmp_valtorgb();
register_node_type_cmp_rgbtobw();
@@ -4903,11 +4922,13 @@ static void registerGeometryNodes()
register_node_type_geo_group();
register_node_type_geo_align_rotation_to_vector();
+ register_node_type_geo_attribute_clamp();
register_node_type_geo_attribute_color_ramp();
register_node_type_geo_attribute_combine_xyz();
register_node_type_geo_attribute_compare();
register_node_type_geo_attribute_convert();
register_node_type_geo_attribute_fill();
+ register_node_type_geo_attribute_map_range();
register_node_type_geo_attribute_math();
register_node_type_geo_attribute_mix();
register_node_type_geo_attribute_proximity();
@@ -4924,9 +4945,9 @@ static void registerGeometryNodes()
register_node_type_geo_mesh_primitive_cone();
register_node_type_geo_mesh_primitive_cube();
register_node_type_geo_mesh_primitive_cylinder();
+ register_node_type_geo_mesh_primitive_grid();
register_node_type_geo_mesh_primitive_ico_sphere();
register_node_type_geo_mesh_primitive_line();
- register_node_type_geo_mesh_primitive_plane();
register_node_type_geo_mesh_primitive_uv_sphere();
register_node_type_geo_object_info();
register_node_type_geo_point_distribute();
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index b07c4b22c39..8c5a4966633 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -4353,8 +4353,6 @@ void BKE_object_handle_update_ex(Depsgraph *depsgraph,
BKE_object_handle_data_update(depsgraph, scene, ob);
}
- ob->id.recalc &= ID_RECALC_ALL;
-
object_handle_update_proxy(depsgraph, scene, ob, do_proxy_update);
}
@@ -4474,6 +4472,37 @@ Mesh *BKE_object_get_original_mesh(Object *object)
return result;
}
+Lattice *BKE_object_get_lattice(const Object *object)
+{
+ ID *data = object->data;
+ if (data == NULL || GS(data->name) != ID_LT) {
+ return NULL;
+ }
+
+ Lattice *lt = (Lattice *)data;
+ if (lt->editlatt) {
+ return lt->editlatt->latt;
+ }
+
+ return lt;
+}
+
+Lattice *BKE_object_get_evaluated_lattice(const Object *object)
+{
+ ID *data_eval = object->runtime.data_eval;
+
+ if (data_eval == NULL || GS(data_eval->name) != ID_LT) {
+ return NULL;
+ }
+
+ Lattice *lt_eval = (Lattice *)data_eval;
+ if (lt_eval->editlatt) {
+ return lt_eval->editlatt->latt;
+ }
+
+ return lt_eval;
+}
+
static int pc_cmp(const void *a, const void *b)
{
const LinkData *ad = a, *bd = b;
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 6a0c9460a01..89451d70c74 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -1530,9 +1530,6 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area)
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
-
- v3d->flag |= V3D_INVALID_BACKBUF;
-
if (v3d->gpd) {
BLO_read_data_address(reader, &v3d->gpd);
BKE_gpencil_blend_read_data(reader, v3d->gpd);
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index de88e8a941c..d52e4443ac1 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -3181,9 +3181,11 @@ void sbFree(Object *ob)
return;
}
+ const bool is_orig = (ob->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0;
+
free_softbody_intern(sb);
- if ((ob->id.tag & LIB_TAG_NO_MAIN) == 0) {
+ if (is_orig) {
/* Only free shared data on non-CoW copies */
BKE_ptcache_free_list(&sb->shared->ptcaches);
sb->shared->pointcache = NULL;
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index d124922acd1..f3d6bc4a6e3 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -3251,6 +3251,11 @@ static void tracking_dopesheet_calc_coverage(MovieTracking *tracking)
end_frame = max_ii(end_frame, track->markers[track->markersnr - 1].framenr);
}
+ if (start_frame > end_frame) {
+ /* There are no markers at all, nothing to calculate coverage from. */
+ return;
+ }
+
frames = end_frame - start_frame + 1;
/* this is a per-frame counter of markers (how many markers belongs to the same frame) */
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 0991d804882..7fc9e8cc0ef 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -567,9 +567,6 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
/* Set up the codec context */
c = st->codec;
- c->thread_count = BLI_system_thread_count();
- c->thread_type = FF_THREAD_SLICE;
-
c->codec_id = codec_id;
c->codec_type = AVMEDIA_TYPE_VIDEO;
@@ -727,6 +724,20 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
set_ffmpeg_properties(rd, c, "video", &opts);
+ if (codec->capabilities & AV_CODEC_CAP_AUTO_THREADS) {
+ c->thread_count = 0;
+ }
+ else {
+ c->thread_count = BLI_system_thread_count();
+ }
+
+ if (codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) {
+ c->thread_type = FF_THREAD_FRAME;
+ }
+ else if (codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
+ c->thread_type = FF_THREAD_SLICE;
+ }
+
if (avcodec_open2(c, codec, &opts) < 0) {
BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
av_dict_free(&opts);
diff --git a/source/blender/blenlib/BLI_asan.h b/source/blender/blenlib/BLI_asan.h
index a2a44e164ab..c38ad6b39d0 100644
--- a/source/blender/blenlib/BLI_asan.h
+++ b/source/blender/blenlib/BLI_asan.h
@@ -21,7 +21,7 @@
# define __has_feature(x) 0
#endif
-#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)
+#if (defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)) && !defined(_MSC_VER)
# include "sanitizer/asan_interface.h"
#else
/* Ensure return value is used. Just using UNUSED_VARS results in a warning. */
diff --git a/source/blender/blenlib/BLI_hash.hh b/source/blender/blenlib/BLI_hash.hh
index 39695b110b1..4022c2baa1f 100644
--- a/source/blender/blenlib/BLI_hash.hh
+++ b/source/blender/blenlib/BLI_hash.hh
@@ -206,19 +206,38 @@ template<typename T> struct DefaultHash<T *> {
}
};
+template<typename T> uint64_t get_default_hash(const T &v)
+{
+ return DefaultHash<T>{}(v);
+}
+
+template<typename T1, typename T2> uint64_t get_default_hash_2(const T1 &v1, const T2 &v2)
+{
+ const uint64_t h1 = get_default_hash(v1);
+ const uint64_t h2 = get_default_hash(v2);
+ return h1 ^ (h2 * 19349669);
+}
+
+template<typename T1, typename T2, typename T3>
+uint64_t get_default_hash_3(const T1 &v1, const T2 &v2, const T3 &v3)
+{
+ const uint64_t h1 = get_default_hash(v1);
+ const uint64_t h2 = get_default_hash(v2);
+ const uint64_t h3 = get_default_hash(v3);
+ return h1 ^ (h2 * 19349669) ^ (h3 * 83492791);
+}
+
template<typename T> struct DefaultHash<std::unique_ptr<T>> {
uint64_t operator()(const std::unique_ptr<T> &value) const
{
- return DefaultHash<T *>{}(value.get());
+ return get_default_hash(value.get());
}
};
template<typename T1, typename T2> struct DefaultHash<std::pair<T1, T2>> {
uint64_t operator()(const std::pair<T1, T2> &value) const
{
- uint64_t hash1 = DefaultHash<T1>{}(value.first);
- uint64_t hash2 = DefaultHash<T2>{}(value.second);
- return hash1 ^ (hash2 * 33);
+ return get_default_hash_2(value.first, value.second);
}
};
diff --git a/source/blender/blenlib/BLI_set.hh b/source/blender/blenlib/BLI_set.hh
index fef657b2d8f..a8ccf957f6c 100644
--- a/source/blender/blenlib/BLI_set.hh
+++ b/source/blender/blenlib/BLI_set.hh
@@ -788,6 +788,8 @@ class Set {
template<typename ForwardKey>
const Key &lookup_key_or_add__impl(ForwardKey &&key, const uint64_t hash)
{
+ this->ensure_can_add();
+
SET_SLOT_PROBING_BEGIN (hash, slot) {
if (slot.contains(key, is_equal_, hash)) {
return *slot.key();
diff --git a/source/blender/blenlib/BLI_user_counter.hh b/source/blender/blenlib/BLI_user_counter.hh
index ef276814981..3e6d5af4c3f 100644
--- a/source/blender/blenlib/BLI_user_counter.hh
+++ b/source/blender/blenlib/BLI_user_counter.hh
@@ -125,7 +125,7 @@ template<typename T> class UserCounter {
uint64_t hash() const
{
- return DefaultHash<T *>{}(data_);
+ return get_default_hash(data_);
}
friend bool operator==(const UserCounter &a, const UserCounter &b)
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 37b0f742b8b..d7a27cc4531 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -263,6 +263,7 @@ set(SRC
BLI_session_uuid.h
BLI_set.hh
BLI_set_slots.hh
+ BLI_simd.h
BLI_smallhash.h
BLI_sort.h
BLI_sort_utils.h
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index 6481fac5a14..2a7c091d1b9 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -192,6 +192,13 @@ MINLINE double ratiod(double min, double max, double pos)
return range == 0 ? 0 : ((pos - min) / range);
}
+/* Map a normalized value, i.e. from interval [0, 1] to interval [a, b] */
+MINLINE float scalenorm(float a, float b, float x)
+{
+ BLI_assert(x <= 1 && x >= 0);
+ return (x * (b - a)) + a;
+}
+
/* used for zoom values*/
MINLINE float power_of_2(float val)
{
diff --git a/source/blender/blenlib/intern/math_vec.cc b/source/blender/blenlib/intern/math_vec.cc
index 1d138d0b0f4..223c0e273f0 100644
--- a/source/blender/blenlib/intern/math_vec.cc
+++ b/source/blender/blenlib/intern/math_vec.cc
@@ -173,7 +173,7 @@ mpq3 mpq3::cross_poly(Span<mpq3> poly)
uint64_t hash_mpq_class(const mpq_class &value)
{
/* TODO: better/faster implementation of this. */
- return DefaultHash<float>{}(static_cast<float>(value.get_d()));
+ return get_default_hash(static_cast<float>(value.get_d()));
}
uint64_t mpq2::hash() const
diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc
index bc12ff1a652..bf70b044d0d 100644
--- a/source/blender/blenlib/intern/mesh_boolean.cc
+++ b/source/blender/blenlib/intern/mesh_boolean.cc
@@ -97,10 +97,7 @@ class Edge {
uint64_t hash() const
{
- constexpr uint64_t h1 = 33;
- uint64_t v0hash = DefaultHash<int>{}(v_[0]->id);
- uint64_t v1hash = DefaultHash<int>{}(v_[1]->id);
- return v0hash ^ (v1hash * h1);
+ return get_default_hash_2(v_[0]->id, v_[1]->id);
}
};
diff --git a/source/blender/blenlib/tests/BLI_set_test.cc b/source/blender/blenlib/tests/BLI_set_test.cc
index 56f1d57e4ae..3a4733a218f 100644
--- a/source/blender/blenlib/tests/BLI_set_test.cc
+++ b/source/blender/blenlib/tests/BLI_set_test.cc
@@ -456,8 +456,8 @@ TEST(set, LookupKeyPtr)
TEST(set, LookupKeyOrAdd)
{
Set<MyKeyType> set;
- set.add({1, 10});
- set.add({2, 20});
+ set.lookup_key_or_add({1, 10});
+ set.lookup_key_or_add({2, 20});
EXPECT_EQ(set.size(), 2);
EXPECT_EQ(set.lookup_key_or_add({2, 40}).attached_data, 20);
EXPECT_EQ(set.size(), 2);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index f97f6f65551..b657cb8b2f9 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2497,9 +2497,12 @@ static void direct_link_id_common(
/* Link direct data of overrides. */
if (id->override_library) {
BLO_read_data_address(reader, &id->override_library);
- BLO_read_list_cb(
- reader, &id->override_library->properties, direct_link_id_override_property_cb);
- id->override_library->runtime = NULL;
+ /* Work around file corruption on writing, see T86853. */
+ if (id->override_library != NULL) {
+ BLO_read_list_cb(
+ reader, &id->override_library->properties, direct_link_id_override_property_cb);
+ id->override_library->runtime = NULL;
+ }
}
DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index 80cd21338d6..0cd18d27587 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -27,6 +27,7 @@
#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
#include "DNA_brush_types.h"
#include "DNA_cachefile_types.h"
#include "DNA_collection_types.h"
@@ -1926,6 +1927,18 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 293, 15)) {
+ LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
+ if (ntree->type == NTREE_GEOMETRY) {
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ if (STREQ(node->idname, "GeometryNodeMeshPlane")) {
+ STRNCPY(node->idname, "GeometryNodeMeshGrid");
+ }
+ }
+ }
+ }
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
@@ -1937,6 +1950,20 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
*/
{
/* Keep this block, even when empty. */
+
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_GEOMETRY) {
+ version_node_socket_name(ntree, GEO_NODE_VOLUME_TO_MESH, "Grid", "Density");
+ }
+ }
+ FOREACH_NODETREE_END;
+
+ if (!DNA_struct_elem_find(fd->filesdna, "bArmature", "float", "axes_position")) {
+ /* Convert the axes draw position to its old default (tip of bone). */
+ LISTBASE_FOREACH (struct bArmature *, arm, &bmain->armatures) {
+ arm->axes_position = 1.0;
+ }
+ }
}
{
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index e43f8153bd1..f2e73e161ca 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -81,6 +81,7 @@
#include "BKE_pointcache.h"
#include "SEQ_iterator.h"
+#include "SEQ_sequencer.h"
#include "NOD_socket.h"
@@ -2560,18 +2561,16 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
if (bmain->versionfile < 249 && bmain->subversionfile < 2) {
Scene *sce = bmain->scenes.first;
- Sequence *seq;
Editing *ed;
while (sce) {
ed = sce->ed;
if (ed) {
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (seq->strip && seq->strip->proxy) {
seq->strip->proxy->quality = 90;
}
}
- SEQ_CURRENT_END;
}
sce = sce->id.next;
diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c
index 8cbedb05931..847b10192f8 100644
--- a/source/blender/blenloader/intern/versioning_userdef.c
+++ b/source/blender/blenloader/intern/versioning_userdef.c
@@ -261,17 +261,7 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
FROM_DEFAULT_V4_UCHAR(space_node.nodeclass_shader);
}
- /**
- * Versioning code until next subversion bump goes here.
- *
- * \note Be sure to check when bumping the version:
- * - #blo_do_versions_userdef in this file.
- * - "versioning_{BLENDER_VERSION}.c"
- *
- * \note Keep this message at the bottom of the function.
- */
- {
- /* Keep this block, even when empty. */
+ if (!USER_VERSION_ATLEAST(293, 15)) {
FROM_DEFAULT_V4_UCHAR(space_properties.active);
FROM_DEFAULT_V4_UCHAR(space_info.info_error);
@@ -286,6 +276,19 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
btheme->space_spreadsheet = btheme->space_outliner;
}
+ /**
+ * Versioning code until next subversion bump goes here.
+ *
+ * \note Be sure to check when bumping the version:
+ * - #blo_do_versions_userdef in this file.
+ * - "versioning_{BLENDER_VERSION}.c"
+ *
+ * \note Keep this message at the bottom of the function.
+ */
+ {
+ /* Keep this block, even when empty. */
+ }
+
#undef FROM_DEFAULT_V4_UCHAR
#undef USER_VERSION_ATLEAST
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index 64033cbe5c4..c8ee8af4542 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -87,8 +87,6 @@ set(SRC
intern/COM_OpenCLDevice.h
intern/COM_SingleThreadedOperation.cc
intern/COM_SingleThreadedOperation.h
- intern/COM_SocketReader.cc
- intern/COM_SocketReader.h
intern/COM_WorkPackage.cc
intern/COM_WorkPackage.h
intern/COM_WorkScheduler.cc
@@ -296,6 +294,9 @@ set(SRC
nodes/COM_FilterNode.h
nodes/COM_InpaintNode.cc
nodes/COM_InpaintNode.h
+ nodes/COM_AntiAliasingNode.cc
+ nodes/COM_AntiAliasingNode.h
+
operations/COM_BlurBaseOperation.cc
operations/COM_BlurBaseOperation.h
operations/COM_BokehBlurOperation.cc
@@ -322,6 +323,8 @@ set(SRC
operations/COM_MovieDistortionOperation.h
operations/COM_VariableSizeBokehBlurOperation.cc
operations/COM_VariableSizeBokehBlurOperation.h
+ operations/COM_SMAAOperation.cc
+ operations/COM_SMAAOperation.h
# Matte nodes
nodes/COM_BoxMaskNode.cc
@@ -568,6 +571,23 @@ data_to_c(
add_definitions(-DCL_USE_DEPRECATED_OPENCL_1_1_APIS)
+set(GENSRC_DIR ${CMAKE_CURRENT_BINARY_DIR}/operations)
+set(GENSRC ${GENSRC_DIR}/COM_SMAAAreaTexture.h)
+add_custom_command(
+ OUTPUT ${GENSRC}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${GENSRC_DIR}
+ COMMAND "$<TARGET_FILE:smaa_areatex>" ${GENSRC}
+ DEPENDS smaa_areatex
+)
+add_custom_target(smaa_areatex_header
+ SOURCES ${GENSRC}
+)
+list(APPEND SRC
+ ${GENSRC}
+)
+unset(GENSRC)
+unset(GENSRC_DIR)
+
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
@@ -586,3 +606,5 @@ if(WITH_OPENIMAGEDENOISE)
endif()
blender_add_lib(bf_compositor "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
+
+add_dependencies(bf_compositor smaa_areatex_header)
diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h
index 8e3caf7aaf5..300a06005ac 100644
--- a/source/blender/compositor/COM_compositor.h
+++ b/source/blender/compositor/COM_compositor.h
@@ -113,11 +113,11 @@ extern "C" {
*
* When the chunk-order is determined, the first few chunks will be checked if they can be scheduled.
* Chunks can have three states:
- * - [@ref eChunkExecutionState.NOT_SCHEDULED]:
+ * - [@ref eChunkExecutionState.NotScheduled]:
* Chunk is not yet scheduled, or dependencies are not met.
- * - [@ref eChunkExecutionState.SCHEDULED]:
+ * - [@ref eChunkExecutionState.Scheduled]:
* All dependencies are met, chunk is scheduled, but not finished.
- * - [@ref eChunkExecutionState.EXECUTED]:
+ * - [@ref eChunkExecutionState.Executed]:
* Chunk is finished.
*
* \see ExecutionGroup.execute
diff --git a/source/blender/compositor/COM_defines.h b/source/blender/compositor/COM_defines.h
index 266f532ebb8..5a5868f1909 100644
--- a/source/blender/compositor/COM_defines.h
+++ b/source/blender/compositor/COM_defines.h
@@ -18,6 +18,8 @@
#pragma once
+namespace blender::compositor {
+
/**
* \brief possible data types for sockets
* \ingroup Model
@@ -32,6 +34,25 @@ enum class DataType {
};
/**
+ * Utility to get the number of channels of the given data type.
+ */
+constexpr int COM_data_type_num_channels(const DataType datatype)
+{
+ switch (datatype) {
+ case DataType::Value:
+ return 1;
+ case DataType::Vector:
+ return 3;
+ case DataType::Color:
+ default:
+ return 4;
+ }
+}
+
+constexpr int COM_DATA_TYPE_VALUE_CHANNELS = COM_data_type_num_channels(DataType::Value);
+constexpr int COM_DATA_TYPE_COLOR_CHANNELS = COM_data_type_num_channels(DataType::Color);
+
+/**
* \brief Possible quality settings
* \see CompositorContext.quality
* \ingroup Execution
@@ -58,11 +79,29 @@ enum class CompositorPriority {
Low = 0,
};
+/**
+ * \brief the execution state of a chunk in an ExecutionGroup
+ * \ingroup Execution
+ */
+enum class eChunkExecutionState {
+ /**
+ * \brief chunk is not yet scheduled
+ */
+ NotScheduled = 0,
+ /**
+ * \brief chunk is scheduled, but not yet executed
+ */
+ Scheduled = 1,
+ /**
+ * \brief chunk is executed.
+ */
+ Executed = 2,
+};
+
// configurable items
// chunk size determination
-#define COM_PREVIEW_SIZE 140.0f
-//#define COM_DEBUG
+// #define COM_DEBUG
// chunk order
/**
@@ -82,10 +121,8 @@ enum class ChunkOrdering {
Default = ChunkOrdering::CenterOut,
};
-#define COM_RULE_OF_THIRDS_DIVIDER 100.0f
-
-#define COM_NUM_CHANNELS_VALUE 1
-#define COM_NUM_CHANNELS_VECTOR 3
-#define COM_NUM_CHANNELS_COLOR 4
+constexpr float COM_PREVIEW_SIZE = 140.f;
+constexpr float COM_RULE_OF_THIRDS_DIVIDER = 100.0f;
+constexpr float COM_BLUR_BOKEH_PIXELS = 512;
-#define COM_BLUR_BOKEH_PIXELS 512
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_CPUDevice.cc b/source/blender/compositor/intern/COM_CPUDevice.cc
index b520a437008..29a82bec636 100644
--- a/source/blender/compositor/intern/COM_CPUDevice.cc
+++ b/source/blender/compositor/intern/COM_CPUDevice.cc
@@ -18,19 +18,23 @@
#include "COM_CPUDevice.h"
+#include "COM_ExecutionGroup.h"
+
+#include "BLI_rect.h"
+
+namespace blender::compositor {
+
CPUDevice::CPUDevice(int thread_id) : m_thread_id(thread_id)
{
}
-void CPUDevice::execute(WorkPackage *work)
+void CPUDevice::execute(WorkPackage *work_package)
{
- const unsigned int chunkNumber = work->chunk_number;
- ExecutionGroup *executionGroup = work->execution_group;
- rcti rect;
-
- executionGroup->determineChunkRect(&rect, chunkNumber);
-
- executionGroup->getOutputOperation()->executeRegion(&rect, chunkNumber);
+ const unsigned int chunkNumber = work_package->chunk_number;
+ ExecutionGroup *executionGroup = work_package->execution_group;
+ executionGroup->getOutputOperation()->executeRegion(&work_package->rect, chunkNumber);
executionGroup->finalizeChunkExecution(chunkNumber, nullptr);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_CPUDevice.h b/source/blender/compositor/intern/COM_CPUDevice.h
index 962380d7bc8..99629890b30 100644
--- a/source/blender/compositor/intern/COM_CPUDevice.h
+++ b/source/blender/compositor/intern/COM_CPUDevice.h
@@ -20,6 +20,8 @@
#include "COM_Device.h"
+namespace blender::compositor {
+
/**
* \brief class representing a CPU device.
* \note for every hardware thread in the system a CPUDevice instance
@@ -33,7 +35,7 @@ class CPUDevice : public Device {
* \brief execute a WorkPackage
* \param work: the WorkPackage to execute
*/
- void execute(WorkPackage *work);
+ void execute(WorkPackage *work) override;
int thread_id()
{
@@ -43,3 +45,5 @@ class CPUDevice : public Device {
protected:
int m_thread_id;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_ChunkOrder.cc b/source/blender/compositor/intern/COM_ChunkOrder.cc
index 9687154120d..a03718d720d 100644
--- a/source/blender/compositor/intern/COM_ChunkOrder.cc
+++ b/source/blender/compositor/intern/COM_ChunkOrder.cc
@@ -20,6 +20,8 @@
#include "BLI_math.h"
+namespace blender::compositor {
+
void ChunkOrder::update_distance(ChunkOrderHotspot *hotspots, unsigned int len_hotspots)
{
double new_distance = DBL_MAX;
@@ -36,3 +38,5 @@ bool operator<(const ChunkOrder &a, const ChunkOrder &b)
{
return a.distance < b.distance;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_ChunkOrder.h b/source/blender/compositor/intern/COM_ChunkOrder.h
index a634309f345..a697f9231d9 100644
--- a/source/blender/compositor/intern/COM_ChunkOrder.h
+++ b/source/blender/compositor/intern/COM_ChunkOrder.h
@@ -24,6 +24,8 @@
#include "COM_ChunkOrderHotspot.h"
+namespace blender::compositor {
+
/** Helper to determine the order how chunks are prioritized during execution. */
struct ChunkOrder {
unsigned int index = 0;
@@ -39,3 +41,5 @@ struct ChunkOrder {
MEM_CXX_CLASS_ALLOC_FUNCS("COM:ChunkOrderHotspot")
#endif
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_ChunkOrderHotspot.cc b/source/blender/compositor/intern/COM_ChunkOrderHotspot.cc
index d31ff518ecd..79afcc9deea 100644
--- a/source/blender/compositor/intern/COM_ChunkOrderHotspot.cc
+++ b/source/blender/compositor/intern/COM_ChunkOrderHotspot.cc
@@ -19,6 +19,8 @@
#include "COM_ChunkOrderHotspot.h"
#include <cmath>
+namespace blender::compositor {
+
double ChunkOrderHotspot::calc_distance(int x, int y)
{
int dx = this->x - x;
@@ -27,3 +29,5 @@ double ChunkOrderHotspot::calc_distance(int x, int y)
result += (double)this->addition;
return result;
}
+
+} // namespace blender::compositor \ No newline at end of file
diff --git a/source/blender/compositor/intern/COM_ChunkOrderHotspot.h b/source/blender/compositor/intern/COM_ChunkOrderHotspot.h
index d7f40921836..249b328f5c2 100644
--- a/source/blender/compositor/intern/COM_ChunkOrderHotspot.h
+++ b/source/blender/compositor/intern/COM_ChunkOrderHotspot.h
@@ -22,6 +22,8 @@
# include "MEM_guardedalloc.h"
#endif
+namespace blender::compositor {
+
struct ChunkOrderHotspot {
int x;
int y;
@@ -37,3 +39,5 @@ struct ChunkOrderHotspot {
MEM_CXX_CLASS_ALLOC_FUNCS("COM:ChunkOrderHotspot")
#endif
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_CompositorContext.cc b/source/blender/compositor/intern/COM_CompositorContext.cc
index e2447fb5c13..fdd47a6ca79 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.cc
+++ b/source/blender/compositor/intern/COM_CompositorContext.cc
@@ -20,6 +20,10 @@
#include "COM_defines.h"
#include <cstdio>
+#include "BLI_assert.h"
+
+namespace blender::compositor {
+
CompositorContext::CompositorContext()
{
this->m_scene = nullptr;
@@ -33,9 +37,8 @@ CompositorContext::CompositorContext()
int CompositorContext::getFramenumber() const
{
- if (this->m_rd) {
- return this->m_rd->cfra;
- }
-
- return -1; /* this should never happen */
+ BLI_assert(m_rd);
+ return m_rd->cfra;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h
index 46cf65bbb79..c6468865fc8 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.h
+++ b/source/blender/compositor/intern/COM_CompositorContext.h
@@ -26,6 +26,8 @@
#include <string>
#include <vector>
+namespace blender::compositor {
+
/**
* \brief Overall context of the compositor
*/
@@ -277,3 +279,5 @@ class CompositorContext {
return m_rd->size * 0.01f;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_Converter.cc b/source/blender/compositor/intern/COM_Converter.cc
index d5bce636b8c..af593b2e1b5 100644
--- a/source/blender/compositor/intern/COM_Converter.cc
+++ b/source/blender/compositor/intern/COM_Converter.cc
@@ -26,6 +26,7 @@
#include "COM_NodeOperationBuilder.h"
#include "COM_AlphaOverNode.h"
+#include "COM_AntiAliasingNode.h"
#include "COM_BilateralBlurNode.h"
#include "COM_BlurNode.h"
#include "COM_BokehBlurNode.h"
@@ -115,6 +116,8 @@
#include "COM_ViewerNode.h"
#include "COM_ZCombineNode.h"
+namespace blender::compositor {
+
bool COM_bnode_is_fast_node(const bNode &b_node)
{
return !ELEM(b_node.type,
@@ -418,6 +421,9 @@ Node *COM_convert_bnode(bNode *b_node)
case CMP_NODE_EXPOSURE:
node = new ExposureNode(b_node);
break;
+ case CMP_NODE_ANTIALIASING:
+ node = new AntiAliasingNode(b_node);
+ break;
}
return node;
}
@@ -454,7 +460,7 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
NodeOperationOutput *fromSocket,
NodeOperationInput *toSocket)
{
- InputResizeMode mode = toSocket->getResizeMode();
+ ResizeMode mode = toSocket->getResizeMode();
NodeOperation *toOperation = &toSocket->getOperation();
const float toWidth = toOperation->getWidth();
@@ -470,22 +476,22 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
float scaleY = 0;
switch (mode) {
- case COM_SC_NO_RESIZE:
+ case ResizeMode::None:
break;
- case COM_SC_CENTER:
+ case ResizeMode::Center:
doCenter = true;
break;
- case COM_SC_FIT_WIDTH:
+ case ResizeMode::FitWidth:
doCenter = true;
doScale = true;
scaleX = scaleY = toWidth / fromWidth;
break;
- case COM_SC_FIT_HEIGHT:
+ case ResizeMode::FitHeight:
doCenter = true;
doScale = true;
scaleX = scaleY = toHeight / fromHeight;
break;
- case COM_SC_FIT:
+ case ResizeMode::FitAny:
doCenter = true;
doScale = true;
scaleX = toWidth / fromWidth;
@@ -497,7 +503,7 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
scaleY = scaleX;
}
break;
- case COM_SC_STRETCH:
+ case ResizeMode::Stretch:
doCenter = true;
doScale = true;
scaleX = toWidth / fromWidth;
@@ -510,8 +516,8 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
ScaleOperation *scaleOperation = nullptr;
if (doScale) {
scaleOperation = new ScaleOperation();
- scaleOperation->getInputSocket(1)->setResizeMode(COM_SC_NO_RESIZE);
- scaleOperation->getInputSocket(2)->setResizeMode(COM_SC_NO_RESIZE);
+ scaleOperation->getInputSocket(1)->setResizeMode(ResizeMode::None);
+ scaleOperation->getInputSocket(2)->setResizeMode(ResizeMode::None);
first = scaleOperation;
SetValueOperation *sxop = new SetValueOperation();
sxop->setValue(scaleX);
@@ -530,8 +536,8 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
}
TranslateOperation *translateOperation = new TranslateOperation();
- translateOperation->getInputSocket(1)->setResizeMode(COM_SC_NO_RESIZE);
- translateOperation->getInputSocket(2)->setResizeMode(COM_SC_NO_RESIZE);
+ translateOperation->getInputSocket(1)->setResizeMode(ResizeMode::None);
+ translateOperation->getInputSocket(2)->setResizeMode(ResizeMode::None);
if (!first) {
first = translateOperation;
}
@@ -551,15 +557,17 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
builder.addOperation(translateOperation);
if (doScale) {
- translateOperation->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
+ translateOperation->getInputSocket(0)->setResizeMode(ResizeMode::None);
builder.addLink(scaleOperation->getOutputSocket(), translateOperation->getInputSocket(0));
}
/* remove previous link and replace */
builder.removeInputLink(toSocket);
- first->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
- toSocket->setResizeMode(COM_SC_NO_RESIZE);
+ first->getInputSocket(0)->setResizeMode(ResizeMode::None);
+ toSocket->setResizeMode(ResizeMode::None);
builder.addLink(fromSocket, first->getInputSocket(0));
builder.addLink(translateOperation->getOutputSocket(), toSocket);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_Converter.h b/source/blender/compositor/intern/COM_Converter.h
index 59be34bf0e3..28136437103 100644
--- a/source/blender/compositor/intern/COM_Converter.h
+++ b/source/blender/compositor/intern/COM_Converter.h
@@ -18,14 +18,17 @@
#pragma once
+#include "COM_NodeOperation.h"
+
#ifdef WITH_CXX_GUARDEDALLOC
# include "MEM_guardedalloc.h"
#endif
struct bNode;
+namespace blender::compositor {
+
class Node;
-class NodeOperation;
class NodeOperationInput;
class NodeOperationOutput;
class NodeOperationBuilder;
@@ -65,3 +68,5 @@ NodeOperation *COM_convert_data_type(const NodeOperationOutput &from,
void COM_convert_resolution(NodeOperationBuilder &builder,
NodeOperationOutput *fromSocket,
NodeOperationInput *toSocket);
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_Debug.cc b/source/blender/compositor/intern/COM_Debug.cc
index c299bd1c72d..56bc2dc947f 100644
--- a/source/blender/compositor/intern/COM_Debug.cc
+++ b/source/blender/compositor/intern/COM_Debug.cc
@@ -18,30 +18,31 @@
#include "COM_Debug.h"
-#ifdef COM_DEBUG
-
-# include <map>
-# include <typeinfo>
-# include <vector>
+#include <map>
+#include <typeinfo>
+#include <vector>
extern "C" {
-# include "BLI_fileops.h"
-# include "BLI_path_util.h"
-# include "BLI_string.h"
-# include "BLI_sys_types.h"
-
-# include "BKE_appdir.h"
-# include "BKE_node.h"
-# include "DNA_node_types.h"
+#include "BLI_fileops.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_sys_types.h"
+
+#include "BKE_appdir.h"
+#include "BKE_node.h"
+#include "DNA_node_types.h"
}
-# include "COM_ExecutionGroup.h"
-# include "COM_ExecutionSystem.h"
-# include "COM_Node.h"
+#include "COM_ExecutionSystem.h"
+#include "COM_Node.h"
+
+#include "COM_ReadBufferOperation.h"
+#include "COM_ViewerOperation.h"
+#include "COM_WriteBufferOperation.h"
-# include "COM_ReadBufferOperation.h"
-# include "COM_ViewerOperation.h"
-# include "COM_WriteBufferOperation.h"
+namespace blender::compositor {
+
+#ifdef COM_DEBUG
int DebugInfo::m_file_index = 0;
DebugInfo::NodeNameMap DebugInfo::m_node_names;
@@ -113,7 +114,7 @@ void DebugInfo::execution_group_finished(const ExecutionGroup *group)
}
int DebugInfo::graphviz_operation(const ExecutionSystem *system,
- const NodeOperation *operation,
+ NodeOperation *operation,
const ExecutionGroup *group,
char *str,
int maxlen)
@@ -121,7 +122,7 @@ int DebugInfo::graphviz_operation(const ExecutionSystem *system,
int len = 0;
std::string fillcolor = "gainsboro";
- if (operation->isViewerOperation()) {
+ if (operation->get_flags().is_viewer_operation) {
const ViewerOperation *viewer = (const ViewerOperation *)operation;
if (viewer->isActiveViewerOutput()) {
fillcolor = "lightskyblue1";
@@ -133,13 +134,13 @@ int DebugInfo::graphviz_operation(const ExecutionSystem *system,
else if (operation->isOutputOperation(system->getContext().isRendering())) {
fillcolor = "dodgerblue1";
}
- else if (operation->isSetOperation()) {
+ else if (operation->get_flags().is_set_operation) {
fillcolor = "khaki1";
}
- else if (operation->isReadBufferOperation()) {
+ else if (operation->get_flags().is_read_buffer_operation) {
fillcolor = "darkolivegreen3";
}
- else if (operation->isWriteBufferOperation()) {
+ else if (operation->get_flags().is_write_buffer_operation) {
fillcolor = "darkorange";
}
@@ -360,7 +361,7 @@ bool DebugInfo::graphviz_system(const ExecutionSystem *system, char *str, int ma
}
for (NodeOperation *operation : system->m_operations) {
- if (operation->isReadBufferOperation()) {
+ if (operation->get_flags().is_read_buffer_operation) {
ReadBufferOperation *read = (ReadBufferOperation *)operation;
WriteBufferOperation *write = read->getMemoryProxy()->getWriteBufferOperation();
std::vector<std::string> &read_groups = op_groups[read];
@@ -381,8 +382,8 @@ bool DebugInfo::graphviz_system(const ExecutionSystem *system, char *str, int ma
}
for (NodeOperation *op : system->m_operations) {
- for (NodeOperationInput *to : op->m_inputs) {
- NodeOperationOutput *from = to->getLink();
+ for (NodeOperationInput &to : op->m_inputs) {
+ NodeOperationOutput *from = to.getLink();
if (!from) {
continue;
@@ -401,7 +402,7 @@ bool DebugInfo::graphviz_system(const ExecutionSystem *system, char *str, int ma
break;
}
- NodeOperation *to_op = &to->getOperation();
+ NodeOperation *to_op = &to.getOperation();
NodeOperation *from_op = &from->getOperation();
std::vector<std::string> &from_groups = op_groups[from_op];
std::vector<std::string> &to_groups = op_groups[to_op];
@@ -412,7 +413,7 @@ bool DebugInfo::graphviz_system(const ExecutionSystem *system, char *str, int ma
from_op,
from,
to_op,
- to);
+ &to);
for (int k = 0; k < from_groups.size(); k++) {
for (int l = 0; l < to_groups.size(); l++) {
len += snprintf(str + len,
@@ -423,7 +424,7 @@ bool DebugInfo::graphviz_system(const ExecutionSystem *system, char *str, int ma
from,
to_op,
to_groups[l].c_str(),
- to);
+ &to);
len += snprintf(
str + len, maxlen > len ? maxlen - len : 0, " [color=%s]", color.c_str());
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\r\n");
@@ -495,3 +496,5 @@ void DebugInfo::graphviz(const ExecutionSystem * /*system*/)
}
#endif
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_Debug.h b/source/blender/compositor/intern/COM_Debug.h
index 0107d8b396d..bf7b981fbd5 100644
--- a/source/blender/compositor/intern/COM_Debug.h
+++ b/source/blender/compositor/intern/COM_Debug.h
@@ -21,10 +21,12 @@
#include <map>
#include <string>
+#include "COM_NodeOperation.h"
#include "COM_defines.h"
+namespace blender::compositor {
+
class Node;
-class NodeOperation;
class ExecutionSystem;
class ExecutionGroup;
@@ -55,7 +57,7 @@ class DebugInfo {
#ifdef COM_DEBUG
protected:
static int graphviz_operation(const ExecutionSystem *system,
- const NodeOperation *operation,
+ NodeOperation *operation,
const ExecutionGroup *group,
char *str,
int maxlen);
@@ -81,3 +83,5 @@ class DebugInfo {
static GroupStateMap m_group_states;
#endif
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_Device.h b/source/blender/compositor/intern/COM_Device.h
index 0b0f0f5c1c6..2a43c1be2b4 100644
--- a/source/blender/compositor/intern/COM_Device.h
+++ b/source/blender/compositor/intern/COM_Device.h
@@ -20,6 +20,8 @@
#include "COM_WorkPackage.h"
+namespace blender::compositor {
+
/**
* \brief Abstract class for device implementations to be used by the Compositor.
* devices are queried, initialized and used by the WorkScheduler.
@@ -37,21 +39,6 @@ class Device {
}
/**
- * \brief initialize the device
- */
- virtual bool initialize()
- {
- return true;
- }
-
- /**
- * \brief deinitialize the device
- */
- virtual void deinitialize()
- {
- }
-
- /**
* \brief execute a WorkPackage
* \param work: the WorkPackage to execute
*/
@@ -61,3 +48,5 @@ class Device {
MEM_CXX_CLASS_ALLOC_FUNCS("COM:Device")
#endif
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cc b/source/blender/compositor/intern/COM_ExecutionGroup.cc
index 3cedc5da663..37c363501ad 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.cc
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.cc
@@ -46,10 +46,10 @@
#include "WM_api.h"
#include "WM_types.h"
+namespace blender::compositor {
+
ExecutionGroup::ExecutionGroup()
{
- this->m_is_output = false;
- this->m_complex = false;
this->m_bTree = nullptr;
this->m_height = 0;
this->m_width = 0;
@@ -57,42 +57,39 @@ ExecutionGroup::ExecutionGroup()
this->m_x_chunks_len = 0;
this->m_y_chunks_len = 0;
this->m_chunks_len = 0;
- this->m_initialized = false;
- this->m_openCL = false;
- this->m_singleThreaded = false;
this->m_chunks_finished = 0;
BLI_rcti_init(&this->m_viewerBorder, 0, 0, 0, 0);
this->m_executionStartTime = 0;
}
-CompositorPriority ExecutionGroup::getRenderPriotrity()
+CompositorPriority ExecutionGroup::getRenderPriority()
{
return this->getOutputOperation()->getRenderPriority();
}
bool ExecutionGroup::can_contain(NodeOperation &operation)
{
- if (!this->m_initialized) {
+ if (!m_flags.initialized) {
return true;
}
- if (operation.isReadBufferOperation()) {
+ if (operation.get_flags().is_read_buffer_operation) {
return true;
}
- if (operation.isWriteBufferOperation()) {
+ if (operation.get_flags().is_write_buffer_operation) {
return false;
}
- if (operation.isSetOperation()) {
+ if (operation.get_flags().is_set_operation) {
return true;
}
/* complex groups don't allow further ops (except read buffer and values, see above) */
- if (m_complex) {
+ if (m_flags.complex) {
return false;
}
/* complex ops can't be added to other groups (except their own, which they initialize, see
* above) */
- if (operation.isComplex()) {
+ if (operation.get_flags().complex) {
return false;
}
@@ -105,11 +102,12 @@ bool ExecutionGroup::addOperation(NodeOperation *operation)
return false;
}
- if (!operation->isReadBufferOperation() && !operation->isWriteBufferOperation()) {
- m_complex = operation->isComplex();
- m_openCL = operation->isOpenCL();
- m_singleThreaded = operation->isSingleThreaded();
- m_initialized = true;
+ if (!operation->get_flags().is_read_buffer_operation &&
+ !operation->get_flags().is_write_buffer_operation) {
+ m_flags.complex = operation->get_flags().complex;
+ m_flags.open_cl = operation->get_flags().open_cl;
+ m_flags.single_threaded = operation->get_flags().single_threaded;
+ m_flags.initialized = true;
}
m_operations.append(operation);
@@ -125,20 +123,23 @@ NodeOperation *ExecutionGroup::getOutputOperation() const
void ExecutionGroup::initExecution()
{
- m_chunk_execution_states.clear();
+ m_work_packages.clear();
determineNumberOfChunks();
if (this->m_chunks_len != 0) {
- m_chunk_execution_states.resize(this->m_chunks_len);
- for (int index = 0; index < this->m_chunks_len; index++) {
- m_chunk_execution_states[index] = eChunkExecutionState::NOT_SCHEDULED;
+ m_work_packages.resize(this->m_chunks_len);
+ for (unsigned int index = 0; index < m_chunks_len; index++) {
+ m_work_packages[index].state = eChunkExecutionState::NotScheduled;
+ m_work_packages[index].execution_group = this;
+ m_work_packages[index].chunk_number = index;
+ determineChunkRect(&m_work_packages[index].rect, index);
}
}
unsigned int max_offset = 0;
for (NodeOperation *operation : m_operations) {
- if (operation->isReadBufferOperation()) {
+ if (operation->get_flags().is_read_buffer_operation) {
ReadBufferOperation *readOperation = static_cast<ReadBufferOperation *>(operation);
this->m_read_operations.append(readOperation);
max_offset = MAX2(max_offset, readOperation->getOffset());
@@ -150,7 +151,7 @@ void ExecutionGroup::initExecution()
void ExecutionGroup::deinitExecution()
{
- m_chunk_execution_states.clear();
+ m_work_packages.clear();
this->m_chunks_len = 0;
this->m_x_chunks_len = 0;
this->m_y_chunks_len = 0;
@@ -168,7 +169,7 @@ void ExecutionGroup::determineResolution(unsigned int resolution[2])
void ExecutionGroup::determineNumberOfChunks()
{
- if (this->m_singleThreaded) {
+ if (this->m_flags.single_threaded) {
this->m_x_chunks_len = 1;
this->m_y_chunks_len = 1;
this->m_chunks_len = 1;
@@ -185,7 +186,6 @@ void ExecutionGroup::determineNumberOfChunks()
blender::Array<unsigned int> ExecutionGroup::determine_chunk_execution_order() const
{
- int index;
blender::Array<unsigned int> chunk_order(m_chunks_len);
for (int chunk_index = 0; chunk_index < this->m_chunks_len; chunk_index++) {
chunk_order[chunk_index] = chunk_index;
@@ -196,7 +196,7 @@ blender::Array<unsigned int> ExecutionGroup::determine_chunk_execution_order() c
float centerY = 0.5f;
ChunkOrdering order_type = ChunkOrdering::Default;
- if (operation->isViewerOperation()) {
+ if (operation->get_flags().is_viewer_operation) {
ViewerOperation *viewer = (ViewerOperation *)operation;
centerX = viewer->getCenterX();
centerY = viewer->getCenterY();
@@ -205,7 +205,7 @@ blender::Array<unsigned int> ExecutionGroup::determine_chunk_execution_order() c
const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);
-
+ int index;
switch (order_type) {
case ChunkOrdering::Random: {
static blender::RandomNumberGenerator rng;
@@ -219,11 +219,10 @@ blender::Array<unsigned int> ExecutionGroup::determine_chunk_execution_order() c
ChunkOrderHotspot hotspot(border_width * centerX, border_height * centerY, 0.0f);
blender::Array<ChunkOrder> chunk_orders(m_chunks_len);
for (index = 0; index < this->m_chunks_len; index++) {
- rcti rect;
- determineChunkRect(&rect, index);
+ const WorkPackage &work_package = m_work_packages[index];
chunk_orders[index].index = index;
- chunk_orders[index].x = rect.xmin - this->m_viewerBorder.xmin;
- chunk_orders[index].y = rect.ymin - this->m_viewerBorder.ymin;
+ chunk_orders[index].x = work_package.rect.xmin - this->m_viewerBorder.xmin;
+ chunk_orders[index].y = work_package.rect.ymin - this->m_viewerBorder.ymin;
chunk_orders[index].update_distance(&hotspot, 1);
}
@@ -257,11 +256,10 @@ blender::Array<unsigned int> ExecutionGroup::determine_chunk_execution_order() c
blender::Array<ChunkOrder> chunk_orders(m_chunks_len);
for (index = 0; index < this->m_chunks_len; index++) {
- rcti rect;
- determineChunkRect(&rect, index);
+ const WorkPackage &work_package = m_work_packages[index];
chunk_orders[index].index = index;
- chunk_orders[index].x = rect.xmin - this->m_viewerBorder.xmin;
- chunk_orders[index].y = rect.ymin - this->m_viewerBorder.ymin;
+ chunk_orders[index].x = work_package.rect.xmin - this->m_viewerBorder.xmin;
+ chunk_orders[index].y = work_package.rect.ymin - this->m_viewerBorder.ymin;
chunk_orders[index].update_distance(hotspots, 9);
}
@@ -303,7 +301,6 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
this->m_chunks_finished = 0;
this->m_bTree = bTree;
- unsigned int index;
blender::Array<unsigned int> chunk_order = determine_chunk_execution_order();
@@ -320,13 +317,15 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
finished = true;
int numberEvaluated = 0;
- for (index = startIndex; index < this->m_chunks_len && numberEvaluated < maxNumberEvaluated;
+ for (int index = startIndex;
+ index < this->m_chunks_len && numberEvaluated < maxNumberEvaluated;
index++) {
chunk_index = chunk_order[index];
int yChunk = chunk_index / this->m_x_chunks_len;
int xChunk = chunk_index - (yChunk * this->m_x_chunks_len);
- switch (m_chunk_execution_states[chunk_index]) {
- case eChunkExecutionState::NOT_SCHEDULED: {
+ const WorkPackage &work_package = m_work_packages[chunk_index];
+ switch (work_package.state) {
+ case eChunkExecutionState::NotScheduled: {
scheduleChunkWhenPossible(graph, xChunk, yChunk);
finished = false;
startEvaluated = true;
@@ -337,13 +336,13 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
}
break;
}
- case eChunkExecutionState::SCHEDULED: {
+ case eChunkExecutionState::Scheduled: {
finished = false;
startEvaluated = true;
numberEvaluated++;
break;
}
- case eChunkExecutionState::EXECUTED: {
+ case eChunkExecutionState::Executed: {
if (!startEvaluated) {
startIndex = index + 1;
}
@@ -363,15 +362,14 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
MemoryBuffer **ExecutionGroup::getInputBuffersOpenCL(int chunkNumber)
{
- rcti rect;
- determineChunkRect(&rect, chunkNumber);
+ WorkPackage &work_package = m_work_packages[chunkNumber];
MemoryBuffer **memoryBuffers = (MemoryBuffer **)MEM_callocN(
sizeof(MemoryBuffer *) * this->m_max_read_buffer_offset, __func__);
rcti output;
for (ReadBufferOperation *readOperation : m_read_operations) {
MemoryProxy *memoryProxy = readOperation->getMemoryProxy();
- this->determineDependingAreaOfInterest(&rect, readOperation, &output);
+ this->determineDependingAreaOfInterest(&work_package.rect, readOperation, &output);
MemoryBuffer *memoryBuffer = memoryProxy->getExecutor()->constructConsolidatedMemoryBuffer(
*memoryProxy, output);
memoryBuffers[readOperation->getOffset()] = memoryBuffer;
@@ -390,8 +388,9 @@ MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy &mem
void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memoryBuffers)
{
- if (this->m_chunk_execution_states[chunkNumber] == eChunkExecutionState::SCHEDULED) {
- this->m_chunk_execution_states[chunkNumber] = eChunkExecutionState::EXECUTED;
+ WorkPackage &work_package = m_work_packages[chunkNumber];
+ if (work_package.state == eChunkExecutionState::Scheduled) {
+ work_package.state = eChunkExecutionState::Executed;
}
atomic_add_and_fetch_u(&this->m_chunks_finished, 1);
@@ -423,23 +422,23 @@ void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memo
}
}
-inline void ExecutionGroup::determineChunkRect(rcti *rect,
+inline void ExecutionGroup::determineChunkRect(rcti *r_rect,
const unsigned int xChunk,
const unsigned int yChunk) const
{
const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);
- if (this->m_singleThreaded) {
+ if (this->m_flags.single_threaded) {
BLI_rcti_init(
- rect, this->m_viewerBorder.xmin, border_width, this->m_viewerBorder.ymin, border_height);
+ r_rect, this->m_viewerBorder.xmin, border_width, this->m_viewerBorder.ymin, border_height);
}
else {
const unsigned int minx = xChunk * this->m_chunkSize + this->m_viewerBorder.xmin;
const unsigned int miny = yChunk * this->m_chunkSize + this->m_viewerBorder.ymin;
const unsigned int width = MIN2((unsigned int)this->m_viewerBorder.xmax, this->m_width);
const unsigned int height = MIN2((unsigned int)this->m_viewerBorder.ymax, this->m_height);
- BLI_rcti_init(rect,
+ BLI_rcti_init(r_rect,
MIN2(minx, this->m_width),
MIN2(minx + this->m_chunkSize, width),
MIN2(miny, this->m_height),
@@ -447,18 +446,18 @@ inline void ExecutionGroup::determineChunkRect(rcti *rect,
}
}
-void ExecutionGroup::determineChunkRect(rcti *rect, const unsigned int chunkNumber) const
+void ExecutionGroup::determineChunkRect(rcti *r_rect, const unsigned int chunkNumber) const
{
const unsigned int yChunk = chunkNumber / this->m_x_chunks_len;
const unsigned int xChunk = chunkNumber - (yChunk * this->m_x_chunks_len);
- determineChunkRect(rect, xChunk, yChunk);
+ determineChunkRect(r_rect, xChunk, yChunk);
}
MemoryBuffer *ExecutionGroup::allocateOutputBuffer(rcti &rect)
{
// we assume that this method is only called from complex execution groups.
NodeOperation *operation = this->getOutputOperation();
- if (operation->isWriteBufferOperation()) {
+ if (operation->get_flags().is_write_buffer_operation) {
WriteBufferOperation *writeOperation = (WriteBufferOperation *)operation;
MemoryBuffer *buffer = new MemoryBuffer(
writeOperation->getMemoryProxy(), rect, MemoryBufferState::Temporary);
@@ -469,7 +468,7 @@ MemoryBuffer *ExecutionGroup::allocateOutputBuffer(rcti &rect)
bool ExecutionGroup::scheduleAreaWhenPossible(ExecutionSystem *graph, rcti *area)
{
- if (this->m_singleThreaded) {
+ if (this->m_flags.single_threaded) {
return scheduleChunkWhenPossible(graph, 0, 0);
}
// find all chunks inside the rect
@@ -503,9 +502,10 @@ bool ExecutionGroup::scheduleAreaWhenPossible(ExecutionSystem *graph, rcti *area
bool ExecutionGroup::scheduleChunk(unsigned int chunkNumber)
{
- if (this->m_chunk_execution_states[chunkNumber] == eChunkExecutionState::NOT_SCHEDULED) {
- this->m_chunk_execution_states[chunkNumber] = eChunkExecutionState::SCHEDULED;
- WorkScheduler::schedule(this, chunkNumber);
+ WorkPackage &work_package = m_work_packages[chunkNumber];
+ if (work_package.state == eChunkExecutionState::NotScheduled) {
+ work_package.state = eChunkExecutionState::Scheduled;
+ WorkScheduler::schedule(&work_package);
return true;
}
return false;
@@ -524,22 +524,21 @@ bool ExecutionGroup::scheduleChunkWhenPossible(ExecutionSystem *graph,
// Check if chunk is already executed or scheduled and not yet executed.
const int chunk_index = chunk_y * this->m_x_chunks_len + chunk_x;
- if (this->m_chunk_execution_states[chunk_index] == eChunkExecutionState::EXECUTED) {
+ WorkPackage &work_package = m_work_packages[chunk_index];
+ if (work_package.state == eChunkExecutionState::Executed) {
return true;
}
- if (this->m_chunk_execution_states[chunk_index] == eChunkExecutionState::SCHEDULED) {
+ if (work_package.state == eChunkExecutionState::Scheduled) {
return false;
}
- rcti rect;
- determineChunkRect(&rect, chunk_x, chunk_y);
bool can_be_executed = true;
rcti area;
for (ReadBufferOperation *read_operation : m_read_operations) {
BLI_rcti_init(&area, 0, 0, 0, 0);
MemoryProxy *memory_proxy = read_operation->getMemoryProxy();
- determineDependingAreaOfInterest(&rect, read_operation, &area);
+ determineDependingAreaOfInterest(&work_package.rect, read_operation, &area);
ExecutionGroup *group = memory_proxy->getExecutor();
if (!group->scheduleAreaWhenPossible(graph, &area)) {
@@ -561,16 +560,10 @@ void ExecutionGroup::determineDependingAreaOfInterest(rcti *input,
this->getOutputOperation()->determineDependingAreaOfInterest(input, readOperation, output);
}
-bool ExecutionGroup::isOpenCL()
-{
- return this->m_openCL;
-}
-
void ExecutionGroup::setViewerBorder(float xmin, float xmax, float ymin, float ymax)
{
- NodeOperation *operation = this->getOutputOperation();
-
- if (operation->isViewerOperation() || operation->isPreviewOperation()) {
+ const NodeOperation &operation = *this->getOutputOperation();
+ if (operation.get_flags().use_viewer_border) {
BLI_rcti_init(&this->m_viewerBorder,
xmin * this->m_width,
xmax * this->m_width,
@@ -581,32 +574,14 @@ void ExecutionGroup::setViewerBorder(float xmin, float xmax, float ymin, float y
void ExecutionGroup::setRenderBorder(float xmin, float xmax, float ymin, float ymax)
{
- NodeOperation *operation = this->getOutputOperation();
-
- if (operation->isOutputOperation(true)) {
- /* Basically, setting border need to happen for only operations
- * which operates in render resolution buffers (like compositor
- * output nodes).
- *
- * In this cases adding border will lead to mapping coordinates
- * from output buffer space to input buffer spaces when executing
- * operation.
- *
- * But nodes like viewer and file output just shall display or
- * safe the same exact buffer which goes to their input, no need
- * in any kind of coordinates mapping.
- */
-
- bool operationNeedsBorder = !(operation->isViewerOperation() ||
- operation->isPreviewOperation() ||
- operation->isFileOutputOperation());
-
- if (operationNeedsBorder) {
- BLI_rcti_init(&this->m_viewerBorder,
- xmin * this->m_width,
- xmax * this->m_width,
- ymin * this->m_height,
- ymax * this->m_height);
- }
+ const NodeOperation &operation = *this->getOutputOperation();
+ if (operation.isOutputOperation(true) && operation.get_flags().use_render_border) {
+ BLI_rcti_init(&this->m_viewerBorder,
+ xmin * this->m_width,
+ xmax * this->m_width,
+ ymin * this->m_height,
+ ymax * this->m_height);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h
index 6fd93d2d93c..ff5c1698a75 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.h
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.h
@@ -31,30 +31,46 @@
#include "COM_MemoryProxy.h"
#include "COM_Node.h"
#include "COM_NodeOperation.h"
+#include "COM_WorkPackage.h"
#include <vector>
+namespace blender::compositor {
+
class ExecutionSystem;
class MemoryProxy;
+class MemoryBuffer;
class ReadBufferOperation;
class Device;
-/**
- * \brief the execution state of a chunk in an ExecutionGroup
- * \ingroup Execution
- */
-enum class eChunkExecutionState {
+struct ExecutionGroupFlags {
+ bool initialized : 1;
/**
- * \brief chunk is not yet scheduled
+ * Is this ExecutionGroup an output ExecutionGroup
+ * An OutputExecution group are groups containing a
+ * ViewerOperation, CompositeOperation, PreviewOperation.
*/
- NOT_SCHEDULED = 0,
+ bool is_output : 1;
+ bool complex : 1;
+
/**
- * \brief chunk is scheduled, but not yet executed
+ * Can this ExecutionGroup be scheduled on an OpenCLDevice.
*/
- SCHEDULED = 1,
+ bool open_cl : 1;
+
/**
- * \brief chunk is executed.
+ * Schedule this execution group as a single chunk. This
+ * chunk will be executed by a single thread.
*/
- EXECUTED = 2,
+ bool single_threaded : 1;
+
+ ExecutionGroupFlags()
+ {
+ initialized = false;
+ is_output = false;
+ complex = false;
+ open_cl = false;
+ single_threaded = false;
+ }
};
/**
@@ -72,12 +88,7 @@ class ExecutionGroup {
*/
blender::Vector<NodeOperation *> m_operations;
- /**
- * \brief is this ExecutionGroup an input ExecutionGroup
- * an input execution group is a group that is at the end of the calculation
- * (the output is important for the user).
- */
- bool m_is_output;
+ ExecutionGroupFlags m_flags;
/**
* \brief Width of the output
@@ -111,21 +122,6 @@ class ExecutionGroup {
unsigned int m_chunks_len;
/**
- * \brief contains this ExecutionGroup a complex NodeOperation.
- */
- bool m_complex;
-
- /**
- * \brief can this ExecutionGroup be scheduled on an OpenCLDevice
- */
- bool m_openCL;
-
- /**
- * \brief Is this Execution group SingleThreaded
- */
- bool m_singleThreaded;
-
- /**
* \brief what is the maximum number field of all ReadBufferOperation in this ExecutionGroup.
* \note this is used to construct the MemoryBuffers that will be passed during execution.
*/
@@ -149,24 +145,9 @@ class ExecutionGroup {
unsigned int m_chunks_finished;
/**
- * \brief m_chunk_execution_states holds per chunk the execution state. this state can be
- * - eChunkExecutionState::NOT_SCHEDULED: not scheduled
- * - eChunkExecutionState::SCHEDULED: scheduled
- * - eChunkExecutionState::EXECUTED: executed
+ * \brief m_work_packages holds all unit of work.
*/
- blender::Vector<eChunkExecutionState> m_chunk_execution_states;
-
- /**
- * \brief indicator when this ExecutionGroup has valid Operations in its vector for Execution
- * \note When building the ExecutionGroup Operations are added via recursion.
- * First a WriteBufferOperations is added, then the.
- * \note Operation containing the settings that is important for the ExecutiongGroup is added,
- * \note When this occurs, these settings are copied over from the node to the ExecutionGroup
- * \note and the Initialized flag is set to true.
- * \see complex
- * \see openCL
- */
- bool m_initialized;
+ blender::Vector<WorkPackage> m_work_packages;
/**
* \brief denotes boundary for border compositing
@@ -187,19 +168,11 @@ class ExecutionGroup {
bool can_contain(NodeOperation &operation);
/**
- * \brief calculate the actual chunk size of this execution group.
- * \note A chunk size is an unsigned int that is both the height and width of a chunk.
- * \note The chunk size will not be stored in the chunkSize field. This needs to be done
- * \note by the calling method.
- */
- unsigned int determineChunkSize();
-
- /**
* \brief Determine the rect (minx, maxx, miny, maxy) of a chunk at a position.
- * \note Only gives useful results after the determination of the chunksize
- * \see determineChunkSize()
*/
- void determineChunkRect(rcti *rect, const unsigned int xChunk, const unsigned int yChunk) const;
+ void determineChunkRect(rcti *r_rect,
+ const unsigned int xChunk,
+ const unsigned int yChunk) const;
/**
* \brief determine the number of chunks, based on the chunkSize, width and height.
@@ -258,6 +231,11 @@ class ExecutionGroup {
// constructors
ExecutionGroup();
+ const ExecutionGroupFlags get_flags() const
+ {
+ return m_flags;
+ }
+
// methods
/**
* \brief add an operation to this ExecutionGroup
@@ -270,23 +248,12 @@ class ExecutionGroup {
bool addOperation(NodeOperation *operation);
/**
- * \brief is this ExecutionGroup an output ExecutionGroup
- * \note An OutputExecution group are groups containing a
- * \note ViewerOperation, CompositeOperation, PreviewOperation.
- * \see NodeOperation.isOutputOperation
- */
- bool isOutputExecutionGroup() const
- {
- return this->m_is_output;
- }
-
- /**
* \brief set whether this ExecutionGroup is an output
* \param isOutput:
*/
void setOutputExecutionGroup(bool is_output)
{
- this->m_is_output = is_output;
+ this->m_flags.is_output = is_output;
}
/**
@@ -322,14 +289,6 @@ class ExecutionGroup {
}
/**
- * \brief does this ExecutionGroup contains a complex NodeOperation
- */
- bool isComplex() const
- {
- return m_complex;
- }
-
- /**
* \brief get the output operation of this ExecutionGroup
* \return NodeOperation *output operation
*/
@@ -404,16 +363,8 @@ class ExecutionGroup {
/**
* \brief Determine the rect (minx, maxx, miny, maxy) of a chunk.
- * \note Only gives useful results after the determination of the chunksize
- * \see determineChunkSize()
*/
- void determineChunkRect(rcti *rect, const unsigned int chunkNumber) const;
-
- /**
- * \brief can this ExecutionGroup be scheduled on an OpenCLDevice
- * \see WorkScheduler.schedule
- */
- bool isOpenCL();
+ void determineChunkRect(rcti *r_rect, const unsigned int chunkNumber) const;
void setChunksize(int chunksize)
{
@@ -424,7 +375,7 @@ class ExecutionGroup {
* \brief get the Render priority of this ExecutionGroup
* \see ExecutionSystem.execute
*/
- CompositorPriority getRenderPriotrity();
+ CompositorPriority getRenderPriority();
/**
* \brief set border for viewer operation
@@ -441,3 +392,5 @@ class ExecutionGroup {
MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionGroup")
#endif
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cc b/source/blender/compositor/intern/COM_ExecutionSystem.cc
index 993aedf7715..9a3dc6ee56f 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.cc
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.cc
@@ -37,6 +37,8 @@
# include "MEM_guardedalloc.h"
#endif
+namespace blender::compositor {
+
ExecutionSystem::ExecutionSystem(RenderData *rd,
Scene *scene,
bNodeTree *editingtree,
@@ -71,7 +73,6 @@ ExecutionSystem::ExecutionSystem(RenderData *rd,
builder.convertToOperations(this);
}
- unsigned int index;
unsigned int resolution[2];
rctf *viewer_border = &editingtree->viewer_border;
@@ -81,10 +82,9 @@ ExecutionSystem::ExecutionSystem(RenderData *rd,
editingtree->stats_draw(editingtree->sdh, TIP_("Compositing | Determining resolution"));
- for (index = 0; index < this->m_groups.size(); index++) {
+ for (ExecutionGroup *executionGroup : m_groups) {
resolution[0] = 0;
resolution[1] = 0;
- ExecutionGroup *executionGroup = this->m_groups[index];
executionGroup->determineResolution(resolution);
if (rendering) {
@@ -108,14 +108,12 @@ ExecutionSystem::ExecutionSystem(RenderData *rd,
ExecutionSystem::~ExecutionSystem()
{
- unsigned int index;
- for (index = 0; index < this->m_operations.size(); index++) {
- NodeOperation *operation = this->m_operations[index];
+ for (NodeOperation *operation : m_operations) {
delete operation;
}
this->m_operations.clear();
- for (index = 0; index < this->m_groups.size(); index++) {
- ExecutionGroup *group = this->m_groups[index];
+
+ for (ExecutionGroup *group : m_groups) {
delete group;
}
this->m_groups.clear();
@@ -128,92 +126,100 @@ void ExecutionSystem::set_operations(const blender::Vector<NodeOperation *> &ope
m_groups = groups;
}
-void ExecutionSystem::execute()
+static void update_read_buffer_offset(blender::Vector<NodeOperation *> &operations)
{
- const bNodeTree *editingtree = this->m_context.getbNodeTree();
- editingtree->stats_draw(editingtree->sdh, TIP_("Compositing | Initializing execution"));
-
- DebugInfo::execute_started(this);
-
unsigned int order = 0;
- for (NodeOperation *operation : m_operations) {
- if (operation->isReadBufferOperation()) {
+ for (NodeOperation *operation : operations) {
+ if (operation->get_flags().is_read_buffer_operation) {
ReadBufferOperation *readOperation = (ReadBufferOperation *)operation;
readOperation->setOffset(order);
order++;
}
}
- unsigned int index;
+}
- // First allocale all write buffer
- for (index = 0; index < this->m_operations.size(); index++) {
- NodeOperation *operation = this->m_operations[index];
- if (operation->isWriteBufferOperation()) {
- operation->setbNodeTree(this->m_context.getbNodeTree());
+static void init_write_operations_for_execution(blender::Vector<NodeOperation *> &operations,
+ const bNodeTree *bTree)
+{
+ for (NodeOperation *operation : operations) {
+ if (operation->get_flags().is_write_buffer_operation) {
+ operation->setbNodeTree(bTree);
operation->initExecution();
}
}
- // Connect read buffers to their write buffers
- for (index = 0; index < this->m_operations.size(); index++) {
- NodeOperation *operation = this->m_operations[index];
- if (operation->isReadBufferOperation()) {
- ReadBufferOperation *readOperation = (ReadBufferOperation *)operation;
+}
+
+static void link_write_buffers(blender::Vector<NodeOperation *> &operations)
+{
+ for (NodeOperation *operation : operations) {
+ if (operation->get_flags().is_read_buffer_operation) {
+ ReadBufferOperation *readOperation = static_cast<ReadBufferOperation *>(operation);
readOperation->updateMemoryBuffer();
}
}
- // initialize other operations
- for (index = 0; index < this->m_operations.size(); index++) {
- NodeOperation *operation = this->m_operations[index];
- if (!operation->isWriteBufferOperation()) {
- operation->setbNodeTree(this->m_context.getbNodeTree());
+}
+
+static void init_non_write_operations_for_execution(blender::Vector<NodeOperation *> &operations,
+ const bNodeTree *bTree)
+{
+ for (NodeOperation *operation : operations) {
+ if (!operation->get_flags().is_write_buffer_operation) {
+ operation->setbNodeTree(bTree);
operation->initExecution();
}
}
- for (index = 0; index < this->m_groups.size(); index++) {
- ExecutionGroup *executionGroup = this->m_groups[index];
- executionGroup->setChunksize(this->m_context.getChunksize());
- executionGroup->initExecution();
+}
+
+static void init_execution_groups_for_execution(blender::Vector<ExecutionGroup *> &groups,
+ const int chunk_size)
+{
+ for (ExecutionGroup *execution_group : groups) {
+ execution_group->setChunksize(chunk_size);
+ execution_group->initExecution();
}
+}
- WorkScheduler::start(this->m_context);
+void ExecutionSystem::execute()
+{
+ const bNodeTree *editingtree = this->m_context.getbNodeTree();
+ editingtree->stats_draw(editingtree->sdh, TIP_("Compositing | Initializing execution"));
+
+ DebugInfo::execute_started(this);
+ update_read_buffer_offset(m_operations);
+ init_write_operations_for_execution(m_operations, m_context.getbNodeTree());
+ link_write_buffers(m_operations);
+ init_non_write_operations_for_execution(m_operations, m_context.getbNodeTree());
+ init_execution_groups_for_execution(m_groups, m_context.getChunksize());
+
+ WorkScheduler::start(this->m_context);
execute_groups(CompositorPriority::High);
if (!this->getContext().isFastCalculation()) {
execute_groups(CompositorPriority::Medium);
execute_groups(CompositorPriority::Low);
}
-
WorkScheduler::finish();
WorkScheduler::stop();
editingtree->stats_draw(editingtree->sdh, TIP_("Compositing | De-initializing execution"));
- for (index = 0; index < this->m_operations.size(); index++) {
- NodeOperation *operation = this->m_operations[index];
+
+ for (NodeOperation *operation : m_operations) {
operation->deinitExecution();
}
- for (index = 0; index < this->m_groups.size(); index++) {
- ExecutionGroup *executionGroup = this->m_groups[index];
- executionGroup->deinitExecution();
- }
-}
-void ExecutionSystem::execute_groups(CompositorPriority priority)
-{
- blender::Vector<ExecutionGroup *> execution_groups = find_output_execution_groups(priority);
- for (ExecutionGroup *group : execution_groups) {
- group->execute(this);
+ for (ExecutionGroup *execution_group : m_groups) {
+ execution_group->deinitExecution();
}
}
-blender::Vector<ExecutionGroup *> ExecutionSystem::find_output_execution_groups(
- CompositorPriority priority) const
+void ExecutionSystem::execute_groups(CompositorPriority priority)
{
- blender::Vector<ExecutionGroup *> result;
-
- for (ExecutionGroup *group : m_groups) {
- if (group->isOutputExecutionGroup() && group->getRenderPriotrity() == priority) {
- result.append(group);
+ for (ExecutionGroup *execution_group : m_groups) {
+ if (execution_group->get_flags().is_output &&
+ execution_group->getRenderPriority() == priority) {
+ execution_group->execute(this);
}
}
- return result;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h
index 6a50cc6906b..b8dcd90e1a6 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.h
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.h
@@ -31,6 +31,8 @@ class ExecutionGroup;
#include "BLI_vector.hh"
+namespace blender::compositor {
+
/**
* \page execution Execution model
* In order to get to an efficient model for execution, several steps are being done. these steps
@@ -70,17 +72,17 @@ class ExecutionGroup;
*
* - Image size conversions: the system can automatically convert when resolutions do not match.
* An NodeInput has a resize mode. This can be any of the following settings.
- * - [@ref InputSocketResizeMode.COM_SC_CENTER]:
+ * - [@ref InputSocketResizeMode.ResizeMode::Center]:
* The center of both images are aligned
- * - [@ref InputSocketResizeMode.COM_SC_FIT_WIDTH]:
+ * - [@ref InputSocketResizeMode.ResizeMode::FitWidth]:
* The width of both images are aligned
- * - [@ref InputSocketResizeMode.COM_SC_FIT_HEIGHT]:
+ * - [@ref InputSocketResizeMode.ResizeMode::FitHeight]:
* The height of both images are aligned
- * - [@ref InputSocketResizeMode.COM_SC_FIT]:
+ * - [@ref InputSocketResizeMode.ResizeMode::FitAny]:
* The width, or the height of both images are aligned to make sure that it fits.
- * - [@ref InputSocketResizeMode.COM_SC_STRETCH]:
+ * - [@ref InputSocketResizeMode.ResizeMode::Stretch]:
* The width and the height of both images are aligned.
- * - [@ref InputSocketResizeMode.COM_SC_NO_RESIZE]:
+ * - [@ref InputSocketResizeMode.ResizeMode::None]:
* Bottom left of the images are aligned.
*
* \see COM_convert_data_type Datatype conversions
@@ -135,12 +137,6 @@ class ExecutionSystem {
blender::Vector<ExecutionGroup *> m_groups;
private: // methods
- /**
- * find all execution group with output nodes
- */
- blender::Vector<ExecutionGroup *> find_output_execution_groups(
- CompositorPriority priority) const;
-
public:
/**
* \brief Create a new ExecutionSystem and initialize it with the
@@ -192,3 +188,5 @@ class ExecutionSystem {
MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionSystem")
#endif
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cc b/source/blender/compositor/intern/COM_MemoryBuffer.cc
index 0b28168720e..68e39b19eaf 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.cc
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.cc
@@ -20,24 +20,13 @@
#include "MEM_guardedalloc.h"
-static unsigned int determine_num_channels(DataType datatype)
-{
- switch (datatype) {
- case DataType::Value:
- return COM_NUM_CHANNELS_VALUE;
- case DataType::Vector:
- return COM_NUM_CHANNELS_VECTOR;
- case DataType::Color:
- default:
- return COM_NUM_CHANNELS_COLOR;
- }
-}
+namespace blender::compositor {
MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, const rcti &rect, MemoryBufferState state)
{
m_rect = rect;
this->m_memoryProxy = memoryProxy;
- this->m_num_channels = determine_num_channels(memoryProxy->getDataType());
+ this->m_num_channels = COM_data_type_num_channels(memoryProxy->getDataType());
this->m_buffer = (float *)MEM_mallocN_aligned(
sizeof(float) * buffer_len() * this->m_num_channels, 16, "COM_MemoryBuffer");
this->m_state = state;
@@ -48,7 +37,7 @@ MemoryBuffer::MemoryBuffer(DataType dataType, const rcti &rect)
{
m_rect = rect;
this->m_memoryProxy = nullptr;
- this->m_num_channels = determine_num_channels(dataType);
+ this->m_num_channels = COM_data_type_num_channels(dataType);
this->m_buffer = (float *)MEM_mallocN_aligned(
sizeof(float) * buffer_len() * this->m_num_channels, 16, "COM_MemoryBuffer");
this->m_state = MemoryBufferState::Temporary;
@@ -183,3 +172,5 @@ void MemoryBuffer::readEWA(float *result, const float uv[2], const float derivat
this,
result);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h
index 6f719b61122..060a67f8797 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.h
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.h
@@ -16,17 +16,16 @@
* Copyright 2011, Blender Foundation.
*/
-class MemoryBuffer;
-
#pragma once
#include "COM_ExecutionGroup.h"
#include "COM_MemoryProxy.h"
-#include "COM_SocketReader.h"
#include "BLI_math.h"
#include "BLI_rect.h"
+namespace blender::compositor {
+
/**
* \brief state of a memory buffer
* \ingroup Memory
@@ -331,3 +330,5 @@ class MemoryBuffer {
MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryBuffer")
#endif
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_MemoryProxy.cc b/source/blender/compositor/intern/COM_MemoryProxy.cc
index 8ef834e1efe..6023850c944 100644
--- a/source/blender/compositor/intern/COM_MemoryProxy.cc
+++ b/source/blender/compositor/intern/COM_MemoryProxy.cc
@@ -18,6 +18,12 @@
#include "COM_MemoryProxy.h"
+#include "COM_MemoryBuffer.h"
+
+#include "BLI_rect.h"
+
+namespace blender::compositor {
+
MemoryProxy::MemoryProxy(DataType datatype)
{
this->m_writeBufferOperation = nullptr;
@@ -43,3 +49,5 @@ void MemoryProxy::free()
this->m_buffer = nullptr;
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_MemoryProxy.h b/source/blender/compositor/intern/COM_MemoryProxy.h
index a40e6f95dce..0966eadadb2 100644
--- a/source/blender/compositor/intern/COM_MemoryProxy.h
+++ b/source/blender/compositor/intern/COM_MemoryProxy.h
@@ -16,13 +16,14 @@
* Copyright 2011, Blender Foundation.
*/
-class MemoryProxy;
-
#pragma once
-#include "COM_ExecutionGroup.h"
-#include "COM_MemoryBuffer.h"
+#include "COM_defines.h"
+
+namespace blender::compositor {
+/* Forward declarations. */
+class MemoryBuffer;
class ExecutionGroup;
class WriteBufferOperation;
@@ -45,16 +46,6 @@ class MemoryProxy {
ExecutionGroup *m_executor;
/**
- * \brief datatype of this MemoryProxy
- */
- /* DataType m_datatype; */ /* UNUSED */
-
- /**
- * \brief channel information of this buffer
- */
- /* ChannelInfo m_channelInfo[COM_NUMBER_OF_CHANNELS]; */ /* UNUSED */
-
- /**
* \brief the allocated memory
*/
MemoryBuffer *m_buffer;
@@ -129,3 +120,5 @@ class MemoryProxy {
MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryProxy")
#endif
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_MetaData.cc b/source/blender/compositor/intern/COM_MetaData.cc
index ad72b242c8c..6762955ef78 100644
--- a/source/blender/compositor/intern/COM_MetaData.cc
+++ b/source/blender/compositor/intern/COM_MetaData.cc
@@ -24,6 +24,8 @@
#include <string_view>
+namespace blender::compositor {
+
void MetaData::add(const blender::StringRef key, const blender::StringRef value)
{
entries_.add(key, value);
@@ -104,3 +106,5 @@ void MetaDataExtractCallbackData::extract_cryptomatte_meta_data(void *_data,
data->addMetaData(META_DATA_KEY_CRYPTOMATTE_MANIFEST, propvalue);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_MetaData.h b/source/blender/compositor/intern/COM_MetaData.h
index fa3de895b4e..ce437fd5df8 100644
--- a/source/blender/compositor/intern/COM_MetaData.h
+++ b/source/blender/compositor/intern/COM_MetaData.h
@@ -28,6 +28,8 @@
/* Forward declarations. */
struct RenderResult;
+namespace blender::compositor {
+
/* Cryptomatte includes hash in its meta data keys. The hash is generated from the render
* layer/pass name. Compositing happens without the knowledge of the original layer and pass. The
* next keys are used to transfer the cryptomatte meta data in a neutral way. The file output node
@@ -69,3 +71,5 @@ struct MetaDataExtractCallbackData {
char *propvalue,
int UNUSED(len));
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_Node.cc b/source/blender/compositor/intern/COM_Node.cc
index 819f1c02b14..6ac48e3646c 100644
--- a/source/blender/compositor/intern/COM_Node.cc
+++ b/source/blender/compositor/intern/COM_Node.cc
@@ -32,6 +32,8 @@
#include "COM_Node.h" /* own include */
+namespace blender::compositor {
+
/**************
**** Node ****
**************/
@@ -74,13 +76,11 @@ Node::Node(bNode *editorNode, bool create_sockets)
Node::~Node()
{
- while (!this->m_outputsockets.empty()) {
- delete (this->m_outputsockets.back());
- this->m_outputsockets.pop_back();
+ while (!this->outputs.is_empty()) {
+ delete (this->outputs.pop_last());
}
- while (!this->m_inputsockets.empty()) {
- delete (this->m_inputsockets.back());
- this->m_inputsockets.pop_back();
+ while (!this->inputs.is_empty()) {
+ delete (this->inputs.pop_last());
}
}
@@ -92,7 +92,7 @@ void Node::addInputSocket(DataType datatype)
void Node::addInputSocket(DataType datatype, bNodeSocket *bSocket)
{
NodeInput *socket = new NodeInput(this, bSocket, datatype);
- this->m_inputsockets.push_back(socket);
+ this->inputs.append(socket);
}
void Node::addOutputSocket(DataType datatype)
@@ -102,19 +102,17 @@ void Node::addOutputSocket(DataType datatype)
void Node::addOutputSocket(DataType datatype, bNodeSocket *bSocket)
{
NodeOutput *socket = new NodeOutput(this, bSocket, datatype);
- this->m_outputsockets.push_back(socket);
+ outputs.append(socket);
}
NodeOutput *Node::getOutputSocket(unsigned int index) const
{
- BLI_assert(index < this->m_outputsockets.size());
- return this->m_outputsockets[index];
+ return outputs[index];
}
NodeInput *Node::getInputSocket(unsigned int index) const
{
- BLI_assert(index < this->m_inputsockets.size());
- return this->m_inputsockets[index];
+ return inputs[index];
}
bNodeSocket *Node::getEditorInputSocket(int editorNodeInputSocketIndex)
@@ -208,3 +206,5 @@ void NodeOutput::getEditorValueVector(float *value)
RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
return RNA_float_get_array(&ptr, "default_value", value);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_Node.h b/source/blender/compositor/intern/COM_Node.h
index 99f1b58b5ef..9aca1a8ff44 100644
--- a/source/blender/compositor/intern/COM_Node.h
+++ b/source/blender/compositor/intern/COM_Node.h
@@ -18,10 +18,12 @@
#pragma once
+#include "BLI_vector.hh"
+
#include "DNA_node_types.h"
+
#include <algorithm>
#include <string>
-#include <vector>
/* common node includes
* added here so node files don't have to include themselves
@@ -29,7 +31,8 @@
#include "COM_CompositorContext.h"
#include "COM_NodeConverter.h"
-class Node;
+namespace blender::compositor {
+
class NodeOperation;
class NodeConverter;
@@ -37,10 +40,6 @@ class NodeConverter;
* My node documentation.
*/
class Node {
- public:
- typedef std::vector<NodeInput *> Inputs;
- typedef std::vector<NodeOutput *> Outputs;
-
private:
/**
* \brief stores the reference to the SDNA bNode struct
@@ -53,16 +52,6 @@ class Node {
bNode *m_editorNode;
/**
- * \brief the list of actual inputsockets \see NodeInput
- */
- Inputs m_inputsockets;
-
- /**
- * \brief the list of actual outputsockets \see NodeOutput
- */
- Outputs m_outputsockets;
-
- /**
* \brief Is this node part of the active group
*/
bool m_inActiveGroup;
@@ -74,20 +63,14 @@ class Node {
protected:
/**
- * \brief get access to the vector of input sockets
+ * \brief the list of actual inputsockets \see NodeInput
*/
- const Inputs &getInputSockets() const
- {
- return this->m_inputsockets;
- }
+ blender::Vector<NodeInput *> inputs;
/**
- * \brief get access to the vector of input sockets
+ * \brief the list of actual outputsockets \see NodeOutput
*/
- const Outputs &getOutputSockets() const
- {
- return this->m_outputsockets;
- }
+ blender::Vector<NodeOutput *> outputs;
public:
Node(bNode *editorNode, bool create_sockets = true);
@@ -130,19 +113,19 @@ class Node {
}
/**
- * \brief Return the number of input sockets of this node.
+ * \brief get access to the vector of input sockets
*/
- unsigned int getNumberOfInputSockets() const
+ const blender::Vector<NodeInput *> &getInputSockets() const
{
- return this->m_inputsockets.size();
+ return this->inputs;
}
/**
- * \brief Return the number of output sockets of this node.
+ * \brief get access to the vector of input sockets
*/
- unsigned int getNumberOfOutputSockets() const
+ const blender::Vector<NodeOutput *> &getOutputSockets() const
{
- return this->m_outputsockets.size();
+ return this->outputs;
}
/**
@@ -150,17 +133,7 @@ class Node {
* \param index:
* the index of the needed outputsocket
*/
- NodeOutput *getOutputSocket(const unsigned int index) const;
-
- /**
- * get the reference to the first outputsocket
- * \param index:
- * the index of the needed outputsocket
- */
- inline NodeOutput *getOutputSocket() const
- {
- return getOutputSocket(0);
- }
+ NodeOutput *getOutputSocket(const unsigned int index = 0) const;
/**
* get the reference to a certain inputsocket
@@ -169,14 +142,6 @@ class Node {
*/
NodeInput *getInputSocket(const unsigned int index) const;
- /** Check if this is an input node
- * An input node is a node that only has output sockets and no input sockets
- */
- bool isInputNode() const
- {
- return m_inputsockets.empty();
- }
-
/**
* \brief Is this node in the active group (the group that is being edited)
* \param isInActiveGroup:
@@ -317,3 +282,5 @@ class NodeOutput {
void getEditorValueColor(float *value);
void getEditorValueVector(float *value);
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_NodeConverter.cc b/source/blender/compositor/intern/COM_NodeConverter.cc
index 2db31bd4133..49a2e7988c4 100644
--- a/source/blender/compositor/intern/COM_NodeConverter.cc
+++ b/source/blender/compositor/intern/COM_NodeConverter.cc
@@ -29,6 +29,8 @@
#include "COM_NodeConverter.h" /* own include */
+namespace blender::compositor {
+
NodeConverter::NodeConverter(NodeOperationBuilder *builder) : m_builder(builder)
{
}
@@ -160,3 +162,5 @@ ViewerOperation *NodeConverter::active_viewer() const
{
return m_builder->active_viewer();
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_NodeConverter.h b/source/blender/compositor/intern/COM_NodeConverter.h
index e9b05184857..b3f03485249 100644
--- a/source/blender/compositor/intern/COM_NodeConverter.h
+++ b/source/blender/compositor/intern/COM_NodeConverter.h
@@ -22,6 +22,8 @@
# include "MEM_guardedalloc.h"
#endif
+namespace blender::compositor {
+
class NodeInput;
class NodeOutput;
@@ -120,3 +122,5 @@ class NodeConverter {
MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeCompiler")
#endif
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_NodeGraph.cc b/source/blender/compositor/intern/COM_NodeGraph.cc
index d8220099f1f..7e05bf637b7 100644
--- a/source/blender/compositor/intern/COM_NodeGraph.cc
+++ b/source/blender/compositor/intern/COM_NodeGraph.cc
@@ -33,6 +33,8 @@
#include "COM_NodeGraph.h" /* own include */
+namespace blender::compositor {
+
/*******************
**** NodeGraph ****
*******************/
@@ -43,9 +45,8 @@ NodeGraph::NodeGraph()
NodeGraph::~NodeGraph()
{
- for (int index = 0; index < this->m_nodes.size(); index++) {
- Node *node = this->m_nodes[index];
- delete node;
+ while (m_nodes.size()) {
+ delete m_nodes.pop_last();
}
}
@@ -83,7 +84,7 @@ void NodeGraph::add_node(Node *node,
node->setInstanceKey(key);
node->setIsInActiveGroup(is_active_group);
- m_nodes.push_back(node);
+ m_nodes.append(node);
DebugInfo::node_added(node);
}
@@ -153,27 +154,11 @@ void NodeGraph::add_bNode(const CompositorContext &context,
}
}
-NodeGraph::NodeInputs NodeGraph::find_inputs(const NodeRange &node_range, bNodeSocket *b_socket)
-{
- NodeInputs result;
- for (NodeGraph::NodeIterator it = node_range.first; it != node_range.second; ++it) {
- Node *node = *it;
- for (int index = 0; index < node->getNumberOfInputSockets(); index++) {
- NodeInput *input = node->getInputSocket(index);
- if (input->getbNodeSocket() == b_socket) {
- result.push_back(input);
- }
- }
- }
- return result;
-}
-
NodeOutput *NodeGraph::find_output(const NodeRange &node_range, bNodeSocket *b_socket)
{
- for (NodeGraph::NodeIterator it = node_range.first; it != node_range.second; ++it) {
+ for (blender::Vector<Node *>::iterator it = node_range.first; it != node_range.second; ++it) {
Node *node = *it;
- for (int index = 0; index < node->getNumberOfOutputSockets(); index++) {
- NodeOutput *output = node->getOutputSocket(index);
+ for (NodeOutput *output : node->getOutputSockets()) {
if (output->getbNodeSocket() == b_socket) {
return output;
}
@@ -202,12 +187,13 @@ void NodeGraph::add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink
return;
}
- NodeInputs inputs = find_inputs(node_range, b_nodelink->tosock);
- for (NodeInput *input : inputs) {
- if (input->isLinked()) {
- continue;
+ for (blender::Vector<Node *>::iterator it = node_range.first; it != node_range.second; ++it) {
+ Node *node = *it;
+ for (NodeInput *input : node->getInputSockets()) {
+ if (input->getbNodeSocket() == b_nodelink->tosock && !input->isLinked()) {
+ add_link(output, input);
+ }
}
- add_link(output, input);
}
}
@@ -331,3 +317,5 @@ void NodeGraph::add_proxies_reroute(bNodeTree *b_ntree,
b_node, (bNodeSocket *)b_node->inputs.first, (bNodeSocket *)b_node->outputs.first, false);
add_node(proxy, b_ntree, key, is_active_group);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_NodeGraph.h b/source/blender/compositor/intern/COM_NodeGraph.h
index 990e3a30831..9347df5d9e2 100644
--- a/source/blender/compositor/intern/COM_NodeGraph.h
+++ b/source/blender/compositor/intern/COM_NodeGraph.h
@@ -22,7 +22,6 @@
#include <map>
#include <set>
-#include <vector>
#include "DNA_node_types.h"
@@ -30,6 +29,8 @@
# include "MEM_guardedalloc.h"
#endif
+namespace blender::compositor {
+
class CompositorContext;
class Node;
class NodeInput;
@@ -50,18 +51,15 @@ class NodeGraph {
}
};
- typedef std::vector<Node *> Nodes;
- typedef Nodes::iterator NodeIterator;
-
private:
- Nodes m_nodes;
+ blender::Vector<Node *> m_nodes;
blender::Vector<Link> m_links;
public:
NodeGraph();
~NodeGraph();
- const Nodes &nodes() const
+ const blender::Vector<Node *> &nodes() const
{
return m_nodes;
}
@@ -73,8 +71,8 @@ class NodeGraph {
void from_bNodeTree(const CompositorContext &context, bNodeTree *tree);
protected:
- typedef std::pair<NodeIterator, NodeIterator> NodeRange;
- typedef std::vector<NodeInput *> NodeInputs;
+ typedef std::pair<blender::Vector<Node *>::iterator, blender::Vector<Node *>::iterator>
+ NodeRange;
static bNodeSocket *find_b_node_input(bNode *b_node, const char *identifier);
static bNodeSocket *find_b_node_output(bNode *b_node, const char *identifier);
@@ -93,7 +91,6 @@ class NodeGraph {
bNodeInstanceKey key,
bool is_active_group);
- NodeInputs find_inputs(const NodeRange &node_range, bNodeSocket *b_socket);
NodeOutput *find_output(const NodeRange &node_range, bNodeSocket *b_socket);
void add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink);
@@ -124,3 +121,5 @@ class NodeGraph {
MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeGraph")
#endif
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_NodeOperation.cc b/source/blender/compositor/intern/COM_NodeOperation.cc
index 0cc642479ac..297ef100a1b 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.cc
+++ b/source/blender/compositor/intern/COM_NodeOperation.cc
@@ -24,6 +24,8 @@
#include "COM_NodeOperation.h" /* own include */
+namespace blender::compositor {
+
/*******************
**** NodeOperation ****
*******************/
@@ -31,76 +33,52 @@
NodeOperation::NodeOperation()
{
this->m_resolutionInputSocketIndex = 0;
- this->m_complex = false;
this->m_width = 0;
this->m_height = 0;
- this->m_isResolutionSet = false;
- this->m_openCL = false;
this->m_btree = nullptr;
}
-NodeOperation::~NodeOperation()
-{
- while (!this->m_outputs.empty()) {
- delete (this->m_outputs.back());
- this->m_outputs.pop_back();
- }
- while (!this->m_inputs.empty()) {
- delete (this->m_inputs.back());
- this->m_inputs.pop_back();
- }
-}
-
-NodeOperationOutput *NodeOperation::getOutputSocket(unsigned int index) const
+NodeOperationOutput *NodeOperation::getOutputSocket(unsigned int index)
{
- BLI_assert(index < m_outputs.size());
- return m_outputs[index];
+ return &m_outputs[index];
}
-NodeOperationInput *NodeOperation::getInputSocket(unsigned int index) const
+NodeOperationInput *NodeOperation::getInputSocket(unsigned int index)
{
- BLI_assert(index < m_inputs.size());
- return m_inputs[index];
+ return &m_inputs[index];
}
-void NodeOperation::addInputSocket(DataType datatype, InputResizeMode resize_mode)
+void NodeOperation::addInputSocket(DataType datatype, ResizeMode resize_mode)
{
- NodeOperationInput *socket = new NodeOperationInput(this, datatype, resize_mode);
- m_inputs.push_back(socket);
+ m_inputs.append(NodeOperationInput(this, datatype, resize_mode));
}
void NodeOperation::addOutputSocket(DataType datatype)
{
- NodeOperationOutput *socket = new NodeOperationOutput(this, datatype);
- m_outputs.push_back(socket);
+ m_outputs.append(NodeOperationOutput(this, datatype));
}
void NodeOperation::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
{
- unsigned int temp[2];
- unsigned int temp2[2];
+ if (m_resolutionInputSocketIndex < m_inputs.size()) {
+ NodeOperationInput &input = m_inputs[m_resolutionInputSocketIndex];
+ input.determineResolution(resolution, preferredResolution);
+ }
+ unsigned int temp2[2] = {resolution[0], resolution[1]};
+ unsigned int temp[2];
for (unsigned int index = 0; index < m_inputs.size(); index++) {
- NodeOperationInput *input = m_inputs[index];
- if (input->isConnected()) {
- if (index == this->m_resolutionInputSocketIndex) {
- input->determineResolution(resolution, preferredResolution);
- temp2[0] = resolution[0];
- temp2[1] = resolution[1];
- break;
- }
+ if (index == this->m_resolutionInputSocketIndex) {
+ continue;
}
- }
- for (unsigned int index = 0; index < m_inputs.size(); index++) {
- NodeOperationInput *input = m_inputs[index];
- if (input->isConnected()) {
- if (index != this->m_resolutionInputSocketIndex) {
- input->determineResolution(temp, temp2);
- }
+ NodeOperationInput &input = m_inputs[index];
+ if (input.isConnected()) {
+ input.determineResolution(temp, temp2);
}
}
}
+
void NodeOperation::setResolutionInputSocketIndex(unsigned int index)
{
this->m_resolutionInputSocketIndex = index;
@@ -149,20 +127,11 @@ NodeOperation *NodeOperation::getInputOperation(unsigned int inputSocketIndex)
return nullptr;
}
-void NodeOperation::getConnectedInputSockets(Inputs *sockets)
-{
- for (NodeOperationInput *input : m_inputs) {
- if (input->isConnected()) {
- sockets->push_back(input);
- }
- }
-}
-
bool NodeOperation::determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
rcti *output)
{
- if (isInputOperation()) {
+ if (m_inputs.size() == 0) {
BLI_rcti_init(output, input->xmin, input->xmax, input->ymin, input->ymax);
return false;
}
@@ -195,9 +164,7 @@ bool NodeOperation::determineDependingAreaOfInterest(rcti *input,
**** OpInput ****
*****************/
-NodeOperationInput::NodeOperationInput(NodeOperation *op,
- DataType datatype,
- InputResizeMode resizeMode)
+NodeOperationInput::NodeOperationInput(NodeOperation *op, DataType datatype, ResizeMode resizeMode)
: m_operation(op), m_datatype(datatype), m_resizeMode(resizeMode), m_link(nullptr)
{
}
@@ -232,7 +199,7 @@ void NodeOperationOutput::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
{
NodeOperation &operation = getOperation();
- if (operation.isResolutionSet()) {
+ if (operation.get_flags().is_resolution_set) {
resolution[0] = operation.getWidth();
resolution[1] = operation.getHeight();
}
@@ -241,3 +208,5 @@ void NodeOperationOutput::determineResolution(unsigned int resolution[2],
operation.setResolution(resolution);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index 7857837a95d..f300fb092a3 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -28,75 +28,235 @@
#include "COM_MemoryBuffer.h"
#include "COM_MemoryProxy.h"
+#include "COM_MetaData.h"
#include "COM_Node.h"
-#include "COM_SocketReader.h"
#include "clew.h"
+namespace blender::compositor {
+
class OpenCLDevice;
class ReadBufferOperation;
class WriteBufferOperation;
-class NodeOperationInput;
-class NodeOperationOutput;
+class NodeOperation;
+typedef NodeOperation SocketReader;
/**
* \brief Resize modes of inputsockets
* How are the input and working resolutions matched
* \ingroup Model
*/
-typedef enum InputResizeMode {
+enum class ResizeMode {
/** \brief Center the input image to the center of the working area of the node, no resizing
* occurs */
- COM_SC_CENTER = NS_CR_CENTER,
+ Center = NS_CR_CENTER,
/** \brief The bottom left of the input image is the bottom left of the working area of the node,
* no resizing occurs */
- COM_SC_NO_RESIZE = NS_CR_NONE,
+ None = NS_CR_NONE,
/** \brief Fit the width of the input image to the width of the working area of the node */
- COM_SC_FIT_WIDTH = NS_CR_FIT_WIDTH,
+ FitWidth = NS_CR_FIT_WIDTH,
/** \brief Fit the height of the input image to the height of the working area of the node */
- COM_SC_FIT_HEIGHT = NS_CR_FIT_HEIGHT,
+ FitHeight = NS_CR_FIT_HEIGHT,
/** \brief Fit the width or the height of the input image to the width or height of the working
* area of the node, image will be larger than the working area */
- COM_SC_FIT = NS_CR_FIT,
+ FitAny = NS_CR_FIT,
/** \brief Fit the width and the height of the input image to the width and height of the working
* area of the node, image will be equally larger than the working area */
- COM_SC_STRETCH = NS_CR_STRETCH,
-} InputResizeMode;
+ Stretch = NS_CR_STRETCH,
+};
+
+enum class PixelSampler {
+ Nearest = 0,
+ Bilinear = 1,
+ Bicubic = 2,
+};
+
+class NodeOperationInput {
+ private:
+ NodeOperation *m_operation;
+
+ /** Datatype of this socket. Is used for automatically data transformation.
+ * \section data-conversion
+ */
+ DataType m_datatype;
+
+ /** Resize mode of this socket */
+ ResizeMode m_resizeMode;
+
+ /** Connected output */
+ NodeOperationOutput *m_link;
-/**
- * \brief NodeOperation contains calculation logic
- *
- * Subclasses needs to implement the execution method (defined in SocketReader) to implement logic.
- * \ingroup Model
- */
-class NodeOperation : public SocketReader {
public:
- typedef std::vector<NodeOperationInput *> Inputs;
- typedef std::vector<NodeOperationOutput *> Outputs;
+ NodeOperationInput(NodeOperation *op,
+ DataType datatype,
+ ResizeMode resizeMode = ResizeMode::Center);
+ NodeOperation &getOperation() const
+ {
+ return *m_operation;
+ }
+ DataType getDataType() const
+ {
+ return m_datatype;
+ }
+
+ void setLink(NodeOperationOutput *link)
+ {
+ m_link = link;
+ }
+ NodeOperationOutput *getLink() const
+ {
+ return m_link;
+ }
+ bool isConnected() const
+ {
+ return m_link;
+ }
+
+ void setResizeMode(ResizeMode resizeMode)
+ {
+ this->m_resizeMode = resizeMode;
+ }
+ ResizeMode getResizeMode() const
+ {
+ return this->m_resizeMode;
+ }
+
+ SocketReader *getReader();
+
+ void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
+#endif
+};
+
+class NodeOperationOutput {
private:
- Inputs m_inputs;
- Outputs m_outputs;
+ NodeOperation *m_operation;
+
+ /** Datatype of this socket. Is used for automatically data transformation.
+ * \section data-conversion
+ */
+ DataType m_datatype;
+
+ public:
+ NodeOperationOutput(NodeOperation *op, DataType datatype);
+
+ NodeOperation &getOperation() const
+ {
+ return *m_operation;
+ }
+ DataType getDataType() const
+ {
+ return m_datatype;
+ }
/**
- * \brief the index of the input socket that will be used to determine the resolution
+ * \brief determine the resolution of this data going through this socket
+ * \param resolution: the result of this operation
+ * \param preferredResolution: the preferable resolution as no resolution could be determined
*/
- unsigned int m_resolutionInputSocketIndex;
+ void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
+#endif
+};
+struct NodeOperationFlags {
/**
- * \brief is this operation a complex one.
+ * Is this an complex operation.
+ *
+ * The input and output buffers of Complex operations are stored in buffers. It allows
+ * sequential and read/write.
*
* Complex operations are typically doing many reads to calculate the output of a single pixel.
* Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
*/
- bool m_complex;
+ bool complex : 1;
+
+ /**
+ * Does this operation support OpenCL.
+ */
+ bool open_cl : 1;
+
+ bool single_threaded : 1;
+
+ /**
+ * Does the operation needs a viewer border.
+ * Basically, setting border need to happen for only operations
+ * which operates in render resolution buffers (like compositor
+ * output nodes).
+ *
+ * In this cases adding border will lead to mapping coordinates
+ * from output buffer space to input buffer spaces when executing
+ * operation.
+ *
+ * But nodes like viewer and file output just shall display or
+ * safe the same exact buffer which goes to their input, no need
+ * in any kind of coordinates mapping.
+ */
+ bool use_render_border : 1;
+ bool use_viewer_border : 1;
+
+ /**
+ * Is the resolution of the operation set.
+ */
+ bool is_resolution_set : 1;
+
+ /**
+ * Is this a set operation (value, color, vector).
+ */
+ bool is_set_operation : 1;
+ bool is_write_buffer_operation : 1;
+ bool is_read_buffer_operation : 1;
+ bool is_proxy_operation : 1;
+ bool is_viewer_operation : 1;
+ bool is_preview_operation : 1;
+
+ /**
+ * When set additional data conversion operations are added to
+ * convert the data. SocketProxyOperation don't always need to do data conversions.
+ *
+ * By default data conversions are enabled.
+ */
+ bool use_datatype_conversion : 1;
+
+ NodeOperationFlags()
+ {
+ complex = false;
+ single_threaded = false;
+ open_cl = false;
+ use_render_border = false;
+ use_viewer_border = false;
+ is_resolution_set = false;
+ is_set_operation = false;
+ is_read_buffer_operation = false;
+ is_write_buffer_operation = false;
+ is_proxy_operation = false;
+ is_viewer_operation = false;
+ is_preview_operation = false;
+ use_datatype_conversion = true;
+ }
+};
+
+/**
+ * \brief NodeOperation contains calculation logic
+ *
+ * Subclasses needs to implement the execution method (defined in SocketReader) to implement logic.
+ * \ingroup Model
+ */
+class NodeOperation {
+ private:
+ blender::Vector<NodeOperationInput> m_inputs;
+ blender::Vector<NodeOperationOutput> m_outputs;
/**
- * \brief can this operation be scheduled on an OpenCL device.
- * \note Only applicable if complex is True
+ * \brief the index of the input socket that will be used to determine the resolution
*/
- bool m_openCL;
+ unsigned int m_resolutionInputSocketIndex;
/**
* \brief mutex reference for very special node initializations
@@ -114,13 +274,31 @@ class NodeOperation : public SocketReader {
*/
const bNodeTree *m_btree;
+ protected:
/**
- * \brief set to truth when resolution for this operation is set
+ * Width of the output of this operation.
*/
- bool m_isResolutionSet;
+ unsigned int m_width;
+
+ /**
+ * Height of the output of this operation.
+ */
+ unsigned int m_height;
+
+ /**
+ * Flags how to evaluate this operation.
+ */
+ NodeOperationFlags flags;
public:
- virtual ~NodeOperation();
+ virtual ~NodeOperation()
+ {
+ }
+
+ const NodeOperationFlags get_flags() const
+ {
+ return flags;
+ }
unsigned int getNumberOfInputSockets() const
{
@@ -130,20 +308,8 @@ class NodeOperation : public SocketReader {
{
return m_outputs.size();
}
- NodeOperationOutput *getOutputSocket(unsigned int index) const;
- NodeOperationOutput *getOutputSocket() const
- {
- return getOutputSocket(0);
- }
- NodeOperationInput *getInputSocket(unsigned int index) const;
-
- /** Check if this is an input operation
- * An input operation is an operation that only has output sockets and no input sockets
- */
- bool isInputOperation() const
- {
- return m_inputs.empty();
- }
+ NodeOperationOutput *getOutputSocket(unsigned int index = 0);
+ NodeOperationInput *getInputSocket(unsigned int index);
/**
* \brief determine the resolution of this node
@@ -155,11 +321,11 @@ class NodeOperation : public SocketReader {
unsigned int preferredResolution[2]);
/**
- * \brief isOutputOperation determines whether this operation is an output of the ExecutionSystem
- * during rendering or editing.
+ * \brief isOutputOperation determines whether this operation is an output of the
+ * ExecutionSystem during rendering or editing.
*
- * Default behavior if not overridden, this operation will not be evaluated as being an output of
- * the ExecutionSystem.
+ * Default behavior if not overridden, this operation will not be evaluated as being an output
+ * of the ExecutionSystem.
*
* \see ExecutionSystem
* \ingroup check
@@ -174,11 +340,6 @@ class NodeOperation : public SocketReader {
return false;
}
- virtual int isSingleThreaded()
- {
- return false;
- }
-
void setbNodeTree(const bNodeTree *tree)
{
this->m_btree = tree;
@@ -241,62 +402,19 @@ class NodeOperation : public SocketReader {
}
virtual void deinitExecution();
- bool isResolutionSet()
- {
- return this->m_isResolutionSet;
- }
-
/**
* \brief set the resolution
* \param resolution: the resolution to set
*/
void setResolution(unsigned int resolution[2])
{
- if (!isResolutionSet()) {
+ if (!this->flags.is_resolution_set) {
this->m_width = resolution[0];
this->m_height = resolution[1];
- this->m_isResolutionSet = true;
+ this->flags.is_resolution_set = true;
}
}
- void getConnectedInputSockets(Inputs *sockets);
-
- /**
- * \brief is this operation complex
- *
- * Complex operations are typically doing many reads to calculate the output of a single pixel.
- * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
- */
- bool isComplex() const
- {
- return this->m_complex;
- }
-
- virtual bool isSetOperation() const
- {
- return false;
- }
-
- /**
- * \brief is this operation of type ReadBufferOperation
- * \return [true:false]
- * \see ReadBufferOperation
- */
- virtual bool isReadBufferOperation() const
- {
- return false;
- }
-
- /**
- * \brief is this operation of type WriteBufferOperation
- * \return [true:false]
- * \see WriteBufferOperation
- */
- virtual bool isWriteBufferOperation() const
- {
- return false;
- }
-
/**
* \brief is this operation the active viewer output
* user can select an ViewerNode to be active
@@ -314,8 +432,8 @@ class NodeOperation : public SocketReader {
rcti *output);
/**
- * \brief set the index of the input socket that will determine the resolution of this operation
- * \param index: the index to set
+ * \brief set the index of the input socket that will determine the resolution of this
+ * operation \param index: the index to set
*/
void setResolutionInputSocketIndex(unsigned int index);
@@ -329,65 +447,81 @@ class NodeOperation : public SocketReader {
return CompositorPriority::Low;
}
- /**
- * \brief can this NodeOperation be scheduled on an OpenCLDevice
- * \see WorkScheduler.schedule
- * \see ExecutionGroup.addOperation
- */
- bool isOpenCL() const
+ inline bool isBraked() const
{
- return this->m_openCL;
+ return this->m_btree->test_break(this->m_btree->tbh);
}
- virtual bool isViewerOperation() const
+ inline void updateDraw()
{
- return false;
+ if (this->m_btree->update_draw) {
+ this->m_btree->update_draw(this->m_btree->udh);
+ }
}
- virtual bool isPreviewOperation() const
+
+ unsigned int getWidth() const
{
- return false;
+ return m_width;
}
- virtual bool isFileOutputOperation() const
+
+ unsigned int getHeight() const
{
- return false;
+ return m_height;
}
- virtual bool isProxyOperation() const
+
+ inline void readSampled(float result[4], float x, float y, PixelSampler sampler)
{
- return false;
+ executePixelSampled(result, x, y, sampler);
}
- virtual bool useDatatypeConversion() const
+ inline void readFiltered(float result[4], float x, float y, float dx[2], float dy[2])
{
- return true;
+ executePixelFiltered(result, x, y, dx, dy);
}
- inline bool isBraked() const
+ inline void read(float result[4], int x, int y, void *chunkData)
{
- return this->m_btree->test_break(this->m_btree->tbh);
+ executePixel(result, x, y, chunkData);
}
- inline void updateDraw()
+ virtual void *initializeTileData(rcti * /*rect*/)
+ {
+ return 0;
+ }
+
+ virtual void deinitializeTileData(rcti * /*rect*/, void * /*data*/)
{
- if (this->m_btree->update_draw) {
- this->m_btree->update_draw(this->m_btree->udh);
- }
+ }
+
+ virtual MemoryBuffer *getInputMemoryBuffer(MemoryBuffer ** /*memoryBuffers*/)
+ {
+ return 0;
+ }
+
+ /**
+ * Return the meta data associated with this branch.
+ *
+ * The return parameter holds an instance or is an nullptr. */
+ virtual std::unique_ptr<MetaData> getMetaData()
+ {
+ return std::unique_ptr<MetaData>();
}
protected:
NodeOperation();
- void addInputSocket(DataType datatype, InputResizeMode resize_mode = COM_SC_CENTER);
+ void addInputSocket(DataType datatype, ResizeMode resize_mode = ResizeMode::Center);
void addOutputSocket(DataType datatype);
void setWidth(unsigned int width)
{
this->m_width = width;
- this->m_isResolutionSet = true;
+ this->flags.is_resolution_set = true;
}
void setHeight(unsigned int height)
{
this->m_height = height;
- this->m_isResolutionSet = true;
+ this->flags.is_resolution_set = true;
}
SocketReader *getInputSocketReader(unsigned int inputSocketindex);
NodeOperation *getInputOperation(unsigned int inputSocketindex);
@@ -405,114 +539,59 @@ class NodeOperation : public SocketReader {
*/
void setComplex(bool complex)
{
- this->m_complex = complex;
+ this->flags.complex = complex;
}
/**
- * \brief set if this NodeOperation can be scheduled on a OpenCLDevice
+ * \brief calculate a single pixel
+ * \note this method is called for non-complex
+ * \param result: is a float[4] array to store the result
+ * \param x: the x-coordinate of the pixel to calculate in image space
+ * \param y: the y-coordinate of the pixel to calculate in image space
+ * \param inputBuffers: chunks that can be read by their ReadBufferOperation.
*/
- void setOpenCL(bool openCL)
+ virtual void executePixelSampled(float /*output*/[4],
+ float /*x*/,
+ float /*y*/,
+ PixelSampler /*sampler*/)
{
- this->m_openCL = openCL;
}
- /* allow the DebugInfo class to look at internals */
- friend class DebugInfo;
-
-#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
-#endif
-};
-
-class NodeOperationInput {
- private:
- NodeOperation *m_operation;
-
- /** Datatype of this socket. Is used for automatically data transformation.
- * \section data-conversion
+ /**
+ * \brief calculate a single pixel
+ * \note this method is called for complex
+ * \param result: is a float[4] array to store the result
+ * \param x: the x-coordinate of the pixel to calculate in image space
+ * \param y: the y-coordinate of the pixel to calculate in image space
+ * \param inputBuffers: chunks that can be read by their ReadBufferOperation.
+ * \param chunkData: chunk specific data a during execution time.
*/
- DataType m_datatype;
-
- /** Resize mode of this socket */
- InputResizeMode m_resizeMode;
-
- /** Connected output */
- NodeOperationOutput *m_link;
-
- public:
- NodeOperationInput(NodeOperation *op,
- DataType datatype,
- InputResizeMode resizeMode = COM_SC_CENTER);
-
- NodeOperation &getOperation() const
- {
- return *m_operation;
- }
- DataType getDataType() const
- {
- return m_datatype;
- }
-
- void setLink(NodeOperationOutput *link)
- {
- m_link = link;
- }
- NodeOperationOutput *getLink() const
- {
- return m_link;
- }
- bool isConnected() const
- {
- return m_link;
- }
-
- void setResizeMode(InputResizeMode resizeMode)
- {
- this->m_resizeMode = resizeMode;
- }
- InputResizeMode getResizeMode() const
+ virtual void executePixel(float output[4], int x, int y, void * /*chunkData*/)
{
- return this->m_resizeMode;
+ executePixelSampled(output, x, y, PixelSampler::Nearest);
}
- SocketReader *getReader();
-
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
-
-#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
-#endif
-};
-
-class NodeOperationOutput {
- private:
- NodeOperation *m_operation;
-
- /** Datatype of this socket. Is used for automatically data transformation.
- * \section data-conversion
+ /**
+ * \brief calculate a single pixel using an EWA filter
+ * \note this method is called for complex
+ * \param result: is a float[4] array to store the result
+ * \param x: the x-coordinate of the pixel to calculate in image space
+ * \param y: the y-coordinate of the pixel to calculate in image space
+ * \param dx:
+ * \param dy:
+ * \param inputBuffers: chunks that can be read by their ReadBufferOperation.
*/
- DataType m_datatype;
-
- public:
- NodeOperationOutput(NodeOperation *op, DataType datatype);
-
- NodeOperation &getOperation() const
+ virtual void executePixelFiltered(
+ float /*output*/[4], float /*x*/, float /*y*/, float /*dx*/[2], float /*dy*/[2])
{
- return *m_operation;
- }
- DataType getDataType() const
- {
- return m_datatype;
}
- /**
- * \brief determine the resolution of this data going through this socket
- * \param resolution: the result of this operation
- * \param preferredResolution: the preferable resolution as no resolution could be determined
- */
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ /* allow the DebugInfo class to look at internals */
+ friend class DebugInfo;
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
#endif
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cc b/source/blender/compositor/intern/COM_NodeOperationBuilder.cc
index 1c741283c7b..fdd48da3fb4 100644
--- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cc
+++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cc
@@ -38,6 +38,8 @@
#include "COM_NodeOperationBuilder.h" /* own include */
+namespace blender::compositor {
+
NodeOperationBuilder::NodeOperationBuilder(const CompositorContext *context, bNodeTree *b_nodetree)
: m_context(context), m_current_node(nullptr), m_active_viewer(nullptr)
{
@@ -53,9 +55,7 @@ void NodeOperationBuilder::convertToOperations(ExecutionSystem *system)
/* interface handle for nodes */
NodeConverter converter(this);
- for (int index = 0; index < m_graph.nodes().size(); index++) {
- Node *node = (Node *)m_graph.nodes()[index];
-
+ for (Node *node : m_graph.nodes()) {
m_current_node = node;
DebugInfo::node_to_operations(node);
@@ -256,7 +256,8 @@ void NodeOperationBuilder::add_datatype_conversions()
/* proxy operations can skip data type conversion */
NodeOperation *from_op = &link.from()->getOperation();
NodeOperation *to_op = &link.to()->getOperation();
- if (!(from_op->useDatatypeConversion() || to_op->useDatatypeConversion())) {
+ if (!(from_op->get_flags().use_datatype_conversion ||
+ to_op->get_flags().use_datatype_conversion)) {
continue;
}
@@ -352,8 +353,8 @@ void NodeOperationBuilder::resolve_proxies()
blender::Vector<Link> proxy_links;
for (const Link &link : m_links) {
/* don't replace links from proxy to proxy, since we may need them for replacing others! */
- if (link.from()->getOperation().isProxyOperation() &&
- !link.to()->getOperation().isProxyOperation()) {
+ if (link.from()->getOperation().get_flags().is_proxy_operation &&
+ !link.to()->getOperation().get_flags().is_proxy_operation) {
proxy_links.append(link);
}
}
@@ -364,7 +365,7 @@ void NodeOperationBuilder::resolve_proxies()
do {
/* walk upstream bypassing the proxy operation */
from = from->getOperation().getInputSocket(0)->getLink();
- } while (from && from->getOperation().isProxyOperation());
+ } while (from && from->getOperation().get_flags().is_proxy_operation);
removeInputLink(to);
/* we may not have a final proxy input link,
@@ -380,7 +381,7 @@ void NodeOperationBuilder::determineResolutions()
{
/* determine all resolutions of the operations (Width/Height) */
for (NodeOperation *op : m_operations) {
- if (op->isOutputOperation(m_context->isRendering()) && !op->isPreviewOperation()) {
+ if (op->isOutputOperation(m_context->isRendering()) && !op->get_flags().is_preview_operation) {
unsigned int resolution[2] = {0, 0};
unsigned int preferredResolution[2] = {0, 0};
op->determineResolution(resolution, preferredResolution);
@@ -389,7 +390,7 @@ void NodeOperationBuilder::determineResolutions()
}
for (NodeOperation *op : m_operations) {
- if (op->isOutputOperation(m_context->isRendering()) && op->isPreviewOperation()) {
+ if (op->isOutputOperation(m_context->isRendering()) && op->get_flags().is_preview_operation) {
unsigned int resolution[2] = {0, 0};
unsigned int preferredResolution[2] = {0, 0};
op->determineResolution(resolution, preferredResolution);
@@ -401,7 +402,7 @@ void NodeOperationBuilder::determineResolutions()
{
blender::Vector<Link> convert_links;
for (const Link &link : m_links) {
- if (link.to()->getResizeMode() != COM_SC_NO_RESIZE) {
+ if (link.to()->getResizeMode() != ResizeMode::None) {
NodeOperation &from_op = link.from()->getOperation();
NodeOperation &to_op = link.to()->getOperation();
if (from_op.getWidth() != to_op.getWidth() || from_op.getHeight() != to_op.getHeight()) {
@@ -433,7 +434,7 @@ WriteBufferOperation *NodeOperationBuilder::find_attached_write_buffer_operation
for (const Link &link : m_links) {
if (link.from() == output) {
NodeOperation &op = link.to()->getOperation();
- if (op.isWriteBufferOperation()) {
+ if (op.get_flags().is_write_buffer_operation) {
return (WriteBufferOperation *)(&op);
}
}
@@ -449,7 +450,7 @@ void NodeOperationBuilder::add_input_buffers(NodeOperation * /*operation*/,
}
NodeOperationOutput *output = input->getLink();
- if (output->getOperation().isReadBufferOperation()) {
+ if (output->getOperation().get_flags().is_read_buffer_operation) {
/* input is already buffered, no need to add another */
return;
}
@@ -491,7 +492,7 @@ void NodeOperationBuilder::add_output_buffers(NodeOperation *operation,
WriteBufferOperation *writeOperation = nullptr;
for (NodeOperationInput *target : targets) {
/* try to find existing write buffer operation */
- if (target->getOperation().isWriteBufferOperation()) {
+ if (target->getOperation().get_flags().is_write_buffer_operation) {
BLI_assert(writeOperation == nullptr); /* there should only be one write op connected */
writeOperation = (WriteBufferOperation *)(&target->getOperation());
}
@@ -536,7 +537,7 @@ void NodeOperationBuilder::add_complex_operation_buffers()
*/
blender::Vector<NodeOperation *> complex_ops;
for (NodeOperation *operation : m_operations) {
- if (operation->isComplex()) {
+ if (operation->get_flags().complex) {
complex_ops.append(operation);
}
}
@@ -571,7 +572,7 @@ static void find_reachable_operations_recursive(Tags &reachable, NodeOperation *
}
/* associated write-buffer operations are executed as well */
- if (op->isReadBufferOperation()) {
+ if (op->get_flags().is_read_buffer_operation) {
ReadBufferOperation *read_op = (ReadBufferOperation *)op;
MemoryProxy *memproxy = read_op->getMemoryProxy();
find_reachable_operations_recursive(reachable, memproxy->getWriteBufferOperation());
@@ -675,7 +676,7 @@ void NodeOperationBuilder::group_operations()
}
/* add new groups for associated memory proxies where needed */
- if (op->isReadBufferOperation()) {
+ if (op->get_flags().is_read_buffer_operation) {
ReadBufferOperation *read_op = (ReadBufferOperation *)op;
MemoryProxy *memproxy = read_op->getMemoryProxy();
@@ -686,3 +687,5 @@ void NodeOperationBuilder::group_operations()
}
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.h b/source/blender/compositor/intern/COM_NodeOperationBuilder.h
index 8f55574fa88..8e5ec58c3be 100644
--- a/source/blender/compositor/intern/COM_NodeOperationBuilder.h
+++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.h
@@ -24,6 +24,8 @@
#include "COM_NodeGraph.h"
+namespace blender::compositor {
+
class CompositorContext;
class Node;
@@ -157,3 +159,5 @@ class NodeOperationBuilder {
MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeCompilerImpl")
#endif
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cc b/source/blender/compositor/intern/COM_OpenCLDevice.cc
index 9a6012e5c68..b96dbe91434 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.cc
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.cc
@@ -19,6 +19,8 @@
#include "COM_OpenCLDevice.h"
#include "COM_WorkScheduler.h"
+namespace blender::compositor {
+
enum COM_VendorID { NVIDIA = 0x10DE, AMD = 0x1002 };
const cl_image_format IMAGE_FORMAT_COLOR = {
CL_RGBA,
@@ -43,34 +45,28 @@ OpenCLDevice::OpenCLDevice(cl_context context,
this->m_program = program;
this->m_queue = nullptr;
this->m_vendorID = vendorId;
-}
-bool OpenCLDevice::initialize()
-{
cl_int error;
this->m_queue = clCreateCommandQueue(this->m_context, this->m_device, 0, &error);
- return false;
}
-void OpenCLDevice::deinitialize()
+OpenCLDevice::~OpenCLDevice()
{
if (this->m_queue) {
clReleaseCommandQueue(this->m_queue);
}
}
-void OpenCLDevice::execute(WorkPackage *work)
+void OpenCLDevice::execute(WorkPackage *work_package)
{
- const unsigned int chunkNumber = work->chunk_number;
- ExecutionGroup *executionGroup = work->execution_group;
- rcti rect;
+ const unsigned int chunkNumber = work_package->chunk_number;
+ ExecutionGroup *executionGroup = work_package->execution_group;
- executionGroup->determineChunkRect(&rect, chunkNumber);
MemoryBuffer **inputBuffers = executionGroup->getInputBuffersOpenCL(chunkNumber);
- MemoryBuffer *outputBuffer = executionGroup->allocateOutputBuffer(rect);
+ MemoryBuffer *outputBuffer = executionGroup->allocateOutputBuffer(work_package->rect);
executionGroup->getOutputOperation()->executeOpenCLRegion(
- this, &rect, chunkNumber, inputBuffers, outputBuffer);
+ this, &work_package->rect, chunkNumber, inputBuffers, outputBuffer);
delete outputBuffer;
@@ -274,3 +270,5 @@ cl_kernel OpenCLDevice::COM_clCreateKernel(const char *kernelname,
}
return kernel;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.h b/source/blender/compositor/intern/COM_OpenCLDevice.h
index e4fd397b4e8..355451cef68 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.h
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.h
@@ -25,6 +25,8 @@ class OpenCLDevice;
#include "COM_WorkScheduler.h"
#include "clew.h"
+namespace blender::compositor {
+
/**
* \brief device representing an GPU OpenCL device.
* an instance of this class represents a single cl_device
@@ -65,26 +67,13 @@ class OpenCLDevice : public Device {
* \param vendorID:
*/
OpenCLDevice(cl_context context, cl_device_id device, cl_program program, cl_int vendorId);
-
- /**
- * \brief initialize the device
- * During initialization the OpenCL cl_command_queue is created
- * the command queue is stored in the field queue.
- * \see queue
- */
- bool initialize();
-
- /**
- * \brief de-initialize the device
- * During de-initialization the command queue is cleared
- */
- void deinitialize();
+ ~OpenCLDevice();
/**
* \brief execute a WorkPackage
* \param work: the WorkPackage to execute
*/
- void execute(WorkPackage *work);
+ void execute(WorkPackage *work) override;
/**
* \brief determine an image format
@@ -130,3 +119,5 @@ class OpenCLDevice : public Device {
NodeOperation *operation);
cl_kernel COM_clCreateKernel(const char *kernelname, std::list<cl_kernel> *clKernelsToCleanUp);
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_SingleThreadedOperation.cc b/source/blender/compositor/intern/COM_SingleThreadedOperation.cc
index 5febf3802de..01be6e1afed 100644
--- a/source/blender/compositor/intern/COM_SingleThreadedOperation.cc
+++ b/source/blender/compositor/intern/COM_SingleThreadedOperation.cc
@@ -18,10 +18,13 @@
#include "COM_SingleThreadedOperation.h"
+namespace blender::compositor {
+
SingleThreadedOperation::SingleThreadedOperation()
{
this->m_cachedInstance = nullptr;
- setComplex(true);
+ flags.complex = true;
+ flags.single_threaded = true;
}
void SingleThreadedOperation::initExecution()
@@ -56,3 +59,5 @@ void *SingleThreadedOperation::initializeTileData(rcti *rect)
unlockMutex();
return this->m_cachedInstance;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_SingleThreadedOperation.h b/source/blender/compositor/intern/COM_SingleThreadedOperation.h
index 32f4515cf2a..9945f938ff9 100644
--- a/source/blender/compositor/intern/COM_SingleThreadedOperation.h
+++ b/source/blender/compositor/intern/COM_SingleThreadedOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class SingleThreadedOperation : public NodeOperation {
private:
MemoryBuffer *m_cachedInstance;
@@ -36,24 +38,21 @@ class SingleThreadedOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
virtual MemoryBuffer *createMemoryBuffer(rcti *rect) = 0;
-
- int isSingleThreaded()
- {
- return true;
- }
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_SocketReader.h b/source/blender/compositor/intern/COM_SocketReader.h
deleted file mode 100644
index 7c4132efe60..00000000000
--- a/source/blender/compositor/intern/COM_SocketReader.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 2011, Blender Foundation.
- */
-
-#pragma once
-
-#include "BLI_rect.h"
-#include "COM_MetaData.h"
-#include "COM_defines.h"
-
-#include <memory>
-#include <optional>
-
-#ifdef WITH_CXX_GUARDEDALLOC
-# include "MEM_guardedalloc.h"
-#endif
-
-typedef enum PixelSampler {
- COM_PS_NEAREST = 0,
- COM_PS_BILINEAR = 1,
- COM_PS_BICUBIC = 2,
-} PixelSampler;
-
-class MemoryBuffer;
-
-/**
- * \brief Helper class for reading socket data.
- * Only use this class for dispatching (un-ary and n-ary) executions.
- * \ingroup Execution
- */
-class SocketReader {
- private:
- protected:
- /**
- * \brief Holds the width of the output of this operation.
- */
- unsigned int m_width;
-
- /**
- * \brief Holds the height of the output of this operation.
- */
- unsigned int m_height;
-
- /**
- * \brief calculate a single pixel
- * \note this method is called for non-complex
- * \param result: is a float[4] array to store the result
- * \param x: the x-coordinate of the pixel to calculate in image space
- * \param y: the y-coordinate of the pixel to calculate in image space
- * \param inputBuffers: chunks that can be read by their ReadBufferOperation.
- */
- virtual void executePixelSampled(float /*output*/[4],
- float /*x*/,
- float /*y*/,
- PixelSampler /*sampler*/)
- {
- }
-
- /**
- * \brief calculate a single pixel
- * \note this method is called for complex
- * \param result: is a float[4] array to store the result
- * \param x: the x-coordinate of the pixel to calculate in image space
- * \param y: the y-coordinate of the pixel to calculate in image space
- * \param inputBuffers: chunks that can be read by their ReadBufferOperation.
- * \param chunkData: chunk specific data a during execution time.
- */
- virtual void executePixel(float output[4], int x, int y, void * /*chunkData*/)
- {
- executePixelSampled(output, x, y, COM_PS_NEAREST);
- }
-
- /**
- * \brief calculate a single pixel using an EWA filter
- * \note this method is called for complex
- * \param result: is a float[4] array to store the result
- * \param x: the x-coordinate of the pixel to calculate in image space
- * \param y: the y-coordinate of the pixel to calculate in image space
- * \param dx:
- * \param dy:
- * \param inputBuffers: chunks that can be read by their ReadBufferOperation.
- */
- virtual void executePixelFiltered(
- float /*output*/[4], float /*x*/, float /*y*/, float /*dx*/[2], float /*dy*/[2])
- {
- }
-
- public:
- inline void readSampled(float result[4], float x, float y, PixelSampler sampler)
- {
- executePixelSampled(result, x, y, sampler);
- }
- inline void read(float result[4], int x, int y, void *chunkData)
- {
- executePixel(result, x, y, chunkData);
- }
- inline void readFiltered(float result[4], float x, float y, float dx[2], float dy[2])
- {
- executePixelFiltered(result, x, y, dx, dy);
- }
-
- virtual void *initializeTileData(rcti * /*rect*/)
- {
- return 0;
- }
- virtual void deinitializeTileData(rcti * /*rect*/, void * /*data*/)
- {
- }
-
- virtual ~SocketReader()
- {
- }
-
- virtual MemoryBuffer *getInputMemoryBuffer(MemoryBuffer ** /*memoryBuffers*/)
- {
- return 0;
- }
-
- inline unsigned int getWidth() const
- {
- return this->m_width;
- }
- inline unsigned int getHeight() const
- {
- return this->m_height;
- }
-
- /* Return the meta data associated with this branch.
- *
- * The return parameter holds an instance or is an nullptr. */
- virtual std::unique_ptr<MetaData> getMetaData() const
- {
- return std::unique_ptr<MetaData>();
- }
-
-#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:SocketReader")
-#endif
-};
diff --git a/source/blender/compositor/intern/COM_WorkPackage.cc b/source/blender/compositor/intern/COM_WorkPackage.cc
index 60684f2c45c..c0bc274da8f 100644
--- a/source/blender/compositor/intern/COM_WorkPackage.cc
+++ b/source/blender/compositor/intern/COM_WorkPackage.cc
@@ -18,8 +18,6 @@
#include "COM_WorkPackage.h"
-WorkPackage::WorkPackage(ExecutionGroup *execution_group, unsigned int chunk_number)
-{
- this->execution_group = execution_group;
- this->chunk_number = chunk_number;
-}
+namespace blender::compositor {
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_WorkPackage.h b/source/blender/compositor/intern/COM_WorkPackage.h
index db5eb3d3072..4541a778711 100644
--- a/source/blender/compositor/intern/COM_WorkPackage.h
+++ b/source/blender/compositor/intern/COM_WorkPackage.h
@@ -18,14 +18,21 @@
#pragma once
+#include "COM_defines.h"
+
+#include "BLI_rect.h"
+
+namespace blender::compositor {
+// Forward Declarations.
class ExecutionGroup;
-#include "COM_ExecutionGroup.h"
/**
* \brief contains data about work that can be scheduled
* \see WorkScheduler
*/
struct WorkPackage {
+ eChunkExecutionState state = eChunkExecutionState::NotScheduled;
+
/**
* \brief executionGroup with the operations-setup to be evaluated
*/
@@ -37,13 +44,13 @@ struct WorkPackage {
unsigned int chunk_number;
/**
- * constructor
- * \param group: the ExecutionGroup
- * \param chunk_number: the number of the chunk
+ * Area of the execution group that the work package calculates.
*/
- WorkPackage(ExecutionGroup *group, unsigned int chunk_number);
+ rcti rect;
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:WorkPackage")
#endif
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cc b/source/blender/compositor/intern/COM_WorkScheduler.cc
index 56956b9d097..55114e6b72a 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.cc
+++ b/source/blender/compositor/intern/COM_WorkScheduler.cc
@@ -37,6 +37,8 @@
#include "BKE_global.h"
+namespace blender::compositor {
+
enum class ThreadingModel {
/** Everything is executed in the caller thread. easy for debugging. */
SingleThreaded,
@@ -70,7 +72,7 @@ static struct {
/** \brief list of all CPUDevices. for every hardware thread an instance of CPUDevice is
* created
*/
- blender::Vector<CPUDevice *> devices;
+ blender::Vector<CPUDevice> devices;
/** \brief list of all thread for every CPUDevice in cpudevices a thread exists. */
ListBase threads;
@@ -89,7 +91,7 @@ static struct {
cl_program program;
/** \brief list of all OpenCLDevices. for every OpenCL GPU device an instance of OpenCLDevice
* is created. */
- blender::Vector<OpenCLDevice *> devices;
+ blender::Vector<OpenCLDevice> devices;
/** \brief list of all thread for every GPUDevice in cpudevices a thread exists. */
ListBase threads;
/** \brief all scheduled work for the GPU. */
@@ -117,7 +119,6 @@ static void *thread_execute_gpu(void *data)
while ((work = (WorkPackage *)BLI_thread_queue_pop(g_work_scheduler.opencl.queue))) {
device->execute(work);
- delete work;
}
return nullptr;
@@ -130,9 +131,8 @@ static void opencl_start(CompositorContext &context)
BLI_threadpool_init(&g_work_scheduler.opencl.threads,
thread_execute_gpu,
g_work_scheduler.opencl.devices.size());
- for (int index = 0; index < g_work_scheduler.opencl.devices.size(); index++) {
- Device *device = g_work_scheduler.opencl.devices[index];
- BLI_threadpool_insert(&g_work_scheduler.opencl.threads, device);
+ for (Device &device : g_work_scheduler.opencl.devices) {
+ BLI_threadpool_insert(&g_work_scheduler.opencl.threads, &device);
}
g_work_scheduler.opencl.active = true;
}
@@ -143,7 +143,7 @@ static void opencl_start(CompositorContext &context)
static bool opencl_schedule(WorkPackage *package)
{
- if (package->execution_group->isOpenCL() && g_work_scheduler.opencl.active) {
+ if (package->execution_group->get_flags().open_cl && g_work_scheduler.opencl.active) {
BLI_thread_queue_push(g_work_scheduler.opencl.queue, package);
return true;
}
@@ -263,12 +263,10 @@ static void opencl_initialize(const bool use_opencl)
if (error2 != CL_SUCCESS) {
printf("CLERROR[%d]: %s\n", error2, clewErrorString(error2));
}
- OpenCLDevice *clDevice = new OpenCLDevice(g_work_scheduler.opencl.context,
- device,
- g_work_scheduler.opencl.program,
- vendorID);
- clDevice->initialize();
- g_work_scheduler.opencl.devices.append(clDevice);
+ g_work_scheduler.opencl.devices.append(OpenCLDevice(g_work_scheduler.opencl.context,
+ device,
+ g_work_scheduler.opencl.program,
+ vendorID));
}
}
MEM_freeN(cldevices);
@@ -282,26 +280,19 @@ static void opencl_initialize(const bool use_opencl)
static void opencl_deinitialize()
{
- /* Deinitialize OpenCL GPU's. */
- if (g_work_scheduler.opencl.initialized) {
- while (!g_work_scheduler.opencl.devices.is_empty()) {
- Device *device = g_work_scheduler.opencl.devices.pop_last();
- device->deinitialize();
- delete device;
- }
- g_work_scheduler.opencl.devices.clear_and_make_inline();
+ g_work_scheduler.opencl.devices.clear_and_make_inline();
- if (g_work_scheduler.opencl.program) {
- clReleaseProgram(g_work_scheduler.opencl.program);
- g_work_scheduler.opencl.program = nullptr;
- }
- if (g_work_scheduler.opencl.context) {
- clReleaseContext(g_work_scheduler.opencl.context);
- g_work_scheduler.opencl.context = nullptr;
- }
+ if (g_work_scheduler.opencl.program) {
+ clReleaseProgram(g_work_scheduler.opencl.program);
+ g_work_scheduler.opencl.program = nullptr;
+ }
- g_work_scheduler.opencl.initialized = false;
+ if (g_work_scheduler.opencl.context) {
+ clReleaseContext(g_work_scheduler.opencl.context);
+ g_work_scheduler.opencl.context = nullptr;
}
+
+ g_work_scheduler.opencl.initialized = false;
}
/* \} */
@@ -314,7 +305,6 @@ static void threading_model_single_thread_execute(WorkPackage *package)
{
CPUDevice device(0);
device.execute(package);
- delete package;
}
/* \} */
@@ -330,7 +320,6 @@ static void *threading_model_queue_execute(void *data)
BLI_thread_local_set(g_thread_device, device);
while ((work = (WorkPackage *)BLI_thread_queue_pop(g_work_scheduler.queue.queue))) {
device->execute(work);
- delete work;
}
return nullptr;
@@ -347,9 +336,8 @@ static void threading_model_queue_start()
BLI_threadpool_init(&g_work_scheduler.queue.threads,
threading_model_queue_execute,
g_work_scheduler.queue.devices.size());
- for (int index = 0; index < g_work_scheduler.queue.devices.size(); index++) {
- Device *device = g_work_scheduler.queue.devices[index];
- BLI_threadpool_insert(&g_work_scheduler.queue.threads, device);
+ for (Device &device : g_work_scheduler.queue.devices) {
+ BLI_threadpool_insert(&g_work_scheduler.queue.threads, &device);
}
}
@@ -370,25 +358,17 @@ static void threading_model_queue_initialize(const int num_cpu_threads)
{
/* Reinitialize if number of threads doesn't match. */
if (g_work_scheduler.queue.devices.size() != num_cpu_threads) {
- Device *device;
-
- while (!g_work_scheduler.queue.devices.is_empty()) {
- device = g_work_scheduler.queue.devices.pop_last();
- device->deinitialize();
- delete device;
- }
+ g_work_scheduler.queue.devices.clear();
if (g_work_scheduler.queue.initialized) {
BLI_thread_local_delete(g_thread_device);
+ g_work_scheduler.queue.initialized = false;
}
- g_work_scheduler.queue.initialized = false;
}
/* Initialize CPU threads. */
if (!g_work_scheduler.queue.initialized) {
for (int index = 0; index < num_cpu_threads; index++) {
- CPUDevice *device = new CPUDevice(index);
- device->initialize();
- g_work_scheduler.queue.devices.append(device);
+ g_work_scheduler.queue.devices.append(CPUDevice(index));
}
BLI_thread_local_create(g_thread_device);
g_work_scheduler.queue.initialized = true;
@@ -398,11 +378,6 @@ static void threading_model_queue_deinitialize()
{
/* deinitialize CPU threads */
if (g_work_scheduler.queue.initialized) {
- while (!g_work_scheduler.queue.devices.is_empty()) {
- Device *device = g_work_scheduler.queue.devices.pop_last();
- device->deinitialize();
- delete device;
- }
g_work_scheduler.queue.devices.clear_and_make_inline();
BLI_thread_local_delete(g_thread_device);
@@ -455,10 +430,8 @@ static void threading_model_task_stop()
/** \name Public API
* \{ */
-void WorkScheduler::schedule(ExecutionGroup *group, int chunkNumber)
+void WorkScheduler::schedule(WorkPackage *package)
{
- WorkPackage *package = new WorkPackage(group, chunkNumber);
-
if (COM_is_opencl_enabled()) {
if (opencl_schedule(package)) {
return;
@@ -607,3 +580,5 @@ int WorkScheduler::current_thread_id()
}
/* \} */
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.h b/source/blender/compositor/intern/COM_WorkScheduler.h
index 6b53cc3efd6..85b1d7e2ebf 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.h
+++ b/source/blender/compositor/intern/COM_WorkScheduler.h
@@ -24,6 +24,8 @@
#include "COM_WorkPackage.h"
#include "COM_defines.h"
+namespace blender::compositor {
+
/** \brief the workscheduler
* \ingroup execution
*/
@@ -31,13 +33,11 @@ struct WorkScheduler {
/**
* \brief schedule a chunk of a group to be calculated.
* An execution group schedules a chunk in the WorkScheduler
- * when ExecutionGroup.isOpenCL is set the work will be handled by a OpenCLDevice
+ * when ExecutionGroup.get_flags().open_cl is set the work will be handled by a OpenCLDevice
* otherwise the work is scheduled for an CPUDevice
* \see ExecutionGroup.execute
- * \param group: the execution group
- * \param chunkNumber: the number of the chunk in the group to be executed
*/
- static void schedule(ExecutionGroup *group, int chunkNumber);
+ static void schedule(WorkPackage *package);
/**
* \brief initialize the WorkScheduler
@@ -93,3 +93,5 @@ struct WorkScheduler {
MEM_CXX_CLASS_ALLOC_FUNCS("COM:WorkScheduler")
#endif
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/intern/COM_compositor.cc b/source/blender/compositor/intern/COM_compositor.cc
index 68e4f80f91f..5839f53976b 100644
--- a/source/blender/compositor/intern/COM_compositor.cc
+++ b/source/blender/compositor/intern/COM_compositor.cc
@@ -46,12 +46,12 @@ static void compositor_init_node_previews(const RenderData *render_data, bNodeTr
1.0f;
int preview_width, preview_height;
if (aspect < 1.0f) {
- preview_width = COM_PREVIEW_SIZE;
- preview_height = (int)(COM_PREVIEW_SIZE * aspect);
+ preview_width = blender::compositor::COM_PREVIEW_SIZE;
+ preview_height = (int)(blender::compositor::COM_PREVIEW_SIZE * aspect);
}
else {
- preview_width = (int)(COM_PREVIEW_SIZE / aspect);
- preview_height = COM_PREVIEW_SIZE;
+ preview_width = (int)(blender::compositor::COM_PREVIEW_SIZE / aspect);
+ preview_height = blender::compositor::COM_PREVIEW_SIZE;
}
BKE_node_preview_init_tree(node_tree, preview_width, preview_height, false);
}
@@ -92,12 +92,12 @@ void COM_execute(RenderData *render_data,
/* Initialize workscheduler. */
const bool use_opencl = (node_tree->flag & NTREE_COM_OPENCL) != 0;
- WorkScheduler::initialize(use_opencl, BKE_render_num_threads(render_data));
+ blender::compositor::WorkScheduler::initialize(use_opencl, BKE_render_num_threads(render_data));
/* Execute. */
const bool twopass = (node_tree->flag & NTREE_TWO_PASS) && !rendering;
if (twopass) {
- ExecutionSystem fast_pass(
+ blender::compositor::ExecutionSystem fast_pass(
render_data, scene, node_tree, rendering, true, viewSettings, displaySettings, viewName);
fast_pass.execute();
@@ -107,7 +107,7 @@ void COM_execute(RenderData *render_data,
}
}
- ExecutionSystem system(
+ blender::compositor::ExecutionSystem system(
render_data, scene, node_tree, rendering, false, viewSettings, displaySettings, viewName);
system.execute();
@@ -118,7 +118,7 @@ void COM_deinitialize()
{
if (g_compositor.is_initialized) {
BLI_mutex_lock(&g_compositor.mutex);
- WorkScheduler::deinitialize();
+ blender::compositor::WorkScheduler::deinitialize();
g_compositor.is_initialized = false;
BLI_mutex_unlock(&g_compositor.mutex);
BLI_mutex_end(&g_compositor.mutex);
diff --git a/source/blender/compositor/nodes/COM_AlphaOverNode.cc b/source/blender/compositor/nodes/COM_AlphaOverNode.cc
index 640fbf49808..5e09902aee2 100644
--- a/source/blender/compositor/nodes/COM_AlphaOverNode.cc
+++ b/source/blender/compositor/nodes/COM_AlphaOverNode.cc
@@ -26,6 +26,8 @@
#include "COM_SetValueOperation.h"
#include "DNA_material_types.h" /* the ramp types */
+namespace blender::compositor {
+
void AlphaOverNode::convertToOperations(NodeConverter &converter,
const CompositorContext & /*context*/) const
{
@@ -64,3 +66,5 @@ void AlphaOverNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(2), convertProg->getInputSocket(2));
converter.mapOutputSocket(getOutputSocket(0), convertProg->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_AlphaOverNode.h b/source/blender/compositor/nodes/COM_AlphaOverNode.h
index 32cd2e20204..201c8ed5b6e 100644
--- a/source/blender/compositor/nodes/COM_AlphaOverNode.h
+++ b/source/blender/compositor/nodes/COM_AlphaOverNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief AlphaOverNode
* \ingroup Node
@@ -29,5 +31,8 @@ class AlphaOverNode : public Node {
AlphaOverNode(bNode *editorNode) : Node(editorNode)
{
}
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_AntiAliasingNode.cc b/source/blender/compositor/nodes/COM_AntiAliasingNode.cc
new file mode 100644
index 00000000000..af4832665df
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_AntiAliasingNode.cc
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2017, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor: IRIE Shinsuke
+ */
+
+#include "COM_AntiAliasingNode.h"
+#include "COM_SMAAOperation.h"
+#include "DNA_node_types.h"
+
+namespace blender::compositor {
+
+void AntiAliasingNode::convertToOperations(NodeConverter &converter,
+ const CompositorContext & /*context*/) const
+{
+ bNode *node = this->getbNode();
+ NodeAntiAliasingData *data = (NodeAntiAliasingData *)node->storage;
+
+ /* Edge Detection (First Pass) */
+ SMAAEdgeDetectionOperation *operation1 = nullptr;
+
+ operation1 = new SMAAEdgeDetectionOperation();
+ operation1->setThreshold(data->threshold);
+ operation1->setLocalContrastAdaptationFactor(data->contrast_limit);
+ converter.addOperation(operation1);
+
+ converter.mapInputSocket(getInputSocket(0), operation1->getInputSocket(0));
+
+ /* Blending Weight Calculation Pixel Shader (Second Pass) */
+ SMAABlendingWeightCalculationOperation *operation2 =
+ new SMAABlendingWeightCalculationOperation();
+ operation2->setCornerRounding(data->corner_rounding);
+ converter.addOperation(operation2);
+
+ converter.addLink(operation1->getOutputSocket(), operation2->getInputSocket(0));
+
+ /* Neighborhood Blending Pixel Shader (Third Pass) */
+ SMAANeighborhoodBlendingOperation *operation3 = new SMAANeighborhoodBlendingOperation();
+ converter.addOperation(operation3);
+
+ converter.mapInputSocket(getInputSocket(0), operation3->getInputSocket(0));
+ converter.addLink(operation2->getOutputSocket(), operation3->getInputSocket(1));
+ converter.mapOutputSocket(getOutputSocket(0), operation3->getOutputSocket());
+}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_AntiAliasingNode.h b/source/blender/compositor/nodes/COM_AntiAliasingNode.h
new file mode 100644
index 00000000000..d4a6d0d26dc
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_AntiAliasingNode.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor: IRIE Shinsuke
+ */
+
+#pragma once
+
+#include "COM_Node.h"
+
+namespace blender::compositor {
+
+/**
+ * @brief AntiAliasingNode
+ * @ingroup Node
+ */
+class AntiAliasingNode : public Node {
+ public:
+ AntiAliasingNode(bNode *editorNode) : Node(editorNode)
+ {
+ }
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
+};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_BilateralBlurNode.cc b/source/blender/compositor/nodes/COM_BilateralBlurNode.cc
index e8037f923f2..1b9da789d3c 100644
--- a/source/blender/compositor/nodes/COM_BilateralBlurNode.cc
+++ b/source/blender/compositor/nodes/COM_BilateralBlurNode.cc
@@ -21,6 +21,8 @@
#include "COM_ExecutionSystem.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
BilateralBlurNode::BilateralBlurNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -39,3 +41,5 @@ void BilateralBlurNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_BilateralBlurNode.h b/source/blender/compositor/nodes/COM_BilateralBlurNode.h
index 39308c7d1b6..fed2612ac02 100644
--- a/source/blender/compositor/nodes/COM_BilateralBlurNode.h
+++ b/source/blender/compositor/nodes/COM_BilateralBlurNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief BilateralBlurNode
* \ingroup Node
@@ -27,5 +29,8 @@
class BilateralBlurNode : public Node {
public:
BilateralBlurNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_BlurNode.cc b/source/blender/compositor/nodes/COM_BlurNode.cc
index b82bede8443..e55a594b9c0 100644
--- a/source/blender/compositor/nodes/COM_BlurNode.cc
+++ b/source/blender/compositor/nodes/COM_BlurNode.cc
@@ -29,6 +29,8 @@
#include "COM_SetValueOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
BlurNode::BlurNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -168,3 +170,5 @@ void BlurNode::convertToOperations(NodeConverter &converter,
converter.addPreview(output_operation->getOutputSocket());
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_BlurNode.h b/source/blender/compositor/nodes/COM_BlurNode.h
index 3c832c93ca2..61cdc17f3a9 100644
--- a/source/blender/compositor/nodes/COM_BlurNode.h
+++ b/source/blender/compositor/nodes/COM_BlurNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief BlurNode
* \ingroup Node
@@ -27,5 +29,8 @@
class BlurNode : public Node {
public:
BlurNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_BokehBlurNode.cc b/source/blender/compositor/nodes/COM_BokehBlurNode.cc
index 5096dbef608..1d2a0dae390 100644
--- a/source/blender/compositor/nodes/COM_BokehBlurNode.cc
+++ b/source/blender/compositor/nodes/COM_BokehBlurNode.cc
@@ -25,6 +25,8 @@
#include "DNA_node_types.h"
#include "DNA_object_types.h"
+namespace blender::compositor {
+
BokehBlurNode::BokehBlurNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -75,3 +77,5 @@ void BokehBlurNode::convertToOperations(NodeConverter &converter,
}
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_BokehBlurNode.h b/source/blender/compositor/nodes/COM_BokehBlurNode.h
index 87aca9af1f6..2c060936025 100644
--- a/source/blender/compositor/nodes/COM_BokehBlurNode.h
+++ b/source/blender/compositor/nodes/COM_BokehBlurNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief BokehBlurNode
* \ingroup Node
@@ -27,5 +29,8 @@
class BokehBlurNode : public Node {
public:
BokehBlurNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_BokehImageNode.cc b/source/blender/compositor/nodes/COM_BokehImageNode.cc
index 87fe4979c1d..2b0a47c76bc 100644
--- a/source/blender/compositor/nodes/COM_BokehImageNode.cc
+++ b/source/blender/compositor/nodes/COM_BokehImageNode.cc
@@ -20,6 +20,8 @@
#include "COM_BokehImageOperation.h"
#include "COM_ExecutionSystem.h"
+namespace blender::compositor {
+
BokehImageNode::BokehImageNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -36,3 +38,5 @@ void BokehImageNode::convertToOperations(NodeConverter &converter,
converter.addPreview(operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_BokehImageNode.h b/source/blender/compositor/nodes/COM_BokehImageNode.h
index b9d957cd6df..323561a7e4f 100644
--- a/source/blender/compositor/nodes/COM_BokehImageNode.h
+++ b/source/blender/compositor/nodes/COM_BokehImageNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief BokehImageNode
* \ingroup Node
@@ -27,5 +29,8 @@
class BokehImageNode : public Node {
public:
BokehImageNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_BoxMaskNode.cc b/source/blender/compositor/nodes/COM_BoxMaskNode.cc
index fe59bd32939..14f42cc42f7 100644
--- a/source/blender/compositor/nodes/COM_BoxMaskNode.cc
+++ b/source/blender/compositor/nodes/COM_BoxMaskNode.cc
@@ -23,6 +23,8 @@
#include "COM_ScaleOperation.h"
#include "COM_SetValueOperation.h"
+namespace blender::compositor {
+
BoxMaskNode::BoxMaskNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -60,7 +62,7 @@ void BoxMaskNode::convertToOperations(NodeConverter &converter,
scaleOperation->setOffset(0.0f, 0.0f);
scaleOperation->setNewWidth(rd->xsch * render_size_factor);
scaleOperation->setNewHeight(rd->ysch * render_size_factor);
- scaleOperation->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
+ scaleOperation->getInputSocket(0)->setResizeMode(ResizeMode::None);
converter.addOperation(scaleOperation);
converter.addLink(valueOperation->getOutputSocket(0), scaleOperation->getInputSocket(0));
@@ -70,3 +72,5 @@ void BoxMaskNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_BoxMaskNode.h b/source/blender/compositor/nodes/COM_BoxMaskNode.h
index b815fd75284..46cedf7af75 100644
--- a/source/blender/compositor/nodes/COM_BoxMaskNode.h
+++ b/source/blender/compositor/nodes/COM_BoxMaskNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief BoxMaskNode
* \ingroup Node
@@ -27,5 +29,8 @@
class BoxMaskNode : public Node {
public:
BoxMaskNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_BrightnessNode.cc b/source/blender/compositor/nodes/COM_BrightnessNode.cc
index fcd2a6de1f4..b64f1fea99f 100644
--- a/source/blender/compositor/nodes/COM_BrightnessNode.cc
+++ b/source/blender/compositor/nodes/COM_BrightnessNode.cc
@@ -20,6 +20,8 @@
#include "COM_BrightnessOperation.h"
#include "COM_ExecutionSystem.h"
+namespace blender::compositor {
+
BrightnessNode::BrightnessNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -38,3 +40,5 @@ void BrightnessNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(2));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_BrightnessNode.h b/source/blender/compositor/nodes/COM_BrightnessNode.h
index b64b622dd71..1084108b1c3 100644
--- a/source/blender/compositor/nodes/COM_BrightnessNode.h
+++ b/source/blender/compositor/nodes/COM_BrightnessNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief BrightnessNode
* \ingroup Node
@@ -27,5 +29,8 @@
class BrightnessNode : public Node {
public:
BrightnessNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ChannelMatteNode.cc b/source/blender/compositor/nodes/COM_ChannelMatteNode.cc
index 598cd7b7745..d0f72274aea 100644
--- a/source/blender/compositor/nodes/COM_ChannelMatteNode.cc
+++ b/source/blender/compositor/nodes/COM_ChannelMatteNode.cc
@@ -22,6 +22,8 @@
#include "COM_ConvertOperation.h"
#include "COM_SetAlphaMultiplyOperation.h"
+namespace blender::compositor {
+
ChannelMatteNode::ChannelMatteNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -93,3 +95,5 @@ void ChannelMatteNode::convertToOperations(NodeConverter &converter,
converter.addPreview(operationAlpha->getOutputSocket());
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ChannelMatteNode.h b/source/blender/compositor/nodes/COM_ChannelMatteNode.h
index bca821fa60c..46100b3f7ea 100644
--- a/source/blender/compositor/nodes/COM_ChannelMatteNode.h
+++ b/source/blender/compositor/nodes/COM_ChannelMatteNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief ChannelMatteNode
* \ingroup Node
@@ -27,5 +29,8 @@
class ChannelMatteNode : public Node {
public:
ChannelMatteNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ChromaMatteNode.cc b/source/blender/compositor/nodes/COM_ChromaMatteNode.cc
index 83e88b35f92..9abf183a843 100644
--- a/source/blender/compositor/nodes/COM_ChromaMatteNode.cc
+++ b/source/blender/compositor/nodes/COM_ChromaMatteNode.cc
@@ -22,6 +22,8 @@
#include "COM_ConvertOperation.h"
#include "COM_SetAlphaMultiplyOperation.h"
+namespace blender::compositor {
+
ChromaMatteNode::ChromaMatteNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -63,3 +65,5 @@ void ChromaMatteNode::convertToOperations(NodeConverter &converter,
converter.addPreview(operationAlpha->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ChromaMatteNode.h b/source/blender/compositor/nodes/COM_ChromaMatteNode.h
index d8febdde36f..f3ddd013fa4 100644
--- a/source/blender/compositor/nodes/COM_ChromaMatteNode.h
+++ b/source/blender/compositor/nodes/COM_ChromaMatteNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief ChromaMatteNode
* \ingroup Node
@@ -27,5 +29,8 @@
class ChromaMatteNode : public Node {
public:
ChromaMatteNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorBalanceNode.cc b/source/blender/compositor/nodes/COM_ColorBalanceNode.cc
index 596d9631297..03e4e143061 100644
--- a/source/blender/compositor/nodes/COM_ColorBalanceNode.cc
+++ b/source/blender/compositor/nodes/COM_ColorBalanceNode.cc
@@ -23,6 +23,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_MixOperation.h"
+namespace blender::compositor {
+
ColorBalanceNode::ColorBalanceNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -71,3 +73,5 @@ void ColorBalanceNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(inputImageSocket, operation->getInputSocket(1));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorBalanceNode.h b/source/blender/compositor/nodes/COM_ColorBalanceNode.h
index 302b66863ca..243713b4912 100644
--- a/source/blender/compositor/nodes/COM_ColorBalanceNode.h
+++ b/source/blender/compositor/nodes/COM_ColorBalanceNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief ColorBalanceNode
* \ingroup Node
@@ -27,5 +29,8 @@
class ColorBalanceNode : public Node {
public:
ColorBalanceNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorCorrectionNode.cc b/source/blender/compositor/nodes/COM_ColorCorrectionNode.cc
index 92b334fddb9..6397b1d8e4b 100644
--- a/source/blender/compositor/nodes/COM_ColorCorrectionNode.cc
+++ b/source/blender/compositor/nodes/COM_ColorCorrectionNode.cc
@@ -20,6 +20,8 @@
#include "COM_ColorCorrectionOperation.h"
#include "COM_ExecutionSystem.h"
+namespace blender::compositor {
+
ColorCorrectionNode::ColorCorrectionNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -41,3 +43,5 @@ void ColorCorrectionNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorCorrectionNode.h b/source/blender/compositor/nodes/COM_ColorCorrectionNode.h
index be6545f0cfa..aee07ee07a3 100644
--- a/source/blender/compositor/nodes/COM_ColorCorrectionNode.h
+++ b/source/blender/compositor/nodes/COM_ColorCorrectionNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief ColorCorrectionNode
* \ingroup Node
@@ -27,5 +29,8 @@
class ColorCorrectionNode : public Node {
public:
ColorCorrectionNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorCurveNode.cc b/source/blender/compositor/nodes/COM_ColorCurveNode.cc
index e1888f3f0bc..774dd689a46 100644
--- a/source/blender/compositor/nodes/COM_ColorCurveNode.cc
+++ b/source/blender/compositor/nodes/COM_ColorCurveNode.cc
@@ -20,6 +20,8 @@
#include "COM_ColorCurveOperation.h"
#include "COM_ExecutionSystem.h"
+namespace blender::compositor {
+
ColorCurveNode::ColorCurveNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -55,3 +57,5 @@ void ColorCurveNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorCurveNode.h b/source/blender/compositor/nodes/COM_ColorCurveNode.h
index 6eaf1db6fbb..89786b47cf5 100644
--- a/source/blender/compositor/nodes/COM_ColorCurveNode.h
+++ b/source/blender/compositor/nodes/COM_ColorCurveNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief ColorCurveNode
* \ingroup Node
@@ -27,5 +29,8 @@
class ColorCurveNode : public Node {
public:
ColorCurveNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorExposureNode.cc b/source/blender/compositor/nodes/COM_ColorExposureNode.cc
index cd0285ac373..a8f164e6b66 100644
--- a/source/blender/compositor/nodes/COM_ColorExposureNode.cc
+++ b/source/blender/compositor/nodes/COM_ColorExposureNode.cc
@@ -20,6 +20,8 @@
#include "COM_ColorExposureOperation.h"
#include "COM_ExecutionSystem.h"
+namespace blender::compositor {
+
ExposureNode::ExposureNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -35,3 +37,5 @@ void ExposureNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorExposureNode.h b/source/blender/compositor/nodes/COM_ColorExposureNode.h
index c17e798b979..df9bfc65f81 100644
--- a/source/blender/compositor/nodes/COM_ColorExposureNode.h
+++ b/source/blender/compositor/nodes/COM_ColorExposureNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief ExposureNode
* \ingroup Node
@@ -27,5 +29,8 @@
class ExposureNode : public Node {
public:
ExposureNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorMatteNode.cc b/source/blender/compositor/nodes/COM_ColorMatteNode.cc
index 865eee5427f..eadb8ce4f96 100644
--- a/source/blender/compositor/nodes/COM_ColorMatteNode.cc
+++ b/source/blender/compositor/nodes/COM_ColorMatteNode.cc
@@ -22,6 +22,8 @@
#include "COM_ConvertOperation.h"
#include "COM_SetAlphaMultiplyOperation.h"
+namespace blender::compositor {
+
ColorMatteNode::ColorMatteNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -61,3 +63,5 @@ void ColorMatteNode::convertToOperations(NodeConverter &converter,
converter.addPreview(operationAlpha->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorMatteNode.h b/source/blender/compositor/nodes/COM_ColorMatteNode.h
index e84bdfc836f..9d70b6d8416 100644
--- a/source/blender/compositor/nodes/COM_ColorMatteNode.h
+++ b/source/blender/compositor/nodes/COM_ColorMatteNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief ColorMatteNode
* \ingroup Node
@@ -27,5 +29,8 @@
class ColorMatteNode : public Node {
public:
ColorMatteNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorNode.cc b/source/blender/compositor/nodes/COM_ColorNode.cc
index e6f8bfa01fe..f8277645a4b 100644
--- a/source/blender/compositor/nodes/COM_ColorNode.cc
+++ b/source/blender/compositor/nodes/COM_ColorNode.cc
@@ -20,6 +20,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_SetColorOperation.h"
+namespace blender::compositor {
+
ColorNode::ColorNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -37,3 +39,5 @@ void ColorNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(output, operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorNode.h b/source/blender/compositor/nodes/COM_ColorNode.h
index 9b50e9ab7d4..ae3bf575bb4 100644
--- a/source/blender/compositor/nodes/COM_ColorNode.h
+++ b/source/blender/compositor/nodes/COM_ColorNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief ColorNode
* \ingroup Node
@@ -27,5 +29,8 @@
class ColorNode : public Node {
public:
ColorNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorRampNode.cc b/source/blender/compositor/nodes/COM_ColorRampNode.cc
index 1504a76cee7..6b44ef3057e 100644
--- a/source/blender/compositor/nodes/COM_ColorRampNode.cc
+++ b/source/blender/compositor/nodes/COM_ColorRampNode.cc
@@ -23,6 +23,8 @@
#include "COM_ExecutionSystem.h"
#include "DNA_texture_types.h"
+namespace blender::compositor {
+
ColorRampNode::ColorRampNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -50,3 +52,5 @@ void ColorRampNode::convertToOperations(NodeConverter &converter,
converter.addLink(operation->getOutputSocket(), operation2->getInputSocket(0));
converter.mapOutputSocket(outputSocketAlpha, operation2->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorRampNode.h b/source/blender/compositor/nodes/COM_ColorRampNode.h
index b53edf14dbd..d0c0e43d56c 100644
--- a/source/blender/compositor/nodes/COM_ColorRampNode.h
+++ b/source/blender/compositor/nodes/COM_ColorRampNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief ColorRampNode
* \ingroup Node
@@ -27,5 +29,8 @@
class ColorRampNode : public Node {
public:
ColorRampNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorSpillNode.cc b/source/blender/compositor/nodes/COM_ColorSpillNode.cc
index d1a3099e998..119cff93e84 100644
--- a/source/blender/compositor/nodes/COM_ColorSpillNode.cc
+++ b/source/blender/compositor/nodes/COM_ColorSpillNode.cc
@@ -20,6 +20,8 @@
#include "BKE_node.h"
#include "COM_ColorSpillOperation.h"
+namespace blender::compositor {
+
ColorSpillNode::ColorSpillNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -45,3 +47,5 @@ void ColorSpillNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(inputSocketFac, operation->getInputSocket(1));
converter.mapOutputSocket(outputSocketImage, operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorSpillNode.h b/source/blender/compositor/nodes/COM_ColorSpillNode.h
index 3cf8072c7b7..731a76e8811 100644
--- a/source/blender/compositor/nodes/COM_ColorSpillNode.h
+++ b/source/blender/compositor/nodes/COM_ColorSpillNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief ColorSpillNode
* \ingroup Node
@@ -27,5 +29,8 @@
class ColorSpillNode : public Node {
public:
ColorSpillNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorToBWNode.cc b/source/blender/compositor/nodes/COM_ColorToBWNode.cc
index 4115bad5d3f..dcedfc19e4d 100644
--- a/source/blender/compositor/nodes/COM_ColorToBWNode.cc
+++ b/source/blender/compositor/nodes/COM_ColorToBWNode.cc
@@ -21,6 +21,8 @@
#include "COM_ConvertOperation.h"
#include "COM_ExecutionSystem.h"
+namespace blender::compositor {
+
ColorToBWNode::ColorToBWNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -38,3 +40,5 @@ void ColorToBWNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(colorSocket, convertProg->getInputSocket(0));
converter.mapOutputSocket(valueSocket, convertProg->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ColorToBWNode.h b/source/blender/compositor/nodes/COM_ColorToBWNode.h
index 6e7025de496..60c08a3c886 100644
--- a/source/blender/compositor/nodes/COM_ColorToBWNode.h
+++ b/source/blender/compositor/nodes/COM_ColorToBWNode.h
@@ -20,6 +20,9 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
+
+namespace blender::compositor {
+
/**
* \brief ColorToBWNode
* \ingroup Node
@@ -27,5 +30,8 @@
class ColorToBWNode : public Node {
public:
ColorToBWNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_CombineColorNode.cc b/source/blender/compositor/nodes/COM_CombineColorNode.cc
index 12968f06a10..8a2bbba1c1e 100644
--- a/source/blender/compositor/nodes/COM_CombineColorNode.cc
+++ b/source/blender/compositor/nodes/COM_CombineColorNode.cc
@@ -20,6 +20,8 @@
#include "COM_ConvertOperation.h"
+namespace blender::compositor {
+
CombineColorNode::CombineColorNode(bNode *editorNode) : Node(editorNode)
{
}
@@ -87,3 +89,5 @@ NodeOperation *CombineYUVANode::getColorConverter(const CompositorContext & /*co
{
return new ConvertYUVToRGBOperation();
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_CombineColorNode.h b/source/blender/compositor/nodes/COM_CombineColorNode.h
index 378a4855abf..29d3fa37817 100644
--- a/source/blender/compositor/nodes/COM_CombineColorNode.h
+++ b/source/blender/compositor/nodes/COM_CombineColorNode.h
@@ -20,10 +20,13 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
class CombineColorNode : public Node {
public:
CombineColorNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
protected:
virtual NodeOperation *getColorConverter(const CompositorContext &context) const = 0;
@@ -35,7 +38,7 @@ class CombineRGBANode : public CombineColorNode {
{
}
- NodeOperation *getColorConverter(const CompositorContext &context) const;
+ NodeOperation *getColorConverter(const CompositorContext &context) const override;
};
class CombineHSVANode : public CombineColorNode {
@@ -44,7 +47,7 @@ class CombineHSVANode : public CombineColorNode {
{
}
- NodeOperation *getColorConverter(const CompositorContext &context) const;
+ NodeOperation *getColorConverter(const CompositorContext &context) const override;
};
class CombineYCCANode : public CombineColorNode {
@@ -53,7 +56,7 @@ class CombineYCCANode : public CombineColorNode {
{
}
- NodeOperation *getColorConverter(const CompositorContext &context) const;
+ NodeOperation *getColorConverter(const CompositorContext &context) const override;
};
class CombineYUVANode : public CombineColorNode {
@@ -62,5 +65,7 @@ class CombineYUVANode : public CombineColorNode {
{
}
- NodeOperation *getColorConverter(const CompositorContext &context) const;
+ NodeOperation *getColorConverter(const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_CompositorNode.cc b/source/blender/compositor/nodes/COM_CompositorNode.cc
index 32ac1fccec9..262fa550915 100644
--- a/source/blender/compositor/nodes/COM_CompositorNode.cc
+++ b/source/blender/compositor/nodes/COM_CompositorNode.cc
@@ -20,6 +20,8 @@
#include "COM_CompositorOperation.h"
#include "COM_ExecutionSystem.h"
+namespace blender::compositor {
+
CompositorNode::CompositorNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -59,3 +61,5 @@ void CompositorNode::convertToOperations(NodeConverter &converter,
converter.addNodeInputPreview(imageSocket);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_CompositorNode.h b/source/blender/compositor/nodes/COM_CompositorNode.h
index a75355dfc14..4da9f9a766f 100644
--- a/source/blender/compositor/nodes/COM_CompositorNode.h
+++ b/source/blender/compositor/nodes/COM_CompositorNode.h
@@ -20,6 +20,9 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
+
+namespace blender::compositor {
+
/**
* \brief CompositorNode
* \ingroup Node
@@ -27,5 +30,8 @@
class CompositorNode : public Node {
public:
CompositorNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cc b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cc
index 2921b44c95b..ac4e45357dc 100644
--- a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cc
+++ b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cc
@@ -20,6 +20,8 @@
#include "COM_ConvertOperation.h"
#include "COM_ExecutionSystem.h"
+namespace blender::compositor {
+
void ConvertAlphaNode::convertToOperations(NodeConverter &converter,
const CompositorContext & /*context*/) const
{
@@ -39,3 +41,5 @@ void ConvertAlphaNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ConvertAlphaNode.h b/source/blender/compositor/nodes/COM_ConvertAlphaNode.h
index 372f34a576f..f3d0ef2cd5b 100644
--- a/source/blender/compositor/nodes/COM_ConvertAlphaNode.h
+++ b/source/blender/compositor/nodes/COM_ConvertAlphaNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief ConvertAlphaNode
* \ingroup Node
@@ -29,5 +31,8 @@ class ConvertAlphaNode : public Node {
ConvertAlphaNode(bNode *editorNode) : Node(editorNode)
{
}
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_CornerPinNode.cc b/source/blender/compositor/nodes/COM_CornerPinNode.cc
index efe847bbfbf..6a120cffe0a 100644
--- a/source/blender/compositor/nodes/COM_CornerPinNode.cc
+++ b/source/blender/compositor/nodes/COM_CornerPinNode.cc
@@ -20,6 +20,8 @@
#include "COM_PlaneCornerPinOperation.h"
+namespace blender::compositor {
+
CornerPinNode::CornerPinNode(bNode *editorNode) : Node(editorNode)
{
}
@@ -53,3 +55,5 @@ void CornerPinNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(output_warped_image, warp_image_operation->getOutputSocket());
converter.mapOutputSocket(output_plane, plane_mask_operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_CornerPinNode.h b/source/blender/compositor/nodes/COM_CornerPinNode.h
index ba845a614fb..779e057ebb5 100644
--- a/source/blender/compositor/nodes/COM_CornerPinNode.h
+++ b/source/blender/compositor/nodes/COM_CornerPinNode.h
@@ -21,6 +21,8 @@
#include "DNA_node_types.h"
+namespace blender::compositor {
+
/**
* \brief CornerPinNode
* \ingroup Node
@@ -28,5 +30,8 @@
class CornerPinNode : public Node {
public:
CornerPinNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_CropNode.cc b/source/blender/compositor/nodes/COM_CropNode.cc
index 0f0883b0151..3f01062c789 100644
--- a/source/blender/compositor/nodes/COM_CropNode.cc
+++ b/source/blender/compositor/nodes/COM_CropNode.cc
@@ -19,6 +19,8 @@
#include "COM_CropNode.h"
#include "COM_CropOperation.h"
+namespace blender::compositor {
+
CropNode::CropNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -45,3 +47,5 @@ void CropNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapOutputSocket(getOutputSocket(), operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_CropNode.h b/source/blender/compositor/nodes/COM_CropNode.h
index f643ebbabcc..be3c9a268f9 100644
--- a/source/blender/compositor/nodes/COM_CropNode.h
+++ b/source/blender/compositor/nodes/COM_CropNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief CropNode
* \ingroup Node
@@ -27,5 +29,8 @@
class CropNode : public Node {
public:
CropNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_CryptomatteNode.cc b/source/blender/compositor/nodes/COM_CryptomatteNode.cc
index 591db8a96e5..23305fa06f8 100644
--- a/source/blender/compositor/nodes/COM_CryptomatteNode.cc
+++ b/source/blender/compositor/nodes/COM_CryptomatteNode.cc
@@ -31,6 +31,8 @@
#include <iterator>
#include <string>
+namespace blender::compositor {
+
/** \name Cryptomatte base
* \{ */
@@ -176,7 +178,12 @@ void CryptomatteNode::input_operations_from_image_source(
}
const std::string prefix = prefix_from_node(node);
- LISTBASE_FOREACH (RenderLayer *, render_layer, &image->rr->layers) {
+ int layer_index;
+ LISTBASE_FOREACH_INDEX (RenderLayer *, render_layer, &image->rr->layers, layer_index) {
+ if (!blender::StringRef(prefix).startswith(blender::StringRef(
+ render_layer->name, BLI_strnlen(render_layer->name, sizeof(render_layer->name))))) {
+ continue;
+ }
LISTBASE_FOREACH (RenderPass *, render_pass, &render_layer->passes) {
const std::string combined_name = combined_layer_pass_name(render_layer, render_pass);
if (blender::StringRef(combined_name).startswith(prefix)) {
@@ -184,10 +191,12 @@ void CryptomatteNode::input_operations_from_image_source(
render_layer, render_pass, view);
op->setImage(image);
op->setImageUser(iuser);
+ iuser->layer = layer_index;
op->setFramenumber(context.getFramenumber());
r_input_operations.append(op);
}
}
+ break;
}
}
BKE_image_release_ibuf(image, ibuf, nullptr);
@@ -245,7 +254,7 @@ CryptomatteOperation *CryptomatteLegacyNode::create_cryptomatte_operation(
const bNode &UNUSED(node),
const NodeCryptomatte *cryptomatte_settings) const
{
- const int num_inputs = getNumberOfInputSockets() - 1;
+ const int num_inputs = inputs.size() - 1;
CryptomatteOperation *operation = new CryptomatteOperation(num_inputs);
if (cryptomatte_settings) {
LISTBASE_FOREACH (CryptomatteEntry *, cryptomatte_entry, &cryptomatte_settings->entries) {
@@ -261,3 +270,5 @@ CryptomatteOperation *CryptomatteLegacyNode::create_cryptomatte_operation(
}
/* \} */
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_CryptomatteNode.h b/source/blender/compositor/nodes/COM_CryptomatteNode.h
index e99a104c914..a6ba860c678 100644
--- a/source/blender/compositor/nodes/COM_CryptomatteNode.h
+++ b/source/blender/compositor/nodes/COM_CryptomatteNode.h
@@ -24,6 +24,8 @@
#include "COM_CryptomatteOperation.h"
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief CryptomatteNode
* \ingroup Node
@@ -36,7 +38,8 @@ class CryptomatteBaseNode : public Node {
}
public:
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
protected:
virtual CryptomatteOperation *create_cryptomatte_operation(
@@ -87,3 +90,5 @@ class CryptomatteLegacyNode : public CryptomatteBaseNode {
const bNode &node,
const NodeCryptomatte *cryptomatte_settings) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DefocusNode.cc b/source/blender/compositor/nodes/COM_DefocusNode.cc
index 2343b14f68d..fee7c477d9c 100644
--- a/source/blender/compositor/nodes/COM_DefocusNode.cc
+++ b/source/blender/compositor/nodes/COM_DefocusNode.cc
@@ -30,6 +30,8 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+namespace blender::compositor {
+
DefocusNode::DefocusNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -141,3 +143,5 @@ void DefocusNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(getOutputSocket(), operation->getOutputSocket());
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DefocusNode.h b/source/blender/compositor/nodes/COM_DefocusNode.h
index c042e98c515..5e51a0ccd52 100644
--- a/source/blender/compositor/nodes/COM_DefocusNode.h
+++ b/source/blender/compositor/nodes/COM_DefocusNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief DefocusNode
* \ingroup Node
@@ -27,5 +29,8 @@
class DefocusNode : public Node {
public:
DefocusNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DenoiseNode.cc b/source/blender/compositor/nodes/COM_DenoiseNode.cc
index 1aae81e1e7b..e58a9c7ba9a 100644
--- a/source/blender/compositor/nodes/COM_DenoiseNode.cc
+++ b/source/blender/compositor/nodes/COM_DenoiseNode.cc
@@ -21,6 +21,8 @@
#include "COM_SetValueOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
DenoiseNode::DenoiseNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -41,3 +43,5 @@ void DenoiseNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(2));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DenoiseNode.h b/source/blender/compositor/nodes/COM_DenoiseNode.h
index 99f59c89fdb..91be8e3e3ad 100644
--- a/source/blender/compositor/nodes/COM_DenoiseNode.h
+++ b/source/blender/compositor/nodes/COM_DenoiseNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief DenoiseNode
* \ingroup Node
@@ -27,5 +29,8 @@
class DenoiseNode : public Node {
public:
DenoiseNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DespeckleNode.cc b/source/blender/compositor/nodes/COM_DespeckleNode.cc
index 58734917831..beda479025d 100644
--- a/source/blender/compositor/nodes/COM_DespeckleNode.cc
+++ b/source/blender/compositor/nodes/COM_DespeckleNode.cc
@@ -22,6 +22,8 @@
#include "COM_ExecutionSystem.h"
#include "DNA_scene_types.h"
+namespace blender::compositor {
+
DespeckleNode::DespeckleNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -46,3 +48,5 @@ void DespeckleNode::convertToOperations(NodeConverter &converter,
converter.addPreview(operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DespeckleNode.h b/source/blender/compositor/nodes/COM_DespeckleNode.h
index 6b39dd94ac7..2f268e99e1b 100644
--- a/source/blender/compositor/nodes/COM_DespeckleNode.h
+++ b/source/blender/compositor/nodes/COM_DespeckleNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief DespeckleNode
* \ingroup Node
@@ -27,5 +29,8 @@
class DespeckleNode : public Node {
public:
DespeckleNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DifferenceMatteNode.cc b/source/blender/compositor/nodes/COM_DifferenceMatteNode.cc
index 3d538e9b4a0..8c989bfc04e 100644
--- a/source/blender/compositor/nodes/COM_DifferenceMatteNode.cc
+++ b/source/blender/compositor/nodes/COM_DifferenceMatteNode.cc
@@ -21,6 +21,8 @@
#include "COM_DifferenceMatteOperation.h"
#include "COM_SetAlphaMultiplyOperation.h"
+namespace blender::compositor {
+
DifferenceMatteNode::DifferenceMatteNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -52,3 +54,5 @@ void DifferenceMatteNode::convertToOperations(NodeConverter &converter,
converter.addPreview(operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DifferenceMatteNode.h b/source/blender/compositor/nodes/COM_DifferenceMatteNode.h
index 26be5fe1e80..a173c723192 100644
--- a/source/blender/compositor/nodes/COM_DifferenceMatteNode.h
+++ b/source/blender/compositor/nodes/COM_DifferenceMatteNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief DifferenceMatteNode
* \ingroup Node
@@ -27,5 +29,8 @@
class DifferenceMatteNode : public Node {
public:
DifferenceMatteNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DilateErodeNode.cc b/source/blender/compositor/nodes/COM_DilateErodeNode.cc
index e90707618e5..81af1687959 100644
--- a/source/blender/compositor/nodes/COM_DilateErodeNode.cc
+++ b/source/blender/compositor/nodes/COM_DilateErodeNode.cc
@@ -24,6 +24,8 @@
#include "COM_GaussianAlphaXBlurOperation.h"
#include "COM_GaussianAlphaYBlurOperation.h"
+namespace blender::compositor {
+
DilateErodeNode::DilateErodeNode(bNode *editorNode) : Node(editorNode)
{
/* initialize node data */
@@ -147,3 +149,5 @@ void DilateErodeNode::convertToOperations(NodeConverter &converter,
}
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DilateErodeNode.h b/source/blender/compositor/nodes/COM_DilateErodeNode.h
index 090095df447..7684d7e3834 100644
--- a/source/blender/compositor/nodes/COM_DilateErodeNode.h
+++ b/source/blender/compositor/nodes/COM_DilateErodeNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief DilateErodeNode
* \ingroup Node
@@ -30,5 +32,8 @@ class DilateErodeNode : public Node {
public:
DilateErodeNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DirectionalBlurNode.cc b/source/blender/compositor/nodes/COM_DirectionalBlurNode.cc
index f8d0eaf4675..90c4236bce8 100644
--- a/source/blender/compositor/nodes/COM_DirectionalBlurNode.cc
+++ b/source/blender/compositor/nodes/COM_DirectionalBlurNode.cc
@@ -21,6 +21,8 @@
#include "COM_ExecutionSystem.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
DirectionalBlurNode::DirectionalBlurNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -38,3 +40,5 @@ void DirectionalBlurNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DirectionalBlurNode.h b/source/blender/compositor/nodes/COM_DirectionalBlurNode.h
index dfb705cbe64..ce3ef378aaf 100644
--- a/source/blender/compositor/nodes/COM_DirectionalBlurNode.h
+++ b/source/blender/compositor/nodes/COM_DirectionalBlurNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief DirectionalBlurNode
* \ingroup Node
@@ -27,5 +29,8 @@
class DirectionalBlurNode : public Node {
public:
DirectionalBlurNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DisplaceNode.cc b/source/blender/compositor/nodes/COM_DisplaceNode.cc
index 5b63bc1f393..8217caecf44 100644
--- a/source/blender/compositor/nodes/COM_DisplaceNode.cc
+++ b/source/blender/compositor/nodes/COM_DisplaceNode.cc
@@ -21,6 +21,8 @@
#include "COM_DisplaceSimpleOperation.h"
#include "COM_ExecutionSystem.h"
+namespace blender::compositor {
+
DisplaceNode::DisplaceNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -44,3 +46,5 @@ void DisplaceNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(3), operation->getInputSocket(3));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DisplaceNode.h b/source/blender/compositor/nodes/COM_DisplaceNode.h
index a9e8a5ad657..b2495839da3 100644
--- a/source/blender/compositor/nodes/COM_DisplaceNode.h
+++ b/source/blender/compositor/nodes/COM_DisplaceNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief DisplaceNode
* \ingroup Node
@@ -27,5 +29,8 @@
class DisplaceNode : public Node {
public:
DisplaceNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DistanceMatteNode.cc b/source/blender/compositor/nodes/COM_DistanceMatteNode.cc
index 37aeb5c8504..4450c4a2f4a 100644
--- a/source/blender/compositor/nodes/COM_DistanceMatteNode.cc
+++ b/source/blender/compositor/nodes/COM_DistanceMatteNode.cc
@@ -23,6 +23,8 @@
#include "COM_DistanceYCCMatteOperation.h"
#include "COM_SetAlphaMultiplyOperation.h"
+namespace blender::compositor {
+
DistanceMatteNode::DistanceMatteNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -96,3 +98,5 @@ void DistanceMatteNode::convertToOperations(NodeConverter &converter,
converter.addPreview(operationAlpha->getOutputSocket());
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DistanceMatteNode.h b/source/blender/compositor/nodes/COM_DistanceMatteNode.h
index 6ae71ef715f..0baa531b4d2 100644
--- a/source/blender/compositor/nodes/COM_DistanceMatteNode.h
+++ b/source/blender/compositor/nodes/COM_DistanceMatteNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief DistanceMatteNode
* \ingroup Node
@@ -27,5 +29,8 @@
class DistanceMatteNode : public Node {
public:
DistanceMatteNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.cc b/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.cc
index 907a9f49353..847dcc2f8f1 100644
--- a/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.cc
+++ b/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.cc
@@ -20,6 +20,8 @@
#include "COM_DoubleEdgeMaskOperation.h"
#include "COM_ExecutionSystem.h"
+namespace blender::compositor {
+
DoubleEdgeMaskNode::DoubleEdgeMaskNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -40,3 +42,5 @@ void DoubleEdgeMaskNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.h b/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.h
index 6d26cbbf528..90e009747c1 100644
--- a/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.h
+++ b/source/blender/compositor/nodes/COM_DoubleEdgeMaskNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief DoubleEdgeMaskNode
* \ingroup Node
@@ -27,5 +29,8 @@
class DoubleEdgeMaskNode : public Node {
public:
DoubleEdgeMaskNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_EllipseMaskNode.cc b/source/blender/compositor/nodes/COM_EllipseMaskNode.cc
index 1ae855c0f1d..3b4f5ca8c94 100644
--- a/source/blender/compositor/nodes/COM_EllipseMaskNode.cc
+++ b/source/blender/compositor/nodes/COM_EllipseMaskNode.cc
@@ -23,6 +23,8 @@
#include "COM_ScaleOperation.h"
#include "COM_SetValueOperation.h"
+namespace blender::compositor {
+
EllipseMaskNode::EllipseMaskNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -60,7 +62,7 @@ void EllipseMaskNode::convertToOperations(NodeConverter &converter,
scaleOperation->setOffset(0.0f, 0.0f);
scaleOperation->setNewWidth(rd->xsch * render_size_factor);
scaleOperation->setNewHeight(rd->ysch * render_size_factor);
- scaleOperation->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
+ scaleOperation->getInputSocket(0)->setResizeMode(ResizeMode::None);
converter.addOperation(scaleOperation);
converter.addLink(valueOperation->getOutputSocket(0), scaleOperation->getInputSocket(0));
@@ -70,3 +72,5 @@ void EllipseMaskNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_EllipseMaskNode.h b/source/blender/compositor/nodes/COM_EllipseMaskNode.h
index d7376cad52e..cbe189be9f6 100644
--- a/source/blender/compositor/nodes/COM_EllipseMaskNode.h
+++ b/source/blender/compositor/nodes/COM_EllipseMaskNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief EllipseMaskNode
* \ingroup Node
@@ -27,5 +29,8 @@
class EllipseMaskNode : public Node {
public:
EllipseMaskNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_FilterNode.cc b/source/blender/compositor/nodes/COM_FilterNode.cc
index 1147c11794f..351219155c2 100644
--- a/source/blender/compositor/nodes/COM_FilterNode.cc
+++ b/source/blender/compositor/nodes/COM_FilterNode.cc
@@ -23,6 +23,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_MixOperation.h"
+namespace blender::compositor {
+
FilterNode::FilterNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -94,3 +96,5 @@ void FilterNode::convertToOperations(NodeConverter &converter,
converter.addPreview(operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_FilterNode.h b/source/blender/compositor/nodes/COM_FilterNode.h
index 735d8925b48..f7f4176cea5 100644
--- a/source/blender/compositor/nodes/COM_FilterNode.h
+++ b/source/blender/compositor/nodes/COM_FilterNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief FilterNode
* \ingroup Node
@@ -27,5 +29,8 @@
class FilterNode : public Node {
public:
FilterNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_FlipNode.cc b/source/blender/compositor/nodes/COM_FlipNode.cc
index d89e6b7b844..bca6cd3c4f7 100644
--- a/source/blender/compositor/nodes/COM_FlipNode.cc
+++ b/source/blender/compositor/nodes/COM_FlipNode.cc
@@ -21,6 +21,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_FlipOperation.h"
+namespace blender::compositor {
+
FlipNode::FlipNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -52,3 +54,5 @@ void FlipNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_FlipNode.h b/source/blender/compositor/nodes/COM_FlipNode.h
index e819c003430..ee61d09fbba 100644
--- a/source/blender/compositor/nodes/COM_FlipNode.h
+++ b/source/blender/compositor/nodes/COM_FlipNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief FlipNode
* \ingroup Node
@@ -27,5 +29,8 @@
class FlipNode : public Node {
public:
FlipNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_GammaNode.cc b/source/blender/compositor/nodes/COM_GammaNode.cc
index 1ce17faa0dc..52148a80a8f 100644
--- a/source/blender/compositor/nodes/COM_GammaNode.cc
+++ b/source/blender/compositor/nodes/COM_GammaNode.cc
@@ -20,6 +20,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_GammaOperation.h"
+namespace blender::compositor {
+
GammaNode::GammaNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -35,3 +37,5 @@ void GammaNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_GammaNode.h b/source/blender/compositor/nodes/COM_GammaNode.h
index 1a4d02af160..29c9ed170fa 100644
--- a/source/blender/compositor/nodes/COM_GammaNode.h
+++ b/source/blender/compositor/nodes/COM_GammaNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief GammaNode
* \ingroup Node
@@ -27,5 +29,8 @@
class GammaNode : public Node {
public:
GammaNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_GlareNode.cc b/source/blender/compositor/nodes/COM_GlareNode.cc
index ef088e42205..dbe9aaf73ed 100644
--- a/source/blender/compositor/nodes/COM_GlareNode.cc
+++ b/source/blender/compositor/nodes/COM_GlareNode.cc
@@ -27,6 +27,8 @@
#include "COM_SetValueOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
GlareNode::GlareNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -65,7 +67,7 @@ void GlareNode::convertToOperations(NodeConverter &converter,
MixGlareOperation *mixoperation = new MixGlareOperation();
mixoperation->setResolutionInputSocketIndex(1);
- mixoperation->getInputSocket(2)->setResizeMode(COM_SC_FIT);
+ mixoperation->getInputSocket(2)->setResizeMode(ResizeMode::FitAny);
converter.addOperation(glareoperation);
converter.addOperation(thresholdOperation);
@@ -80,3 +82,5 @@ void GlareNode::convertToOperations(NodeConverter &converter,
converter.addLink(glareoperation->getOutputSocket(), mixoperation->getInputSocket(2));
converter.mapOutputSocket(getOutputSocket(), mixoperation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_GlareNode.h b/source/blender/compositor/nodes/COM_GlareNode.h
index 7463af97306..7db5fa85e04 100644
--- a/source/blender/compositor/nodes/COM_GlareNode.h
+++ b/source/blender/compositor/nodes/COM_GlareNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief GlareNode
* \ingroup Node
@@ -27,5 +29,8 @@
class GlareNode : public Node {
public:
GlareNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cc b/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cc
index 00125ba2ea5..5042d217f9a 100644
--- a/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cc
+++ b/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cc
@@ -26,6 +26,8 @@
#include "COM_SetValueOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
HueSaturationValueCorrectNode::HueSaturationValueCorrectNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -62,3 +64,5 @@ void HueSaturationValueCorrectNode::convertToOperations(
converter.mapInputSocket(valueSocket, blend->getInputSocket(0));
converter.mapOutputSocket(outputSocket, blend->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.h b/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.h
index 01790c1a5fb..d75b2ba51ca 100644
--- a/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.h
+++ b/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief HueSaturationValueCorrectNode
* \ingroup Node
@@ -27,5 +29,8 @@
class HueSaturationValueCorrectNode : public Node {
public:
HueSaturationValueCorrectNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cc b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cc
index dc2e5187e8f..54d2caa75af 100644
--- a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cc
+++ b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cc
@@ -26,6 +26,8 @@
#include "COM_SetValueOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
HueSaturationValueNode::HueSaturationValueNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -65,3 +67,5 @@ void HueSaturationValueNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(facSocket, blend->getInputSocket(0));
converter.mapOutputSocket(outputSocket, blend->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueNode.h b/source/blender/compositor/nodes/COM_HueSaturationValueNode.h
index 7ef7abe4188..0b295158cc7 100644
--- a/source/blender/compositor/nodes/COM_HueSaturationValueNode.h
+++ b/source/blender/compositor/nodes/COM_HueSaturationValueNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief HueSaturationValueNode
* \ingroup Node
@@ -27,5 +29,8 @@
class HueSaturationValueNode : public Node {
public:
HueSaturationValueNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_IDMaskNode.cc b/source/blender/compositor/nodes/COM_IDMaskNode.cc
index 5ba54d75bcd..9798dabd035 100644
--- a/source/blender/compositor/nodes/COM_IDMaskNode.cc
+++ b/source/blender/compositor/nodes/COM_IDMaskNode.cc
@@ -21,6 +21,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_IDMaskOperation.h"
+namespace blender::compositor {
+
IDMaskNode::IDMaskNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -47,3 +49,5 @@ void IDMaskNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(getOutputSocket(0), antiAliasOperation->getOutputSocket(0));
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_IDMaskNode.h b/source/blender/compositor/nodes/COM_IDMaskNode.h
index 51076619951..f702732a8ed 100644
--- a/source/blender/compositor/nodes/COM_IDMaskNode.h
+++ b/source/blender/compositor/nodes/COM_IDMaskNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief IDMaskNode
* \ingroup Node
@@ -27,5 +29,8 @@
class IDMaskNode : public Node {
public:
IDMaskNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ImageNode.cc b/source/blender/compositor/nodes/COM_ImageNode.cc
index 711399ccd63..f0bfda0f40e 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.cc
+++ b/source/blender/compositor/nodes/COM_ImageNode.cc
@@ -29,6 +29,8 @@
#include "COM_SetValueOperation.h"
#include "COM_SetVectorOperation.h"
+namespace blender::compositor {
+
ImageNode::ImageNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -77,7 +79,6 @@ void ImageNode::convertToOperations(NodeConverter &converter,
Image *image = (Image *)editorNode->id;
ImageUser *imageuser = (ImageUser *)editorNode->storage;
int framenumber = context.getFramenumber();
- int numberOfOutputs = this->getNumberOfOutputSockets();
bool outputStraightAlpha = (editorNode->custom1 & CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT) != 0;
BKE_image_user_frame_calc(image, imageuser, context.getFramenumber());
/* force a load, we assume iuser index will be set OK anyway */
@@ -87,14 +88,11 @@ void ImageNode::convertToOperations(NodeConverter &converter,
if (image->rr) {
RenderLayer *rl = (RenderLayer *)BLI_findlink(&image->rr->layers, imageuser->layer);
if (rl) {
- NodeOutput *socket;
- int index;
-
is_multilayer_ok = true;
- for (index = 0; index < numberOfOutputs; index++) {
+ for (int64_t index = 0; index < outputs.size(); index++) {
+ NodeOutput *socket = outputs[index];
NodeOperation *operation = nullptr;
- socket = this->getOutputSocket(index);
bNodeSocket *bnodeSocket = socket->getbNodeSocket();
NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage;
RenderPass *rpass = (RenderPass *)BLI_findstring(
@@ -171,8 +169,7 @@ void ImageNode::convertToOperations(NodeConverter &converter,
converter.addPreview(operation->getOutputSocket());
}
if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
- for (int alphaIndex = 0; alphaIndex < numberOfOutputs; alphaIndex++) {
- NodeOutput *alphaSocket = this->getOutputSocket(alphaIndex);
+ for (NodeOutput *alphaSocket : getOutputSockets()) {
bNodeSocket *bnodeAlphaSocket = alphaSocket->getbNodeSocket();
if (!STREQ(bnodeAlphaSocket->name, "Alpha")) {
continue;
@@ -204,12 +201,13 @@ void ImageNode::convertToOperations(NodeConverter &converter,
/* without this, multilayer that fail to load will crash blender T32490. */
if (is_multilayer_ok == false) {
- for (int i = 0; i < getNumberOfOutputSockets(); i++) {
- converter.setInvalidOutput(getOutputSocket(i));
+ for (NodeOutput *output : getOutputSockets()) {
+ converter.setInvalidOutput(output);
}
}
}
else {
+ const int64_t numberOfOutputs = getOutputSockets().size();
if (numberOfOutputs > 0) {
ImageOperation *operation = new ImageOperation();
operation->setImage(image);
@@ -296,4 +294,6 @@ void ImageNode::convertToOperations(NodeConverter &converter,
}
}
}
-}
+} // namespace blender::compositor
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ImageNode.h b/source/blender/compositor/nodes/COM_ImageNode.h
index b99fc07f105..047cc496f83 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.h
+++ b/source/blender/compositor/nodes/COM_ImageNode.h
@@ -26,6 +26,8 @@
#include "RE_engine.h"
#include "RE_pipeline.h"
+namespace blender::compositor {
+
/**
* \brief ImageNode
* \ingroup Node
@@ -44,5 +46,8 @@ class ImageNode : public Node {
public:
ImageNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_InpaintNode.cc b/source/blender/compositor/nodes/COM_InpaintNode.cc
index 40fe63ec9f3..01ec5523939 100644
--- a/source/blender/compositor/nodes/COM_InpaintNode.cc
+++ b/source/blender/compositor/nodes/COM_InpaintNode.cc
@@ -22,6 +22,8 @@
#include "COM_InpaintOperation.h"
#include "DNA_scene_types.h"
+namespace blender::compositor {
+
InpaintNode::InpaintNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -43,3 +45,5 @@ void InpaintNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_InpaintNode.h b/source/blender/compositor/nodes/COM_InpaintNode.h
index 3f778c8ba5c..3a10c11bf61 100644
--- a/source/blender/compositor/nodes/COM_InpaintNode.h
+++ b/source/blender/compositor/nodes/COM_InpaintNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief InpaintNode
* \ingroup Node
@@ -27,5 +29,8 @@
class InpaintNode : public Node {
public:
InpaintNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_InvertNode.cc b/source/blender/compositor/nodes/COM_InvertNode.cc
index 913452c42c8..5fe2033227f 100644
--- a/source/blender/compositor/nodes/COM_InvertNode.cc
+++ b/source/blender/compositor/nodes/COM_InvertNode.cc
@@ -21,6 +21,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_InvertOperation.h"
+namespace blender::compositor {
+
InvertNode::InvertNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -39,3 +41,5 @@ void InvertNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_InvertNode.h b/source/blender/compositor/nodes/COM_InvertNode.h
index d90d6e48713..1cc975b8236 100644
--- a/source/blender/compositor/nodes/COM_InvertNode.h
+++ b/source/blender/compositor/nodes/COM_InvertNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief InvertNode
* \ingroup Node
@@ -27,5 +29,8 @@
class InvertNode : public Node {
public:
InvertNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_KeyingNode.cc b/source/blender/compositor/nodes/COM_KeyingNode.cc
index 9b493d3f332..2054ed67190 100644
--- a/source/blender/compositor/nodes/COM_KeyingNode.cc
+++ b/source/blender/compositor/nodes/COM_KeyingNode.cc
@@ -37,6 +37,8 @@
#include "COM_GaussianAlphaXBlurOperation.h"
#include "COM_GaussianAlphaYBlurOperation.h"
+namespace blender::compositor {
+
KeyingNode::KeyingNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -348,3 +350,5 @@ void KeyingNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(outputEdges, edgesMatte);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_KeyingNode.h b/source/blender/compositor/nodes/COM_KeyingNode.h
index 6920d2af09d..6d5e3ca1883 100644
--- a/source/blender/compositor/nodes/COM_KeyingNode.h
+++ b/source/blender/compositor/nodes/COM_KeyingNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief KeyingNode
* \ingroup Node
@@ -55,5 +57,8 @@ class KeyingNode : public Node {
public:
KeyingNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_KeyingScreenNode.cc b/source/blender/compositor/nodes/COM_KeyingScreenNode.cc
index 93a9a071226..cbe4f165a45 100644
--- a/source/blender/compositor/nodes/COM_KeyingScreenNode.cc
+++ b/source/blender/compositor/nodes/COM_KeyingScreenNode.cc
@@ -22,6 +22,8 @@
#include "DNA_movieclip_types.h"
+namespace blender::compositor {
+
KeyingScreenNode::KeyingScreenNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -45,3 +47,5 @@ void KeyingScreenNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(outputScreen, operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_KeyingScreenNode.h b/source/blender/compositor/nodes/COM_KeyingScreenNode.h
index ce9ef54543d..f2ad3b344f1 100644
--- a/source/blender/compositor/nodes/COM_KeyingScreenNode.h
+++ b/source/blender/compositor/nodes/COM_KeyingScreenNode.h
@@ -21,6 +21,8 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
/**
* \brief KeyingScreenNode
* \ingroup Node
@@ -28,5 +30,8 @@
class KeyingScreenNode : public Node {
public:
KeyingScreenNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_LensDistortionNode.cc b/source/blender/compositor/nodes/COM_LensDistortionNode.cc
index 34d2fba6433..f5226d31989 100644
--- a/source/blender/compositor/nodes/COM_LensDistortionNode.cc
+++ b/source/blender/compositor/nodes/COM_LensDistortionNode.cc
@@ -21,6 +21,8 @@
#include "COM_ProjectorLensDistortionOperation.h"
#include "COM_ScreenLensDistortionOperation.h"
+namespace blender::compositor {
+
LensDistortionNode::LensDistortionNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -59,3 +61,5 @@ void LensDistortionNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_LensDistortionNode.h b/source/blender/compositor/nodes/COM_LensDistortionNode.h
index 8df0e3f7df1..4de1b0fe4da 100644
--- a/source/blender/compositor/nodes/COM_LensDistortionNode.h
+++ b/source/blender/compositor/nodes/COM_LensDistortionNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief LensDistortionNode
* \ingroup Node
@@ -27,5 +29,8 @@
class LensDistortionNode : public Node {
public:
LensDistortionNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cc b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cc
index 8bfea1eff49..920da53231f 100644
--- a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cc
+++ b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cc
@@ -22,6 +22,8 @@
#include "COM_LuminanceMatteOperation.h"
#include "COM_SetAlphaMultiplyOperation.h"
+namespace blender::compositor {
+
LuminanceMatteNode::LuminanceMatteNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -51,3 +53,5 @@ void LuminanceMatteNode::convertToOperations(NodeConverter &converter,
converter.addPreview(operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_LuminanceMatteNode.h b/source/blender/compositor/nodes/COM_LuminanceMatteNode.h
index 7f2d9dfbe95..ef4ebc8ad92 100644
--- a/source/blender/compositor/nodes/COM_LuminanceMatteNode.h
+++ b/source/blender/compositor/nodes/COM_LuminanceMatteNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief LuminanceMatteNode
* \ingroup Node
@@ -27,5 +29,8 @@
class LuminanceMatteNode : public Node {
public:
LuminanceMatteNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MapRangeNode.cc b/source/blender/compositor/nodes/COM_MapRangeNode.cc
index 352bc0dd48d..718a6d9e47b 100644
--- a/source/blender/compositor/nodes/COM_MapRangeNode.cc
+++ b/source/blender/compositor/nodes/COM_MapRangeNode.cc
@@ -21,6 +21,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_MapRangeOperation.h"
+namespace blender::compositor {
+
MapRangeNode::MapRangeNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -47,3 +49,5 @@ void MapRangeNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(destMaxSocket, operation->getInputSocket(4));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MapRangeNode.h b/source/blender/compositor/nodes/COM_MapRangeNode.h
index b838ea858ee..ad6fd78a7d5 100644
--- a/source/blender/compositor/nodes/COM_MapRangeNode.h
+++ b/source/blender/compositor/nodes/COM_MapRangeNode.h
@@ -20,6 +20,9 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
+
+namespace blender::compositor {
+
/**
* \brief MapRangeNode
* \ingroup Node
@@ -27,5 +30,8 @@
class MapRangeNode : public Node {
public:
MapRangeNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MapUVNode.cc b/source/blender/compositor/nodes/COM_MapUVNode.cc
index feb9c75ec56..4b7a9e8af0f 100644
--- a/source/blender/compositor/nodes/COM_MapUVNode.cc
+++ b/source/blender/compositor/nodes/COM_MapUVNode.cc
@@ -20,6 +20,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_MapUVOperation.h"
+namespace blender::compositor {
+
MapUVNode::MapUVNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -39,3 +41,5 @@ void MapUVNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MapUVNode.h b/source/blender/compositor/nodes/COM_MapUVNode.h
index f9fc413dbe5..f7f4db167ea 100644
--- a/source/blender/compositor/nodes/COM_MapUVNode.h
+++ b/source/blender/compositor/nodes/COM_MapUVNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief MapUVNode
* \ingroup Node
@@ -27,5 +29,8 @@
class MapUVNode : public Node {
public:
MapUVNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MapValueNode.cc b/source/blender/compositor/nodes/COM_MapValueNode.cc
index e07df8ad367..ae48bda6cb8 100644
--- a/source/blender/compositor/nodes/COM_MapValueNode.cc
+++ b/source/blender/compositor/nodes/COM_MapValueNode.cc
@@ -21,6 +21,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_MapValueOperation.h"
+namespace blender::compositor {
+
MapValueNode::MapValueNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -41,3 +43,5 @@ void MapValueNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(colorSocket, convertProg->getInputSocket(0));
converter.mapOutputSocket(valueSocket, convertProg->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MapValueNode.h b/source/blender/compositor/nodes/COM_MapValueNode.h
index 60ee262d447..dcac1d6e3c5 100644
--- a/source/blender/compositor/nodes/COM_MapValueNode.h
+++ b/source/blender/compositor/nodes/COM_MapValueNode.h
@@ -20,6 +20,9 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
+
+namespace blender::compositor {
+
/**
* \brief MapValueNode
* \ingroup Node
@@ -27,5 +30,8 @@
class MapValueNode : public Node {
public:
MapValueNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MaskNode.cc b/source/blender/compositor/nodes/COM_MaskNode.cc
index a6415a3992e..ef171c01653 100644
--- a/source/blender/compositor/nodes/COM_MaskNode.cc
+++ b/source/blender/compositor/nodes/COM_MaskNode.cc
@@ -22,6 +22,8 @@
#include "DNA_mask_types.h"
+namespace blender::compositor {
+
MaskNode::MaskNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -68,3 +70,5 @@ void MaskNode::convertToOperations(NodeConverter &converter,
converter.addOperation(operation);
converter.mapOutputSocket(outputMask, operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MaskNode.h b/source/blender/compositor/nodes/COM_MaskNode.h
index 4a03916b3c2..5890cf5957a 100644
--- a/source/blender/compositor/nodes/COM_MaskNode.h
+++ b/source/blender/compositor/nodes/COM_MaskNode.h
@@ -21,6 +21,8 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
/**
* \brief MaskNode
* \ingroup Node
@@ -28,5 +30,8 @@
class MaskNode : public Node {
public:
MaskNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MathNode.cc b/source/blender/compositor/nodes/COM_MathNode.cc
index 0edf880400f..dd0d8931d58 100644
--- a/source/blender/compositor/nodes/COM_MathNode.cc
+++ b/source/blender/compositor/nodes/COM_MathNode.cc
@@ -20,6 +20,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_MathBaseOperation.h"
+namespace blender::compositor {
+
void MathNode::convertToOperations(NodeConverter &converter,
const CompositorContext & /*context*/) const
{
@@ -159,3 +161,5 @@ void MathNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MathNode.h b/source/blender/compositor/nodes/COM_MathNode.h
index 41b144679ac..5db59e62bab 100644
--- a/source/blender/compositor/nodes/COM_MathNode.h
+++ b/source/blender/compositor/nodes/COM_MathNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief MathNode
* \ingroup Node
@@ -29,5 +31,8 @@ class MathNode : public Node {
MathNode(bNode *editorNode) : Node(editorNode)
{
}
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MixNode.cc b/source/blender/compositor/nodes/COM_MixNode.cc
index d082590d21b..cfa8d0ee6a6 100644
--- a/source/blender/compositor/nodes/COM_MixNode.cc
+++ b/source/blender/compositor/nodes/COM_MixNode.cc
@@ -24,6 +24,8 @@
#include "COM_SetValueOperation.h"
#include "DNA_material_types.h" /* the ramp types */
+namespace blender::compositor {
+
MixNode::MixNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -110,3 +112,5 @@ void MixNode::convertToOperations(NodeConverter &converter,
converter.addPreview(convertProg->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MixNode.h b/source/blender/compositor/nodes/COM_MixNode.h
index 91ce29fdbf2..81f9c41871e 100644
--- a/source/blender/compositor/nodes/COM_MixNode.h
+++ b/source/blender/compositor/nodes/COM_MixNode.h
@@ -20,6 +20,9 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
+
+namespace blender::compositor {
+
/**
* \brief MixNode
* \ingroup Node
@@ -27,5 +30,8 @@
class MixNode : public Node {
public:
MixNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MovieClipNode.cc b/source/blender/compositor/nodes/COM_MovieClipNode.cc
index 7cc8f2ea19c..50bd9b4d71b 100644
--- a/source/blender/compositor/nodes/COM_MovieClipNode.cc
+++ b/source/blender/compositor/nodes/COM_MovieClipNode.cc
@@ -29,6 +29,8 @@
#include "IMB_imbuf.h"
+namespace blender::compositor {
+
MovieClipNode::MovieClipNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -106,3 +108,5 @@ void MovieClipNode::convertToOperations(NodeConverter &converter,
IMB_freeImBuf(ibuf);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MovieClipNode.h b/source/blender/compositor/nodes/COM_MovieClipNode.h
index 58262592dca..a469ce9e2a4 100644
--- a/source/blender/compositor/nodes/COM_MovieClipNode.h
+++ b/source/blender/compositor/nodes/COM_MovieClipNode.h
@@ -21,6 +21,8 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
/**
* \brief MovieClipNode
* \ingroup Node
@@ -28,5 +30,8 @@
class MovieClipNode : public Node {
public:
MovieClipNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MovieDistortionNode.cc b/source/blender/compositor/nodes/COM_MovieDistortionNode.cc
index ebace6d5fff..8f17ef8bb98 100644
--- a/source/blender/compositor/nodes/COM_MovieDistortionNode.cc
+++ b/source/blender/compositor/nodes/COM_MovieDistortionNode.cc
@@ -22,6 +22,8 @@
#include "COM_MovieDistortionOperation.h"
#include "DNA_movieclip_types.h"
+namespace blender::compositor {
+
MovieDistortionNode::MovieDistortionNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -44,3 +46,5 @@ void MovieDistortionNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_MovieDistortionNode.h b/source/blender/compositor/nodes/COM_MovieDistortionNode.h
index f4df48dac13..0c1610aa3d3 100644
--- a/source/blender/compositor/nodes/COM_MovieDistortionNode.h
+++ b/source/blender/compositor/nodes/COM_MovieDistortionNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief MovieDistortionNode
* \ingroup Node
@@ -27,5 +29,8 @@
class MovieDistortionNode : public Node {
public:
MovieDistortionNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_NormalNode.cc b/source/blender/compositor/nodes/COM_NormalNode.cc
index 1f48a26fd75..5a97b0932ef 100644
--- a/source/blender/compositor/nodes/COM_NormalNode.cc
+++ b/source/blender/compositor/nodes/COM_NormalNode.cc
@@ -22,6 +22,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_SetVectorOperation.h"
+namespace blender::compositor {
+
NormalNode::NormalNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -54,3 +56,5 @@ void NormalNode::convertToOperations(NodeConverter &converter,
converter.addLink(operationSet->getOutputSocket(0), operation->getInputSocket(1));
converter.mapOutputSocket(outputSocketDotproduct, operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_NormalNode.h b/source/blender/compositor/nodes/COM_NormalNode.h
index c23e83fb023..6d5cbb394a0 100644
--- a/source/blender/compositor/nodes/COM_NormalNode.h
+++ b/source/blender/compositor/nodes/COM_NormalNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief NormalNode
* \ingroup Node
@@ -27,5 +29,8 @@
class NormalNode : public Node {
public:
NormalNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_NormalizeNode.cc b/source/blender/compositor/nodes/COM_NormalizeNode.cc
index 72459fd477c..639dd8e5a51 100644
--- a/source/blender/compositor/nodes/COM_NormalizeNode.cc
+++ b/source/blender/compositor/nodes/COM_NormalizeNode.cc
@@ -20,6 +20,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_NormalizeOperation.h"
+namespace blender::compositor {
+
NormalizeNode::NormalizeNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -34,3 +36,5 @@ void NormalizeNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_NormalizeNode.h b/source/blender/compositor/nodes/COM_NormalizeNode.h
index 7e53ac7e9a0..7770fc49b61 100644
--- a/source/blender/compositor/nodes/COM_NormalizeNode.h
+++ b/source/blender/compositor/nodes/COM_NormalizeNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief NormalizeNode
* \ingroup Node
@@ -27,5 +29,8 @@
class NormalizeNode : public Node {
public:
NormalizeNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cc b/source/blender/compositor/nodes/COM_OutputFileNode.cc
index dcc1fbdec67..10f176d71f5 100644
--- a/source/blender/compositor/nodes/COM_OutputFileNode.cc
+++ b/source/blender/compositor/nodes/COM_OutputFileNode.cc
@@ -25,6 +25,8 @@
#include "BLI_path_util.h"
+namespace blender::compositor {
+
OutputFileNode::OutputFileNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -69,17 +71,16 @@ void OutputFileNode::convertToOperations(NodeConverter &converter,
}
converter.addOperation(outputOperation);
- int num_inputs = getNumberOfInputSockets();
bool previewAdded = false;
- for (int i = 0; i < num_inputs; i++) {
- NodeInput *input = getInputSocket(i);
+ int index = 0;
+ for (NodeInput *input : inputs) {
NodeImageMultiFileSocket *sockdata =
(NodeImageMultiFileSocket *)input->getbNodeSocket()->storage;
/* note: layer becomes an empty placeholder if the input is not linked */
outputOperation->add_layer(sockdata->layer, input->getDataType(), input->isLinked());
- converter.mapInputSocket(input, outputOperation->getInputSocket(i));
+ converter.mapInputSocket(input, outputOperation->getInputSocket(index++));
if (!previewAdded) {
converter.addNodeInputPreview(input);
@@ -88,10 +89,8 @@ void OutputFileNode::convertToOperations(NodeConverter &converter,
}
}
else { /* single layer format */
- int num_inputs = getNumberOfInputSockets();
bool previewAdded = false;
- for (int i = 0; i < num_inputs; i++) {
- NodeInput *input = getInputSocket(i);
+ for (NodeInput *input : inputs) {
if (input->isLinked()) {
NodeImageMultiFileSocket *sockdata =
(NodeImageMultiFileSocket *)input->getbNodeSocket()->storage;
@@ -151,3 +150,5 @@ void OutputFileNode::convertToOperations(NodeConverter &converter,
}
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.h b/source/blender/compositor/nodes/COM_OutputFileNode.h
index 037a345fa50..d1826797c6e 100644
--- a/source/blender/compositor/nodes/COM_OutputFileNode.h
+++ b/source/blender/compositor/nodes/COM_OutputFileNode.h
@@ -21,6 +21,8 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
/**
* \brief OutputFileNode
* \ingroup Node
@@ -28,5 +30,8 @@
class OutputFileNode : public Node {
public:
OutputFileNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_PixelateNode.cc b/source/blender/compositor/nodes/COM_PixelateNode.cc
index f238f68727e..396f339e5a2 100644
--- a/source/blender/compositor/nodes/COM_PixelateNode.cc
+++ b/source/blender/compositor/nodes/COM_PixelateNode.cc
@@ -21,6 +21,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_PixelateOperation.h"
+namespace blender::compositor {
+
PixelateNode::PixelateNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -44,3 +46,5 @@ void PixelateNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_PixelateNode.h b/source/blender/compositor/nodes/COM_PixelateNode.h
index 87cb4df59e8..1a6555550cf 100644
--- a/source/blender/compositor/nodes/COM_PixelateNode.h
+++ b/source/blender/compositor/nodes/COM_PixelateNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief PixelateNode
* \ingroup Node
@@ -27,5 +29,8 @@
class PixelateNode : public Node {
public:
PixelateNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cc b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cc
index 6b9b51631ec..54a0f4d0452 100644
--- a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cc
+++ b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cc
@@ -25,6 +25,8 @@
#include "BKE_node.h"
#include "BKE_tracking.h"
+namespace blender::compositor {
+
PlaneTrackDeformNode::PlaneTrackDeformNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -70,3 +72,5 @@ void PlaneTrackDeformNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(output_plane, plane_mask_operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h
index 36844bc1650..307738fcaf0 100644
--- a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h
+++ b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h
@@ -23,6 +23,8 @@
#include "DNA_movieclip_types.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
/**
* \brief PlaneTrackDeformNode
* \ingroup Node
@@ -30,5 +32,8 @@
class PlaneTrackDeformNode : public Node {
public:
PlaneTrackDeformNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.cc b/source/blender/compositor/nodes/COM_RenderLayersNode.cc
index ea3eeb13393..851d0366546 100644
--- a/source/blender/compositor/nodes/COM_RenderLayersNode.cc
+++ b/source/blender/compositor/nodes/COM_RenderLayersNode.cc
@@ -25,6 +25,8 @@
#include "COM_SetVectorOperation.h"
#include "COM_TranslateOperation.h"
+namespace blender::compositor {
+
RenderLayersNode::RenderLayersNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -72,9 +74,8 @@ void RenderLayersNode::testRenderLink(NodeConverter &converter,
missingRenderLink(converter);
return;
}
- const int num_outputs = this->getNumberOfOutputSockets();
- for (int i = 0; i < num_outputs; i++) {
- NodeOutput *output = this->getOutputSocket(i);
+
+ for (NodeOutput *output : getOutputSockets()) {
NodeImageLayer *storage = (NodeImageLayer *)output->getbNodeSocket()->storage;
RenderPass *rpass = (RenderPass *)BLI_findstring(
&rl->passes, storage->pass_name, offsetof(RenderPass, name));
@@ -153,9 +154,7 @@ void RenderLayersNode::missingSocketLink(NodeConverter &converter, NodeOutput *o
void RenderLayersNode::missingRenderLink(NodeConverter &converter) const
{
- const int num_outputs = this->getNumberOfOutputSockets();
- for (int i = 0; i < num_outputs; i++) {
- NodeOutput *output = this->getOutputSocket(i);
+ for (NodeOutput *output : outputs) {
missingSocketLink(converter, output);
}
}
@@ -174,3 +173,5 @@ void RenderLayersNode::convertToOperations(NodeConverter &converter,
missingRenderLink(converter);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.h b/source/blender/compositor/nodes/COM_RenderLayersNode.h
index 1ffd084ad1e..4eb2427c8e0 100644
--- a/source/blender/compositor/nodes/COM_RenderLayersNode.h
+++ b/source/blender/compositor/nodes/COM_RenderLayersNode.h
@@ -23,6 +23,7 @@
#include "DNA_node_types.h"
struct Render;
+namespace blender::compositor {
/**
* \brief RenderLayersNode
@@ -31,7 +32,8 @@ struct Render;
class RenderLayersNode : public Node {
public:
RenderLayersNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
private:
void testSocketLink(NodeConverter &converter,
@@ -48,3 +50,5 @@ class RenderLayersNode : public Node {
void missingSocketLink(NodeConverter &converter, NodeOutput *output) const;
void missingRenderLink(NodeConverter &converter) const;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_RotateNode.cc b/source/blender/compositor/nodes/COM_RotateNode.cc
index cbade778bcb..af5baa733dc 100644
--- a/source/blender/compositor/nodes/COM_RotateNode.cc
+++ b/source/blender/compositor/nodes/COM_RotateNode.cc
@@ -22,6 +22,8 @@
#include "COM_RotateOperation.h"
#include "COM_SetSamplerOperation.h"
+namespace blender::compositor {
+
RotateNode::RotateNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -45,3 +47,5 @@ void RotateNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(inputDegreeSocket, operation->getInputSocket(1));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_RotateNode.h b/source/blender/compositor/nodes/COM_RotateNode.h
index b75fdd52683..5d8bcb2e3e4 100644
--- a/source/blender/compositor/nodes/COM_RotateNode.h
+++ b/source/blender/compositor/nodes/COM_RotateNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief RotateNode
* \ingroup Node
@@ -27,5 +29,8 @@
class RotateNode : public Node {
public:
RotateNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ScaleNode.cc b/source/blender/compositor/nodes/COM_ScaleNode.cc
index 9ffcd5306b0..50d2902f375 100644
--- a/source/blender/compositor/nodes/COM_ScaleNode.cc
+++ b/source/blender/compositor/nodes/COM_ScaleNode.cc
@@ -24,6 +24,8 @@
#include "COM_SetSamplerOperation.h"
#include "COM_SetValueOperation.h"
+namespace blender::compositor {
+
ScaleNode::ScaleNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -79,7 +81,7 @@ void ScaleNode::convertToOperations(NodeConverter &converter,
operation->setOffset(bnode->custom3, bnode->custom4);
operation->setNewWidth(rd->xsch * render_size_factor);
operation->setNewHeight(rd->ysch * render_size_factor);
- operation->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
+ operation->getInputSocket(0)->setResizeMode(ResizeMode::None);
converter.addOperation(operation);
converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
@@ -105,3 +107,5 @@ void ScaleNode::convertToOperations(NodeConverter &converter,
}
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ScaleNode.h b/source/blender/compositor/nodes/COM_ScaleNode.h
index c9a02411b1c..186ffa8bdce 100644
--- a/source/blender/compositor/nodes/COM_ScaleNode.h
+++ b/source/blender/compositor/nodes/COM_ScaleNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief ScaleNode
* \ingroup Node
@@ -27,5 +29,8 @@
class ScaleNode : public Node {
public:
ScaleNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SeparateColorNode.cc b/source/blender/compositor/nodes/COM_SeparateColorNode.cc
index 203aa25c9e9..fcaf52c701d 100644
--- a/source/blender/compositor/nodes/COM_SeparateColorNode.cc
+++ b/source/blender/compositor/nodes/COM_SeparateColorNode.cc
@@ -20,6 +20,8 @@
#include "COM_ConvertOperation.h"
+namespace blender::compositor {
+
SeparateColorNode::SeparateColorNode(bNode *editorNode) : Node(editorNode)
{
}
@@ -119,3 +121,5 @@ NodeOperation *SeparateYUVANode::getColorConverter(const CompositorContext & /*c
{
return new ConvertRGBToYUVOperation();
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SeparateColorNode.h b/source/blender/compositor/nodes/COM_SeparateColorNode.h
index aaf86c6e22b..eaf543df51f 100644
--- a/source/blender/compositor/nodes/COM_SeparateColorNode.h
+++ b/source/blender/compositor/nodes/COM_SeparateColorNode.h
@@ -20,10 +20,13 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
class SeparateColorNode : public Node {
public:
SeparateColorNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
protected:
virtual NodeOperation *getColorConverter(const CompositorContext &context) const = 0;
@@ -35,7 +38,7 @@ class SeparateRGBANode : public SeparateColorNode {
{
}
- NodeOperation *getColorConverter(const CompositorContext &context) const;
+ NodeOperation *getColorConverter(const CompositorContext &context) const override;
};
class SeparateHSVANode : public SeparateColorNode {
@@ -44,7 +47,7 @@ class SeparateHSVANode : public SeparateColorNode {
{
}
- NodeOperation *getColorConverter(const CompositorContext &context) const;
+ NodeOperation *getColorConverter(const CompositorContext &context) const override;
};
class SeparateYCCANode : public SeparateColorNode {
@@ -53,7 +56,7 @@ class SeparateYCCANode : public SeparateColorNode {
{
}
- NodeOperation *getColorConverter(const CompositorContext &context) const;
+ NodeOperation *getColorConverter(const CompositorContext &context) const override;
};
class SeparateYUVANode : public SeparateColorNode {
@@ -62,5 +65,7 @@ class SeparateYUVANode : public SeparateColorNode {
{
}
- NodeOperation *getColorConverter(const CompositorContext &context) const;
+ NodeOperation *getColorConverter(const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SetAlphaNode.cc b/source/blender/compositor/nodes/COM_SetAlphaNode.cc
index 233a5e96ff4..dc41c126ba8 100644
--- a/source/blender/compositor/nodes/COM_SetAlphaNode.cc
+++ b/source/blender/compositor/nodes/COM_SetAlphaNode.cc
@@ -21,6 +21,8 @@
#include "COM_SetAlphaMultiplyOperation.h"
#include "COM_SetAlphaReplaceOperation.h"
+namespace blender::compositor {
+
void SetAlphaNode::convertToOperations(NodeConverter &converter,
const CompositorContext & /*context*/) const
{
@@ -46,3 +48,5 @@ void SetAlphaNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SetAlphaNode.h b/source/blender/compositor/nodes/COM_SetAlphaNode.h
index 2e652539cec..c8d340eb64b 100644
--- a/source/blender/compositor/nodes/COM_SetAlphaNode.h
+++ b/source/blender/compositor/nodes/COM_SetAlphaNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief SetAlphaNode
* \ingroup Node
@@ -29,5 +31,8 @@ class SetAlphaNode : public Node {
SetAlphaNode(bNode *editorNode) : Node(editorNode)
{
}
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SocketProxyNode.cc b/source/blender/compositor/nodes/COM_SocketProxyNode.cc
index 93d8d399cad..b3aa1770551 100644
--- a/source/blender/compositor/nodes/COM_SocketProxyNode.cc
+++ b/source/blender/compositor/nodes/COM_SocketProxyNode.cc
@@ -25,6 +25,8 @@
#include "COM_SocketProxyOperation.h"
#include "COM_WriteBufferOperation.h"
+namespace blender::compositor {
+
SocketProxyNode::SocketProxyNode(bNode *editorNode,
bNodeSocket *editorInput,
bNodeSocket *editorOutput,
@@ -101,3 +103,5 @@ void SocketBufferNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(input, writeOperation->getInputSocket(0));
converter.mapOutputSocket(output, readOperation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SocketProxyNode.h b/source/blender/compositor/nodes/COM_SocketProxyNode.h
index a0c0b63dafd..d19fb802767 100644
--- a/source/blender/compositor/nodes/COM_SocketProxyNode.h
+++ b/source/blender/compositor/nodes/COM_SocketProxyNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief SocketProxyNode
* \ingroup Node
@@ -30,7 +32,8 @@ class SocketProxyNode : public Node {
bNodeSocket *editorInput,
bNodeSocket *editorOutput,
bool use_conversion);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
bool getUseConversion() const
{
@@ -49,5 +52,8 @@ class SocketProxyNode : public Node {
class SocketBufferNode : public Node {
public:
SocketBufferNode(bNode *editorNode, bNodeSocket *editorInput, bNodeSocket *editorOutput);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SplitViewerNode.cc b/source/blender/compositor/nodes/COM_SplitViewerNode.cc
index 681adeaf1d3..582c650f205 100644
--- a/source/blender/compositor/nodes/COM_SplitViewerNode.cc
+++ b/source/blender/compositor/nodes/COM_SplitViewerNode.cc
@@ -25,6 +25,8 @@
#include "COM_SplitOperation.h"
#include "COM_ViewerOperation.h"
+namespace blender::compositor {
+
SplitViewerNode::SplitViewerNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -73,3 +75,5 @@ void SplitViewerNode::convertToOperations(NodeConverter &converter,
converter.registerViewer(viewerOperation);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SplitViewerNode.h b/source/blender/compositor/nodes/COM_SplitViewerNode.h
index c9ce5164ef4..8a42775eb0d 100644
--- a/source/blender/compositor/nodes/COM_SplitViewerNode.h
+++ b/source/blender/compositor/nodes/COM_SplitViewerNode.h
@@ -20,6 +20,9 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
+
+namespace blender::compositor {
+
/**
* \brief SplitViewerNode
* \ingroup Node
@@ -27,5 +30,8 @@
class SplitViewerNode : public Node {
public:
SplitViewerNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_Stabilize2dNode.cc b/source/blender/compositor/nodes/COM_Stabilize2dNode.cc
index 38db080a154..fc72b48eca2 100644
--- a/source/blender/compositor/nodes/COM_Stabilize2dNode.cc
+++ b/source/blender/compositor/nodes/COM_Stabilize2dNode.cc
@@ -28,6 +28,8 @@
#include "DNA_movieclip_types.h"
+namespace blender::compositor {
+
Stabilize2dNode::Stabilize2dNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -111,3 +113,5 @@ void Stabilize2dNode::convertToOperations(NodeConverter &converter,
converter.addLink(translateOperation->getOutputSocket(), psoperation->getInputSocket(0));
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_Stabilize2dNode.h b/source/blender/compositor/nodes/COM_Stabilize2dNode.h
index cb46926a3f3..34ed8871e33 100644
--- a/source/blender/compositor/nodes/COM_Stabilize2dNode.h
+++ b/source/blender/compositor/nodes/COM_Stabilize2dNode.h
@@ -21,6 +21,8 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
/**
* \brief Stabilize2dNode
* \ingroup Node
@@ -28,5 +30,8 @@
class Stabilize2dNode : public Node {
public:
Stabilize2dNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SunBeamsNode.cc b/source/blender/compositor/nodes/COM_SunBeamsNode.cc
index d899a54c03c..1e5aa0b8020 100644
--- a/source/blender/compositor/nodes/COM_SunBeamsNode.cc
+++ b/source/blender/compositor/nodes/COM_SunBeamsNode.cc
@@ -18,6 +18,8 @@
#include "COM_SunBeamsNode.h"
#include "COM_SunBeamsOperation.h"
+namespace blender::compositor {
+
SunBeamsNode::SunBeamsNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -37,3 +39,5 @@ void SunBeamsNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SunBeamsNode.h b/source/blender/compositor/nodes/COM_SunBeamsNode.h
index 9a56fc1fcea..8b68d3f4cb5 100644
--- a/source/blender/compositor/nodes/COM_SunBeamsNode.h
+++ b/source/blender/compositor/nodes/COM_SunBeamsNode.h
@@ -19,6 +19,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief SunBeamsNode
* \ingroup Node
@@ -26,5 +28,8 @@
class SunBeamsNode : public Node {
public:
SunBeamsNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SwitchNode.cc b/source/blender/compositor/nodes/COM_SwitchNode.cc
index 947774e98ae..4006d10dafb 100644
--- a/source/blender/compositor/nodes/COM_SwitchNode.cc
+++ b/source/blender/compositor/nodes/COM_SwitchNode.cc
@@ -18,6 +18,8 @@
#include "COM_SwitchNode.h"
+namespace blender::compositor {
+
SwitchNode::SwitchNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -38,3 +40,5 @@ void SwitchNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(getOutputSocket(0), result);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SwitchNode.h b/source/blender/compositor/nodes/COM_SwitchNode.h
index d4d8dd23a98..aa6caa2e59f 100644
--- a/source/blender/compositor/nodes/COM_SwitchNode.h
+++ b/source/blender/compositor/nodes/COM_SwitchNode.h
@@ -21,6 +21,9 @@
#include "COM_Node.h"
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
+
+namespace blender::compositor {
+
/**
* \brief SwitchNode
* \ingroup Node
@@ -28,5 +31,8 @@
class SwitchNode : public Node {
public:
SwitchNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SwitchViewNode.cc b/source/blender/compositor/nodes/COM_SwitchViewNode.cc
index e534ebfac9a..395122dd11b 100644
--- a/source/blender/compositor/nodes/COM_SwitchViewNode.cc
+++ b/source/blender/compositor/nodes/COM_SwitchViewNode.cc
@@ -19,6 +19,8 @@
#include "COM_SwitchViewNode.h"
#include "BLI_listbase.h"
+namespace blender::compositor {
+
SwitchViewNode::SwitchViewNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -38,3 +40,5 @@ void SwitchViewNode::convertToOperations(NodeConverter &converter,
result = converter.addInputProxy(getInputSocket(nr), false);
converter.mapOutputSocket(getOutputSocket(0), result);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_SwitchViewNode.h b/source/blender/compositor/nodes/COM_SwitchViewNode.h
index 9423740f668..ce6de52182c 100644
--- a/source/blender/compositor/nodes/COM_SwitchViewNode.h
+++ b/source/blender/compositor/nodes/COM_SwitchViewNode.h
@@ -21,6 +21,9 @@
#include "COM_Node.h"
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
+
+namespace blender::compositor {
+
/**
* \brief SwitchViewNode
* \ingroup Node
@@ -28,5 +31,8 @@
class SwitchViewNode : public Node {
public:
SwitchViewNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_TextureNode.cc b/source/blender/compositor/nodes/COM_TextureNode.cc
index 3381b5098d7..317355b8c9a 100644
--- a/source/blender/compositor/nodes/COM_TextureNode.cc
+++ b/source/blender/compositor/nodes/COM_TextureNode.cc
@@ -20,6 +20,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_TextureOperation.h"
+namespace blender::compositor {
+
TextureNode::TextureNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -54,3 +56,5 @@ void TextureNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(1), alphaOperation->getInputSocket(1));
converter.mapOutputSocket(getOutputSocket(0), alphaOperation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_TextureNode.h b/source/blender/compositor/nodes/COM_TextureNode.h
index 4d780850190..b886e3b74e1 100644
--- a/source/blender/compositor/nodes/COM_TextureNode.h
+++ b/source/blender/compositor/nodes/COM_TextureNode.h
@@ -21,6 +21,8 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
/**
* \brief TextureNode
* \ingroup Node
@@ -28,5 +30,8 @@
class TextureNode : public Node {
public:
TextureNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_TimeNode.cc b/source/blender/compositor/nodes/COM_TimeNode.cc
index 247e0d11df6..c14c5344eee 100644
--- a/source/blender/compositor/nodes/COM_TimeNode.cc
+++ b/source/blender/compositor/nodes/COM_TimeNode.cc
@@ -24,6 +24,8 @@
#include "BLI_utildefines.h"
+namespace blender::compositor {
+
TimeNode::TimeNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -56,3 +58,5 @@ void TimeNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_TimeNode.h b/source/blender/compositor/nodes/COM_TimeNode.h
index 78177014dc1..5688e2cff03 100644
--- a/source/blender/compositor/nodes/COM_TimeNode.h
+++ b/source/blender/compositor/nodes/COM_TimeNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief TimeNode
* \ingroup Node
@@ -27,5 +29,8 @@
class TimeNode : public Node {
public:
TimeNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_TonemapNode.cc b/source/blender/compositor/nodes/COM_TonemapNode.cc
index db329e56f9b..844fe3e8cb6 100644
--- a/source/blender/compositor/nodes/COM_TonemapNode.cc
+++ b/source/blender/compositor/nodes/COM_TonemapNode.cc
@@ -20,6 +20,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_TonemapOperation.h"
+namespace blender::compositor {
+
TonemapNode::TonemapNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -38,3 +40,5 @@ void TonemapNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_TonemapNode.h b/source/blender/compositor/nodes/COM_TonemapNode.h
index d934a1ede5b..cac9004c32a 100644
--- a/source/blender/compositor/nodes/COM_TonemapNode.h
+++ b/source/blender/compositor/nodes/COM_TonemapNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief TonemapNode
* \ingroup Node
@@ -27,5 +29,8 @@
class TonemapNode : public Node {
public:
TonemapNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_TrackPositionNode.cc b/source/blender/compositor/nodes/COM_TrackPositionNode.cc
index 52e7f7d832b..3fb5fc02f20 100644
--- a/source/blender/compositor/nodes/COM_TrackPositionNode.cc
+++ b/source/blender/compositor/nodes/COM_TrackPositionNode.cc
@@ -26,6 +26,8 @@
#include "BKE_node.h"
+namespace blender::compositor {
+
TrackPositionNode::TrackPositionNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -109,3 +111,5 @@ void TrackPositionNode::convertToOperations(NodeConverter &converter,
converter.addLink(operationMotionPostY->getOutputSocket(), combine_operation->getInputSocket(3));
converter.mapOutputSocket(outputSpeed, combine_operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_TrackPositionNode.h b/source/blender/compositor/nodes/COM_TrackPositionNode.h
index 37d3d25d592..665ba36fe09 100644
--- a/source/blender/compositor/nodes/COM_TrackPositionNode.h
+++ b/source/blender/compositor/nodes/COM_TrackPositionNode.h
@@ -21,6 +21,8 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
/**
* \brief TrackPositionNode
* \ingroup Node
@@ -28,5 +30,8 @@
class TrackPositionNode : public Node {
public:
TrackPositionNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_TransformNode.cc b/source/blender/compositor/nodes/COM_TransformNode.cc
index cd5ba8ba201..cd12939ab43 100644
--- a/source/blender/compositor/nodes/COM_TransformNode.cc
+++ b/source/blender/compositor/nodes/COM_TransformNode.cc
@@ -24,6 +24,8 @@
#include "COM_SetValueOperation.h"
#include "COM_TranslateOperation.h"
+namespace blender::compositor {
+
TransformNode::TransformNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -66,3 +68,5 @@ void TransformNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(getOutputSocket(), translateOperation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_TransformNode.h b/source/blender/compositor/nodes/COM_TransformNode.h
index bd01808d662..137e162256d 100644
--- a/source/blender/compositor/nodes/COM_TransformNode.h
+++ b/source/blender/compositor/nodes/COM_TransformNode.h
@@ -21,6 +21,8 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
/**
* \brief TransformNode
* \ingroup Node
@@ -28,5 +30,8 @@
class TransformNode : public Node {
public:
TransformNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_TranslateNode.cc b/source/blender/compositor/nodes/COM_TranslateNode.cc
index 13a73953ea0..922393f006a 100644
--- a/source/blender/compositor/nodes/COM_TranslateNode.cc
+++ b/source/blender/compositor/nodes/COM_TranslateNode.cc
@@ -23,6 +23,8 @@
#include "COM_WrapOperation.h"
#include "COM_WriteBufferOperation.h"
+namespace blender::compositor {
+
TranslateNode::TranslateNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -69,3 +71,5 @@ void TranslateNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_TranslateNode.h b/source/blender/compositor/nodes/COM_TranslateNode.h
index d381274c0e5..0cea234bff8 100644
--- a/source/blender/compositor/nodes/COM_TranslateNode.h
+++ b/source/blender/compositor/nodes/COM_TranslateNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief TranslateNode
* \ingroup Node
@@ -27,5 +29,8 @@
class TranslateNode : public Node {
public:
TranslateNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ValueNode.cc b/source/blender/compositor/nodes/COM_ValueNode.cc
index 4227db0d10e..6b640fa2a3a 100644
--- a/source/blender/compositor/nodes/COM_ValueNode.cc
+++ b/source/blender/compositor/nodes/COM_ValueNode.cc
@@ -20,6 +20,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_SetValueOperation.h"
+namespace blender::compositor {
+
ValueNode::ValueNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -35,3 +37,5 @@ void ValueNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(output, operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ValueNode.h b/source/blender/compositor/nodes/COM_ValueNode.h
index 5179e6828e4..1401b2c7e0a 100644
--- a/source/blender/compositor/nodes/COM_ValueNode.h
+++ b/source/blender/compositor/nodes/COM_ValueNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief ValueNode
* \ingroup Node
@@ -27,5 +29,8 @@
class ValueNode : public Node {
public:
ValueNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_VectorBlurNode.cc b/source/blender/compositor/nodes/COM_VectorBlurNode.cc
index a92991c8b49..7aa5f5668c9 100644
--- a/source/blender/compositor/nodes/COM_VectorBlurNode.cc
+++ b/source/blender/compositor/nodes/COM_VectorBlurNode.cc
@@ -20,6 +20,8 @@
#include "COM_VectorBlurOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
VectorBlurNode::VectorBlurNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -41,3 +43,5 @@ void VectorBlurNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(2));
converter.mapOutputSocket(getOutputSocket(), operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_VectorBlurNode.h b/source/blender/compositor/nodes/COM_VectorBlurNode.h
index f370c82a1ee..8c98a0b81a1 100644
--- a/source/blender/compositor/nodes/COM_VectorBlurNode.h
+++ b/source/blender/compositor/nodes/COM_VectorBlurNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief VectorBlurNode
* \ingroup Node
@@ -27,5 +29,8 @@
class VectorBlurNode : public Node {
public:
VectorBlurNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_VectorCurveNode.cc b/source/blender/compositor/nodes/COM_VectorCurveNode.cc
index 1201a9f9613..f2fd80cd93e 100644
--- a/source/blender/compositor/nodes/COM_VectorCurveNode.cc
+++ b/source/blender/compositor/nodes/COM_VectorCurveNode.cc
@@ -20,6 +20,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_VectorCurveOperation.h"
+namespace blender::compositor {
+
VectorCurveNode::VectorCurveNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -35,3 +37,5 @@ void VectorCurveNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_VectorCurveNode.h b/source/blender/compositor/nodes/COM_VectorCurveNode.h
index 4d7f92897a1..ee4df5d3a42 100644
--- a/source/blender/compositor/nodes/COM_VectorCurveNode.h
+++ b/source/blender/compositor/nodes/COM_VectorCurveNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief VectorCurveNode
* \ingroup Node
@@ -27,5 +29,8 @@
class VectorCurveNode : public Node {
public:
VectorCurveNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ViewLevelsNode.cc b/source/blender/compositor/nodes/COM_ViewLevelsNode.cc
index 7b86fb1d64d..dc454b95080 100644
--- a/source/blender/compositor/nodes/COM_ViewLevelsNode.cc
+++ b/source/blender/compositor/nodes/COM_ViewLevelsNode.cc
@@ -22,6 +22,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_SetValueOperation.h"
+namespace blender::compositor {
+
ViewLevelsNode::ViewLevelsNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -59,3 +61,5 @@ void ViewLevelsNode::convertToOperations(NodeConverter &converter,
converter.addOutputValue(getOutputSocket(1), 0.0f);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ViewLevelsNode.h b/source/blender/compositor/nodes/COM_ViewLevelsNode.h
index 0e931fed055..055d871498e 100644
--- a/source/blender/compositor/nodes/COM_ViewLevelsNode.h
+++ b/source/blender/compositor/nodes/COM_ViewLevelsNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief ViewLevelsNode
* \ingroup Node
@@ -27,5 +29,8 @@
class ViewLevelsNode : public Node {
public:
ViewLevelsNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ViewerNode.cc b/source/blender/compositor/nodes/COM_ViewerNode.cc
index 359c3d3031d..3833a8d7ca8 100644
--- a/source/blender/compositor/nodes/COM_ViewerNode.cc
+++ b/source/blender/compositor/nodes/COM_ViewerNode.cc
@@ -25,6 +25,8 @@
#include "COM_ExecutionSystem.h"
#include "COM_ViewerOperation.h"
+namespace blender::compositor {
+
ViewerNode::ViewerNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -82,3 +84,5 @@ void ViewerNode::convertToOperations(NodeConverter &converter,
converter.registerViewer(viewerOperation);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ViewerNode.h b/source/blender/compositor/nodes/COM_ViewerNode.h
index 74758417014..544a5e6a504 100644
--- a/source/blender/compositor/nodes/COM_ViewerNode.h
+++ b/source/blender/compositor/nodes/COM_ViewerNode.h
@@ -20,6 +20,9 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
+
+namespace blender::compositor {
+
/**
* \brief ViewerNode
* \ingroup Node
@@ -27,5 +30,8 @@
class ViewerNode : public Node {
public:
ViewerNode(bNode *editorNode);
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ZCombineNode.cc b/source/blender/compositor/nodes/COM_ZCombineNode.cc
index b61c018d029..a76049ff249 100644
--- a/source/blender/compositor/nodes/COM_ZCombineNode.cc
+++ b/source/blender/compositor/nodes/COM_ZCombineNode.cc
@@ -28,6 +28,8 @@
#include "DNA_material_types.h" /* the ramp types */
+namespace blender::compositor {
+
void ZCombineNode::convertToOperations(NodeConverter &converter,
const CompositorContext &context) const
{
@@ -99,3 +101,5 @@ void ZCombineNode::convertToOperations(NodeConverter &converter,
converter.mapOutputSocket(getOutputSocket(1), zoperation->getOutputSocket());
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/nodes/COM_ZCombineNode.h b/source/blender/compositor/nodes/COM_ZCombineNode.h
index ca54fd7fffa..82f2f30fb3c 100644
--- a/source/blender/compositor/nodes/COM_ZCombineNode.h
+++ b/source/blender/compositor/nodes/COM_ZCombineNode.h
@@ -20,6 +20,8 @@
#include "COM_Node.h"
+namespace blender::compositor {
+
/**
* \brief ZCombineNode
* \ingroup Node
@@ -29,5 +31,8 @@ class ZCombineNode : public Node {
ZCombineNode(bNode *editorNode) : Node(editorNode)
{
}
- void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+ void convertToOperations(NodeConverter &converter,
+ const CompositorContext &context) const override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.cc b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.cc
index 668d07c7c3d..34638cbe7d6 100644
--- a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.cc
+++ b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.cc
@@ -18,6 +18,8 @@
#include "COM_AlphaOverKeyOperation.h"
+namespace blender::compositor {
+
AlphaOverKeyOperation::AlphaOverKeyOperation()
{
/* pass */
@@ -52,3 +54,5 @@ void AlphaOverKeyOperation::executePixelSampled(float output[4],
output[3] = (mul * inputColor1[3]) + value[0] * inputOverColor[3];
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h
index f2ec5ff12c2..8b8debefa7a 100644
--- a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h
+++ b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h
@@ -20,6 +20,8 @@
#include "COM_MixOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -34,5 +36,7 @@ class AlphaOverKeyOperation : public MixBaseOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.cc b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.cc
index b8465ab7ccf..c68c79d2263 100644
--- a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.cc
+++ b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.cc
@@ -18,6 +18,8 @@
#include "COM_AlphaOverMixedOperation.h"
+namespace blender::compositor {
+
AlphaOverMixedOperation::AlphaOverMixedOperation()
{
this->m_x = 0.0f;
@@ -53,3 +55,5 @@ void AlphaOverMixedOperation::executePixelSampled(float output[4],
output[3] = (mul * inputColor1[3]) + value[0] * inputOverColor[3];
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h
index 73433ec3077..e2b3af84162 100644
--- a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h
+++ b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h
@@ -20,6 +20,8 @@
#include "COM_MixOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -37,10 +39,12 @@ class AlphaOverMixedOperation : public MixBaseOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
void setX(float x)
{
this->m_x = x;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.cc b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.cc
index 4510c027d46..edb248d16e8 100644
--- a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.cc
+++ b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.cc
@@ -18,6 +18,8 @@
#include "COM_AlphaOverPremultiplyOperation.h"
+namespace blender::compositor {
+
AlphaOverPremultiplyOperation::AlphaOverPremultiplyOperation()
{
/* pass */
@@ -52,3 +54,5 @@ void AlphaOverPremultiplyOperation::executePixelSampled(float output[4],
output[3] = (mul * inputColor1[3]) + value[0] * inputOverColor[3];
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h
index b149789878e..16246231a57 100644
--- a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h
+++ b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h
@@ -20,6 +20,8 @@
#include "COM_MixOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -34,5 +36,7 @@ class AlphaOverPremultiplyOperation : public MixBaseOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_AntiAliasOperation.cc b/source/blender/compositor/operations/COM_AntiAliasOperation.cc
index 740cd3ff609..23d6f4b80c7 100644
--- a/source/blender/compositor/operations/COM_AntiAliasOperation.cc
+++ b/source/blender/compositor/operations/COM_AntiAliasOperation.cc
@@ -24,6 +24,8 @@
#include "RE_texture.h"
+namespace blender::compositor {
+
/* An implementation of the Scale3X edge-extrapolation algorithm.
*
* Code from GIMP plugin, based on code from Adam D. Moss <adam@gimp.org>
@@ -117,7 +119,7 @@ AntiAliasOperation::AntiAliasOperation()
this->addInputSocket(DataType::Value);
this->addOutputSocket(DataType::Value);
this->m_valueReader = nullptr;
- this->setComplex(true);
+ this->flags.complex = true;
}
void AntiAliasOperation::initExecution()
@@ -199,3 +201,5 @@ void *AntiAliasOperation::initializeTileData(rcti *rect)
{
return getInputOperation(0)->initializeTileData(rect);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_AntiAliasOperation.h b/source/blender/compositor/operations/COM_AntiAliasOperation.h
index 571655813ae..fc9102b5b4c 100644
--- a/source/blender/compositor/operations/COM_AntiAliasOperation.h
+++ b/source/blender/compositor/operations/COM_AntiAliasOperation.h
@@ -21,6 +21,8 @@
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
/**
* \brief AntiAlias operations
* it only supports anti aliasing on BW buffers.
@@ -39,20 +41,22 @@ class AntiAliasOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BilateralBlurOperation.cc b/source/blender/compositor/operations/COM_BilateralBlurOperation.cc
index d04fade2e93..64448e2ae95 100644
--- a/source/blender/compositor/operations/COM_BilateralBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_BilateralBlurOperation.cc
@@ -21,12 +21,14 @@
#include "RE_pipeline.h"
+namespace blender::compositor {
+
BilateralBlurOperation::BilateralBlurOperation()
{
this->addInputSocket(DataType::Color);
this->addInputSocket(DataType::Color);
this->addOutputSocket(DataType::Color);
- this->setComplex(true);
+ this->flags.complex = true;
this->m_inputColorProgram = nullptr;
this->m_inputDeterminatorProgram = nullptr;
@@ -112,3 +114,5 @@ bool BilateralBlurOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BilateralBlurOperation.h b/source/blender/compositor/operations/COM_BilateralBlurOperation.h
index d059510f0bc..c56cef35050 100644
--- a/source/blender/compositor/operations/COM_BilateralBlurOperation.h
+++ b/source/blender/compositor/operations/COM_BilateralBlurOperation.h
@@ -21,6 +21,8 @@
#include "COM_NodeOperation.h"
#include "COM_QualityStepHelper.h"
+namespace blender::compositor {
+
class BilateralBlurOperation : public NodeOperation, public QualityStepHelper {
private:
SocketReader *m_inputColorProgram;
@@ -34,24 +36,26 @@ class BilateralBlurOperation : public NodeOperation, public QualityStepHelper {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
void setData(NodeBilateralBlurData *data)
{
this->m_data = data;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cc b/source/blender/compositor/operations/COM_BlurBaseOperation.cc
index fe6ca1cfd4e..8b73624ca79 100644
--- a/source/blender/compositor/operations/COM_BlurBaseOperation.cc
+++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cc
@@ -22,13 +22,15 @@
#include "RE_pipeline.h"
+namespace blender::compositor {
+
BlurBaseOperation::BlurBaseOperation(DataType data_type)
{
/* data_type is almost always DataType::Color except for alpha-blur */
this->addInputSocket(data_type);
this->addInputSocket(DataType::Value);
this->addOutputSocket(data_type);
- this->setComplex(true);
+ this->flags.complex = true;
this->m_inputProgram = nullptr;
memset(&m_data, 0, sizeof(NodeBlurData));
this->m_size = 1.0f;
@@ -167,7 +169,7 @@ void BlurBaseOperation::updateSize()
{
if (!this->m_sizeavailable) {
float result[4];
- this->getInputSocketReader(1)->readSampled(result, 0, 0, COM_PS_NEAREST);
+ this->getInputSocketReader(1)->readSampled(result, 0, 0, PixelSampler::Nearest);
this->m_size = result[0];
this->m_sizeavailable = true;
}
@@ -182,3 +184,5 @@ void BlurBaseOperation::determineResolution(unsigned int resolution[2],
resolution[1] += 2 * this->m_size * m_data.sizey;
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.h b/source/blender/compositor/operations/COM_BlurBaseOperation.h
index 56dacc96710..7937ebd69dc 100644
--- a/source/blender/compositor/operations/COM_BlurBaseOperation.h
+++ b/source/blender/compositor/operations/COM_BlurBaseOperation.h
@@ -25,6 +25,8 @@
#include "BLI_simd.h"
+namespace blender::compositor {
+
class BlurBaseOperation : public NodeOperation, public QualityStepHelper {
private:
protected:
@@ -53,12 +55,12 @@ class BlurBaseOperation : public NodeOperation, public QualityStepHelper {
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setData(const NodeBlurData *data);
@@ -73,5 +75,8 @@ class BlurBaseOperation : public NodeOperation, public QualityStepHelper {
this->m_extend_bounds = extend_bounds;
}
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.cc b/source/blender/compositor/operations/COM_BokehBlurOperation.cc
index 7bb8cd49bfc..3f98732b403 100644
--- a/source/blender/compositor/operations/COM_BokehBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_BokehBlurOperation.cc
@@ -22,15 +22,18 @@
#include "RE_pipeline.h"
+namespace blender::compositor {
+
BokehBlurOperation::BokehBlurOperation()
{
this->addInputSocket(DataType::Color);
- this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
+ this->addInputSocket(DataType::Color, ResizeMode::None);
this->addInputSocket(DataType::Value);
this->addInputSocket(DataType::Value);
this->addOutputSocket(DataType::Color);
- this->setComplex(true);
- this->setOpenCL(true);
+
+ flags.complex = true;
+ flags.open_cl = true;
this->m_size = 1.0f;
this->m_sizeavailable = false;
@@ -76,7 +79,7 @@ void BokehBlurOperation::executePixel(float output[4], int x, int y, void *data)
float tempBoundingBox[4];
float bokeh[4];
- this->m_inputBoundingBoxReader->readSampled(tempBoundingBox, x, y, COM_PS_NEAREST);
+ this->m_inputBoundingBoxReader->readSampled(tempBoundingBox, x, y, PixelSampler::Nearest);
if (tempBoundingBox[0] > 0.0f) {
float multiplier_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
MemoryBuffer *inputBuffer = (MemoryBuffer *)data;
@@ -90,7 +93,7 @@ void BokehBlurOperation::executePixel(float output[4], int x, int y, void *data)
zero_v4(color_accum);
if (pixelSize < 2) {
- this->m_inputProgram->readSampled(color_accum, x, y, COM_PS_NEAREST);
+ this->m_inputProgram->readSampled(color_accum, x, y, PixelSampler::Nearest);
multiplier_accum[0] = 1.0f;
multiplier_accum[1] = 1.0f;
multiplier_accum[2] = 1.0f;
@@ -106,16 +109,16 @@ void BokehBlurOperation::executePixel(float output[4], int x, int y, void *data)
maxx = MIN2(maxx, input_rect.xmax);
int step = getStep();
- int offsetadd = getOffsetAdd() * COM_NUM_CHANNELS_COLOR;
+ int offsetadd = getOffsetAdd() * COM_DATA_TYPE_COLOR_CHANNELS;
float m = this->m_bokehDimension / pixelSize;
for (int ny = miny; ny < maxy; ny += step) {
- int bufferindex = ((minx - bufferstartx) * COM_NUM_CHANNELS_COLOR) +
- ((ny - bufferstarty) * COM_NUM_CHANNELS_COLOR * bufferwidth);
+ int bufferindex = ((minx - bufferstartx) * COM_DATA_TYPE_COLOR_CHANNELS) +
+ ((ny - bufferstarty) * COM_DATA_TYPE_COLOR_CHANNELS * bufferwidth);
for (int nx = minx; nx < maxx; nx += step) {
float u = this->m_bokehMidX - (nx - x) * m;
float v = this->m_bokehMidY - (ny - y) * m;
- this->m_inputBokehProgram->readSampled(bokeh, u, v, COM_PS_NEAREST);
+ this->m_inputBokehProgram->readSampled(bokeh, u, v, PixelSampler::Nearest);
madd_v4_v4v4(color_accum, bokeh, &buffer[bufferindex]);
add_v4_v4(multiplier_accum, bokeh);
bufferindex += offsetadd;
@@ -127,7 +130,7 @@ void BokehBlurOperation::executePixel(float output[4], int x, int y, void *data)
output[3] = color_accum[3] * (1.0f / multiplier_accum[3]);
}
else {
- this->m_inputProgram->readSampled(output, x, y, COM_PS_NEAREST);
+ this->m_inputProgram->readSampled(output, x, y, PixelSampler::Nearest);
}
}
@@ -224,7 +227,7 @@ void BokehBlurOperation::updateSize()
{
if (!this->m_sizeavailable) {
float result[4];
- this->getInputSocketReader(3)->readSampled(result, 0, 0, COM_PS_NEAREST);
+ this->getInputSocketReader(3)->readSampled(result, 0, 0, PixelSampler::Nearest);
this->m_size = result[0];
CLAMP(this->m_size, 0.0f, 10.0f);
this->m_sizeavailable = true;
@@ -241,3 +244,5 @@ void BokehBlurOperation::determineResolution(unsigned int resolution[2],
resolution[1] += 2 * this->m_size * max_dim / 100.0f;
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.h b/source/blender/compositor/operations/COM_BokehBlurOperation.h
index a2e320dfdad..3ce06adb5d6 100644
--- a/source/blender/compositor/operations/COM_BokehBlurOperation.h
+++ b/source/blender/compositor/operations/COM_BokehBlurOperation.h
@@ -21,6 +21,8 @@
#include "COM_NodeOperation.h"
#include "COM_QualityStepHelper.h"
+namespace blender::compositor {
+
class BokehBlurOperation : public NodeOperation, public QualityStepHelper {
private:
SocketReader *m_inputProgram;
@@ -37,25 +39,25 @@ class BokehBlurOperation : public NodeOperation, public QualityStepHelper {
public:
BokehBlurOperation();
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
void setSize(float size)
{
@@ -68,12 +70,15 @@ class BokehBlurOperation : public NodeOperation, public QualityStepHelper {
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
std::list<cl_mem> *clMemToCleanUp,
- std::list<cl_kernel> *clKernelsToCleanUp);
+ std::list<cl_kernel> *clKernelsToCleanUp) override;
void setExtendBounds(bool extend_bounds)
{
this->m_extend_bounds = extend_bounds;
}
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BokehImageOperation.cc b/source/blender/compositor/operations/COM_BokehImageOperation.cc
index 01f8c81b3b7..63f283b6acc 100644
--- a/source/blender/compositor/operations/COM_BokehImageOperation.cc
+++ b/source/blender/compositor/operations/COM_BokehImageOperation.cc
@@ -19,6 +19,8 @@
#include "COM_BokehImageOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
BokehImageOperation::BokehImageOperation()
{
this->addOutputSocket(DataType::Color);
@@ -124,3 +126,5 @@ void BokehImageOperation::determineResolution(unsigned int resolution[2],
resolution[0] = COM_BLUR_BOKEH_PIXELS;
resolution[1] = COM_BLUR_BOKEH_PIXELS;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BokehImageOperation.h b/source/blender/compositor/operations/COM_BokehImageOperation.h
index 2d775bdf738..2e0bc8a34dc 100644
--- a/source/blender/compositor/operations/COM_BokehImageOperation.h
+++ b/source/blender/compositor/operations/COM_BokehImageOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* \brief The BokehImageOperation class is an operation that creates an image useful to mimic the
*internals of a camera.
@@ -110,23 +112,24 @@ class BokehImageOperation : public NodeOperation {
/**
* \brief The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* \brief Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* \brief Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
/**
* \brief determine the resolution of this operation. currently fixed at [COM_BLUR_BOKEH_PIXELS,
* COM_BLUR_BOKEH_PIXELS] \param resolution: \param preferredResolution:
*/
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
/**
* \brief set the node data
@@ -149,3 +152,5 @@ class BokehImageOperation : public NodeOperation {
this->m_deleteData = true;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BoxMaskOperation.cc b/source/blender/compositor/operations/COM_BoxMaskOperation.cc
index 51b1ea98456..9938d4a85ed 100644
--- a/source/blender/compositor/operations/COM_BoxMaskOperation.cc
+++ b/source/blender/compositor/operations/COM_BoxMaskOperation.cc
@@ -20,6 +20,8 @@
#include "BLI_math.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
BoxMaskOperation::BoxMaskOperation()
{
this->addInputSocket(DataType::Value);
@@ -108,3 +110,5 @@ void BoxMaskOperation::deinitExecution()
this->m_inputMask = nullptr;
this->m_inputValue = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BoxMaskOperation.h b/source/blender/compositor/operations/COM_BoxMaskOperation.h
index c98972b82b7..fdec7bdd8ca 100644
--- a/source/blender/compositor/operations/COM_BoxMaskOperation.h
+++ b/source/blender/compositor/operations/COM_BoxMaskOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class BoxMaskOperation : public NodeOperation {
private:
/**
@@ -41,17 +43,17 @@ class BoxMaskOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setData(NodeBoxMask *data)
{
@@ -63,3 +65,5 @@ class BoxMaskOperation : public NodeOperation {
this->m_maskType = maskType;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BrightnessOperation.cc b/source/blender/compositor/operations/COM_BrightnessOperation.cc
index 3a6ddd178e8..92cab47318a 100644
--- a/source/blender/compositor/operations/COM_BrightnessOperation.cc
+++ b/source/blender/compositor/operations/COM_BrightnessOperation.cc
@@ -18,6 +18,8 @@
#include "COM_BrightnessOperation.h"
+namespace blender::compositor {
+
BrightnessOperation::BrightnessOperation()
{
this->addInputSocket(DataType::Color);
@@ -89,3 +91,5 @@ void BrightnessOperation::deinitExecution()
this->m_inputBrightnessProgram = nullptr;
this->m_inputContrastProgram = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BrightnessOperation.h b/source/blender/compositor/operations/COM_BrightnessOperation.h
index 6fbcfe3a17a..7c33e0b35ec 100644
--- a/source/blender/compositor/operations/COM_BrightnessOperation.h
+++ b/source/blender/compositor/operations/COM_BrightnessOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class BrightnessOperation : public NodeOperation {
private:
/**
@@ -37,17 +39,19 @@ class BrightnessOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setUsePremultiply(bool use_premultiply);
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CalculateMeanOperation.cc b/source/blender/compositor/operations/COM_CalculateMeanOperation.cc
index fdeecd0cb29..a7ea49aed8d 100644
--- a/source/blender/compositor/operations/COM_CalculateMeanOperation.cc
+++ b/source/blender/compositor/operations/COM_CalculateMeanOperation.cc
@@ -22,14 +22,16 @@
#include "IMB_colormanagement.h"
+namespace blender::compositor {
+
CalculateMeanOperation::CalculateMeanOperation()
{
- this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
+ this->addInputSocket(DataType::Color, ResizeMode::None);
this->addOutputSocket(DataType::Value);
this->m_imageReader = nullptr;
this->m_iscalculated = false;
this->m_setting = 1;
- this->setComplex(true);
+ this->flags.complex = true;
}
void CalculateMeanOperation::initExecution()
{
@@ -125,3 +127,5 @@ void CalculateMeanOperation::calculateMean(MemoryBuffer *tile)
}
this->m_result = sum / pixels;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CalculateMeanOperation.h b/source/blender/compositor/operations/COM_CalculateMeanOperation.h
index e4937931df0..8b3bf281c93 100644
--- a/source/blender/compositor/operations/COM_CalculateMeanOperation.h
+++ b/source/blender/compositor/operations/COM_CalculateMeanOperation.h
@@ -21,6 +21,8 @@
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
/**
* \brief base class of CalculateMean, implementing the simple CalculateMean
* \ingroup operation
@@ -42,23 +44,23 @@ class CalculateMeanOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
void setSetting(int setting)
{
this->m_setting = setting;
@@ -67,3 +69,5 @@ class CalculateMeanOperation : public NodeOperation {
protected:
void calculateMean(MemoryBuffer *tile);
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cc b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cc
index 9a1e48177ed..5ddb4b1c859 100644
--- a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cc
+++ b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cc
@@ -22,6 +22,8 @@
#include "IMB_colormanagement.h"
+namespace blender::compositor {
+
CalculateStandardDeviationOperation::CalculateStandardDeviationOperation()
{
/* pass */
@@ -98,3 +100,5 @@ void *CalculateStandardDeviationOperation::initializeTileData(rcti *rect)
unlockMutex();
return nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.h b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.h
index a267663cfc8..b8487e0aa4c 100644
--- a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.h
+++ b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.h
@@ -21,6 +21,9 @@
#include "COM_CalculateMeanOperation.h"
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
+
+namespace blender::compositor {
+
/**
* \brief base class of CalculateStandardDeviation,
* implementing the simple CalculateStandardDeviation.
@@ -36,7 +39,9 @@ class CalculateStandardDeviationOperation : public CalculateMeanOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ChangeHSVOperation.cc b/source/blender/compositor/operations/COM_ChangeHSVOperation.cc
index e53a416f0dd..eee007ce9e6 100644
--- a/source/blender/compositor/operations/COM_ChangeHSVOperation.cc
+++ b/source/blender/compositor/operations/COM_ChangeHSVOperation.cc
@@ -18,6 +18,8 @@
#include "COM_ChangeHSVOperation.h"
+namespace blender::compositor {
+
ChangeHSVOperation::ChangeHSVOperation()
{
this->addInputSocket(DataType::Color);
@@ -68,3 +70,5 @@ void ChangeHSVOperation::executePixelSampled(float output[4],
output[2] = inputColor1[2] * value[0];
output[3] = inputColor1[3];
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ChangeHSVOperation.h b/source/blender/compositor/operations/COM_ChangeHSVOperation.h
index edc532a3f43..d38b4be3efe 100644
--- a/source/blender/compositor/operations/COM_ChangeHSVOperation.h
+++ b/source/blender/compositor/operations/COM_ChangeHSVOperation.h
@@ -20,6 +20,8 @@
#include "COM_MixOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -37,11 +39,13 @@ class ChangeHSVOperation : public NodeOperation {
*/
ChangeHSVOperation();
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ChannelMatteOperation.cc b/source/blender/compositor/operations/COM_ChannelMatteOperation.cc
index 98105a9dfde..89290978608 100644
--- a/source/blender/compositor/operations/COM_ChannelMatteOperation.cc
+++ b/source/blender/compositor/operations/COM_ChannelMatteOperation.cc
@@ -19,6 +19,8 @@
#include "COM_ChannelMatteOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
ChannelMatteOperation::ChannelMatteOperation()
{
addInputSocket(DataType::Color);
@@ -118,3 +120,5 @@ void ChannelMatteOperation::executePixelSampled(float output[4],
/* Don't make something that was more transparent less transparent. */
output[0] = MIN2(alpha, inColor[3]);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ChannelMatteOperation.h b/source/blender/compositor/operations/COM_ChannelMatteOperation.h
index 9a0b888b5a2..6e9dcccd36e 100644
--- a/source/blender/compositor/operations/COM_ChannelMatteOperation.h
+++ b/source/blender/compositor/operations/COM_ChannelMatteOperation.h
@@ -20,6 +20,8 @@
#include "COM_MixOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -56,10 +58,10 @@ class ChannelMatteOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setSettings(NodeChroma *nodeChroma, const int custom2)
{
@@ -70,3 +72,5 @@ class ChannelMatteOperation : public NodeOperation {
this->m_matte_channel = custom2;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ChromaMatteOperation.cc b/source/blender/compositor/operations/COM_ChromaMatteOperation.cc
index 09bf9c76e55..69aa4aac163 100644
--- a/source/blender/compositor/operations/COM_ChromaMatteOperation.cc
+++ b/source/blender/compositor/operations/COM_ChromaMatteOperation.cc
@@ -19,6 +19,8 @@
#include "COM_ChromaMatteOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
ChromaMatteOperation::ChromaMatteOperation()
{
addInputSocket(DataType::Color);
@@ -107,3 +109,5 @@ void ChromaMatteOperation::executePixelSampled(float output[4],
output[0] = inImage[3]; /* make pixel just as transparent as it was before */
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ChromaMatteOperation.h b/source/blender/compositor/operations/COM_ChromaMatteOperation.h
index c8d261284ed..48c3a785011 100644
--- a/source/blender/compositor/operations/COM_ChromaMatteOperation.h
+++ b/source/blender/compositor/operations/COM_ChromaMatteOperation.h
@@ -20,6 +20,8 @@
#include "COM_MixOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -39,13 +41,15 @@ class ChromaMatteOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setSettings(NodeChroma *nodeChroma)
{
this->m_settings = nodeChroma;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cc b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cc
index b21e453699b..d1d3752e402 100644
--- a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cc
@@ -19,6 +19,8 @@
#include "COM_ColorBalanceASCCDLOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
inline float colorbalance_cdl(float in, float offset, float power, float slope)
{
float x = in * slope + offset;
@@ -79,3 +81,5 @@ void ColorBalanceASCCDLOperation::deinitExecution()
this->m_inputValueOperation = nullptr;
this->m_inputColorOperation = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h
index 1ec920cb2da..5851600190f 100644
--- a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h
+++ b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -45,17 +47,17 @@ class ColorBalanceASCCDLOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setOffset(float offset[3])
{
@@ -70,3 +72,5 @@ class ColorBalanceASCCDLOperation : public NodeOperation {
copy_v3_v3(this->m_slope, slope);
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc
index b6ff636bce9..cac16a3f7b0 100644
--- a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc
@@ -19,6 +19,8 @@
#include "COM_ColorBalanceLGGOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
inline float colorbalance_lgg(float in, float lift_lgg, float gamma_inv, float gain)
{
/* 1:1 match with the sequencer with linear/srgb conversions, the conversion isn't pretty
@@ -84,3 +86,5 @@ void ColorBalanceLGGOperation::deinitExecution()
this->m_inputValueOperation = nullptr;
this->m_inputColorOperation = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h
index e6acd16e4f0..23f70247b66 100644
--- a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h
+++ b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -45,17 +47,17 @@ class ColorBalanceLGGOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setGain(const float gain[3])
{
@@ -70,3 +72,5 @@ class ColorBalanceLGGOperation : public NodeOperation {
copy_v3_v3(this->m_gamma_inv, gamma_inv);
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cc b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cc
index b2578451180..168e9b57eb2 100644
--- a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cc
@@ -21,6 +21,8 @@
#include "IMB_colormanagement.h"
+namespace blender::compositor {
+
ColorCorrectionOperation::ColorCorrectionOperation()
{
this->addInputSocket(DataType::Color);
@@ -160,3 +162,5 @@ void ColorCorrectionOperation::deinitExecution()
this->m_inputImage = nullptr;
this->m_inputMask = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorCorrectionOperation.h b/source/blender/compositor/operations/COM_ColorCorrectionOperation.h
index 9a2e60c0d77..c5826ed0152 100644
--- a/source/blender/compositor/operations/COM_ColorCorrectionOperation.h
+++ b/source/blender/compositor/operations/COM_ColorCorrectionOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class ColorCorrectionOperation : public NodeOperation {
private:
/**
@@ -39,17 +41,17 @@ class ColorCorrectionOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setData(NodeColorCorrection *data)
{
@@ -68,3 +70,5 @@ class ColorCorrectionOperation : public NodeOperation {
this->m_blueChannelEnabled = enabled;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorCurveOperation.cc b/source/blender/compositor/operations/COM_ColorCurveOperation.cc
index 35218cef7cc..cb0565a81a2 100644
--- a/source/blender/compositor/operations/COM_ColorCurveOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorCurveOperation.cc
@@ -22,6 +22,8 @@
#include "MEM_guardedalloc.h"
+namespace blender::compositor {
+
ColorCurveOperation::ColorCurveOperation()
{
this->addInputSocket(DataType::Value);
@@ -151,3 +153,5 @@ void ConstantLevelColorCurveOperation::deinitExecution()
this->m_inputFacProgram = nullptr;
this->m_inputImageProgram = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorCurveOperation.h b/source/blender/compositor/operations/COM_ColorCurveOperation.h
index 2eb20148db9..6fc7759b8d2 100644
--- a/source/blender/compositor/operations/COM_ColorCurveOperation.h
+++ b/source/blender/compositor/operations/COM_ColorCurveOperation.h
@@ -22,6 +22,8 @@
#include "COM_NodeOperation.h"
#include "DNA_color_types.h"
+namespace blender::compositor {
+
class ColorCurveOperation : public CurveBaseOperation {
private:
/**
@@ -38,17 +40,17 @@ class ColorCurveOperation : public CurveBaseOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
};
class ConstantLevelColorCurveOperation : public CurveBaseOperation {
@@ -67,17 +69,17 @@ class ConstantLevelColorCurveOperation : public CurveBaseOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setBlackLevel(float black[3])
{
@@ -88,3 +90,5 @@ class ConstantLevelColorCurveOperation : public CurveBaseOperation {
copy_v3_v3(this->m_white, white);
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorExposureOperation.cc b/source/blender/compositor/operations/COM_ColorExposureOperation.cc
index 0e24620846e..1512ff87658 100644
--- a/source/blender/compositor/operations/COM_ColorExposureOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorExposureOperation.cc
@@ -18,6 +18,8 @@
#include "COM_ColorExposureOperation.h"
+namespace blender::compositor {
+
ExposureOperation::ExposureOperation()
{
this->addInputSocket(DataType::Color);
@@ -55,3 +57,5 @@ void ExposureOperation::deinitExecution()
this->m_inputProgram = nullptr;
this->m_inputExposureProgram = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorExposureOperation.h b/source/blender/compositor/operations/COM_ColorExposureOperation.h
index 97590b85d77..0cfaa059e41 100644
--- a/source/blender/compositor/operations/COM_ColorExposureOperation.h
+++ b/source/blender/compositor/operations/COM_ColorExposureOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class ExposureOperation : public NodeOperation {
private:
/**
@@ -34,15 +36,17 @@ class ExposureOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorMatteOperation.cc b/source/blender/compositor/operations/COM_ColorMatteOperation.cc
index cc7a81f68d1..89f56ac4aae 100644
--- a/source/blender/compositor/operations/COM_ColorMatteOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorMatteOperation.cc
@@ -19,6 +19,8 @@
#include "COM_ColorMatteOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
ColorMatteOperation::ColorMatteOperation()
{
addInputSocket(DataType::Color);
@@ -79,3 +81,5 @@ void ColorMatteOperation::executePixelSampled(float output[4],
output[0] = inColor[3]; /* make pixel just as transparent as it was before */
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorMatteOperation.h b/source/blender/compositor/operations/COM_ColorMatteOperation.h
index 91ba27ce2b6..439a3b0741d 100644
--- a/source/blender/compositor/operations/COM_ColorMatteOperation.h
+++ b/source/blender/compositor/operations/COM_ColorMatteOperation.h
@@ -20,6 +20,8 @@
#include "COM_MixOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -39,13 +41,15 @@ class ColorMatteOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setSettings(NodeChroma *nodeChroma)
{
this->m_settings = nodeChroma;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorRampOperation.cc b/source/blender/compositor/operations/COM_ColorRampOperation.cc
index 4fde951fd3c..0ee65a6529e 100644
--- a/source/blender/compositor/operations/COM_ColorRampOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorRampOperation.cc
@@ -20,6 +20,8 @@
#include "BKE_colorband.h"
+namespace blender::compositor {
+
ColorRampOperation::ColorRampOperation()
{
this->addInputSocket(DataType::Value);
@@ -48,3 +50,5 @@ void ColorRampOperation::deinitExecution()
{
this->m_inputProgram = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorRampOperation.h b/source/blender/compositor/operations/COM_ColorRampOperation.h
index 49bdb266ce9..d32af9bea24 100644
--- a/source/blender/compositor/operations/COM_ColorRampOperation.h
+++ b/source/blender/compositor/operations/COM_ColorRampOperation.h
@@ -21,6 +21,8 @@
#include "COM_NodeOperation.h"
#include "DNA_texture_types.h"
+namespace blender::compositor {
+
class ColorRampOperation : public NodeOperation {
private:
/**
@@ -35,20 +37,22 @@ class ColorRampOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setColorBand(ColorBand *colorBand)
{
this->m_colorBand = colorBand;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorSpillOperation.cc b/source/blender/compositor/operations/COM_ColorSpillOperation.cc
index 8e8eaabfc6b..7dc7e2775fc 100644
--- a/source/blender/compositor/operations/COM_ColorSpillOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorSpillOperation.cc
@@ -20,6 +20,8 @@
#include "BLI_math.h"
#define AVG(a, b) ((a + b) / 2)
+namespace blender::compositor {
+
ColorSpillOperation::ColorSpillOperation()
{
addInputSocket(DataType::Color);
@@ -115,3 +117,5 @@ void ColorSpillOperation::executePixelSampled(float output[4],
copy_v4_v4(output, input);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorSpillOperation.h b/source/blender/compositor/operations/COM_ColorSpillOperation.h
index e51101adf84..9b82e720527 100644
--- a/source/blender/compositor/operations/COM_ColorSpillOperation.h
+++ b/source/blender/compositor/operations/COM_ColorSpillOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -44,10 +46,10 @@ class ColorSpillOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setSettings(NodeColorspill *nodeColorSpill)
{
@@ -64,3 +66,5 @@ class ColorSpillOperation : public NodeOperation {
float calculateMapValue(float fac, float *input);
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cc b/source/blender/compositor/operations/COM_CompositorOperation.cc
index 0454bae8b38..94d41b28f5d 100644
--- a/source/blender/compositor/operations/COM_CompositorOperation.cc
+++ b/source/blender/compositor/operations/COM_CompositorOperation.cc
@@ -31,6 +31,8 @@
#include "PIL_time.h"
+namespace blender::compositor {
+
CompositorOperation::CompositorOperation()
{
this->addInputSocket(DataType::Color);
@@ -50,6 +52,8 @@ CompositorOperation::CompositorOperation()
this->m_scene = nullptr;
this->m_sceneName[0] = '\0';
this->m_viewName = nullptr;
+
+ flags.use_render_border = true;
}
void CompositorOperation::initExecution()
@@ -147,7 +151,7 @@ void CompositorOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
int y2 = rect->ymax;
int offset = (y1 * this->getWidth() + x1);
int add = (this->getWidth() - (x2 - x1));
- int offset4 = offset * COM_NUM_CHANNELS_COLOR;
+ int offset4 = offset * COM_DATA_TYPE_COLOR_CHANNELS;
int x;
int y;
bool breaked = false;
@@ -196,23 +200,23 @@ void CompositorOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
for (x = x1; x < x2 && (!breaked); x++) {
int input_x = x + dx, input_y = y + dy;
- this->m_imageInput->readSampled(color, input_x, input_y, COM_PS_NEAREST);
+ this->m_imageInput->readSampled(color, input_x, input_y, PixelSampler::Nearest);
if (this->m_useAlphaInput) {
- this->m_alphaInput->readSampled(&(color[3]), input_x, input_y, COM_PS_NEAREST);
+ this->m_alphaInput->readSampled(&(color[3]), input_x, input_y, PixelSampler::Nearest);
}
copy_v4_v4(buffer + offset4, color);
- this->m_depthInput->readSampled(color, input_x, input_y, COM_PS_NEAREST);
+ this->m_depthInput->readSampled(color, input_x, input_y, PixelSampler::Nearest);
zbuffer[offset] = color[0];
- offset4 += COM_NUM_CHANNELS_COLOR;
+ offset4 += COM_DATA_TYPE_COLOR_CHANNELS;
offset++;
if (isBraked()) {
breaked = true;
}
}
offset += add;
- offset4 += add * COM_NUM_CHANNELS_COLOR;
+ offset4 += add * COM_DATA_TYPE_COLOR_CHANNELS;
}
}
@@ -242,3 +246,5 @@ void CompositorOperation::determineResolution(unsigned int resolution[2],
resolution[0] = width;
resolution[1] = height;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CompositorOperation.h b/source/blender/compositor/operations/COM_CompositorOperation.h
index 63b87563852..49ed65f01fc 100644
--- a/source/blender/compositor/operations/COM_CompositorOperation.h
+++ b/source/blender/compositor/operations/COM_CompositorOperation.h
@@ -24,6 +24,8 @@
struct Scene;
+namespace blender::compositor {
+
/**
* \brief Compositor output operation
*/
@@ -86,7 +88,7 @@ class CompositorOperation : public NodeOperation {
{
return this->m_active;
}
- void executeRegion(rcti *rect, unsigned int tileNumber);
+ void executeRegion(rcti *rect, unsigned int tileNumber) override;
void setScene(const struct Scene *scene)
{
m_scene = scene;
@@ -103,17 +105,18 @@ class CompositorOperation : public NodeOperation {
{
this->m_rd = rd;
}
- bool isOutputOperation(bool /*rendering*/) const
+ bool isOutputOperation(bool /*rendering*/) const override
{
return this->isActiveCompositorOutput();
}
- void initExecution();
- void deinitExecution();
- CompositorPriority getRenderPriority() const
+ void initExecution() override;
+ void deinitExecution() override;
+ CompositorPriority getRenderPriority() const override
{
return CompositorPriority::Medium;
}
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
void setUseAlphaInput(bool value)
{
this->m_useAlphaInput = value;
@@ -123,3 +126,5 @@ class CompositorOperation : public NodeOperation {
this->m_active = active;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cc b/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cc
index 431f0e9c880..c00fe5d5f61 100644
--- a/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cc
+++ b/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cc
@@ -20,6 +20,8 @@
#include "IMB_imbuf.h"
+namespace blender::compositor {
+
ConvertColorProfileOperation::ConvertColorProfileOperation()
{
this->addInputSocket(DataType::Color);
@@ -48,3 +50,5 @@ void ConvertColorProfileOperation::deinitExecution()
{
this->m_inputOperation = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConvertColorProfileOperation.h b/source/blender/compositor/operations/COM_ConvertColorProfileOperation.h
index 7b96895d845..6162408501b 100644
--- a/source/blender/compositor/operations/COM_ConvertColorProfileOperation.h
+++ b/source/blender/compositor/operations/COM_ConvertColorProfileOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -55,17 +57,17 @@ class ConvertColorProfileOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setFromColorProfile(int colorProfile)
{
@@ -80,3 +82,5 @@ class ConvertColorProfileOperation : public NodeOperation {
this->m_predivided = predivided;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cc b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cc
index 17b351cb14c..57027c11949 100644
--- a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cc
+++ b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cc
@@ -21,6 +21,8 @@
#include "BLI_math.h"
#include "DNA_camera_types.h"
+namespace blender::compositor {
+
ConvertDepthToRadiusOperation::ConvertDepthToRadiusOperation()
{
this->addInputSocket(DataType::Value);
@@ -113,3 +115,5 @@ void ConvertDepthToRadiusOperation::deinitExecution()
{
this->m_inputOperation = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.h b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.h
index 564a0facec7..1f4e856b128 100644
--- a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.h
+++ b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.h
@@ -21,6 +21,9 @@
#include "COM_FastGaussianBlurOperation.h"
#include "COM_NodeOperation.h"
#include "DNA_object_types.h"
+
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -51,17 +54,17 @@ class ConvertDepthToRadiusOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setfStop(float fStop)
{
@@ -81,3 +84,5 @@ class ConvertDepthToRadiusOperation : public NodeOperation {
this->m_blurPostOperation = operation;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConvertOperation.cc b/source/blender/compositor/operations/COM_ConvertOperation.cc
index 648b3f0b30a..2ea15185c0f 100644
--- a/source/blender/compositor/operations/COM_ConvertOperation.cc
+++ b/source/blender/compositor/operations/COM_ConvertOperation.cc
@@ -20,6 +20,8 @@
#include "IMB_colormanagement.h"
+namespace blender::compositor {
+
ConvertBaseOperation::ConvertBaseOperation()
{
this->m_inputOperation = nullptr;
@@ -478,3 +480,5 @@ void CombineChannelsOperation::executePixelSampled(float output[4],
output[3] = input[0];
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConvertOperation.h b/source/blender/compositor/operations/COM_ConvertOperation.h
index ca026528a38..7a726e35c7c 100644
--- a/source/blender/compositor/operations/COM_ConvertOperation.h
+++ b/source/blender/compositor/operations/COM_ConvertOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class ConvertBaseOperation : public NodeOperation {
protected:
SocketReader *m_inputOperation;
@@ -27,57 +29,57 @@ class ConvertBaseOperation : public NodeOperation {
public:
ConvertBaseOperation();
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
};
class ConvertValueToColorOperation : public ConvertBaseOperation {
public:
ConvertValueToColorOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ConvertColorToValueOperation : public ConvertBaseOperation {
public:
ConvertColorToValueOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ConvertColorToBWOperation : public ConvertBaseOperation {
public:
ConvertColorToBWOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ConvertColorToVectorOperation : public ConvertBaseOperation {
public:
ConvertColorToVectorOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ConvertValueToVectorOperation : public ConvertBaseOperation {
public:
ConvertValueToVectorOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ConvertVectorToColorOperation : public ConvertBaseOperation {
public:
ConvertVectorToColorOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ConvertVectorToValueOperation : public ConvertBaseOperation {
public:
ConvertVectorToValueOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ConvertRGBToYCCOperation : public ConvertBaseOperation {
@@ -88,7 +90,7 @@ class ConvertRGBToYCCOperation : public ConvertBaseOperation {
public:
ConvertRGBToYCCOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/** Set the YCC mode */
void setMode(int mode);
@@ -102,7 +104,7 @@ class ConvertYCCToRGBOperation : public ConvertBaseOperation {
public:
ConvertYCCToRGBOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/** Set the YCC mode */
void setMode(int mode);
@@ -112,42 +114,42 @@ class ConvertRGBToYUVOperation : public ConvertBaseOperation {
public:
ConvertRGBToYUVOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ConvertYUVToRGBOperation : public ConvertBaseOperation {
public:
ConvertYUVToRGBOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ConvertRGBToHSVOperation : public ConvertBaseOperation {
public:
ConvertRGBToHSVOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ConvertHSVToRGBOperation : public ConvertBaseOperation {
public:
ConvertHSVToRGBOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ConvertPremulToStraightOperation : public ConvertBaseOperation {
public:
ConvertPremulToStraightOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ConvertStraightToPremulOperation : public ConvertBaseOperation {
public:
ConvertStraightToPremulOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class SeparateChannelOperation : public NodeOperation {
@@ -157,10 +159,10 @@ class SeparateChannelOperation : public NodeOperation {
public:
SeparateChannelOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setChannel(int channel)
{
@@ -177,8 +179,10 @@ class CombineChannelsOperation : public NodeOperation {
public:
CombineChannelsOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cc b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cc
index a5f2ae404e3..9114200a8ec 100644
--- a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cc
+++ b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cc
@@ -19,6 +19,8 @@
#include "COM_ConvolutionEdgeFilterOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
ConvolutionEdgeFilterOperation::ConvolutionEdgeFilterOperation()
{
/* pass */
@@ -97,3 +99,5 @@ void ConvolutionEdgeFilterOperation::executePixel(float output[4], int x, int y,
output[2] = MAX2(output[2], 0.0f);
output[3] = MAX2(output[3], 0.0f);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.h b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.h
index ab4b8a1dad1..98bfa1768d8 100644
--- a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.h
+++ b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.h
@@ -20,8 +20,12 @@
#include "COM_ConvolutionFilterOperation.h"
+namespace blender::compositor {
+
class ConvolutionEdgeFilterOperation : public ConvolutionFilterOperation {
public:
ConvolutionEdgeFilterOperation();
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cc b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cc
index f80144fb06d..72cbbf4283a 100644
--- a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cc
+++ b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cc
@@ -22,6 +22,8 @@
#include "MEM_guardedalloc.h"
+namespace blender::compositor {
+
ConvolutionFilterOperation::ConvolutionFilterOperation()
{
this->addInputSocket(DataType::Color);
@@ -29,7 +31,7 @@ ConvolutionFilterOperation::ConvolutionFilterOperation()
this->addOutputSocket(DataType::Color);
this->setResolutionInputSocketIndex(0);
this->m_inputOperation = nullptr;
- this->setComplex(true);
+ this->flags.complex = true;
}
void ConvolutionFilterOperation::initExecution()
{
@@ -124,3 +126,5 @@ bool ConvolutionFilterOperation::determineDependingAreaOfInterest(
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.h b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.h
index d178b0a7418..16dee502929 100644
--- a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.h
+++ b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class ConvolutionFilterOperation : public NodeOperation {
private:
int m_filterWidth;
@@ -36,9 +38,11 @@ class ConvolutionFilterOperation : public NodeOperation {
float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9);
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
- void executePixel(float output[4], int x, int y, void *data);
+ rcti *output) override;
+ void executePixel(float output[4], int x, int y, void *data) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CropOperation.cc b/source/blender/compositor/operations/COM_CropOperation.cc
index 55a1e505ec8..f12d93bc8d3 100644
--- a/source/blender/compositor/operations/COM_CropOperation.cc
+++ b/source/blender/compositor/operations/COM_CropOperation.cc
@@ -19,9 +19,11 @@
#include "COM_CropOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
CropBaseOperation::CropBaseOperation()
{
- this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
+ this->addInputSocket(DataType::Color, ResizeMode::None);
this->addOutputSocket(DataType::Color);
this->m_inputOperation = nullptr;
this->m_settings = nullptr;
@@ -133,3 +135,5 @@ void CropImageOperation::executePixelSampled(float output[4],
zero_v4(output);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CropOperation.h b/source/blender/compositor/operations/COM_CropOperation.h
index f20664f0501..acdff79a77c 100644
--- a/source/blender/compositor/operations/COM_CropOperation.h
+++ b/source/blender/compositor/operations/COM_CropOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class CropBaseOperation : public NodeOperation {
protected:
SocketReader *m_inputOperation;
@@ -34,8 +36,8 @@ class CropBaseOperation : public NodeOperation {
public:
CropBaseOperation();
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setCropSettings(NodeTwoXYs *settings)
{
this->m_settings = settings;
@@ -50,7 +52,7 @@ class CropOperation : public CropBaseOperation {
private:
public:
CropOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class CropImageOperation : public CropBaseOperation {
@@ -59,7 +61,10 @@ class CropImageOperation : public CropBaseOperation {
CropImageOperation();
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ rcti *output) override;
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CryptomatteOperation.cc b/source/blender/compositor/operations/COM_CryptomatteOperation.cc
index 8d42a756f51..52ae1d6d5b5 100644
--- a/source/blender/compositor/operations/COM_CryptomatteOperation.cc
+++ b/source/blender/compositor/operations/COM_CryptomatteOperation.cc
@@ -18,14 +18,16 @@
#include "COM_CryptomatteOperation.h"
+namespace blender::compositor {
+
CryptomatteOperation::CryptomatteOperation(size_t num_inputs)
{
+ inputs.resize(num_inputs);
for (size_t i = 0; i < num_inputs; i++) {
this->addInputSocket(DataType::Color);
}
- inputs.resize(num_inputs);
this->addOutputSocket(DataType::Color);
- this->setComplex(true);
+ this->flags.complex = true;
}
void CryptomatteOperation::initExecution()
@@ -38,7 +40,7 @@ void CryptomatteOperation::initExecution()
void CryptomatteOperation::addObjectIndex(float objectIndex)
{
if (objectIndex != 0.0f) {
- m_objectIndex.push_back(objectIndex);
+ m_objectIndex.append(objectIndex);
}
}
@@ -58,13 +60,15 @@ void CryptomatteOperation::executePixel(float output[4], int x, int y, void *dat
output[1] = ((float)((m3hash << 8)) / (float)UINT32_MAX);
output[2] = ((float)((m3hash << 16)) / (float)UINT32_MAX);
}
- for (size_t i = 0; i < m_objectIndex.size(); i++) {
- if (m_objectIndex[i] == input[0]) {
+ for (float hash : m_objectIndex) {
+ if (input[0] == hash) {
output[3] += input[1];
}
- if (m_objectIndex[i] == input[2]) {
+ if (input[2] == hash) {
output[3] += input[3];
}
}
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CryptomatteOperation.h b/source/blender/compositor/operations/COM_CryptomatteOperation.h
index 8c5a3134720..40a1fbf5a80 100644
--- a/source/blender/compositor/operations/COM_CryptomatteOperation.h
+++ b/source/blender/compositor/operations/COM_CryptomatteOperation.h
@@ -20,17 +20,21 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class CryptomatteOperation : public NodeOperation {
private:
- std::vector<float> m_objectIndex;
+ blender::Vector<float> m_objectIndex;
public:
- std::vector<SocketReader *> inputs;
+ blender::Vector<SocketReader *> inputs;
CryptomatteOperation(size_t num_inputs = 6);
- void initExecution();
- void executePixel(float output[4], int x, int y, void *data);
+ void initExecution() override;
+ void executePixel(float output[4], int x, int y, void *data) override;
void addObjectIndex(float objectIndex);
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CurveBaseOperation.cc b/source/blender/compositor/operations/COM_CurveBaseOperation.cc
index b58efcf0cca..8f655964570 100644
--- a/source/blender/compositor/operations/COM_CurveBaseOperation.cc
+++ b/source/blender/compositor/operations/COM_CurveBaseOperation.cc
@@ -20,6 +20,8 @@
#include "BKE_colortools.h"
+namespace blender::compositor {
+
CurveBaseOperation::CurveBaseOperation()
{
this->m_curveMapping = nullptr;
@@ -53,3 +55,5 @@ void CurveBaseOperation::setCurveMapping(CurveMapping *mapping)
}
this->m_curveMapping = BKE_curvemapping_copy(mapping);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CurveBaseOperation.h b/source/blender/compositor/operations/COM_CurveBaseOperation.h
index 63e667cfe12..fff0f3168ba 100644
--- a/source/blender/compositor/operations/COM_CurveBaseOperation.h
+++ b/source/blender/compositor/operations/COM_CurveBaseOperation.h
@@ -21,6 +21,8 @@
#include "COM_NodeOperation.h"
#include "DNA_color_types.h"
+namespace blender::compositor {
+
class CurveBaseOperation : public NodeOperation {
protected:
/**
@@ -35,8 +37,10 @@ class CurveBaseOperation : public NodeOperation {
/**
* Initialize the execution
*/
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setCurveMapping(CurveMapping *mapping);
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DenoiseOperation.cc b/source/blender/compositor/operations/COM_DenoiseOperation.cc
index 66d0f3fd9bd..587afdc2d00 100644
--- a/source/blender/compositor/operations/COM_DenoiseOperation.cc
+++ b/source/blender/compositor/operations/COM_DenoiseOperation.cc
@@ -26,6 +26,8 @@ static pthread_mutex_t oidn_lock = BLI_MUTEX_INITIALIZER;
#endif
#include <iostream>
+namespace blender::compositor {
+
DenoiseOperation::DenoiseOperation()
{
this->addInputSocket(DataType::Color);
@@ -164,3 +166,5 @@ void DenoiseOperation::generateDenoise(float *data,
inputBufferColor,
sizeof(float[4]) * inputTileColor->getWidth() * inputTileColor->getHeight());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DenoiseOperation.h b/source/blender/compositor/operations/COM_DenoiseOperation.h
index 5af6e16c958..a9298c17e92 100644
--- a/source/blender/compositor/operations/COM_DenoiseOperation.h
+++ b/source/blender/compositor/operations/COM_DenoiseOperation.h
@@ -21,6 +21,8 @@
#include "COM_SingleThreadedOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
class DenoiseOperation : public SingleThreadedOperation {
private:
/**
@@ -40,12 +42,12 @@ class DenoiseOperation : public SingleThreadedOperation {
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setDenoiseSettings(NodeDenoise *settings)
{
@@ -53,7 +55,7 @@ class DenoiseOperation : public SingleThreadedOperation {
}
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
protected:
void generateDenoise(float *data,
@@ -62,5 +64,7 @@ class DenoiseOperation : public SingleThreadedOperation {
MemoryBuffer *inputTileAlbedo,
NodeDenoise *settings);
- MemoryBuffer *createMemoryBuffer(rcti *rect);
+ MemoryBuffer *createMemoryBuffer(rcti *rect) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DespeckleOperation.cc b/source/blender/compositor/operations/COM_DespeckleOperation.cc
index 813ae07a97a..fc8778c7d2e 100644
--- a/source/blender/compositor/operations/COM_DespeckleOperation.cc
+++ b/source/blender/compositor/operations/COM_DespeckleOperation.cc
@@ -22,6 +22,8 @@
#include "BLI_utildefines.h"
+namespace blender::compositor {
+
DespeckleOperation::DespeckleOperation()
{
this->addInputSocket(DataType::Color);
@@ -29,7 +31,7 @@ DespeckleOperation::DespeckleOperation()
this->addOutputSocket(DataType::Color);
this->setResolutionInputSocketIndex(0);
this->m_inputOperation = nullptr;
- this->setComplex(true);
+ this->flags.complex = true;
}
void DespeckleOperation::initExecution()
{
@@ -141,3 +143,5 @@ bool DespeckleOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DespeckleOperation.h b/source/blender/compositor/operations/COM_DespeckleOperation.h
index af37c276bd2..e8d3461d2ec 100644
--- a/source/blender/compositor/operations/COM_DespeckleOperation.h
+++ b/source/blender/compositor/operations/COM_DespeckleOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class DespeckleOperation : public NodeOperation {
private:
float m_threshold;
@@ -36,8 +38,8 @@ class DespeckleOperation : public NodeOperation {
DespeckleOperation();
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
- void executePixel(float output[4], int x, int y, void *data);
+ rcti *output) override;
+ void executePixel(float output[4], int x, int y, void *data) override;
void setThreshold(float threshold)
{
@@ -48,6 +50,8 @@ class DespeckleOperation : public NodeOperation {
this->m_threshold_neighbor = threshold;
}
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DifferenceMatteOperation.cc b/source/blender/compositor/operations/COM_DifferenceMatteOperation.cc
index 1ce91aeb4c3..e380131634f 100644
--- a/source/blender/compositor/operations/COM_DifferenceMatteOperation.cc
+++ b/source/blender/compositor/operations/COM_DifferenceMatteOperation.cc
@@ -19,6 +19,8 @@
#include "COM_DifferenceMatteOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
DifferenceMatteOperation::DifferenceMatteOperation()
{
addInputSocket(DataType::Color);
@@ -83,3 +85,5 @@ void DifferenceMatteOperation::executePixelSampled(float output[4],
output[0] = inColor1[3];
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DifferenceMatteOperation.h b/source/blender/compositor/operations/COM_DifferenceMatteOperation.h
index 0ee5eab3fe7..d3963fee1c1 100644
--- a/source/blender/compositor/operations/COM_DifferenceMatteOperation.h
+++ b/source/blender/compositor/operations/COM_DifferenceMatteOperation.h
@@ -20,6 +20,8 @@
#include "COM_MixOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -39,13 +41,15 @@ class DifferenceMatteOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setSettings(NodeChroma *nodeChroma)
{
this->m_settings = nodeChroma;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cc b/source/blender/compositor/operations/COM_DilateErodeOperation.cc
index 33ddf9187b0..9e18a8e2f2c 100644
--- a/source/blender/compositor/operations/COM_DilateErodeOperation.cc
+++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cc
@@ -22,12 +22,14 @@
#include "MEM_guardedalloc.h"
+namespace blender::compositor {
+
// DilateErode Distance Threshold
DilateErodeThresholdOperation::DilateErodeThresholdOperation()
{
this->addInputSocket(DataType::Value);
this->addOutputSocket(DataType::Value);
- this->setComplex(true);
+ this->flags.complex = true;
this->m_inputProgram = nullptr;
this->m_inset = 0.0f;
this->m__switch = 0.5f;
@@ -163,10 +165,10 @@ DilateDistanceOperation::DilateDistanceOperation()
{
this->addInputSocket(DataType::Value);
this->addOutputSocket(DataType::Value);
- this->setComplex(true);
this->m_inputProgram = nullptr;
this->m_distance = 0.0f;
- this->setOpenCL(true);
+ flags.complex = true;
+ flags.open_cl = true;
}
void DilateDistanceOperation::initExecution()
{
@@ -321,7 +323,7 @@ DilateStepOperation::DilateStepOperation()
{
this->addInputSocket(DataType::Value);
this->addOutputSocket(DataType::Value);
- this->setComplex(true);
+ this->flags.complex = true;
this->m_inputProgram = nullptr;
}
void DilateStepOperation::initExecution()
@@ -568,3 +570,5 @@ void *ErodeStepOperation::initializeTileData(rcti *rect)
return result;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.h b/source/blender/compositor/operations/COM_DilateErodeOperation.h
index 35f9be89220..a489e293e8e 100644
--- a/source/blender/compositor/operations/COM_DilateErodeOperation.h
+++ b/source/blender/compositor/operations/COM_DilateErodeOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class DilateErodeThresholdOperation : public NodeOperation {
private:
/**
@@ -43,18 +45,18 @@ class DilateErodeThresholdOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setDistance(float distance)
{
@@ -71,7 +73,7 @@ class DilateErodeThresholdOperation : public NodeOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
};
class DilateDistanceOperation : public NodeOperation {
@@ -90,18 +92,18 @@ class DilateDistanceOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setDistance(float distance)
{
@@ -109,14 +111,14 @@ class DilateDistanceOperation : public NodeOperation {
}
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
void executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
std::list<cl_mem> *clMemToCleanUp,
- std::list<cl_kernel> *clKernelsToCleanUp);
+ std::list<cl_kernel> *clKernelsToCleanUp) override;
};
class ErodeDistanceOperation : public DilateDistanceOperation {
public:
@@ -125,14 +127,14 @@ class ErodeDistanceOperation : public DilateDistanceOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
void executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
std::list<cl_mem> *clMemToCleanUp,
- std::list<cl_kernel> *clKernelsToCleanUp);
+ std::list<cl_kernel> *clKernelsToCleanUp) override;
};
class DilateStepOperation : public NodeOperation {
@@ -150,19 +152,19 @@ class DilateStepOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
- void deinitializeTileData(rcti *rect, void *data);
+ void deinitExecution() override;
+ void deinitializeTileData(rcti *rect, void *data) override;
void setIterations(int iterations)
{
@@ -171,12 +173,14 @@ class DilateStepOperation : public NodeOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
};
class ErodeStepOperation : public DilateStepOperation {
public:
ErodeStepOperation();
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cc b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cc
index 1a2701a681d..97bdc25af3b 100644
--- a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cc
@@ -23,13 +23,14 @@
#include "RE_pipeline.h"
+namespace blender::compositor {
+
DirectionalBlurOperation::DirectionalBlurOperation()
{
this->addInputSocket(DataType::Color);
this->addOutputSocket(DataType::Color);
- this->setComplex(true);
-
- this->setOpenCL(true);
+ flags.complex = true;
+ flags.open_cl = true;
this->m_inputProgram = nullptr;
}
@@ -66,7 +67,7 @@ void DirectionalBlurOperation::executePixel(float output[4], int x, int y, void
const int iterations = pow(2.0f, this->m_data->iter);
float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float col2[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- this->m_inputProgram->readSampled(col2, x, y, COM_PS_BILINEAR);
+ this->m_inputProgram->readSampled(col2, x, y, PixelSampler::Bilinear);
float ltx = this->m_tx;
float lty = this->m_ty;
float lsc = this->m_sc;
@@ -82,7 +83,7 @@ void DirectionalBlurOperation::executePixel(float output[4], int x, int y, void
this->m_inputProgram->readSampled(col,
cs * u + ss * v + this->m_center_x_pix,
cs * v - ss * u + this->m_center_y_pix,
- COM_PS_BILINEAR);
+ PixelSampler::Bilinear);
add_v4_v4(col2, col);
@@ -144,3 +145,5 @@ bool DirectionalBlurOperation::determineDependingAreaOfInterest(rcti * /*input*/
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DirectionalBlurOperation.h b/source/blender/compositor/operations/COM_DirectionalBlurOperation.h
index 0c220f0e239..5555520462b 100644
--- a/source/blender/compositor/operations/COM_DirectionalBlurOperation.h
+++ b/source/blender/compositor/operations/COM_DirectionalBlurOperation.h
@@ -21,6 +21,8 @@
#include "COM_NodeOperation.h"
#include "COM_QualityStepHelper.h"
+namespace blender::compositor {
+
class DirectionalBlurOperation : public NodeOperation, public QualityStepHelper {
private:
SocketReader *m_inputProgram;
@@ -36,21 +38,21 @@ class DirectionalBlurOperation : public NodeOperation, public QualityStepHelper
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
void setData(NodeDBlurData *data)
{
@@ -62,5 +64,7 @@ class DirectionalBlurOperation : public NodeOperation, public QualityStepHelper
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
std::list<cl_mem> *clMemToCleanUp,
- std::list<cl_kernel> *clKernelsToCleanUp);
+ std::list<cl_kernel> *clKernelsToCleanUp) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DisplaceOperation.cc b/source/blender/compositor/operations/COM_DisplaceOperation.cc
index 12c7d29a210..9f3f5cfe489 100644
--- a/source/blender/compositor/operations/COM_DisplaceOperation.cc
+++ b/source/blender/compositor/operations/COM_DisplaceOperation.cc
@@ -20,6 +20,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+namespace blender::compositor {
+
DisplaceOperation::DisplaceOperation()
{
this->addInputSocket(DataType::Color);
@@ -27,7 +29,7 @@ DisplaceOperation::DisplaceOperation()
this->addInputSocket(DataType::Value);
this->addInputSocket(DataType::Value);
this->addOutputSocket(DataType::Color);
- this->setComplex(true);
+ this->flags.complex = true;
this->m_inputColorProgram = nullptr;
this->m_inputVectorProgram = nullptr;
@@ -56,7 +58,7 @@ void DisplaceOperation::executePixelSampled(float output[4],
pixelTransform(xy, uv, deriv);
if (is_zero_v2(deriv[0]) && is_zero_v2(deriv[1])) {
- this->m_inputColorProgram->readSampled(output, uv[0], uv[1], COM_PS_BILINEAR);
+ this->m_inputColorProgram->readSampled(output, uv[0], uv[1], PixelSampler::Bilinear);
}
else {
/* EWA filtering (without nearest it gets blurry with NO distortion) */
@@ -76,7 +78,7 @@ bool DisplaceOperation::read_displacement(
}
float col[4];
- m_inputVectorProgram->readSampled(col, x, y, COM_PS_BILINEAR);
+ m_inputVectorProgram->readSampled(col, x, y, PixelSampler::Bilinear);
r_u = origin[0] - col[0] * xscale;
r_v = origin[1] - col[1] * yscale;
return true;
@@ -88,9 +90,9 @@ void DisplaceOperation::pixelTransform(const float xy[2], float r_uv[2], float r
float uv[2]; /* temporary variables for derivative estimation */
int num;
- m_inputScaleXProgram->readSampled(col, xy[0], xy[1], COM_PS_NEAREST);
+ m_inputScaleXProgram->readSampled(col, xy[0], xy[1], PixelSampler::Nearest);
float xs = col[0];
- m_inputScaleYProgram->readSampled(col, xy[0], xy[1], COM_PS_NEAREST);
+ m_inputScaleYProgram->readSampled(col, xy[0], xy[1], PixelSampler::Nearest);
float ys = col[0];
/* clamp x and y displacement to triple image resolution -
* to prevent hangs from huge values mistakenly plugged in eg. z buffers */
@@ -192,3 +194,5 @@ bool DisplaceOperation::determineDependingAreaOfInterest(rcti *input,
return false;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DisplaceOperation.h b/source/blender/compositor/operations/COM_DisplaceOperation.h
index 52874779f73..fd82692f687 100644
--- a/source/blender/compositor/operations/COM_DisplaceOperation.h
+++ b/source/blender/compositor/operations/COM_DisplaceOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class DisplaceOperation : public NodeOperation {
private:
/**
@@ -41,26 +43,28 @@ class DisplaceOperation : public NodeOperation {
*/
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
void pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2]);
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
private:
bool read_displacement(
float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v);
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cc b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cc
index 9d00c2cb148..f4b77f5d32c 100644
--- a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cc
+++ b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cc
@@ -20,6 +20,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+namespace blender::compositor {
+
DisplaceSimpleOperation::DisplaceSimpleOperation()
{
this->addInputSocket(DataType::Color);
@@ -129,3 +131,5 @@ bool DisplaceSimpleOperation::determineDependingAreaOfInterest(rcti *input,
return false;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h
index 3b850d94750..15e6fcd0523 100644
--- a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h
+++ b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class DisplaceSimpleOperation : public NodeOperation {
private:
/**
@@ -41,20 +43,22 @@ class DisplaceSimpleOperation : public NodeOperation {
*/
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.cc b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.cc
index ae024d497d6..12cb7e7d075 100644
--- a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.cc
+++ b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.cc
@@ -19,6 +19,8 @@
#include "COM_DistanceRGBMatteOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
DistanceRGBMatteOperation::DistanceRGBMatteOperation()
{
this->addInputSocket(DataType::Color);
@@ -90,3 +92,5 @@ void DistanceRGBMatteOperation::executePixelSampled(float output[4],
output[0] = inImage[3];
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h
index 5c8c2204637..6fe603233b7 100644
--- a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h
+++ b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h
@@ -20,6 +20,8 @@
#include "COM_MixOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -41,13 +43,15 @@ class DistanceRGBMatteOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setSettings(NodeChroma *nodeChroma)
{
this->m_settings = nodeChroma;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.cc b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.cc
index f333cc1ecd9..15ed2b0aaa4 100644
--- a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.cc
+++ b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.cc
@@ -19,6 +19,8 @@
#include "COM_DistanceYCCMatteOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
DistanceYCCMatteOperation::DistanceYCCMatteOperation()
{
/* pass */
@@ -29,3 +31,5 @@ float DistanceYCCMatteOperation::calculateDistance(float key[4], float image[4])
/* only measure the second 2 values */
return len_v2v2(key + 1, image + 1);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h
index e9b2cda6251..9027fbabe7b 100644
--- a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h
+++ b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h
@@ -21,13 +21,15 @@
#include "COM_DistanceRGBMatteOperation.h"
#include "COM_MixOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
class DistanceYCCMatteOperation : public DistanceRGBMatteOperation {
protected:
- virtual float calculateDistance(float key[4], float image[4]);
+ float calculateDistance(float key[4], float image[4]) override;
public:
/**
@@ -35,3 +37,5 @@ class DistanceYCCMatteOperation : public DistanceRGBMatteOperation {
*/
DistanceYCCMatteOperation();
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DotproductOperation.cc b/source/blender/compositor/operations/COM_DotproductOperation.cc
index c5b89bb7fae..07075ae1d9d 100644
--- a/source/blender/compositor/operations/COM_DotproductOperation.cc
+++ b/source/blender/compositor/operations/COM_DotproductOperation.cc
@@ -18,6 +18,8 @@
#include "COM_DotproductOperation.h"
+namespace blender::compositor {
+
DotproductOperation::DotproductOperation()
{
this->addInputSocket(DataType::Vector);
@@ -52,3 +54,5 @@ void DotproductOperation::executePixelSampled(float output[4],
this->m_input2Operation->readSampled(input2, x, y, sampler);
output[0] = -(input1[0] * input2[0] + input1[1] * input2[1] + input1[2] * input2[2]);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DotproductOperation.h b/source/blender/compositor/operations/COM_DotproductOperation.h
index 63b735ce30f..728033bcf32 100644
--- a/source/blender/compositor/operations/COM_DotproductOperation.h
+++ b/source/blender/compositor/operations/COM_DotproductOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class DotproductOperation : public NodeOperation {
private:
SocketReader *m_input1Operation;
@@ -27,8 +29,10 @@ class DotproductOperation : public NodeOperation {
public:
DotproductOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cc b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cc
index 4c7cbb3cc7e..a3a86a6c502 100644
--- a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cc
+++ b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cc
@@ -23,6 +23,8 @@
#include "DNA_node_types.h"
#include "MEM_guardedalloc.h"
+namespace blender::compositor {
+
// this part has been copied from the double edge mask
static void do_adjacentKeepBorders(unsigned int t,
unsigned int rw,
@@ -1315,7 +1317,7 @@ DoubleEdgeMaskOperation::DoubleEdgeMaskOperation()
this->m_inputOuterMask = nullptr;
this->m_adjacentOnly = false;
this->m_keepInside = false;
- this->setComplex(true);
+ this->flags.complex = true;
}
bool DoubleEdgeMaskOperation::determineDependingAreaOfInterest(rcti * /*input*/,
@@ -1379,3 +1381,5 @@ void DoubleEdgeMaskOperation::deinitExecution()
this->m_cachedInstance = nullptr;
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h
index 813f5009815..e956e8edc3e 100644
--- a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h
+++ b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class DoubleEdgeMaskOperation : public NodeOperation {
private:
/**
@@ -38,23 +40,23 @@ class DoubleEdgeMaskOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
void setAdjecentOnly(bool adjacentOnly)
{
@@ -65,3 +67,5 @@ class DoubleEdgeMaskOperation : public NodeOperation {
this->m_keepInside = keepInside;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_EllipseMaskOperation.cc b/source/blender/compositor/operations/COM_EllipseMaskOperation.cc
index 956b5e50edc..5a4503fecec 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"
+namespace blender::compositor {
+
EllipseMaskOperation::EllipseMaskOperation()
{
this->addInputSocket(DataType::Value);
@@ -117,3 +119,5 @@ void EllipseMaskOperation::deinitExecution()
this->m_inputMask = nullptr;
this->m_inputValue = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_EllipseMaskOperation.h b/source/blender/compositor/operations/COM_EllipseMaskOperation.h
index 8fce7166900..64afe0145cf 100644
--- a/source/blender/compositor/operations/COM_EllipseMaskOperation.h
+++ b/source/blender/compositor/operations/COM_EllipseMaskOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class EllipseMaskOperation : public NodeOperation {
private:
/**
@@ -41,17 +43,17 @@ class EllipseMaskOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setData(NodeEllipseMask *data)
{
@@ -63,3 +65,5 @@ class EllipseMaskOperation : public NodeOperation {
this->m_maskType = maskType;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc
index 4dded61fba5..2be6e4d1be7 100644
--- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc
@@ -22,6 +22,8 @@
#include "COM_FastGaussianBlurOperation.h"
#include "MEM_guardedalloc.h"
+namespace blender::compositor {
+
FastGaussianBlurOperation::FastGaussianBlurOperation() : BlurBaseOperation(DataType::Color)
{
this->m_iirgaus = nullptr;
@@ -88,18 +90,18 @@ void *FastGaussianBlurOperation::initializeTileData(rcti *rect)
this->m_sy = this->m_data.sizey * this->m_size / 2.0f;
if ((this->m_sx == this->m_sy) && (this->m_sx > 0.0f)) {
- for (c = 0; c < COM_NUM_CHANNELS_COLOR; c++) {
+ for (c = 0; c < COM_DATA_TYPE_COLOR_CHANNELS; c++) {
IIR_gauss(copy, this->m_sx, c, 3);
}
}
else {
if (this->m_sx > 0.0f) {
- for (c = 0; c < COM_NUM_CHANNELS_COLOR; c++) {
+ for (c = 0; c < COM_DATA_TYPE_COLOR_CHANNELS; c++) {
IIR_gauss(copy, this->m_sx, c, 1);
}
}
if (this->m_sy > 0.0f) {
- for (c = 0; c < COM_NUM_CHANNELS_COLOR; c++) {
+ for (c = 0; c < COM_DATA_TYPE_COLOR_CHANNELS; c++) {
IIR_gauss(copy, this->m_sy, c, 2);
}
}
@@ -264,7 +266,7 @@ FastGaussianBlurValueOperation::FastGaussianBlurValueOperation()
this->m_inputprogram = nullptr;
this->m_sigma = 1.0f;
this->m_overlay = 0;
- setComplex(true);
+ flags.complex = true;
}
void FastGaussianBlurValueOperation::executePixel(float output[4], int x, int y, void *data)
@@ -317,7 +319,7 @@ void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect)
float *src = newBuf->getBuffer();
float *dst = copy->getBuffer();
for (int i = copy->getWidth() * copy->getHeight(); i != 0;
- i--, src += COM_NUM_CHANNELS_VALUE, dst += COM_NUM_CHANNELS_VALUE) {
+ i--, src += COM_DATA_TYPE_VALUE_CHANNELS, dst += COM_DATA_TYPE_VALUE_CHANNELS) {
if (*src < *dst) {
*dst = *src;
}
@@ -327,7 +329,7 @@ void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect)
float *src = newBuf->getBuffer();
float *dst = copy->getBuffer();
for (int i = copy->getWidth() * copy->getHeight(); i != 0;
- i--, src += COM_NUM_CHANNELS_VALUE, dst += COM_NUM_CHANNELS_VALUE) {
+ i--, src += COM_DATA_TYPE_VALUE_CHANNELS, dst += COM_DATA_TYPE_VALUE_CHANNELS) {
if (*src > *dst) {
*dst = *src;
}
@@ -341,3 +343,5 @@ void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect)
unlockMutex();
return this->m_iirgaus;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h
index 6ab6474c20a..c25afe6c4a4 100644
--- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h
+++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h
@@ -21,6 +21,8 @@
#include "COM_BlurBaseOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
class FastGaussianBlurOperation : public BlurBaseOperation {
private:
float m_sx;
@@ -31,13 +33,13 @@ class FastGaussianBlurOperation : public BlurBaseOperation {
FastGaussianBlurOperation();
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
- void executePixel(float output[4], int x, int y, void *data);
+ rcti *output) override;
+ void executePixel(float output[4], int x, int y, void *data) override;
static void IIR_gauss(MemoryBuffer *src, float sigma, unsigned int channel, unsigned int xy);
- void *initializeTileData(rcti *rect);
- void deinitExecution();
- void initExecution();
+ void *initializeTileData(rcti *rect) override;
+ void deinitExecution() override;
+ void initExecution() override;
};
enum {
@@ -62,12 +64,12 @@ class FastGaussianBlurValueOperation : public NodeOperation {
FastGaussianBlurValueOperation();
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
- void executePixel(float output[4], int x, int y, void *data);
+ rcti *output) override;
+ void executePixel(float output[4], int x, int y, void *data) override;
- void *initializeTileData(rcti *rect);
- void deinitExecution();
- void initExecution();
+ void *initializeTileData(rcti *rect) override;
+ void deinitExecution() override;
+ void initExecution() override;
void setSigma(float sigma)
{
this->m_sigma = sigma;
@@ -79,3 +81,5 @@ class FastGaussianBlurValueOperation : public NodeOperation {
this->m_overlay = overlay;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_FlipOperation.cc b/source/blender/compositor/operations/COM_FlipOperation.cc
index 4837766b5eb..8afbec4ddbe 100644
--- a/source/blender/compositor/operations/COM_FlipOperation.cc
+++ b/source/blender/compositor/operations/COM_FlipOperation.cc
@@ -18,6 +18,8 @@
#include "COM_FlipOperation.h"
+namespace blender::compositor {
+
FlipOperation::FlipOperation()
{
this->addInputSocket(DataType::Color);
@@ -72,3 +74,5 @@ bool FlipOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_FlipOperation.h b/source/blender/compositor/operations/COM_FlipOperation.h
index 711b51261e6..f26d587fde6 100644
--- a/source/blender/compositor/operations/COM_FlipOperation.h
+++ b/source/blender/compositor/operations/COM_FlipOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class FlipOperation : public NodeOperation {
private:
SocketReader *m_inputOperation;
@@ -30,11 +32,11 @@ class FlipOperation : public NodeOperation {
FlipOperation();
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ rcti *output) override;
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setFlipX(bool flipX)
{
this->m_flipX = flipX;
@@ -44,3 +46,5 @@ class FlipOperation : public NodeOperation {
this->m_flipY = flipY;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GammaCorrectOperation.cc b/source/blender/compositor/operations/COM_GammaCorrectOperation.cc
index 51c033498ef..16b79fddd06 100644
--- a/source/blender/compositor/operations/COM_GammaCorrectOperation.cc
+++ b/source/blender/compositor/operations/COM_GammaCorrectOperation.cc
@@ -19,6 +19,8 @@
#include "COM_GammaCorrectOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
GammaCorrectOperation::GammaCorrectOperation()
{
this->addInputSocket(DataType::Color);
@@ -102,3 +104,5 @@ void GammaUncorrectOperation::deinitExecution()
{
this->m_inputProgram = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GammaCorrectOperation.h b/source/blender/compositor/operations/COM_GammaCorrectOperation.h
index 077493bbd2f..ac3d45b94b1 100644
--- a/source/blender/compositor/operations/COM_GammaCorrectOperation.h
+++ b/source/blender/compositor/operations/COM_GammaCorrectOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class GammaCorrectOperation : public NodeOperation {
private:
/**
@@ -33,17 +35,17 @@ class GammaCorrectOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
};
class GammaUncorrectOperation : public NodeOperation {
@@ -59,15 +61,17 @@ class GammaUncorrectOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GammaOperation.cc b/source/blender/compositor/operations/COM_GammaOperation.cc
index 327c5c24929..343e335070a 100644
--- a/source/blender/compositor/operations/COM_GammaOperation.cc
+++ b/source/blender/compositor/operations/COM_GammaOperation.cc
@@ -19,6 +19,8 @@
#include "COM_GammaOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
GammaOperation::GammaOperation()
{
this->addInputSocket(DataType::Color);
@@ -54,3 +56,5 @@ void GammaOperation::deinitExecution()
this->m_inputProgram = nullptr;
this->m_inputGammaProgram = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GammaOperation.h b/source/blender/compositor/operations/COM_GammaOperation.h
index 8641f2fde62..034046106d6 100644
--- a/source/blender/compositor/operations/COM_GammaOperation.h
+++ b/source/blender/compositor/operations/COM_GammaOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class GammaOperation : public NodeOperation {
private:
/**
@@ -34,15 +36,17 @@ class GammaOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cc b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cc
index 1f03bb8d9cb..7ca5dc4ca76 100644
--- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cc
@@ -22,6 +22,8 @@
#include "RE_pipeline.h"
+namespace blender::compositor {
+
GaussianAlphaXBlurOperation::GaussianAlphaXBlurOperation() : BlurBaseOperation(DataType::Value)
{
this->m_gausstab = nullptr;
@@ -190,3 +192,5 @@ bool GaussianAlphaXBlurOperation::determineDependingAreaOfInterest(
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h
index 2d536a98bee..949956fae04 100644
--- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h
@@ -21,6 +21,8 @@
#include "COM_BlurBaseOperation.h"
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class GaussianAlphaXBlurOperation : public BlurBaseOperation {
private:
float *m_gausstab;
@@ -36,22 +38,22 @@ class GaussianAlphaXBlurOperation : public BlurBaseOperation {
/**
* \brief The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* \brief initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* \brief Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
/**
* Set subtract for Dilate/Erode functionality
@@ -65,3 +67,5 @@ class GaussianAlphaXBlurOperation : public BlurBaseOperation {
this->m_falloff = falloff;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cc b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cc
index de35c164fc7..d2385a972dd 100644
--- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cc
@@ -22,6 +22,8 @@
#include "RE_pipeline.h"
+namespace blender::compositor {
+
GaussianAlphaYBlurOperation::GaussianAlphaYBlurOperation() : BlurBaseOperation(DataType::Value)
{
this->m_gausstab = nullptr;
@@ -189,3 +191,5 @@ bool GaussianAlphaYBlurOperation::determineDependingAreaOfInterest(
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h
index 7f1dfd78e7c..d25770386c4 100644
--- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h
@@ -21,6 +21,8 @@
#include "COM_BlurBaseOperation.h"
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class GaussianAlphaYBlurOperation : public BlurBaseOperation {
private:
float *m_gausstab;
@@ -36,22 +38,22 @@ class GaussianAlphaYBlurOperation : public BlurBaseOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* \brief initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
/**
* Set subtract for Dilate/Erode functionality
@@ -65,3 +67,5 @@ class GaussianAlphaYBlurOperation : public BlurBaseOperation {
this->m_falloff = falloff;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cc b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cc
index 73b0914c086..b2c65ff2c96 100644
--- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cc
@@ -22,6 +22,8 @@
#include "RE_pipeline.h"
+namespace blender::compositor {
+
GaussianBokehBlurOperation::GaussianBokehBlurOperation() : BlurBaseOperation(DataType::Color)
{
this->m_gausstab = nullptr;
@@ -303,7 +305,7 @@ void GaussianBlurReferenceOperation::executePixel(float output[4], int x, int y,
int minyr = y - refrady < 0 ? -y : -refrady;
int maxyr = y + refrady > imgy ? imgy - y : refrady;
- float *srcd = buffer + COM_NUM_CHANNELS_COLOR * ((y + minyr) * imgx + x + minxr);
+ float *srcd = buffer + COM_DATA_TYPE_COLOR_CHANNELS * ((y + minyr) * imgx + x + minxr);
gausstabx = m_maintabs[refradx - 1];
gausstabcentx = gausstabx + refradx;
@@ -311,9 +313,9 @@ void GaussianBlurReferenceOperation::executePixel(float output[4], int x, int y,
gausstabcenty = gausstaby + refrady;
sum = gval = rval = bval = aval = 0.0f;
- for (i = minyr; i < maxyr; i++, srcd += COM_NUM_CHANNELS_COLOR * imgx) {
+ for (i = minyr; i < maxyr; i++, srcd += COM_DATA_TYPE_COLOR_CHANNELS * imgx) {
src = srcd;
- for (j = minxr; j < maxxr; j++, src += COM_NUM_CHANNELS_COLOR) {
+ for (j = minxr; j < maxxr; j++, src += COM_DATA_TYPE_COLOR_CHANNELS) {
val = gausstabcenty[i] * gausstabcentx[j];
sum += val;
@@ -360,3 +362,5 @@ bool GaussianBlurReferenceOperation::determineDependingAreaOfInterest(
newInput.ymin = input->ymin - addy;
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h
index a37a70b4b33..59ba3d06619 100644
--- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.h
@@ -22,6 +22,8 @@
#include "COM_NodeOperation.h"
#include "COM_QualityStepHelper.h"
+namespace blender::compositor {
+
class GaussianBokehBlurOperation : public BlurBaseOperation {
private:
float *m_gausstab;
@@ -30,21 +32,21 @@ class GaussianBokehBlurOperation : public BlurBaseOperation {
public:
GaussianBokehBlurOperation();
- void initExecution();
- void *initializeTileData(rcti *rect);
+ void initExecution() override;
+ void *initializeTileData(rcti *rect) override;
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
};
class GaussianBlurReferenceOperation : public BlurBaseOperation {
@@ -59,19 +61,21 @@ class GaussianBlurReferenceOperation : public BlurBaseOperation {
public:
GaussianBlurReferenceOperation();
- void initExecution();
- void *initializeTileData(rcti *rect);
+ void initExecution() override;
+ void *initializeTileData(rcti *rect) override;
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cc b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cc
index 43bf961cfc4..4b46cfc8776 100644
--- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cc
@@ -23,6 +23,8 @@
#include "RE_pipeline.h"
+namespace blender::compositor {
+
GaussianXBlurOperation::GaussianXBlurOperation() : BlurBaseOperation(DataType::Color)
{
this->m_gausstab = nullptr;
@@ -205,3 +207,5 @@ bool GaussianXBlurOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h
index 78ea6aa3cc2..15277f0a42d 100644
--- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h
@@ -21,6 +21,8 @@
#include "COM_BlurBaseOperation.h"
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class GaussianXBlurOperation : public BlurBaseOperation {
private:
float *m_gausstab;
@@ -36,32 +38,34 @@ class GaussianXBlurOperation : public BlurBaseOperation {
/**
* \brief The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
void executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
std::list<cl_mem> *clMemToCleanUp,
- std::list<cl_kernel> *clKernelsToCleanUp);
+ std::list<cl_kernel> *clKernelsToCleanUp) override;
/**
* \brief initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* \brief Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
void checkOpenCL()
{
- this->setOpenCL(m_data.sizex >= 128);
+ flags.open_cl = (m_data.sizex >= 128);
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cc b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cc
index 1e853dfb8f9..590ac5faa6a 100644
--- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cc
@@ -23,6 +23,8 @@
#include "RE_pipeline.h"
+namespace blender::compositor {
+
GaussianYBlurOperation::GaussianYBlurOperation() : BlurBaseOperation(DataType::Color)
{
this->m_gausstab = nullptr;
@@ -205,3 +207,5 @@ bool GaussianYBlurOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h
index 8e7440b6fe4..56d40849ba4 100644
--- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h
@@ -21,6 +21,8 @@
#include "COM_BlurBaseOperation.h"
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class GaussianYBlurOperation : public BlurBaseOperation {
private:
float *m_gausstab;
@@ -36,32 +38,34 @@ class GaussianYBlurOperation : public BlurBaseOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
void executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
std::list<cl_mem> *clMemToCleanUp,
- std::list<cl_kernel> *clKernelsToCleanUp);
+ std::list<cl_kernel> *clKernelsToCleanUp) override;
/**
* \brief initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
void checkOpenCL()
{
- this->setOpenCL(m_data.sizex >= 128);
+ flags.open_cl = (m_data.sizex >= 128);
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GlareBaseOperation.cc b/source/blender/compositor/operations/COM_GlareBaseOperation.cc
index cdf64ed8b5a..90755d9f27a 100644
--- a/source/blender/compositor/operations/COM_GlareBaseOperation.cc
+++ b/source/blender/compositor/operations/COM_GlareBaseOperation.cc
@@ -19,6 +19,8 @@
#include "COM_GlareBaseOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
GlareBaseOperation::GlareBaseOperation()
{
this->addInputSocket(DataType::Color);
@@ -66,3 +68,5 @@ bool GlareBaseOperation::determineDependingAreaOfInterest(rcti * /*input*/,
newInput.ymin = 0;
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GlareBaseOperation.h b/source/blender/compositor/operations/COM_GlareBaseOperation.h
index aabb76f5cf0..7ae15595e3b 100644
--- a/source/blender/compositor/operations/COM_GlareBaseOperation.h
+++ b/source/blender/compositor/operations/COM_GlareBaseOperation.h
@@ -21,6 +21,8 @@
#include "COM_SingleThreadedOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
/* utility functions used by glare, tonemap and lens distortion */
/* soms macros for color handling */
typedef float fRGB[4];
@@ -51,12 +53,12 @@ class GlareBaseOperation : public SingleThreadedOperation {
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setGlareSettings(NodeGlare *settings)
{
@@ -64,12 +66,14 @@ class GlareBaseOperation : public SingleThreadedOperation {
}
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
protected:
GlareBaseOperation();
virtual void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings) = 0;
- MemoryBuffer *createMemoryBuffer(rcti *rect);
+ MemoryBuffer *createMemoryBuffer(rcti *rect) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cc b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cc
index 23dfc95f9e3..1c1eaebd331 100644
--- a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cc
+++ b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cc
@@ -19,6 +19,8 @@
#include "COM_GlareFogGlowOperation.h"
#include "MEM_guardedalloc.h"
+namespace blender::compositor {
+
/*
* 2D Fast Hartley Transform, used for convolution
*/
@@ -271,7 +273,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
MemoryBuffer *rdst = new MemoryBuffer(DataType::Color, in1->get_rect());
memset(rdst->getBuffer(),
0,
- rdst->getWidth() * rdst->getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float));
+ rdst->getWidth() * rdst->getHeight() * COM_DATA_TYPE_COLOR_CHANNELS * sizeof(float));
// convolution result width & height
w2 = 2 * kernelWidth - 1;
@@ -287,7 +289,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
// normalize convolutor
wt[0] = wt[1] = wt[2] = 0.0f;
for (y = 0; y < kernelHeight; y++) {
- colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUM_CHANNELS_COLOR];
+ colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_DATA_TYPE_COLOR_CHANNELS];
for (x = 0; x < kernelWidth; x++) {
add_v3_v3(wt, colp[x]);
}
@@ -302,7 +304,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
wt[2] = 1.0f / wt[2];
}
for (y = 0; y < kernelHeight; y++) {
- colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUM_CHANNELS_COLOR];
+ colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_DATA_TYPE_COLOR_CHANNELS];
for (x = 0; x < kernelWidth; x++) {
mul_v3_v3(colp[x], wt);
}
@@ -336,7 +338,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
// in2, channel ch -> data1
for (y = 0; y < kernelHeight; y++) {
fp = &data1ch[y * w2];
- colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUM_CHANNELS_COLOR];
+ colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_DATA_TYPE_COLOR_CHANNELS];
for (x = 0; x < kernelWidth; x++) {
fp[x] = colp[x][ch];
}
@@ -351,7 +353,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
continue;
}
fp = &data2[y * w2];
- colp = (fRGB *)&imageBuffer[yy * imageWidth * COM_NUM_CHANNELS_COLOR];
+ colp = (fRGB *)&imageBuffer[yy * imageWidth * COM_DATA_TYPE_COLOR_CHANNELS];
for (x = 0; x < xbsz; x++) {
int xx = xbl * xbsz + x;
if (xx >= imageWidth) {
@@ -381,7 +383,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
continue;
}
fp = &data2[y * w2];
- colp = (fRGB *)&rdst->getBuffer()[yy * imageWidth * COM_NUM_CHANNELS_COLOR];
+ colp = (fRGB *)&rdst->getBuffer()[yy * imageWidth * COM_DATA_TYPE_COLOR_CHANNELS];
for (x = 0; x < (int)w2; x++) {
const int xx = xbl * xbsz + x - hw;
if ((xx < 0) || (xx >= imageWidth)) {
@@ -397,8 +399,9 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
MEM_freeN(data2);
MEM_freeN(data1);
- memcpy(
- dst, rdst->getBuffer(), sizeof(float) * imageWidth * imageHeight * COM_NUM_CHANNELS_COLOR);
+ memcpy(dst,
+ rdst->getBuffer(),
+ sizeof(float) * imageWidth * imageHeight * COM_DATA_TYPE_COLOR_CHANNELS);
delete (rdst);
}
@@ -442,3 +445,5 @@ void GlareFogGlowOperation::generateGlare(float *data,
convolve(data, inputTile, ckrn);
delete ckrn;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GlareFogGlowOperation.h b/source/blender/compositor/operations/COM_GlareFogGlowOperation.h
index 9084f27052e..5701f76ab13 100644
--- a/source/blender/compositor/operations/COM_GlareFogGlowOperation.h
+++ b/source/blender/compositor/operations/COM_GlareFogGlowOperation.h
@@ -22,6 +22,8 @@
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
class GlareFogGlowOperation : public GlareBaseOperation {
public:
GlareFogGlowOperation() : GlareBaseOperation()
@@ -29,5 +31,7 @@ class GlareFogGlowOperation : public GlareBaseOperation {
}
protected:
- void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings);
+ void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GlareGhostOperation.cc b/source/blender/compositor/operations/COM_GlareGhostOperation.cc
index a4cd6dc60c1..22c8767632e 100644
--- a/source/blender/compositor/operations/COM_GlareGhostOperation.cc
+++ b/source/blender/compositor/operations/COM_GlareGhostOperation.cc
@@ -20,6 +20,8 @@
#include "BLI_math.h"
#include "COM_FastGaussianBlurOperation.h"
+namespace blender::compositor {
+
static float smoothMask(float x, float y)
{
float t;
@@ -123,7 +125,7 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No
memset(tbuf1.getBuffer(),
0,
- tbuf1.getWidth() * tbuf1.getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float));
+ tbuf1.getWidth() * tbuf1.getHeight() * COM_DATA_TYPE_COLOR_CHANNELS * sizeof(float));
for (n = 1; n < settings->iter && (!breaked); n++) {
for (y = 0; y < gbuf.getHeight() && (!breaked); y++) {
v = ((float)y + 0.5f) / (float)gbuf.getHeight();
@@ -147,9 +149,11 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No
}
memcpy(gbuf.getBuffer(),
tbuf1.getBuffer(),
- tbuf1.getWidth() * tbuf1.getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float));
+ tbuf1.getWidth() * tbuf1.getHeight() * COM_DATA_TYPE_COLOR_CHANNELS * sizeof(float));
}
memcpy(data,
gbuf.getBuffer(),
- gbuf.getWidth() * gbuf.getHeight() * COM_NUM_CHANNELS_COLOR * sizeof(float));
+ gbuf.getWidth() * gbuf.getHeight() * COM_DATA_TYPE_COLOR_CHANNELS * sizeof(float));
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GlareGhostOperation.h b/source/blender/compositor/operations/COM_GlareGhostOperation.h
index 8ecf8da3385..60256d8e0ef 100644
--- a/source/blender/compositor/operations/COM_GlareGhostOperation.h
+++ b/source/blender/compositor/operations/COM_GlareGhostOperation.h
@@ -22,6 +22,8 @@
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
class GlareGhostOperation : public GlareBaseOperation {
public:
GlareGhostOperation() : GlareBaseOperation()
@@ -29,5 +31,7 @@ class GlareGhostOperation : public GlareBaseOperation {
}
protected:
- void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings);
+ void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cc b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cc
index a2cecb7e171..cc24a50a307 100644
--- a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cc
+++ b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cc
@@ -18,6 +18,8 @@
#include "COM_GlareSimpleStarOperation.h"
+namespace blender::compositor {
+
void GlareSimpleStarOperation::generateGlare(float *data,
MemoryBuffer *inputTile,
NodeGlare *settings)
@@ -97,3 +99,5 @@ void GlareSimpleStarOperation::generateGlare(float *data,
data[i] = tbuf1.getBuffer()[i] + tbuf2.getBuffer()[i];
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.h b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.h
index 0f5913fcef9..4a074f53e7b 100644
--- a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.h
+++ b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.h
@@ -22,6 +22,8 @@
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
class GlareSimpleStarOperation : public GlareBaseOperation {
public:
GlareSimpleStarOperation() : GlareBaseOperation()
@@ -29,5 +31,7 @@ class GlareSimpleStarOperation : public GlareBaseOperation {
}
protected:
- void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings);
+ void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GlareStreaksOperation.cc b/source/blender/compositor/operations/COM_GlareStreaksOperation.cc
index 0ea277881da..0af4eb43624 100644
--- a/source/blender/compositor/operations/COM_GlareStreaksOperation.cc
+++ b/source/blender/compositor/operations/COM_GlareStreaksOperation.cc
@@ -19,6 +19,8 @@
#include "COM_GlareStreaksOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
void GlareStreaksOperation::generateGlare(float *data,
MemoryBuffer *inputTile,
NodeGlare *settings)
@@ -97,3 +99,5 @@ void GlareStreaksOperation::generateGlare(float *data,
nump++;
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GlareStreaksOperation.h b/source/blender/compositor/operations/COM_GlareStreaksOperation.h
index df31981170d..487c910960a 100644
--- a/source/blender/compositor/operations/COM_GlareStreaksOperation.h
+++ b/source/blender/compositor/operations/COM_GlareStreaksOperation.h
@@ -22,6 +22,8 @@
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
class GlareStreaksOperation : public GlareBaseOperation {
public:
GlareStreaksOperation() : GlareBaseOperation()
@@ -29,5 +31,7 @@ class GlareStreaksOperation : public GlareBaseOperation {
}
protected:
- void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings);
+ void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GlareThresholdOperation.cc b/source/blender/compositor/operations/COM_GlareThresholdOperation.cc
index 984b433469a..1d3402f5b7b 100644
--- a/source/blender/compositor/operations/COM_GlareThresholdOperation.cc
+++ b/source/blender/compositor/operations/COM_GlareThresholdOperation.cc
@@ -21,9 +21,11 @@
#include "IMB_colormanagement.h"
+namespace blender::compositor {
+
GlareThresholdOperation::GlareThresholdOperation()
{
- this->addInputSocket(DataType::Color, COM_SC_FIT);
+ this->addInputSocket(DataType::Color, ResizeMode::FitAny);
this->addOutputSocket(DataType::Color);
this->m_inputProgram = nullptr;
}
@@ -67,3 +69,5 @@ void GlareThresholdOperation::deinitExecution()
{
this->m_inputProgram = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_GlareThresholdOperation.h b/source/blender/compositor/operations/COM_GlareThresholdOperation.h
index 1e55f401ef3..a6e971dada7 100644
--- a/source/blender/compositor/operations/COM_GlareThresholdOperation.h
+++ b/source/blender/compositor/operations/COM_GlareThresholdOperation.h
@@ -21,6 +21,8 @@
#include "COM_NodeOperation.h"
#include "DNA_light_types.h"
+namespace blender::compositor {
+
class GlareThresholdOperation : public NodeOperation {
private:
/**
@@ -39,22 +41,25 @@ class GlareThresholdOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setGlareSettings(NodeGlare *settings)
{
this->m_settings = settings;
}
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cc b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cc
index 0ef15b2b3d7..e341a88ff71 100644
--- a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cc
+++ b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cc
@@ -22,6 +22,8 @@
#include "BKE_colortools.h"
+namespace blender::compositor {
+
HueSaturationValueCorrectOperation::HueSaturationValueCorrectOperation()
{
this->addInputSocket(DataType::Color);
@@ -70,3 +72,5 @@ void HueSaturationValueCorrectOperation::deinitExecution()
CurveBaseOperation::deinitExecution();
this->m_inputProgram = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h
index dea7eae4a15..703b2894bdb 100644
--- a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h
+++ b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h
@@ -21,6 +21,8 @@
#include "COM_CurveBaseOperation.h"
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class HueSaturationValueCorrectOperation : public CurveBaseOperation {
private:
/**
@@ -34,15 +36,17 @@ class HueSaturationValueCorrectOperation : public CurveBaseOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_IDMaskOperation.cc b/source/blender/compositor/operations/COM_IDMaskOperation.cc
index 8757908e354..1bb247e9bc5 100644
--- a/source/blender/compositor/operations/COM_IDMaskOperation.cc
+++ b/source/blender/compositor/operations/COM_IDMaskOperation.cc
@@ -18,11 +18,13 @@
#include "COM_IDMaskOperation.h"
+namespace blender::compositor {
+
IDMaskOperation::IDMaskOperation()
{
this->addInputSocket(DataType::Value);
this->addOutputSocket(DataType::Value);
- this->setComplex(true);
+ this->flags.complex = true;
}
void *IDMaskOperation::initializeTileData(rcti *rect)
@@ -39,3 +41,5 @@ void IDMaskOperation::executePixel(float output[4], int x, int y, void *data)
int buffer_index = (y * buffer_width + x);
output[0] = (roundf(buffer[buffer_index]) == this->m_objectIndex) ? 1.0f : 0.0f;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_IDMaskOperation.h b/source/blender/compositor/operations/COM_IDMaskOperation.h
index abd2a719371..79b7e53b67c 100644
--- a/source/blender/compositor/operations/COM_IDMaskOperation.h
+++ b/source/blender/compositor/operations/COM_IDMaskOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class IDMaskOperation : public NodeOperation {
private:
float m_objectIndex;
@@ -27,11 +29,13 @@ class IDMaskOperation : public NodeOperation {
public:
IDMaskOperation();
- void *initializeTileData(rcti *rect);
- void executePixel(float output[4], int x, int y, void *data);
+ void *initializeTileData(rcti *rect) override;
+ void executePixel(float output[4], int x, int y, void *data) override;
void setObjectIndex(float objectIndex)
{
this->m_objectIndex = objectIndex;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ImageOperation.cc b/source/blender/compositor/operations/COM_ImageOperation.cc
index 06e8db7b467..a1d401d4499 100644
--- a/source/blender/compositor/operations/COM_ImageOperation.cc
+++ b/source/blender/compositor/operations/COM_ImageOperation.cc
@@ -31,6 +31,8 @@
#include "RE_pipeline.h"
#include "RE_texture.h"
+namespace blender::compositor {
+
BaseImageOperation::BaseImageOperation()
{
this->m_image = nullptr;
@@ -123,13 +125,13 @@ static void sampleImageAtLocation(
{
if (ibuf->rect_float) {
switch (sampler) {
- case COM_PS_NEAREST:
+ case PixelSampler::Nearest:
nearest_interpolation_color(ibuf, nullptr, color, x, y);
break;
- case COM_PS_BILINEAR:
+ case PixelSampler::Bilinear:
bilinear_interpolation_color(ibuf, nullptr, color, x, y);
break;
- case COM_PS_BICUBIC:
+ case PixelSampler::Bicubic:
bicubic_interpolation_color(ibuf, nullptr, color, x, y);
break;
}
@@ -137,13 +139,13 @@ static void sampleImageAtLocation(
else {
unsigned char byte_color[4];
switch (sampler) {
- case COM_PS_NEAREST:
+ case PixelSampler::Nearest:
nearest_interpolation_color(ibuf, byte_color, nullptr, x, y);
break;
- case COM_PS_BILINEAR:
+ case PixelSampler::Bilinear:
bilinear_interpolation_color(ibuf, byte_color, nullptr, x, y);
break;
- case COM_PS_BICUBIC:
+ case PixelSampler::Bicubic:
bicubic_interpolation_color(ibuf, byte_color, nullptr, x, y);
break;
}
@@ -203,3 +205,5 @@ void ImageDepthOperation::executePixelSampled(float output[4],
}
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ImageOperation.h b/source/blender/compositor/operations/COM_ImageOperation.h
index bff8dcc1cea..58373663db5 100644
--- a/source/blender/compositor/operations/COM_ImageOperation.h
+++ b/source/blender/compositor/operations/COM_ImageOperation.h
@@ -27,6 +27,8 @@
#include "RE_pipeline.h"
#include "RE_texture.h"
+namespace blender::compositor {
+
/**
* \brief Base class for all image operations
*/
@@ -49,13 +51,14 @@ class BaseImageOperation : public NodeOperation {
/**
* Determine the output resolution. The resolution is retrieved from the Renderer
*/
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
virtual ImBuf *getImBuf();
public:
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setImage(Image *image)
{
this->m_image = image;
@@ -83,7 +86,7 @@ class ImageOperation : public BaseImageOperation {
* Constructor
*/
ImageOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ImageAlphaOperation : public BaseImageOperation {
public:
@@ -91,7 +94,7 @@ class ImageAlphaOperation : public BaseImageOperation {
* Constructor
*/
ImageAlphaOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ImageDepthOperation : public BaseImageOperation {
public:
@@ -99,5 +102,7 @@ class ImageDepthOperation : public BaseImageOperation {
* Constructor
*/
ImageDepthOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_InpaintOperation.cc b/source/blender/compositor/operations/COM_InpaintOperation.cc
index f4e38c85e50..413ed2694a9 100644
--- a/source/blender/compositor/operations/COM_InpaintOperation.cc
+++ b/source/blender/compositor/operations/COM_InpaintOperation.cc
@@ -23,6 +23,8 @@
#include "BLI_math.h"
+namespace blender::compositor {
+
#define ASSERT_XY_RANGE(x, y) \
BLI_assert(x >= 0 && x < this->getWidth() && y >= 0 && y < this->getHeight())
@@ -31,7 +33,7 @@ InpaintSimpleOperation::InpaintSimpleOperation()
{
this->addInputSocket(DataType::Color);
this->addOutputSocket(DataType::Color);
- this->setComplex(true);
+ this->flags.complex = true;
this->m_inputImageProgram = nullptr;
this->m_pixelorder = nullptr;
this->m_manhattan_distance = nullptr;
@@ -76,7 +78,8 @@ float *InpaintSimpleOperation::get_pixel(int x, int y)
ASSERT_XY_RANGE(x, y);
- return &this->m_cached_buffer[y * width * COM_NUM_CHANNELS_COLOR + x * COM_NUM_CHANNELS_COLOR];
+ return &this->m_cached_buffer[y * width * COM_DATA_TYPE_COLOR_CHANNELS +
+ x * COM_DATA_TYPE_COLOR_CHANNELS];
}
int InpaintSimpleOperation::mdist(int x, int y)
@@ -282,3 +285,5 @@ bool InpaintSimpleOperation::determineDependingAreaOfInterest(rcti * /*input*/,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_InpaintOperation.h b/source/blender/compositor/operations/COM_InpaintOperation.h
index 4c43e433dec..e3d27bf7704 100644
--- a/source/blender/compositor/operations/COM_InpaintOperation.h
+++ b/source/blender/compositor/operations/COM_InpaintOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class InpaintSimpleOperation : public NodeOperation {
protected:
/**
@@ -42,18 +44,18 @@ class InpaintSimpleOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setIterations(int iterations)
{
@@ -62,7 +64,7 @@ class InpaintSimpleOperation : public NodeOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
private:
void calc_manhattan_distance();
@@ -72,3 +74,5 @@ class InpaintSimpleOperation : public NodeOperation {
bool next_pixel(int &x, int &y, int &curr, int iters);
void pix_step(int x, int y);
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_InvertOperation.cc b/source/blender/compositor/operations/COM_InvertOperation.cc
index 53e32baaa3d..339e40a5d1f 100644
--- a/source/blender/compositor/operations/COM_InvertOperation.cc
+++ b/source/blender/compositor/operations/COM_InvertOperation.cc
@@ -18,6 +18,8 @@
#include "COM_InvertOperation.h"
+namespace blender::compositor {
+
InvertOperation::InvertOperation()
{
this->addInputSocket(DataType::Value);
@@ -67,3 +69,5 @@ void InvertOperation::deinitExecution()
this->m_inputValueProgram = nullptr;
this->m_inputColorProgram = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_InvertOperation.h b/source/blender/compositor/operations/COM_InvertOperation.h
index ac0b1c3ab2e..17e5eb95f3e 100644
--- a/source/blender/compositor/operations/COM_InvertOperation.h
+++ b/source/blender/compositor/operations/COM_InvertOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class InvertOperation : public NodeOperation {
private:
/**
@@ -37,17 +39,17 @@ class InvertOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setColor(bool color)
{
@@ -58,3 +60,5 @@ class InvertOperation : public NodeOperation {
this->m_alpha = alpha;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingBlurOperation.cc b/source/blender/compositor/operations/COM_KeyingBlurOperation.cc
index 0d9613eea96..994b00cd3f4 100644
--- a/source/blender/compositor/operations/COM_KeyingBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_KeyingBlurOperation.cc
@@ -23,6 +23,8 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
KeyingBlurOperation::KeyingBlurOperation()
{
this->addInputSocket(DataType::Value);
@@ -31,7 +33,7 @@ KeyingBlurOperation::KeyingBlurOperation()
this->m_size = 0;
this->m_axis = BLUR_AXIS_X;
- this->setComplex(true);
+ this->flags.complex = true;
}
void *KeyingBlurOperation::initializeTileData(rcti *rect)
@@ -93,3 +95,5 @@ bool KeyingBlurOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingBlurOperation.h b/source/blender/compositor/operations/COM_KeyingBlurOperation.h
index 6a2b43a6cd4..b055d7713f1 100644
--- a/source/blender/compositor/operations/COM_KeyingBlurOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingBlurOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* Class with implementation of blurring for keying node
*/
@@ -45,11 +47,13 @@ class KeyingBlurOperation : public NodeOperation {
this->m_axis = value;
}
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingClipOperation.cc b/source/blender/compositor/operations/COM_KeyingClipOperation.cc
index e8556d9d8c9..4029be4e077 100644
--- a/source/blender/compositor/operations/COM_KeyingClipOperation.cc
+++ b/source/blender/compositor/operations/COM_KeyingClipOperation.cc
@@ -23,6 +23,8 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
KeyingClipOperation::KeyingClipOperation()
{
this->addInputSocket(DataType::Value);
@@ -36,7 +38,7 @@ KeyingClipOperation::KeyingClipOperation()
this->m_isEdgeMatte = false;
- this->setComplex(true);
+ this->flags.complex = true;
}
void *KeyingClipOperation::initializeTileData(rcti *rect)
@@ -127,3 +129,5 @@ bool KeyingClipOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingClipOperation.h b/source/blender/compositor/operations/COM_KeyingClipOperation.h
index 9d876966e96..0a21fb48c99 100644
--- a/source/blender/compositor/operations/COM_KeyingClipOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingClipOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* Class with implementation of black/white clipping for keying node
*/
@@ -59,11 +61,13 @@ class KeyingClipOperation : public NodeOperation {
this->m_isEdgeMatte = value;
}
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingDespillOperation.cc b/source/blender/compositor/operations/COM_KeyingDespillOperation.cc
index 5caa450a878..d31a88cb91e 100644
--- a/source/blender/compositor/operations/COM_KeyingDespillOperation.cc
+++ b/source/blender/compositor/operations/COM_KeyingDespillOperation.cc
@@ -23,6 +23,8 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
KeyingDespillOperation::KeyingDespillOperation()
{
this->addInputSocket(DataType::Color);
@@ -79,3 +81,5 @@ void KeyingDespillOperation::executePixelSampled(float output[4],
output[screen_primary_channel] = pixelColor[screen_primary_channel] - amount_despill;
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingDespillOperation.h b/source/blender/compositor/operations/COM_KeyingDespillOperation.h
index 32df7939c43..279ac60e6e9 100644
--- a/source/blender/compositor/operations/COM_KeyingDespillOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingDespillOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* Class with implementation of keying despill node
*/
@@ -33,8 +35,8 @@ class KeyingDespillOperation : public NodeOperation {
public:
KeyingDespillOperation();
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setDespillFactor(float value)
{
@@ -45,5 +47,7 @@ class KeyingDespillOperation : public NodeOperation {
this->m_colorBalance = value;
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingOperation.cc b/source/blender/compositor/operations/COM_KeyingOperation.cc
index 108b7c60874..e786e4b8219 100644
--- a/source/blender/compositor/operations/COM_KeyingOperation.cc
+++ b/source/blender/compositor/operations/COM_KeyingOperation.cc
@@ -23,6 +23,8 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
static float get_pixel_saturation(const float pixelColor[4],
float screen_balance,
int primary_channel)
@@ -107,3 +109,5 @@ void KeyingOperation::executePixelSampled(float output[4], float x, float y, Pix
}
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingOperation.h b/source/blender/compositor/operations/COM_KeyingOperation.h
index 946d7bdc1f7..3d41ecaa0f6 100644
--- a/source/blender/compositor/operations/COM_KeyingOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingOperation.h
@@ -24,6 +24,8 @@
#include "BLI_listbase.h"
+namespace blender::compositor {
+
/**
* Class with implementation of keying node
*/
@@ -37,13 +39,15 @@ class KeyingOperation : public NodeOperation {
public:
KeyingOperation();
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setScreenBalance(float value)
{
this->m_screenBalance = value;
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cc b/source/blender/compositor/operations/COM_KeyingScreenOperation.cc
index 801750d99d0..17b613246ad 100644
--- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cc
+++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cc
@@ -30,13 +30,15 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+namespace blender::compositor {
+
KeyingScreenOperation::KeyingScreenOperation()
{
this->addOutputSocket(DataType::Color);
this->m_movieClip = nullptr;
this->m_framenumber = 0;
this->m_trackingObject[0] = 0;
- setComplex(true);
+ flags.complex = true;
}
void KeyingScreenOperation::initExecution()
@@ -344,3 +346,5 @@ void KeyingScreenOperation::executePixel(float output[4], int x, int y, void *da
}
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.h b/source/blender/compositor/operations/COM_KeyingScreenOperation.h
index 595301bb951..4118d229be9 100644
--- a/source/blender/compositor/operations/COM_KeyingScreenOperation.h
+++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.h
@@ -29,6 +29,8 @@
#include "BLI_voronoi_2d.h"
+namespace blender::compositor {
+
/**
* Class with implementation of green screen gradient rasterization
*/
@@ -54,18 +56,19 @@ class KeyingScreenOperation : public NodeOperation {
/**
* Determine the output resolution. The resolution is retrieved from the Renderer
*/
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
TriangulationData *buildVoronoiTriangulation();
public:
KeyingScreenOperation();
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
- void *initializeTileData(rcti *rect);
- void deinitializeTileData(rcti *rect, void *data);
+ void *initializeTileData(rcti *rect) override;
+ void deinitializeTileData(rcti *rect, void *data) override;
void setMovieClip(MovieClip *clip)
{
@@ -80,5 +83,7 @@ class KeyingScreenOperation : public NodeOperation {
this->m_framenumber = framenumber;
}
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_LuminanceMatteOperation.cc b/source/blender/compositor/operations/COM_LuminanceMatteOperation.cc
index 43cc8f8bf71..0afc4278a45 100644
--- a/source/blender/compositor/operations/COM_LuminanceMatteOperation.cc
+++ b/source/blender/compositor/operations/COM_LuminanceMatteOperation.cc
@@ -21,6 +21,8 @@
#include "IMB_colormanagement.h"
+namespace blender::compositor {
+
LuminanceMatteOperation::LuminanceMatteOperation()
{
addInputSocket(DataType::Color);
@@ -75,3 +77,5 @@ void LuminanceMatteOperation::executePixelSampled(float output[4],
/* don't make something that was more transparent less transparent */
output[0] = min_ff(alpha, inColor[3]);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_LuminanceMatteOperation.h b/source/blender/compositor/operations/COM_LuminanceMatteOperation.h
index 2c3a61d8755..035c68b9d59 100644
--- a/source/blender/compositor/operations/COM_LuminanceMatteOperation.h
+++ b/source/blender/compositor/operations/COM_LuminanceMatteOperation.h
@@ -20,6 +20,8 @@
#include "COM_MixOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -38,13 +40,15 @@ class LuminanceMatteOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setSettings(NodeChroma *nodeChroma)
{
this->m_settings = nodeChroma;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MapRangeOperation.cc b/source/blender/compositor/operations/COM_MapRangeOperation.cc
index 78ba446051e..ada3cd6f159 100644
--- a/source/blender/compositor/operations/COM_MapRangeOperation.cc
+++ b/source/blender/compositor/operations/COM_MapRangeOperation.cc
@@ -18,6 +18,8 @@
#include "COM_MapRangeOperation.h"
+namespace blender::compositor {
+
MapRangeOperation::MapRangeOperation()
{
this->addInputSocket(DataType::Value);
@@ -101,3 +103,5 @@ void MapRangeOperation::deinitExecution()
this->m_destMinOperation = nullptr;
this->m_destMaxOperation = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MapRangeOperation.h b/source/blender/compositor/operations/COM_MapRangeOperation.h
index 95268d5699f..a544c59887e 100644
--- a/source/blender/compositor/operations/COM_MapRangeOperation.h
+++ b/source/blender/compositor/operations/COM_MapRangeOperation.h
@@ -21,6 +21,8 @@
#include "COM_NodeOperation.h"
#include "DNA_texture_types.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -47,17 +49,17 @@ class MapRangeOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
/**
* Clamp the output
@@ -67,3 +69,5 @@ class MapRangeOperation : public NodeOperation {
this->m_useClamp = value;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MapUVOperation.cc b/source/blender/compositor/operations/COM_MapUVOperation.cc
index 7328de7f49f..74e3d965d41 100644
--- a/source/blender/compositor/operations/COM_MapUVOperation.cc
+++ b/source/blender/compositor/operations/COM_MapUVOperation.cc
@@ -19,13 +19,15 @@
#include "COM_MapUVOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
MapUVOperation::MapUVOperation()
{
- this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
+ this->addInputSocket(DataType::Color, ResizeMode::None);
this->addInputSocket(DataType::Vector);
this->addOutputSocket(DataType::Color);
this->m_alpha = 0.0f;
- this->setComplex(true);
+ this->flags.complex = true;
setResolutionInputSocketIndex(1);
this->m_inputUVProgram = nullptr;
@@ -89,7 +91,7 @@ bool MapUVOperation::read_uv(float x, float y, float &r_u, float &r_v, float &r_
}
float vector[3];
- m_inputUVProgram->readSampled(vector, x, y, COM_PS_BILINEAR);
+ m_inputUVProgram->readSampled(vector, x, y, PixelSampler::Bilinear);
r_u = vector[0] * m_inputColorProgram->getWidth();
r_v = vector[1] * m_inputColorProgram->getHeight();
r_alpha = vector[2];
@@ -183,3 +185,5 @@ bool MapUVOperation::determineDependingAreaOfInterest(rcti *input,
return false;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MapUVOperation.h b/source/blender/compositor/operations/COM_MapUVOperation.h
index 66e70a7ab83..eb5f7d49122 100644
--- a/source/blender/compositor/operations/COM_MapUVOperation.h
+++ b/source/blender/compositor/operations/COM_MapUVOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class MapUVOperation : public NodeOperation {
private:
/**
@@ -38,24 +40,24 @@ class MapUVOperation : public NodeOperation {
*/
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
void pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2], float &r_alpha);
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setAlpha(float alpha)
{
@@ -65,3 +67,5 @@ class MapUVOperation : public NodeOperation {
private:
bool read_uv(float x, float y, float &r_u, float &r_v, float &r_alpha);
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MapValueOperation.cc b/source/blender/compositor/operations/COM_MapValueOperation.cc
index 9c28e3c2577..03fa80d220d 100644
--- a/source/blender/compositor/operations/COM_MapValueOperation.cc
+++ b/source/blender/compositor/operations/COM_MapValueOperation.cc
@@ -18,6 +18,8 @@
#include "COM_MapValueOperation.h"
+namespace blender::compositor {
+
MapValueOperation::MapValueOperation()
{
this->addInputSocket(DataType::Value);
@@ -57,3 +59,5 @@ void MapValueOperation::deinitExecution()
{
this->m_inputOperation = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MapValueOperation.h b/source/blender/compositor/operations/COM_MapValueOperation.h
index 3de377ed0fc..eb7714714e9 100644
--- a/source/blender/compositor/operations/COM_MapValueOperation.h
+++ b/source/blender/compositor/operations/COM_MapValueOperation.h
@@ -21,6 +21,8 @@
#include "COM_NodeOperation.h"
#include "DNA_texture_types.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -42,17 +44,17 @@ class MapValueOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
/**
* \brief set the TexMapping settings
@@ -62,3 +64,5 @@ class MapValueOperation : public NodeOperation {
this->m_settings = settings;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MaskOperation.cc b/source/blender/compositor/operations/COM_MaskOperation.cc
index 64d8c9a5492..c7763f08e71 100644
--- a/source/blender/compositor/operations/COM_MaskOperation.cc
+++ b/source/blender/compositor/operations/COM_MaskOperation.cc
@@ -26,6 +26,8 @@
#include "BKE_lib_id.h"
#include "BKE_mask.h"
+namespace blender::compositor {
+
MaskOperation::MaskOperation()
{
this->addOutputSocket(DataType::Value);
@@ -158,3 +160,5 @@ void MaskOperation::executePixelSampled(float output[4],
output[0] /= this->m_rasterMaskHandleTot;
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MaskOperation.h b/source/blender/compositor/operations/COM_MaskOperation.h
index 67e6b64315c..48fd54b00fe 100644
--- a/source/blender/compositor/operations/COM_MaskOperation.h
+++ b/source/blender/compositor/operations/COM_MaskOperation.h
@@ -23,6 +23,11 @@
#include "DNA_mask_types.h"
#include "IMB_imbuf_types.h"
+/* Forward declarations. */
+struct MaskRasterHandle;
+
+namespace blender::compositor {
+
/**
* Class with implementation of mask rasterization
*/
@@ -49,13 +54,14 @@ class MaskOperation : public NodeOperation {
/**
* Determine the output resolution. The resolution is retrieved from the Renderer
*/
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
public:
MaskOperation();
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setMask(Mask *mask)
{
@@ -91,5 +97,7 @@ class MaskOperation : public NodeOperation {
this->m_frame_shutter = shutter;
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.cc b/source/blender/compositor/operations/COM_MathBaseOperation.cc
index 57ccbe7792b..a94c14347fb 100644
--- a/source/blender/compositor/operations/COM_MathBaseOperation.cc
+++ b/source/blender/compositor/operations/COM_MathBaseOperation.cc
@@ -20,6 +20,8 @@
#include "BLI_math.h"
+namespace blender::compositor {
+
MathBaseOperation::MathBaseOperation()
{
this->addInputSocket(DataType::Value);
@@ -748,3 +750,5 @@ void MathSmoothMaxOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.h b/source/blender/compositor/operations/COM_MathBaseOperation.h
index 292326caded..69555524274 100644
--- a/source/blender/compositor/operations/COM_MathBaseOperation.h
+++ b/source/blender/compositor/operations/COM_MathBaseOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -45,24 +47,20 @@ class MathBaseOperation : public NodeOperation {
public:
/**
- * The inner loop of this operation.
- */
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) = 0;
-
- /**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
/**
* Determine resolution
*/
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
void setUseClamp(bool value)
{
@@ -75,49 +73,49 @@ class MathAddOperation : public MathBaseOperation {
MathAddOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathSubtractOperation : public MathBaseOperation {
public:
MathSubtractOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathMultiplyOperation : public MathBaseOperation {
public:
MathMultiplyOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathDivideOperation : public MathBaseOperation {
public:
MathDivideOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathSineOperation : public MathBaseOperation {
public:
MathSineOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathCosineOperation : public MathBaseOperation {
public:
MathCosineOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathTangentOperation : public MathBaseOperation {
public:
MathTangentOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathHyperbolicSineOperation : public MathBaseOperation {
@@ -125,21 +123,21 @@ class MathHyperbolicSineOperation : public MathBaseOperation {
MathHyperbolicSineOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathHyperbolicCosineOperation : public MathBaseOperation {
public:
MathHyperbolicCosineOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathHyperbolicTangentOperation : public MathBaseOperation {
public:
MathHyperbolicTangentOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathArcSineOperation : public MathBaseOperation {
@@ -147,70 +145,70 @@ class MathArcSineOperation : public MathBaseOperation {
MathArcSineOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathArcCosineOperation : public MathBaseOperation {
public:
MathArcCosineOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathArcTangentOperation : public MathBaseOperation {
public:
MathArcTangentOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathPowerOperation : public MathBaseOperation {
public:
MathPowerOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathLogarithmOperation : public MathBaseOperation {
public:
MathLogarithmOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathMinimumOperation : public MathBaseOperation {
public:
MathMinimumOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathMaximumOperation : public MathBaseOperation {
public:
MathMaximumOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathRoundOperation : public MathBaseOperation {
public:
MathRoundOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathLessThanOperation : public MathBaseOperation {
public:
MathLessThanOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathGreaterThanOperation : public MathBaseOperation {
public:
MathGreaterThanOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathModuloOperation : public MathBaseOperation {
@@ -218,7 +216,7 @@ class MathModuloOperation : public MathBaseOperation {
MathModuloOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathAbsoluteOperation : public MathBaseOperation {
@@ -226,7 +224,7 @@ class MathAbsoluteOperation : public MathBaseOperation {
MathAbsoluteOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathRadiansOperation : public MathBaseOperation {
@@ -234,7 +232,7 @@ class MathRadiansOperation : public MathBaseOperation {
MathRadiansOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathDegreesOperation : public MathBaseOperation {
@@ -242,7 +240,7 @@ class MathDegreesOperation : public MathBaseOperation {
MathDegreesOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathArcTan2Operation : public MathBaseOperation {
@@ -250,7 +248,7 @@ class MathArcTan2Operation : public MathBaseOperation {
MathArcTan2Operation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathFloorOperation : public MathBaseOperation {
@@ -258,7 +256,7 @@ class MathFloorOperation : public MathBaseOperation {
MathFloorOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathCeilOperation : public MathBaseOperation {
@@ -266,7 +264,7 @@ class MathCeilOperation : public MathBaseOperation {
MathCeilOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathFractOperation : public MathBaseOperation {
@@ -274,7 +272,7 @@ class MathFractOperation : public MathBaseOperation {
MathFractOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathSqrtOperation : public MathBaseOperation {
@@ -282,7 +280,7 @@ class MathSqrtOperation : public MathBaseOperation {
MathSqrtOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathInverseSqrtOperation : public MathBaseOperation {
@@ -290,7 +288,7 @@ class MathInverseSqrtOperation : public MathBaseOperation {
MathInverseSqrtOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathSignOperation : public MathBaseOperation {
@@ -298,7 +296,7 @@ class MathSignOperation : public MathBaseOperation {
MathSignOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathExponentOperation : public MathBaseOperation {
@@ -306,7 +304,7 @@ class MathExponentOperation : public MathBaseOperation {
MathExponentOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathTruncOperation : public MathBaseOperation {
@@ -314,7 +312,7 @@ class MathTruncOperation : public MathBaseOperation {
MathTruncOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathSnapOperation : public MathBaseOperation {
@@ -322,7 +320,7 @@ class MathSnapOperation : public MathBaseOperation {
MathSnapOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathWrapOperation : public MathBaseOperation {
@@ -330,7 +328,7 @@ class MathWrapOperation : public MathBaseOperation {
MathWrapOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathPingpongOperation : public MathBaseOperation {
@@ -338,7 +336,7 @@ class MathPingpongOperation : public MathBaseOperation {
MathPingpongOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathCompareOperation : public MathBaseOperation {
@@ -346,7 +344,7 @@ class MathCompareOperation : public MathBaseOperation {
MathCompareOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathMultiplyAddOperation : public MathBaseOperation {
@@ -354,7 +352,7 @@ class MathMultiplyAddOperation : public MathBaseOperation {
MathMultiplyAddOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathSmoothMinOperation : public MathBaseOperation {
@@ -362,7 +360,7 @@ class MathSmoothMinOperation : public MathBaseOperation {
MathSmoothMinOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MathSmoothMaxOperation : public MathBaseOperation {
@@ -370,5 +368,7 @@ class MathSmoothMaxOperation : public MathBaseOperation {
MathSmoothMaxOperation() : MathBaseOperation()
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MixOperation.cc b/source/blender/compositor/operations/COM_MixOperation.cc
index e70c59c6a01..70f3242c076 100644
--- a/source/blender/compositor/operations/COM_MixOperation.cc
+++ b/source/blender/compositor/operations/COM_MixOperation.cc
@@ -20,6 +20,8 @@
#include "BLI_math.h"
+namespace blender::compositor {
+
/* ******** Mix Base Operation ******** */
MixBaseOperation::MixBaseOperation()
@@ -944,3 +946,5 @@ void MixValueOperation::executePixelSampled(float output[4],
clampIfNeeded(output);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MixOperation.h b/source/blender/compositor/operations/COM_MixOperation.h
index 2f6e03ca7a3..86200c9836e 100644
--- a/source/blender/compositor/operations/COM_MixOperation.h
+++ b/source/blender/compositor/operations/COM_MixOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* All this programs converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -52,19 +54,20 @@ class MixBaseOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
void setUseValueAlphaMultiply(const bool value)
{
@@ -83,113 +86,115 @@ class MixBaseOperation : public NodeOperation {
class MixAddOperation : public MixBaseOperation {
public:
MixAddOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixBlendOperation : public MixBaseOperation {
public:
MixBlendOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixColorBurnOperation : public MixBaseOperation {
public:
MixColorBurnOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixColorOperation : public MixBaseOperation {
public:
MixColorOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixDarkenOperation : public MixBaseOperation {
public:
MixDarkenOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixDifferenceOperation : public MixBaseOperation {
public:
MixDifferenceOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixDivideOperation : public MixBaseOperation {
public:
MixDivideOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixDodgeOperation : public MixBaseOperation {
public:
MixDodgeOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixGlareOperation : public MixBaseOperation {
public:
MixGlareOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixHueOperation : public MixBaseOperation {
public:
MixHueOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixLightenOperation : public MixBaseOperation {
public:
MixLightenOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixLinearLightOperation : public MixBaseOperation {
public:
MixLinearLightOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixMultiplyOperation : public MixBaseOperation {
public:
MixMultiplyOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixOverlayOperation : public MixBaseOperation {
public:
MixOverlayOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixSaturationOperation : public MixBaseOperation {
public:
MixSaturationOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixScreenOperation : public MixBaseOperation {
public:
MixScreenOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixSoftLightOperation : public MixBaseOperation {
public:
MixSoftLightOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixSubtractOperation : public MixBaseOperation {
public:
MixSubtractOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MixValueOperation : public MixBaseOperation {
public:
MixValueOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cc b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cc
index 3920b4c02bd..a9f187258b2 100644
--- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cc
+++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cc
@@ -21,6 +21,8 @@
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
+namespace blender::compositor {
+
MovieClipAttributeOperation::MovieClipAttributeOperation()
{
this->addOutputSocket(DataType::Value);
@@ -80,3 +82,5 @@ void MovieClipAttributeOperation::determineResolution(unsigned int resolution[2]
resolution[0] = preferredResolution[0];
resolution[1] = preferredResolution[1];
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h
index 50ed6cdb69e..8507e98d08f 100644
--- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h
+++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h
@@ -21,6 +21,8 @@
#include "COM_NodeOperation.h"
#include "DNA_movieclip_types.h"
+namespace blender::compositor {
+
typedef enum MovieClipAttribute {
MCA_SCALE,
MCA_X,
@@ -45,13 +47,14 @@ class MovieClipAttributeOperation : public NodeOperation {
*/
MovieClipAttributeOperation();
- void initExecution();
+ void initExecution() override;
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
void setMovieClip(MovieClip *clip)
{
@@ -70,3 +73,5 @@ class MovieClipAttributeOperation : public NodeOperation {
this->m_invert = invert;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MovieClipOperation.cc b/source/blender/compositor/operations/COM_MovieClipOperation.cc
index 5d5880e14b0..d93a75407c4 100644
--- a/source/blender/compositor/operations/COM_MovieClipOperation.cc
+++ b/source/blender/compositor/operations/COM_MovieClipOperation.cc
@@ -26,6 +26,8 @@
#include "IMB_imbuf.h"
+namespace blender::compositor {
+
MovieClipBaseOperation::MovieClipBaseOperation()
{
this->m_movieClip = nullptr;
@@ -101,13 +103,13 @@ void MovieClipBaseOperation::executePixelSampled(float output[4],
}
else {
switch (sampler) {
- case COM_PS_NEAREST:
+ case PixelSampler::Nearest:
nearest_interpolation_color(ibuf, nullptr, output, x, y);
break;
- case COM_PS_BILINEAR:
+ case PixelSampler::Bilinear:
bilinear_interpolation_color(ibuf, nullptr, output, x, y);
break;
- case COM_PS_BICUBIC:
+ case PixelSampler::Bicubic:
bicubic_interpolation_color(ibuf, nullptr, output, x, y);
break;
}
@@ -133,3 +135,5 @@ void MovieClipAlphaOperation::executePixelSampled(float output[4],
MovieClipBaseOperation::executePixelSampled(result, x, y, sampler);
output[0] = result[3];
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MovieClipOperation.h b/source/blender/compositor/operations/COM_MovieClipOperation.h
index 8897f85f77c..c853ea43762 100644
--- a/source/blender/compositor/operations/COM_MovieClipOperation.h
+++ b/source/blender/compositor/operations/COM_MovieClipOperation.h
@@ -23,6 +23,8 @@
#include "DNA_movieclip_types.h"
#include "IMB_imbuf_types.h"
+namespace blender::compositor {
+
/**
* Base class for movie clip
*/
@@ -39,13 +41,14 @@ class MovieClipBaseOperation : public NodeOperation {
/**
* Determine the output resolution. The resolution is retrieved from the Renderer
*/
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
public:
MovieClipBaseOperation();
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setMovieClip(MovieClip *image)
{
this->m_movieClip = image;
@@ -63,7 +66,7 @@ class MovieClipBaseOperation : public NodeOperation {
{
this->m_framenumber = framenumber;
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class MovieClipOperation : public MovieClipBaseOperation {
@@ -74,5 +77,7 @@ class MovieClipOperation : public MovieClipBaseOperation {
class MovieClipAlphaOperation : public MovieClipBaseOperation {
public:
MovieClipAlphaOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cc b/source/blender/compositor/operations/COM_MovieDistortionOperation.cc
index fcd482a69ef..c8e045ea117 100644
--- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cc
+++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cc
@@ -23,6 +23,8 @@
#include "BLI_linklist.h"
+namespace blender::compositor {
+
MovieDistortionOperation::MovieDistortionOperation(bool distortion)
{
this->addInputSocket(DataType::Color);
@@ -107,10 +109,10 @@ void MovieDistortionOperation::executePixelSampled(float output[4],
float u = out[0] * aspx /* + 0.5 * overscan * w */,
v = (out[1] * aspy /* + 0.5 * overscan * h */) * pixel_aspect;
- this->m_inputOperation->readSampled(output, u, v, COM_PS_BILINEAR);
+ this->m_inputOperation->readSampled(output, u, v, PixelSampler::Bilinear);
}
else {
- this->m_inputOperation->readSampled(output, x, y, COM_PS_BILINEAR);
+ this->m_inputOperation->readSampled(output, x, y, PixelSampler::Bilinear);
}
}
@@ -125,3 +127,5 @@ bool MovieDistortionOperation::determineDependingAreaOfInterest(rcti *input,
newInput.ymax = input->ymax + m_margin[1];
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h
index f11ce485f97..631a62f7ebf 100644
--- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h
+++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h
@@ -24,6 +24,8 @@
#include "BKE_tracking.h"
+namespace blender::compositor {
+
class MovieDistortionOperation : public NodeOperation {
private:
SocketReader *m_inputOperation;
@@ -40,10 +42,10 @@ class MovieDistortionOperation : public NodeOperation {
public:
MovieDistortionOperation(bool distortion);
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setMovieClip(MovieClip *clip)
{
@@ -55,5 +57,7 @@ class MovieDistortionOperation : public NodeOperation {
}
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.cc b/source/blender/compositor/operations/COM_MultilayerImageOperation.cc
index 60936ee1939..647e93225e5 100644
--- a/source/blender/compositor/operations/COM_MultilayerImageOperation.cc
+++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.cc
@@ -21,6 +21,8 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+namespace blender::compositor {
+
MultilayerBaseOperation::MultilayerBaseOperation(RenderLayer *render_layer,
RenderPass *render_pass,
int view)
@@ -49,7 +51,7 @@ ImBuf *MultilayerBaseOperation::getImBuf()
return nullptr;
}
-std::unique_ptr<MetaData> MultilayerColorOperation::getMetaData() const
+std::unique_ptr<MetaData> MultilayerColorOperation::getMetaData()
{
BLI_assert(this->m_buffer);
MetaDataExtractCallbackData callback_data = {nullptr};
@@ -86,13 +88,13 @@ void MultilayerColorOperation::executePixelSampled(float output[4],
else {
if (this->m_numberOfChannels == 4) {
switch (sampler) {
- case COM_PS_NEAREST:
+ case PixelSampler::Nearest:
nearest_interpolation_color(this->m_buffer, nullptr, output, x, y);
break;
- case COM_PS_BILINEAR:
+ case PixelSampler::Bilinear:
bilinear_interpolation_color(this->m_buffer, nullptr, output, x, y);
break;
- case COM_PS_BICUBIC:
+ case PixelSampler::Bicubic:
bicubic_interpolation_color(this->m_buffer, nullptr, output, x, y);
break;
}
@@ -155,3 +157,5 @@ void MultilayerVectorOperation::executePixelSampled(float output[4],
}
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.h b/source/blender/compositor/operations/COM_MultilayerImageOperation.h
index dceb57de140..6e6062cf854 100644
--- a/source/blender/compositor/operations/COM_MultilayerImageOperation.h
+++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.h
@@ -20,6 +20,8 @@
#include "COM_ImageOperation.h"
+namespace blender::compositor {
+
class MultilayerBaseOperation : public BaseImageOperation {
private:
int m_passId;
@@ -45,7 +47,7 @@ class MultilayerColorOperation : public MultilayerBaseOperation {
this->addOutputSocket(DataType::Color);
}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- std::unique_ptr<MetaData> getMetaData() const override;
+ std::unique_ptr<MetaData> getMetaData() override;
};
class MultilayerValueOperation : public MultilayerBaseOperation {
@@ -67,3 +69,5 @@ class MultilayerVectorOperation : public MultilayerBaseOperation {
}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_NormalizeOperation.cc b/source/blender/compositor/operations/COM_NormalizeOperation.cc
index fd3b951c842..faacb429f71 100644
--- a/source/blender/compositor/operations/COM_NormalizeOperation.cc
+++ b/source/blender/compositor/operations/COM_NormalizeOperation.cc
@@ -18,13 +18,15 @@
#include "COM_NormalizeOperation.h"
+namespace blender::compositor {
+
NormalizeOperation::NormalizeOperation()
{
this->addInputSocket(DataType::Value);
this->addOutputSocket(DataType::Value);
this->m_imageReader = nullptr;
this->m_cachedInstance = nullptr;
- this->setComplex(true);
+ this->flags.complex = true;
}
void NormalizeOperation::initExecution()
{
@@ -124,3 +126,5 @@ void NormalizeOperation::deinitializeTileData(rcti * /*rect*/, void * /*data*/)
{
/* pass */
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_NormalizeOperation.h b/source/blender/compositor/operations/COM_NormalizeOperation.h
index 8090cf4973b..93d4a0fc67d 100644
--- a/source/blender/compositor/operations/COM_NormalizeOperation.h
+++ b/source/blender/compositor/operations/COM_NormalizeOperation.h
@@ -21,6 +21,8 @@
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
/**
* \brief base class of normalize, implementing the simple normalize
* \ingroup operation
@@ -44,22 +46,24 @@ class NormalizeOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
- void *initializeTileData(rcti *rect);
- void deinitializeTileData(rcti *rect, void *data);
+ void *initializeTileData(rcti *rect) override;
+ void deinitializeTileData(rcti *rect, void *data) override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cc b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cc
index 7044fe402eb..5b6f650d40e 100644
--- a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cc
+++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cc
@@ -37,6 +37,8 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+namespace blender::compositor {
+
/************************************ OpenEXR Singlelayer Multiview ******************************/
OutputOpenExrSingleLayerMultiViewOperation::OutputOpenExrSingleLayerMultiViewOperation(
@@ -380,3 +382,5 @@ void OutputStereoOperation::deinitExecution()
}
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
index 258ac1f9e98..6230a6f306b 100644
--- a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
+++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
@@ -28,6 +28,8 @@
#include "intern/openexr/openexr_multi.h"
+namespace blender::compositor {
+
class OutputOpenExrSingleLayerMultiViewOperation : public OutputSingleLayerOperation {
private:
public:
@@ -42,7 +44,7 @@ class OutputOpenExrSingleLayerMultiViewOperation : public OutputSingleLayerOpera
const bool saveAsRender);
void *get_handle(const char *filename);
- void deinitExecution();
+ void deinitExecution() override;
};
/* Writes inputs into OpenEXR multilayer channels. */
@@ -58,7 +60,7 @@ class OutputOpenExrMultiLayerMultiViewOperation : public OutputOpenExrMultiLayer
const char *viewName);
void *get_handle(const char *filename);
- void deinitExecution();
+ void deinitExecution() override;
};
class OutputStereoOperation : public OutputSingleLayerOperation {
@@ -78,5 +80,7 @@ class OutputStereoOperation : public OutputSingleLayerOperation {
const char *viewName,
const bool saveAsRender);
void *get_handle(const char *filename);
- void deinitExecution();
+ void deinitExecution() override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cc b/source/blender/compositor/operations/COM_OutputFileOperation.cc
index a6135ef064c..5184cd42b9e 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.cc
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.cc
@@ -40,6 +40,8 @@
#include "RE_pipeline.h"
+namespace blender::compositor {
+
void add_exr_channels(void *exrhandle,
const char *layerName,
const DataType datatype,
@@ -191,7 +193,7 @@ static void write_buffer_rect(rcti *rect,
for (y = y1; y < y2 && (!breaked); y++) {
for (x = x1; x < x2 && (!breaked); x++) {
- reader->readSampled(color, x, y, COM_PS_NEAREST);
+ reader->readSampled(color, x, y, PixelSampler::Nearest);
for (i = 0; i < size; i++) {
buffer[offset + i] = color[i];
@@ -328,7 +330,7 @@ void OutputOpenExrMultiLayerOperation::add_layer(const char *name,
bool use_layer)
{
this->addInputSocket(datatype);
- this->m_layers.push_back(OutputOpenExrLayer(name, datatype, use_layer));
+ this->m_layers.append(OutputOpenExrLayer(name, datatype, use_layer));
}
StampData *OutputOpenExrMultiLayerOperation::createStampData() const
@@ -338,17 +340,16 @@ StampData *OutputOpenExrMultiLayerOperation::createStampData() const
RenderResult render_result;
StampData *stamp_data = BKE_stamp_info_from_scene_static(m_scene);
render_result.stamp_data = stamp_data;
- for (int i = 0; i < this->m_layers.size(); i++) {
- const OutputOpenExrLayer *layer = &this->m_layers[i];
+ for (const OutputOpenExrLayer &layer : m_layers) {
/* Skip unconnected sockets. */
- if (layer->imageInput == nullptr) {
+ if (layer.imageInput == nullptr) {
continue;
}
- std::unique_ptr<MetaData> meta_data = layer->imageInput->getMetaData();
+ std::unique_ptr<MetaData> meta_data = layer.imageInput->getMetaData();
if (meta_data) {
blender::StringRef layer_name =
blender::bke::cryptomatte::BKE_cryptomatte_extract_layer_name(
- blender::StringRef(layer->name, BLI_strnlen(layer->name, sizeof(layer->name))));
+ blender::StringRef(layer.name, BLI_strnlen(layer.name, sizeof(layer.name))));
meta_data->replaceHashNeutralCryptomatteKeys(layer_name);
meta_data->addToRenderResult(&render_result);
}
@@ -441,3 +442,5 @@ void OutputOpenExrMultiLayerOperation::deinitExecution()
BKE_stamp_data_free(stamp_data);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h
index ecc52355824..6415891032a 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.h
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.h
@@ -27,6 +27,8 @@
#include "intern/openexr/openexr_multi.h"
+namespace blender::compositor {
+
/* Writes the image to a single-layer file. */
class OutputSingleLayerOperation : public NodeOperation {
protected:
@@ -57,22 +59,17 @@ class OutputSingleLayerOperation : public NodeOperation {
const char *viewName,
const bool saveAsRender);
- void executeRegion(rcti *rect, unsigned int tileNumber);
- bool isOutputOperation(bool /*rendering*/) const
+ void executeRegion(rcti *rect, unsigned int tileNumber) override;
+ bool isOutputOperation(bool /*rendering*/) const override
{
return true;
}
- void initExecution();
- void deinitExecution();
- CompositorPriority getRenderPriority() const
+ void initExecution() override;
+ void deinitExecution() override;
+ CompositorPriority getRenderPriority() const override
{
return CompositorPriority::Low;
}
-
- bool isFileOutputOperation() const
- {
- return true;
- }
};
/* extra info for OpenEXR layers */
@@ -91,8 +88,6 @@ struct OutputOpenExrLayer {
/* Writes inputs into OpenEXR multilayer channels. */
class OutputOpenExrMultiLayerOperation : public NodeOperation {
protected:
- typedef std::vector<OutputOpenExrLayer> LayerList;
-
const Scene *m_scene;
const RenderData *m_rd;
const bNodeTree *m_tree;
@@ -100,7 +95,7 @@ class OutputOpenExrMultiLayerOperation : public NodeOperation {
char m_path[FILE_MAX];
char m_exr_codec;
bool m_exr_half_float;
- LayerList m_layers;
+ blender::Vector<OutputOpenExrLayer> m_layers;
const char *m_viewName;
StampData *createStampData() const;
@@ -116,22 +111,17 @@ class OutputOpenExrMultiLayerOperation : public NodeOperation {
void add_layer(const char *name, DataType datatype, bool use_layer);
- void executeRegion(rcti *rect, unsigned int tileNumber);
- bool isOutputOperation(bool /*rendering*/) const
+ void executeRegion(rcti *rect, unsigned int tileNumber) override;
+ bool isOutputOperation(bool /*rendering*/) const override
{
return true;
}
- void initExecution();
- void deinitExecution();
- CompositorPriority getRenderPriority() const
+ void initExecution() override;
+ void deinitExecution() override;
+ CompositorPriority getRenderPriority() const override
{
return CompositorPriority::Low;
}
-
- bool isFileOutputOperation() const
- {
- return true;
- }
};
void add_exr_channels(void *exrhandle,
@@ -146,3 +136,5 @@ void free_exr_channels(void *exrhandle,
const char *layerName,
const DataType datatype);
int get_datatype_size(DataType datatype);
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PixelateOperation.cc b/source/blender/compositor/operations/COM_PixelateOperation.cc
index 0d810c80ab4..94827cd1b02 100644
--- a/source/blender/compositor/operations/COM_PixelateOperation.cc
+++ b/source/blender/compositor/operations/COM_PixelateOperation.cc
@@ -18,6 +18,8 @@
#include "COM_PixelateOperation.h"
+namespace blender::compositor {
+
PixelateOperation::PixelateOperation(DataType datatype)
{
this->addInputSocket(datatype);
@@ -45,3 +47,5 @@ void PixelateOperation::executePixelSampled(float output[4],
float ny = round(y);
this->m_inputOperation->readSampled(output, nx, ny, sampler);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PixelateOperation.h b/source/blender/compositor/operations/COM_PixelateOperation.h
index c7595756d39..e8b272853da 100644
--- a/source/blender/compositor/operations/COM_PixelateOperation.h
+++ b/source/blender/compositor/operations/COM_PixelateOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* \brief Pixelate operation
*
@@ -44,12 +46,12 @@ class PixelateOperation : public NodeOperation {
/**
* \brief initialization of the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* \brief de-initialization of the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
/**
* \brief executePixel
@@ -58,5 +60,7 @@ class PixelateOperation : public NodeOperation {
* \param y: y-coordinate
* \param sampler: sampler
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cc b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cc
index bcf79e1c6c6..3577860b93d 100644
--- a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cc
+++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cc
@@ -26,6 +26,8 @@
#include "BKE_node.h"
+namespace blender::compositor {
+
static bool check_corners(float corners[4][2])
{
int i, next, prev;
@@ -60,7 +62,7 @@ static void readCornersFromSockets(rcti *rect, SocketReader *readers[4], float c
{
for (int i = 0; i < 4; i++) {
float result[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- readers[i]->readSampled(result, rect->xmin, rect->ymin, COM_PS_NEAREST);
+ readers[i]->readSampled(result, rect->xmin, rect->ymin, PixelSampler::Nearest);
corners[i][0] = result[0];
corners[i][1] = result[1];
}
@@ -98,7 +100,7 @@ PlaneCornerPinMaskOperation::PlaneCornerPinMaskOperation() : m_corners_ready(fal
* so we can use the initializeTileData function
* to read corners from input sockets ...
*/
- setComplex(true);
+ flags.complex = true;
}
void PlaneCornerPinMaskOperation::initExecution()
@@ -224,3 +226,5 @@ bool PlaneCornerPinWarpImageOperation::determineDependingAreaOfInterest(
input, readOperation, output);
#endif
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h
index 1e892465db8..91c0cd9e16b 100644
--- a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h
@@ -27,6 +27,8 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
+namespace blender::compositor {
+
class PlaneCornerPinMaskOperation : public PlaneDistortMaskOperation {
private:
bool m_corners_ready;
@@ -34,12 +36,13 @@ class PlaneCornerPinMaskOperation : public PlaneDistortMaskOperation {
public:
PlaneCornerPinMaskOperation();
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
};
class PlaneCornerPinWarpImageOperation : public PlaneDistortWarpImageOperation {
@@ -49,12 +52,14 @@ class PlaneCornerPinWarpImageOperation : public PlaneDistortWarpImageOperation {
public:
PlaneCornerPinWarpImageOperation();
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cc b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cc
index 87f837973d2..46ae00dee34 100644
--- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cc
+++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cc
@@ -29,6 +29,8 @@
#include "BKE_node.h"
#include "BKE_tracking.h"
+namespace blender::compositor {
+
/* ******** PlaneDistort WarpImage ******** */
BLI_INLINE void warpCoord(float x, float y, float matrix[3][3], float uv[2], float deriv[2][2])
@@ -46,12 +48,12 @@ BLI_INLINE void warpCoord(float x, float y, float matrix[3][3], float uv[2], flo
PlaneDistortWarpImageOperation::PlaneDistortWarpImageOperation()
{
- this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
+ this->addInputSocket(DataType::Color, ResizeMode::None);
this->addOutputSocket(DataType::Color);
this->m_pixelReader = nullptr;
this->m_motion_blur_samples = 1;
this->m_motion_blur_shutter = 0.5f;
- this->setComplex(true);
+ this->flags.complex = true;
}
void PlaneDistortWarpImageOperation::calculateCorners(const float corners[4][2],
@@ -226,3 +228,5 @@ void PlaneDistortMaskOperation::executePixelSampled(float output[4],
output[0] = (float)inside_counter / (this->m_osa * this->m_motion_blur_samples);
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
index 6cc9456c13f..95e5c86bd4d 100644
--- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
@@ -28,6 +28,8 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
+namespace blender::compositor {
+
#define PLANE_DISTORT_MAX_SAMPLES 64
class PlaneDistortWarpImageOperation : public NodeOperation {
@@ -46,14 +48,14 @@ class PlaneDistortWarpImageOperation : public NodeOperation {
void calculateCorners(const float corners[4][2], bool normalized, int sample);
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
void setMotionBlurSamples(int samples)
{
@@ -82,9 +84,9 @@ class PlaneDistortMaskOperation : public NodeOperation {
void calculateCorners(const float corners[4][2], bool normalized, int sample);
- void initExecution();
+ void initExecution() override;
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
void setMotionBlurSamples(int samples)
{
@@ -96,3 +98,5 @@ class PlaneDistortMaskOperation : public NodeOperation {
this->m_motion_blur_shutter = shutter;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.cc b/source/blender/compositor/operations/COM_PlaneTrackOperation.cc
index 81a598e937b..565bde6c945 100644
--- a/source/blender/compositor/operations/COM_PlaneTrackOperation.cc
+++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.cc
@@ -29,6 +29,8 @@
#include "BKE_node.h"
#include "BKE_tracking.h"
+namespace blender::compositor {
+
/* ******** PlaneTrackCommon ******** */
PlaneTrackCommon::PlaneTrackCommon()
@@ -121,3 +123,5 @@ void PlaneTrackWarpImageOperation::initExecution()
}
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.h b/source/blender/compositor/operations/COM_PlaneTrackOperation.h
index fc325c7db7d..95a7d536742 100644
--- a/source/blender/compositor/operations/COM_PlaneTrackOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.h
@@ -28,6 +28,8 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
+namespace blender::compositor {
+
class PlaneTrackCommon {
protected:
MovieClip *m_movieClip;
@@ -68,9 +70,10 @@ class PlaneTrackMaskOperation : public PlaneDistortMaskOperation, public PlaneTr
{
}
- void initExecution();
+ void initExecution() override;
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override
{
PlaneTrackCommon::determineResolution(resolution, preferredResolution);
@@ -86,12 +89,15 @@ class PlaneTrackWarpImageOperation : public PlaneDistortWarpImageOperation,
{
}
- void initExecution();
+ void initExecution() override;
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override
{
PlaneTrackCommon::determineResolution(resolution, preferredResolution);
unsigned int temp[2];
NodeOperation::determineResolution(temp, resolution);
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PreviewOperation.cc b/source/blender/compositor/operations/COM_PreviewOperation.cc
index 6d1199ab118..9a1990740f4 100644
--- a/source/blender/compositor/operations/COM_PreviewOperation.cc
+++ b/source/blender/compositor/operations/COM_PreviewOperation.cc
@@ -33,13 +33,15 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+namespace blender::compositor {
+
PreviewOperation::PreviewOperation(const ColorManagedViewSettings *viewSettings,
const ColorManagedDisplaySettings *displaySettings,
const unsigned int defaultWidth,
const unsigned int defaultHeight)
{
- this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
+ this->addInputSocket(DataType::Color, ResizeMode::None);
this->m_preview = nullptr;
this->m_outputBuffer = nullptr;
this->m_input = nullptr;
@@ -48,6 +50,8 @@ PreviewOperation::PreviewOperation(const ColorManagedViewSettings *viewSettings,
this->m_displaySettings = displaySettings;
this->m_defaultWidth = defaultWidth;
this->m_defaultHeight = defaultHeight;
+ flags.use_viewer_border = true;
+ flags.is_preview_operation = true;
}
void PreviewOperation::verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key)
@@ -104,7 +108,7 @@ void PreviewOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
color[1] = 0.0f;
color[2] = 0.0f;
color[3] = 1.0f;
- this->m_input->readSampled(color, rx, ry, COM_PS_NEAREST);
+ this->m_input->readSampled(color, rx, ry, PixelSampler::Nearest);
IMB_colormanagement_processor_apply_v4(cm_processor, color);
rgba_float_to_uchar(this->m_outputBuffer + offset, color);
offset += 4;
@@ -166,3 +170,5 @@ CompositorPriority PreviewOperation::getRenderPriority() const
{
return CompositorPriority::Low;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PreviewOperation.h b/source/blender/compositor/operations/COM_PreviewOperation.h
index 03ae6a6c42e..5e2b27475a1 100644
--- a/source/blender/compositor/operations/COM_PreviewOperation.h
+++ b/source/blender/compositor/operations/COM_PreviewOperation.h
@@ -24,6 +24,8 @@
#include "DNA_color_types.h"
#include "DNA_image_types.h"
+namespace blender::compositor {
+
class PreviewOperation : public NodeOperation {
protected:
unsigned char *m_outputBuffer;
@@ -47,21 +49,20 @@ class PreviewOperation : public NodeOperation {
unsigned int defaultHeight);
void verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key);
- bool isOutputOperation(bool /*rendering*/) const
+ bool isOutputOperation(bool /*rendering*/) const override
{
return !G.background;
}
- void initExecution();
- void deinitExecution();
- CompositorPriority getRenderPriority() const;
+ void initExecution() override;
+ void deinitExecution() override;
+ CompositorPriority getRenderPriority() const override;
- void executeRegion(rcti *rect, unsigned int tileNumber);
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void executeRegion(rcti *rect, unsigned int tileNumber) override;
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
- bool isPreviewOperation() const
- {
- return true;
- }
+ rcti *output) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cc b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cc
index 5494c3cd46b..93702d3f0cf 100644
--- a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cc
+++ b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cc
@@ -20,12 +20,14 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+namespace blender::compositor {
+
ProjectorLensDistortionOperation::ProjectorLensDistortionOperation()
{
this->addInputSocket(DataType::Color);
this->addInputSocket(DataType::Value);
this->addOutputSocket(DataType::Color);
- this->setComplex(true);
+ this->flags.complex = true;
this->m_inputProgram = nullptr;
this->m_dispersionAvailable = false;
this->m_dispersion = 0.0f;
@@ -103,7 +105,7 @@ void ProjectorLensDistortionOperation::updateDispersion()
this->lockMutex();
if (!this->m_dispersionAvailable) {
float result[4];
- this->getInputSocketReader(1)->readSampled(result, 1, 1, COM_PS_NEAREST);
+ this->getInputSocketReader(1)->readSampled(result, 1, 1, PixelSampler::Nearest);
this->m_dispersion = result[0];
this->m_kr = 0.25f * max_ff(min_ff(this->m_dispersion, 1.0f), 0.0f);
this->m_kr2 = this->m_kr * 20;
@@ -111,3 +113,5 @@ void ProjectorLensDistortionOperation::updateDispersion()
}
this->unlockMutex();
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h
index 96bede20623..bce61d3de15 100644
--- a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h
+++ b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h
@@ -21,6 +21,8 @@
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
class ProjectorLensDistortionOperation : public NodeOperation {
private:
/**
@@ -39,22 +41,24 @@ class ProjectorLensDistortionOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
void updateDispersion();
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_QualityStepHelper.cc b/source/blender/compositor/operations/COM_QualityStepHelper.cc
index c0d86314fb7..385e0bebca4 100644
--- a/source/blender/compositor/operations/COM_QualityStepHelper.cc
+++ b/source/blender/compositor/operations/COM_QualityStepHelper.cc
@@ -18,6 +18,8 @@
#include "COM_QualityStepHelper.h"
+namespace blender::compositor {
+
QualityStepHelper::QualityStepHelper()
{
this->m_quality = CompositorQuality::High;
@@ -64,3 +66,5 @@ void QualityStepHelper::initExecution(QualityHelper helper)
break;
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_QualityStepHelper.h b/source/blender/compositor/operations/COM_QualityStepHelper.h
index e437613fb29..bc2eaa88e3d 100644
--- a/source/blender/compositor/operations/COM_QualityStepHelper.h
+++ b/source/blender/compositor/operations/COM_QualityStepHelper.h
@@ -20,6 +20,8 @@
#include "COM_defines.h"
+namespace blender::compositor {
+
typedef enum QualityHelper {
COM_QH_INCREASE,
COM_QH_MULTIPLY,
@@ -54,3 +56,5 @@ class QualityStepHelper {
this->m_quality = quality;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.cc b/source/blender/compositor/operations/COM_ReadBufferOperation.cc
index 2977e6685d2..cc58f29e8d9 100644
--- a/source/blender/compositor/operations/COM_ReadBufferOperation.cc
+++ b/source/blender/compositor/operations/COM_ReadBufferOperation.cc
@@ -20,12 +20,15 @@
#include "COM_WriteBufferOperation.h"
#include "COM_defines.h"
+namespace blender::compositor {
+
ReadBufferOperation::ReadBufferOperation(DataType datatype)
{
this->addOutputSocket(datatype);
this->m_single_value = false;
this->m_offset = 0;
this->m_buffer = nullptr;
+ flags.is_read_buffer_operation = true;
}
void *ReadBufferOperation::initializeTileData(rcti * /*rect*/)
@@ -60,14 +63,14 @@ void ReadBufferOperation::executePixelSampled(float output[4],
}
else {
switch (sampler) {
- case COM_PS_NEAREST:
+ case PixelSampler::Nearest:
m_buffer->read(output, x, y);
break;
- case COM_PS_BILINEAR:
+ case PixelSampler::Bilinear:
default:
m_buffer->readBilinear(output, x, y);
break;
- case COM_PS_BICUBIC:
+ case PixelSampler::Bicubic:
m_buffer->readBilinear(output, x, y);
break;
}
@@ -85,7 +88,7 @@ void ReadBufferOperation::executePixelExtend(float output[4],
/* write buffer has a single value stored at (0,0) */
m_buffer->read(output, 0, 0);
}
- else if (sampler == COM_PS_NEAREST) {
+ else if (sampler == PixelSampler::Nearest) {
m_buffer->read(output, x, y, extend_x, extend_y);
}
else {
@@ -131,3 +134,5 @@ void ReadBufferOperation::updateMemoryBuffer()
{
this->m_buffer = this->getMemoryProxy()->getBuffer();
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.h b/source/blender/compositor/operations/COM_ReadBufferOperation.h
index 2ada33906ef..981c09292af 100644
--- a/source/blender/compositor/operations/COM_ReadBufferOperation.h
+++ b/source/blender/compositor/operations/COM_ReadBufferOperation.h
@@ -22,6 +22,8 @@
#include "COM_MemoryProxy.h"
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class ReadBufferOperation : public NodeOperation {
private:
MemoryProxy *m_memoryProxy;
@@ -39,21 +41,18 @@ class ReadBufferOperation : public NodeOperation {
{
return this->m_memoryProxy;
}
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
- void *initializeTileData(rcti *rect);
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void *initializeTileData(rcti *rect) override;
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
void executePixelExtend(float output[4],
float x,
float y,
PixelSampler sampler,
MemoryBufferExtend extend_x,
MemoryBufferExtend extend_y);
- void executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2]);
- bool isReadBufferOperation() const
- {
- return true;
- }
+ void executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2]) override;
void setOffset(unsigned int offset)
{
this->m_offset = offset;
@@ -64,11 +63,13 @@ class ReadBufferOperation : public NodeOperation {
}
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
- MemoryBuffer *getInputMemoryBuffer(MemoryBuffer **memoryBuffers)
+ rcti *output) override;
+ MemoryBuffer *getInputMemoryBuffer(MemoryBuffer **memoryBuffers) override
{
return memoryBuffers[this->m_offset];
}
void readResolutionFromWriteBuffer();
void updateMemoryBuffer();
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cc b/source/blender/compositor/operations/COM_RenderLayersProg.cc
index d622e14b585..1ac451b95c2 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.cc
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.cc
@@ -32,6 +32,8 @@
#include "RE_pipeline.h"
#include "RE_texture.h"
+namespace blender::compositor {
+
/* ******** Render Layers Base Prog ******** */
RenderLayersProg::RenderLayersProg(const char *passName, DataType type, int elementsize)
@@ -92,7 +94,7 @@ void RenderLayersProg::doInterpolation(float output[4], float x, float y, PixelS
}
switch (sampler) {
- case COM_PS_NEAREST: {
+ case PixelSampler::Nearest: {
offset = (iy * width + ix) * this->m_elementsize;
if (this->m_elementsize == 1) {
@@ -107,12 +109,12 @@ void RenderLayersProg::doInterpolation(float output[4], float x, float y, PixelS
break;
}
- case COM_PS_BILINEAR:
+ case PixelSampler::Bilinear:
BLI_bilinear_interpolation_fl(
this->m_inputBuffer, output, width, height, this->m_elementsize, x, y);
break;
- case COM_PS_BICUBIC:
+ case PixelSampler::Bicubic:
BLI_bicubic_interpolation_fl(
this->m_inputBuffer, output, width, height, this->m_elementsize, x, y);
break;
@@ -216,7 +218,7 @@ void RenderLayersProg::determineResolution(unsigned int resolution[2],
}
}
-std::unique_ptr<MetaData> RenderLayersProg::getMetaData() const
+std::unique_ptr<MetaData> RenderLayersProg::getMetaData()
{
Scene *scene = this->getScene();
Render *re = (scene) ? RE_GetSceneRender(scene) : nullptr;
@@ -306,3 +308,5 @@ void RenderLayersDepthProg::executePixelSampled(float output[4],
output[0] = inputBuffer[offset];
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h
index a0d5bc2953b..33e4fb163c5 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.h
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.h
@@ -26,6 +26,8 @@
#include "RE_pipeline.h"
+namespace blender::compositor {
+
/**
* Base class for all renderlayeroperations
*
@@ -123,7 +125,7 @@ class RenderLayersProg : public NodeOperation {
void deinitExecution() override;
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- std::unique_ptr<MetaData> getMetaData() const override;
+ std::unique_ptr<MetaData> getMetaData() override;
};
class RenderLayersAOOperation : public RenderLayersProg {
@@ -132,7 +134,7 @@ class RenderLayersAOOperation : public RenderLayersProg {
: RenderLayersProg(passName, type, elementsize)
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class RenderLayersAlphaProg : public RenderLayersProg {
@@ -141,7 +143,7 @@ class RenderLayersAlphaProg : public RenderLayersProg {
: RenderLayersProg(passName, type, elementsize)
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class RenderLayersDepthProg : public RenderLayersProg {
@@ -150,5 +152,7 @@ class RenderLayersDepthProg : public RenderLayersProg {
: RenderLayersProg(passName, type, elementsize)
{
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_RotateOperation.cc b/source/blender/compositor/operations/COM_RotateOperation.cc
index c2105efe246..4fb3d324992 100644
--- a/source/blender/compositor/operations/COM_RotateOperation.cc
+++ b/source/blender/compositor/operations/COM_RotateOperation.cc
@@ -19,6 +19,8 @@
#include "COM_RotateOperation.h"
#include "BLI_math.h"
+namespace blender::compositor {
+
RotateOperation::RotateOperation()
{
this->addInputSocket(DataType::Color);
@@ -48,7 +50,7 @@ inline void RotateOperation::ensureDegree()
{
if (!this->m_isDegreeSet) {
float degree[4];
- this->m_degreeSocket->readSampled(degree, 0, 0, COM_PS_NEAREST);
+ this->m_degreeSocket->readSampled(degree, 0, 0, PixelSampler::Nearest);
double rad;
if (this->m_doDegree2RadConversion) {
rad = DEG2RAD((double)degree[0]);
@@ -105,3 +107,5 @@ bool RotateOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_RotateOperation.h b/source/blender/compositor/operations/COM_RotateOperation.h
index 0ef4466671a..d76507f9816 100644
--- a/source/blender/compositor/operations/COM_RotateOperation.h
+++ b/source/blender/compositor/operations/COM_RotateOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class RotateOperation : public NodeOperation {
private:
SocketReader *m_imageSocket;
@@ -35,10 +37,10 @@ class RotateOperation : public NodeOperation {
RotateOperation();
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
- void initExecution();
- void deinitExecution();
+ rcti *output) override;
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+ void initExecution() override;
+ void deinitExecution() override;
void setDoDegree2RadConversion(bool abool)
{
this->m_doDegree2RadConversion = abool;
@@ -46,3 +48,5 @@ class RotateOperation : public NodeOperation {
void ensureDegree();
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SMAAOperation.cc b/source/blender/compositor/operations/COM_SMAAOperation.cc
new file mode 100644
index 00000000000..38700c76f07
--- /dev/null
+++ b/source/blender/compositor/operations/COM_SMAAOperation.cc
@@ -0,0 +1,868 @@
+/*
+ * Copyright 2017, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor: IRIE Shinsuke
+ */
+
+#include "COM_SMAAOperation.h"
+#include "BLI_math.h"
+#include "COM_SMAAAreaTexture.h"
+
+extern "C" {
+#include "IMB_colormanagement.h"
+}
+
+namespace blender::compositor {
+
+/*
+ * An implementation of Enhanced Subpixel Morphological Antialiasing (SMAA)
+ *
+ * The algorithm was proposed by:
+ * Jorge Jimenez, Jose I. Echevarria, Tiago Sousa, Diego Gutierrez
+ *
+ * http://www.iryoku.com/smaa/
+ *
+ * This file is based on smaa-cpp:
+ *
+ * https://github.com/iRi-E/smaa-cpp
+ *
+ * Currently only SMAA 1x mode is provided, so the operation will be done
+ * with no spatial multisampling nor temporal supersampling.
+ *
+ * Note: This program assumes the screen coordinates are DirectX style, so
+ * the vertical direction is upside-down. "top" and "bottom" actually mean
+ * bottom and top, respectively.
+ */
+
+/*-----------------------------------------------------------------------------*/
+/* Non-Configurable Defines */
+
+#define SMAA_AREATEX_SIZE 80
+#define SMAA_AREATEX_MAX_DISTANCE 20
+#define SMAA_AREATEX_MAX_DISTANCE_DIAG 20
+#define SMAA_MAX_SEARCH_STEPS 362 /* 362 - 1 = 19^2 */
+#define SMAA_MAX_SEARCH_STEPS_DIAG 19
+
+/*-----------------------------------------------------------------------------*/
+/* Internal Functions to Sample Pixel Color from Image */
+
+static inline void sample(SocketReader *reader, int x, int y, float color[4])
+{
+ if (x < 0 || x >= reader->getWidth() || y < 0 || y >= reader->getHeight()) {
+ color[0] = color[1] = color[2] = color[3] = 0.0;
+ return;
+ }
+
+ reader->read(color, x, y, nullptr);
+}
+
+static void sample_bilinear_vertical(
+ SocketReader *reader, int x, int y, float yoffset, float color[4])
+{
+ float iy = floorf(yoffset);
+ float fy = yoffset - iy;
+ y += (int)iy;
+
+ float color00[4], color01[4];
+
+ sample(reader, x + 0, y + 0, color00);
+ sample(reader, x + 0, y + 1, color01);
+
+ color[0] = interpf(color01[0], color00[0], fy);
+ color[1] = interpf(color01[1], color00[1], fy);
+ color[2] = interpf(color01[2], color00[2], fy);
+ color[3] = interpf(color01[3], color00[3], fy);
+}
+
+static void sample_bilinear_horizontal(
+ SocketReader *reader, int x, int y, float xoffset, float color[4])
+{
+ float ix = floorf(xoffset);
+ float fx = xoffset - ix;
+ x += (int)ix;
+
+ float color00[4], color10[4];
+
+ sample(reader, x + 0, y + 0, color00);
+ sample(reader, x + 1, y + 0, color10);
+
+ color[0] = interpf(color10[0], color00[0], fx);
+ color[1] = interpf(color10[1], color00[1], fx);
+ color[2] = interpf(color10[2], color00[2], fx);
+ color[3] = interpf(color10[3], color00[3], fx);
+}
+
+/*-----------------------------------------------------------------------------*/
+/* Internal Functions to Sample Blending Weights from AreaTex */
+
+static inline const float *areatex_sample_internal(const float *areatex, int x, int y)
+{
+ return &areatex[(CLAMPIS(x, 0, SMAA_AREATEX_SIZE - 1) +
+ CLAMPIS(y, 0, SMAA_AREATEX_SIZE - 1) * SMAA_AREATEX_SIZE) *
+ 2];
+}
+
+/**
+ * We have the distance and both crossing edges. So, what are the areas
+ * at each side of current edge?
+ */
+static void area(int d1, int d2, int e1, int e2, float weights[2])
+{
+ /* The areas texture is compressed quadratically: */
+ float x = (float)(SMAA_AREATEX_MAX_DISTANCE * e1) + sqrtf((float)d1);
+ float y = (float)(SMAA_AREATEX_MAX_DISTANCE * e2) + sqrtf((float)d2);
+
+ float ix = floorf(x), iy = floorf(y);
+ float fx = x - ix, fy = y - iy;
+ int X = (int)ix, Y = (int)iy;
+
+ const float *weights00 = areatex_sample_internal(areatex, X + 0, Y + 0);
+ const float *weights10 = areatex_sample_internal(areatex, X + 1, Y + 0);
+ const float *weights01 = areatex_sample_internal(areatex, X + 0, Y + 1);
+ const float *weights11 = areatex_sample_internal(areatex, X + 1, Y + 1);
+
+ weights[0] = interpf(
+ interpf(weights11[0], weights01[0], fx), interpf(weights10[0], weights00[0], fx), fy);
+ weights[1] = interpf(
+ interpf(weights11[1], weights01[1], fx), interpf(weights10[1], weights00[1], fx), fy);
+}
+
+/**
+ * Similar to area(), this calculates the area corresponding to a certain
+ * diagonal distance and crossing edges 'e'.
+ */
+static void area_diag(int d1, int d2, int e1, int e2, float weights[2])
+{
+ int x = SMAA_AREATEX_MAX_DISTANCE_DIAG * e1 + d1;
+ int y = SMAA_AREATEX_MAX_DISTANCE_DIAG * e2 + d2;
+
+ const float *w = areatex_sample_internal(areatex_diag, x, y);
+ copy_v2_v2(weights, w);
+}
+
+/*-----------------------------------------------------------------------------*/
+/* Edge Detection (First Pass) */
+/*-----------------------------------------------------------------------------*/
+
+SMAAEdgeDetectionOperation::SMAAEdgeDetectionOperation()
+{
+ this->addInputSocket(DataType::Color); /* image */
+ this->addInputSocket(DataType::Value); /* depth, material ID, etc. */
+ this->addOutputSocket(DataType::Color);
+ this->flags.complex = true;
+ this->m_imageReader = nullptr;
+ this->m_valueReader = nullptr;
+ this->m_threshold = 0.1f;
+ this->m_contrast_limit = 2.0f;
+}
+
+void SMAAEdgeDetectionOperation::initExecution()
+{
+ this->m_imageReader = this->getInputSocketReader(0);
+ this->m_valueReader = this->getInputSocketReader(1);
+}
+
+void SMAAEdgeDetectionOperation::deinitExecution()
+{
+ this->m_imageReader = nullptr;
+ this->m_valueReader = nullptr;
+}
+
+void SMAAEdgeDetectionOperation::setThreshold(float threshold)
+{
+ /* UI values are between 0 and 1 for simplicity but algorithm expects values between 0 and 0.5 */
+ m_threshold = scalenorm(0, 0.5, threshold);
+}
+
+void SMAAEdgeDetectionOperation::setLocalContrastAdaptationFactor(float factor)
+{
+ /* UI values are between 0 and 1 for simplicity but algorithm expects values between 1 and 10 */
+ m_contrast_limit = scalenorm(1, 10, factor);
+}
+
+bool SMAAEdgeDetectionOperation::determineDependingAreaOfInterest(
+ rcti *input, ReadBufferOperation *readOperation, rcti *output)
+{
+ rcti newInput;
+ newInput.xmax = input->xmax + 1;
+ newInput.xmin = input->xmin - 2;
+ newInput.ymax = input->ymax + 1;
+ newInput.ymin = input->ymin - 2;
+
+ return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+}
+
+void SMAAEdgeDetectionOperation::executePixel(float output[4], int x, int y, void * /*data*/)
+{
+ float color[4];
+
+ /* Calculate luma deltas: */
+ sample(m_imageReader, x, y, color);
+ float L = IMB_colormanagement_get_luminance(color);
+ sample(m_imageReader, x - 1, y, color);
+ float Lleft = IMB_colormanagement_get_luminance(color);
+ sample(m_imageReader, x, y - 1, color);
+ float Ltop = IMB_colormanagement_get_luminance(color);
+ float Dleft = fabsf(L - Lleft);
+ float Dtop = fabsf(L - Ltop);
+
+ /* We do the usual threshold: */
+ output[0] = (x > 0 && Dleft >= m_threshold) ? 1.0f : 0.0f;
+ output[1] = (y > 0 && Dtop >= m_threshold) ? 1.0f : 0.0f;
+ output[2] = 0.0f;
+ output[3] = 1.0f;
+
+ /* Then discard if there is no edge: */
+ if (is_zero_v2(output)) {
+ return;
+ }
+
+ /* Calculate right and bottom deltas: */
+ sample(m_imageReader, x + 1, y, color);
+ float Lright = IMB_colormanagement_get_luminance(color);
+ sample(m_imageReader, x, y + 1, color);
+ float Lbottom = IMB_colormanagement_get_luminance(color);
+ float Dright = fabsf(L - Lright);
+ float Dbottom = fabsf(L - Lbottom);
+
+ /* Calculate the maximum delta in the direct neighborhood: */
+ float maxDelta = fmaxf(fmaxf(Dleft, Dright), fmaxf(Dtop, Dbottom));
+
+ /* Calculate luma used for both left and top edges: */
+ sample(m_imageReader, x - 1, y - 1, color);
+ float Llefttop = IMB_colormanagement_get_luminance(color);
+
+ /* Left edge */
+ if (output[0] != 0.0f) {
+ /* Calculate deltas around the left pixel: */
+ sample(m_imageReader, x - 2, y, color);
+ float Lleftleft = IMB_colormanagement_get_luminance(color);
+ sample(m_imageReader, x - 1, y + 1, color);
+ float Lleftbottom = IMB_colormanagement_get_luminance(color);
+ float Dleftleft = fabsf(Lleft - Lleftleft);
+ float Dlefttop = fabsf(Lleft - Llefttop);
+ float Dleftbottom = fabsf(Lleft - Lleftbottom);
+
+ /* Calculate the final maximum delta: */
+ maxDelta = fmaxf(maxDelta, fmaxf(Dleftleft, fmaxf(Dlefttop, Dleftbottom)));
+
+ /* Local contrast adaptation: */
+ if (maxDelta > m_contrast_limit * Dleft) {
+ output[0] = 0.0f;
+ }
+ }
+
+ /* Top edge */
+ if (output[1] != 0.0f) {
+ /* Calculate top-top delta: */
+ sample(m_imageReader, x, y - 2, color);
+ float Ltoptop = IMB_colormanagement_get_luminance(color);
+ sample(m_imageReader, x + 1, y - 1, color);
+ float Ltopright = IMB_colormanagement_get_luminance(color);
+ float Dtoptop = fabsf(Ltop - Ltoptop);
+ float Dtopleft = fabsf(Ltop - Llefttop);
+ float Dtopright = fabsf(Ltop - Ltopright);
+
+ /* Calculate the final maximum delta: */
+ maxDelta = fmaxf(maxDelta, fmaxf(Dtoptop, fmaxf(Dtopleft, Dtopright)));
+
+ /* Local contrast adaptation: */
+ if (maxDelta > m_contrast_limit * Dtop) {
+ output[1] = 0.0f;
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------*/
+/* Blending Weight Calculation (Second Pass) */
+/*-----------------------------------------------------------------------------*/
+
+SMAABlendingWeightCalculationOperation::SMAABlendingWeightCalculationOperation()
+{
+ this->addInputSocket(DataType::Color); /* edges */
+ this->addOutputSocket(DataType::Color);
+ this->flags.complex = true;
+ this->m_imageReader = nullptr;
+ this->m_corner_rounding = 25;
+}
+
+void *SMAABlendingWeightCalculationOperation::initializeTileData(rcti *rect)
+{
+ return getInputOperation(0)->initializeTileData(rect);
+}
+
+void SMAABlendingWeightCalculationOperation::initExecution()
+{
+ this->m_imageReader = this->getInputSocketReader(0);
+}
+
+void SMAABlendingWeightCalculationOperation::setCornerRounding(float rounding)
+{
+ /* UI values are between 0 and 1 for simplicity but algorithm expects values between 0 and 100 */
+ m_corner_rounding = static_cast<int>(scalenorm(0, 100, rounding));
+}
+
+void SMAABlendingWeightCalculationOperation::executePixel(float output[4],
+ int x,
+ int y,
+ void * /*data*/)
+{
+ float edges[4], c[4];
+
+ zero_v4(output);
+ sample(m_imageReader, x, y, edges);
+
+ /* Edge at north */
+ if (edges[1] > 0.0f) {
+ /* Diagonals have both north and west edges, so calculating weights for them */
+ /* in one of the boundaries is enough. */
+ calculateDiagWeights(x, y, edges, output);
+
+ /* We give priority to diagonals, so if we find a diagonal we skip */
+ /* horizontal/vertical processing. */
+ if (!is_zero_v2(output)) {
+ return;
+ }
+
+ /* Find the distance to the left and the right: */
+ int left = searchXLeft(x, y);
+ int right = searchXRight(x, y);
+ int d1 = x - left, d2 = right - x;
+
+ /* Fetch the left and right crossing edges: */
+ int e1 = 0, e2 = 0;
+ sample(m_imageReader, left, y - 1, c);
+ if (c[0] > 0.0) {
+ e1 += 1;
+ }
+ sample(m_imageReader, left, y, c);
+ if (c[0] > 0.0) {
+ e1 += 2;
+ }
+ sample(m_imageReader, right + 1, y - 1, c);
+ if (c[0] > 0.0) {
+ e2 += 1;
+ }
+ sample(m_imageReader, right + 1, y, c);
+ if (c[0] > 0.0) {
+ e2 += 2;
+ }
+
+ /* Ok, we know how this pattern looks like, now it is time for getting */
+ /* the actual area: */
+ area(d1, d2, e1, e2, output); /* R, G */
+
+ /* Fix corners: */
+ if (m_corner_rounding) {
+ detectHorizontalCornerPattern(output, left, right, y, d1, d2);
+ }
+ }
+
+ /* Edge at west */
+ if (edges[0] > 0.0f) {
+ /* Did we already do diagonal search for this west edge from the left neighboring pixel? */
+ if (isVerticalSearchUnneeded(x, y)) {
+ return;
+ }
+
+ /* Find the distance to the top and the bottom: */
+ int top = searchYUp(x, y);
+ int bottom = searchYDown(x, y);
+ int d1 = y - top, d2 = bottom - y;
+
+ /* Fetch the top ang bottom crossing edges: */
+ int e1 = 0, e2 = 0;
+ sample(m_imageReader, x - 1, top, c);
+ if (c[1] > 0.0) {
+ e1 += 1;
+ }
+ sample(m_imageReader, x, top, c);
+ if (c[1] > 0.0) {
+ e1 += 2;
+ }
+ sample(m_imageReader, x - 1, bottom + 1, c);
+ if (c[1] > 0.0) {
+ e2 += 1;
+ }
+ sample(m_imageReader, x, bottom + 1, c);
+ if (c[1] > 0.0) {
+ e2 += 2;
+ }
+
+ /* Get the area for this direction: */
+ area(d1, d2, e1, e2, output + 2); /* B, A */
+
+ /* Fix corners: */
+ if (m_corner_rounding) {
+ detectVerticalCornerPattern(output + 2, x, top, bottom, d1, d2);
+ }
+ }
+}
+
+void SMAABlendingWeightCalculationOperation::deinitExecution()
+{
+ this->m_imageReader = nullptr;
+}
+
+bool SMAABlendingWeightCalculationOperation::determineDependingAreaOfInterest(
+ rcti *input, ReadBufferOperation *readOperation, rcti *output)
+{
+ rcti newInput;
+
+ newInput.xmax = input->xmax + fmax(SMAA_MAX_SEARCH_STEPS, SMAA_MAX_SEARCH_STEPS_DIAG + 1);
+ newInput.xmin = input->xmin -
+ fmax(fmax(SMAA_MAX_SEARCH_STEPS - 1, 1), SMAA_MAX_SEARCH_STEPS_DIAG + 1);
+ newInput.ymax = input->ymax + fmax(SMAA_MAX_SEARCH_STEPS, SMAA_MAX_SEARCH_STEPS_DIAG);
+ newInput.ymin = input->ymin -
+ fmax(fmax(SMAA_MAX_SEARCH_STEPS - 1, 1), SMAA_MAX_SEARCH_STEPS_DIAG);
+
+ return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+}
+
+/*-----------------------------------------------------------------------------*/
+/* Diagonal Search Functions */
+
+/**
+ * These functions allows to perform diagonal pattern searches.
+ */
+int SMAABlendingWeightCalculationOperation::searchDiag1(int x, int y, int dir, bool *found)
+{
+ float e[4];
+ int end = x + SMAA_MAX_SEARCH_STEPS_DIAG * dir;
+ *found = false;
+
+ while (x != end) {
+ x += dir;
+ y -= dir;
+ sample(m_imageReader, x, y, e);
+ if (e[1] == 0.0f) {
+ *found = true;
+ break;
+ }
+ if (e[0] == 0.0f) {
+ *found = true;
+ return (dir < 0) ? x : x - dir;
+ }
+ }
+
+ return x - dir;
+}
+
+int SMAABlendingWeightCalculationOperation::searchDiag2(int x, int y, int dir, bool *found)
+{
+ float e[4];
+ int end = x + SMAA_MAX_SEARCH_STEPS_DIAG * dir;
+ *found = false;
+
+ while (x != end) {
+ x += dir;
+ y += dir;
+ sample(m_imageReader, x, y, e);
+ if (e[1] == 0.0f) {
+ *found = true;
+ break;
+ }
+ sample(m_imageReader, x + 1, y, e);
+ if (e[0] == 0.0f) {
+ *found = true;
+ return (dir > 0) ? x : x - dir;
+ }
+ }
+
+ return x - dir;
+}
+
+/**
+ * This searches for diagonal patterns and returns the corresponding weights.
+ */
+void SMAABlendingWeightCalculationOperation::calculateDiagWeights(int x,
+ int y,
+ const float edges[2],
+ float weights[2])
+{
+ int d1, d2;
+ bool d1_found, d2_found;
+ float e[4], c[4];
+
+ zero_v2(weights);
+
+ if (SMAA_MAX_SEARCH_STEPS_DIAG <= 0) {
+ return;
+ }
+
+ /* Search for the line ends: */
+ if (edges[0] > 0.0f) {
+ d1 = x - searchDiag1(x, y, -1, &d1_found);
+ }
+ else {
+ d1 = 0;
+ d1_found = true;
+ }
+ d2 = searchDiag1(x, y, 1, &d2_found) - x;
+
+ if (d1 + d2 > 2) { /* d1 + d2 + 1 > 3 */
+ int e1 = 0, e2 = 0;
+
+ if (d1_found) {
+ /* Fetch the crossing edges: */
+ int left = x - d1, bottom = y + d1;
+
+ sample(m_imageReader, left - 1, bottom, c);
+ if (c[1] > 0.0) {
+ e1 += 2;
+ }
+ sample(m_imageReader, left, bottom, c);
+ if (c[0] > 0.0) {
+ e1 += 1;
+ }
+ }
+
+ if (d2_found) {
+ /* Fetch the crossing edges: */
+ int right = x + d2, top = y - d2;
+
+ sample(m_imageReader, right + 1, top, c);
+ if (c[1] > 0.0) {
+ e2 += 2;
+ }
+ sample(m_imageReader, right + 1, top - 1, c);
+ if (c[0] > 0.0) {
+ e2 += 1;
+ }
+ }
+
+ /* Fetch the areas for this line: */
+ area_diag(d1, d2, e1, e2, weights);
+ }
+
+ /* Search for the line ends: */
+ d1 = x - searchDiag2(x, y, -1, &d1_found);
+ sample(m_imageReader, x + 1, y, e);
+ if (e[0] > 0.0f) {
+ d2 = searchDiag2(x, y, 1, &d2_found) - x;
+ }
+ else {
+ d2 = 0;
+ d2_found = true;
+ }
+
+ if (d1 + d2 > 2) { /* d1 + d2 + 1 > 3 */
+ int e1 = 0, e2 = 0;
+
+ if (d1_found) {
+ /* Fetch the crossing edges: */
+ int left = x - d1, top = y - d1;
+
+ sample(m_imageReader, left - 1, top, c);
+ if (c[1] > 0.0) {
+ e1 += 2;
+ }
+ sample(m_imageReader, left, top - 1, c);
+ if (c[0] > 0.0) {
+ e1 += 1;
+ }
+ }
+
+ if (d2_found) {
+ /* Fetch the crossing edges: */
+ int right = x + d2, bottom = y + d2;
+
+ sample(m_imageReader, right + 1, bottom, c);
+ if (c[1] > 0.0) {
+ e2 += 2;
+ }
+ if (c[0] > 0.0) {
+ e2 += 1;
+ }
+ }
+
+ /* Fetch the areas for this line: */
+ float w[2];
+ area_diag(d1, d2, e1, e2, w);
+ weights[0] += w[1];
+ weights[1] += w[0];
+ }
+}
+
+bool SMAABlendingWeightCalculationOperation::isVerticalSearchUnneeded(int x, int y)
+{
+ int d1, d2;
+ bool found;
+ float e[4];
+
+ if (SMAA_MAX_SEARCH_STEPS_DIAG <= 0) {
+ return false;
+ }
+
+ /* Search for the line ends: */
+ sample(m_imageReader, x - 1, y, e);
+ if (e[1] > 0.0f) {
+ d1 = x - searchDiag2(x - 1, y, -1, &found);
+ }
+ else {
+ d1 = 0;
+ }
+ d2 = searchDiag2(x - 1, y, 1, &found) - x;
+
+ return (d1 + d2 > 2); /* d1 + d2 + 1 > 3 */
+}
+
+/*-----------------------------------------------------------------------------*/
+/* Horizontal/Vertical Search Functions */
+
+int SMAABlendingWeightCalculationOperation::searchXLeft(int x, int y)
+{
+ int end = x - SMAA_MAX_SEARCH_STEPS;
+ float e[4];
+
+ while (x > end) {
+ sample(m_imageReader, x, y, e);
+ if (e[1] == 0.0f) { /* Is the edge not activated? */
+ break;
+ }
+ if (e[0] != 0.0f) { /* Or is there a crossing edge that breaks the line? */
+ return x;
+ }
+ sample(m_imageReader, x, y - 1, e);
+ if (e[0] != 0.0f) { /* Or is there a crossing edge that breaks the line? */
+ return x;
+ }
+ x--;
+ }
+
+ return x + 1;
+}
+
+int SMAABlendingWeightCalculationOperation::searchXRight(int x, int y)
+{
+ int end = x + SMAA_MAX_SEARCH_STEPS;
+ float e[4];
+
+ while (x < end) {
+ x++;
+ sample(m_imageReader, x, y, e);
+ if (e[1] == 0.0f || /* Is the edge not activated? */
+ e[0] != 0.0f) { /* Or is there a crossing edge that breaks the line? */
+ break;
+ }
+ sample(m_imageReader, x, y - 1, e);
+ if (e[0] != 0.0f) { /* Or is there a crossing edge that breaks the line? */
+ break;
+ }
+ }
+
+ return x - 1;
+}
+
+int SMAABlendingWeightCalculationOperation::searchYUp(int x, int y)
+{
+ int end = y - SMAA_MAX_SEARCH_STEPS;
+ float e[4];
+
+ while (y > end) {
+ sample(m_imageReader, x, y, e);
+ if (e[0] == 0.0f) { /* Is the edge not activated? */
+ break;
+ }
+ if (e[1] != 0.0f) { /* Or is there a crossing edge that breaks the line? */
+ return y;
+ }
+ sample(m_imageReader, x - 1, y, e);
+ if (e[1] != 0.0f) { /* Or is there a crossing edge that breaks the line? */
+ return y;
+ }
+ y--;
+ }
+
+ return y + 1;
+}
+
+int SMAABlendingWeightCalculationOperation::searchYDown(int x, int y)
+{
+ int end = y + SMAA_MAX_SEARCH_STEPS;
+ float e[4];
+
+ while (y < end) {
+ y++;
+ sample(m_imageReader, x, y, e);
+ if (e[0] == 0.0f || /* Is the edge not activated? */
+ e[1] != 0.0f) { /* Or is there a crossing edge that breaks the line? */
+ break;
+ }
+ sample(m_imageReader, x - 1, y, e);
+ if (e[1] != 0.0f) { /* Or is there a crossing edge that breaks the line? */
+ break;
+ }
+ }
+
+ return y - 1;
+}
+
+/*-----------------------------------------------------------------------------*/
+/* Corner Detection Functions */
+
+void SMAABlendingWeightCalculationOperation::detectHorizontalCornerPattern(
+ float weights[2], int left, int right, int y, int d1, int d2)
+{
+ float factor[2] = {1.0f, 1.0f};
+ float rounding = m_corner_rounding / 100.0f;
+ float e[4];
+
+ /* Reduce blending for pixels in the center of a line. */
+ rounding *= (d1 == d2) ? 0.5f : 1.0f;
+
+ /* Near the left corner */
+ if (d1 <= d2) {
+ sample(m_imageReader, left, y + 1, e);
+ factor[0] -= rounding * e[0];
+ sample(m_imageReader, left, y - 2, e);
+ factor[1] -= rounding * e[0];
+ }
+ /* Near the right corner */
+ if (d1 >= d2) {
+ sample(m_imageReader, right + 1, y + 1, e);
+ factor[0] -= rounding * e[0];
+ sample(m_imageReader, right + 1, y - 2, e);
+ factor[1] -= rounding * e[0];
+ }
+
+ weights[0] *= CLAMPIS(factor[0], 0.0f, 1.0f);
+ weights[1] *= CLAMPIS(factor[1], 0.0f, 1.0f);
+}
+
+void SMAABlendingWeightCalculationOperation::detectVerticalCornerPattern(
+ float weights[2], int x, int top, int bottom, int d1, int d2)
+{
+ float factor[2] = {1.0f, 1.0f};
+ float rounding = m_corner_rounding / 100.0f;
+ float e[4];
+
+ /* Reduce blending for pixels in the center of a line. */
+ rounding *= (d1 == d2) ? 0.5f : 1.0f;
+
+ /* Near the top corner */
+ if (d1 <= d2) {
+ sample(m_imageReader, x + 1, top, e);
+ factor[0] -= rounding * e[1];
+ sample(m_imageReader, x - 2, top, e);
+ factor[1] -= rounding * e[1];
+ }
+ /* Near the bottom corner */
+ if (d1 >= d2) {
+ sample(m_imageReader, x + 1, bottom + 1, e);
+ factor[0] -= rounding * e[1];
+ sample(m_imageReader, x - 2, bottom + 1, e);
+ factor[1] -= rounding * e[1];
+ }
+
+ weights[0] *= CLAMPIS(factor[0], 0.0f, 1.0f);
+ weights[1] *= CLAMPIS(factor[1], 0.0f, 1.0f);
+}
+
+/*-----------------------------------------------------------------------------*/
+/* Neighborhood Blending (Third Pass) */
+/*-----------------------------------------------------------------------------*/
+
+SMAANeighborhoodBlendingOperation::SMAANeighborhoodBlendingOperation()
+{
+ this->addInputSocket(DataType::Color); /* image */
+ this->addInputSocket(DataType::Color); /* blend */
+ this->addOutputSocket(DataType::Color);
+ this->flags.complex = true;
+ this->m_image1Reader = nullptr;
+ this->m_image2Reader = nullptr;
+}
+
+void *SMAANeighborhoodBlendingOperation::initializeTileData(rcti *rect)
+{
+ return getInputOperation(0)->initializeTileData(rect);
+}
+
+void SMAANeighborhoodBlendingOperation::initExecution()
+{
+ this->m_image1Reader = this->getInputSocketReader(0);
+ this->m_image2Reader = this->getInputSocketReader(1);
+}
+
+void SMAANeighborhoodBlendingOperation::executePixel(float output[4],
+ int x,
+ int y,
+ void * /*data*/)
+{
+ float w[4];
+
+ /* Fetch the blending weights for current pixel: */
+ sample(m_image2Reader, x, y, w);
+ float left = w[2], top = w[0];
+ sample(m_image2Reader, x + 1, y, w);
+ float right = w[3];
+ sample(m_image2Reader, x, y + 1, w);
+ float bottom = w[1];
+
+ /* Is there any blending weight with a value greater than 0.0? */
+ if (right + bottom + left + top < 1e-5f) {
+ sample(m_image1Reader, x, y, output);
+ return;
+ }
+
+ /* Calculate the blending offsets: */
+ void (*samplefunc)(SocketReader * reader, int x, int y, float xoffset, float color[4]);
+ float offset1, offset2, weight1, weight2, color1[4], color2[4];
+
+ if (fmaxf(right, left) > fmaxf(bottom, top)) { /* max(horizontal) > max(vertical) */
+ samplefunc = sample_bilinear_horizontal;
+ offset1 = right;
+ offset2 = -left;
+ weight1 = right / (right + left);
+ weight2 = left / (right + left);
+ }
+ else {
+ samplefunc = sample_bilinear_vertical;
+ offset1 = bottom;
+ offset2 = -top;
+ weight1 = bottom / (bottom + top);
+ weight2 = top / (bottom + top);
+ }
+
+ /* We exploit bilinear filtering to mix current pixel with the chosen neighbor: */
+ samplefunc(m_image1Reader, x, y, offset1, color1);
+ samplefunc(m_image1Reader, x, y, offset2, color2);
+
+ mul_v4_v4fl(output, color1, weight1);
+ madd_v4_v4fl(output, color2, weight2);
+}
+
+void SMAANeighborhoodBlendingOperation::deinitExecution()
+{
+ this->m_image1Reader = nullptr;
+ this->m_image2Reader = nullptr;
+}
+
+bool SMAANeighborhoodBlendingOperation::determineDependingAreaOfInterest(
+ rcti *input, ReadBufferOperation *readOperation, rcti *output)
+{
+ rcti newInput;
+
+ newInput.xmax = input->xmax + 1;
+ newInput.xmin = input->xmin - 1;
+ newInput.ymax = input->ymax + 1;
+ newInput.ymin = input->ymin - 1;
+
+ return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SMAAOperation.h b/source/blender/compositor/operations/COM_SMAAOperation.h
new file mode 100644
index 00000000000..781762202b4
--- /dev/null
+++ b/source/blender/compositor/operations/COM_SMAAOperation.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2017, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor: IRIE Shinsuke
+ */
+
+#pragma once
+
+#include "COM_NodeOperation.h"
+
+namespace blender::compositor {
+
+/*-----------------------------------------------------------------------------*/
+/* Edge Detection (First Pass) */
+
+class SMAAEdgeDetectionOperation : public NodeOperation {
+ protected:
+ SocketReader *m_imageReader;
+ SocketReader *m_valueReader;
+
+ float m_threshold;
+ float m_contrast_limit;
+
+ public:
+ SMAAEdgeDetectionOperation();
+
+ /**
+ * the inner loop of this program
+ */
+ virtual void executePixel(float output[4], int x, int y, void *data) override;
+
+ /**
+ * Initialize the execution
+ */
+ void initExecution() override;
+
+ /**
+ * Deinitialize the execution
+ */
+ void deinitExecution() override;
+
+ void setThreshold(float threshold);
+
+ void setLocalContrastAdaptationFactor(float factor);
+
+ bool determineDependingAreaOfInterest(rcti *input,
+ ReadBufferOperation *readOperation,
+ rcti *output) override;
+};
+
+/*-----------------------------------------------------------------------------*/
+/* Blending Weight Calculation (Second Pass) */
+
+class SMAABlendingWeightCalculationOperation : public NodeOperation {
+ private:
+ SocketReader *m_imageReader;
+
+ int m_corner_rounding;
+
+ public:
+ SMAABlendingWeightCalculationOperation();
+
+ /**
+ * the inner loop of this program
+ */
+ void executePixel(float output[4], int x, int y, void *data) override;
+
+ /**
+ * Initialize the execution
+ */
+ void initExecution() override;
+ void *initializeTileData(rcti *rect) override;
+
+ /**
+ * Deinitialize the execution
+ */
+ void deinitExecution() override;
+
+ void setCornerRounding(float rounding);
+
+ bool determineDependingAreaOfInterest(rcti *input,
+ ReadBufferOperation *readOperation,
+ rcti *output) override;
+
+ private:
+ /* Diagonal Search Functions */
+ int searchDiag1(int x, int y, int dir, bool *found);
+ int searchDiag2(int x, int y, int dir, bool *found);
+ void calculateDiagWeights(int x, int y, const float edges[2], float weights[2]);
+ bool isVerticalSearchUnneeded(int x, int y);
+
+ /* Horizontal/Vertical Search Functions */
+ int searchXLeft(int x, int y);
+ int searchXRight(int x, int y);
+ int searchYUp(int x, int y);
+ int searchYDown(int x, int y);
+
+ /* Corner Detection Functions */
+ void detectHorizontalCornerPattern(float weights[2], int left, int right, int y, int d1, int d2);
+ void detectVerticalCornerPattern(float weights[2], int x, int top, int bottom, int d1, int d2);
+};
+
+/*-----------------------------------------------------------------------------*/
+/* Neighborhood Blending (Third Pass) */
+
+class SMAANeighborhoodBlendingOperation : public NodeOperation {
+ private:
+ SocketReader *m_image1Reader;
+ SocketReader *m_image2Reader;
+
+ public:
+ SMAANeighborhoodBlendingOperation();
+
+ /**
+ * the inner loop of this program
+ */
+ void executePixel(float output[4], int x, int y, void *data) override;
+
+ /**
+ * Initialize the execution
+ */
+ void initExecution() override;
+ void *initializeTileData(rcti *rect) override;
+
+ /**
+ * Deinitialize the execution
+ */
+ void deinitExecution() override;
+
+ bool determineDependingAreaOfInterest(rcti *input,
+ ReadBufferOperation *readOperation,
+ rcti *output) override;
+};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cc b/source/blender/compositor/operations/COM_ScaleOperation.cc
index b0c9bfb2663..03525d4ea01 100644
--- a/source/blender/compositor/operations/COM_ScaleOperation.cc
+++ b/source/blender/compositor/operations/COM_ScaleOperation.cc
@@ -18,6 +18,8 @@
#include "COM_ScaleOperation.h"
+namespace blender::compositor {
+
#define USE_FORCE_BILINEAR
/* XXX - ignore input and use default from old compositor,
* could become an option like the transform node - campbell
@@ -28,7 +30,7 @@
BaseScaleOperation::BaseScaleOperation()
{
#ifdef USE_FORCE_BILINEAR
- m_sampler = (int)COM_PS_BILINEAR;
+ m_sampler = (int)PixelSampler::Bilinear;
#else
m_sampler = -1;
#endif
@@ -89,8 +91,8 @@ bool ScaleOperation::determineDependingAreaOfInterest(rcti *input,
float scaleX[4];
float scaleY[4];
- this->m_inputXOperation->readSampled(scaleX, 0, 0, COM_PS_NEAREST);
- this->m_inputYOperation->readSampled(scaleY, 0, 0, COM_PS_NEAREST);
+ this->m_inputXOperation->readSampled(scaleX, 0, 0, PixelSampler::Nearest);
+ this->m_inputYOperation->readSampled(scaleY, 0, 0, PixelSampler::Nearest);
const float scx = scaleX[0];
const float scy = scaleY[0];
@@ -174,8 +176,8 @@ bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input,
float scaleX[4];
float scaleY[4];
- this->m_inputXOperation->readSampled(scaleX, 0, 0, COM_PS_NEAREST);
- this->m_inputYOperation->readSampled(scaleY, 0, 0, COM_PS_NEAREST);
+ this->m_inputXOperation->readSampled(scaleX, 0, 0, PixelSampler::Nearest);
+ this->m_inputYOperation->readSampled(scaleY, 0, 0, PixelSampler::Nearest);
const float scx = scaleX[0];
const float scy = scaleY[0];
@@ -203,7 +205,7 @@ bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input,
// Absolute fixed size
ScaleFixedSizeOperation::ScaleFixedSizeOperation() : BaseScaleOperation()
{
- this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
+ this->addInputSocket(DataType::Color, ResizeMode::None);
this->addOutputSocket(DataType::Color);
this->setResolutionInputSocketIndex(0);
this->m_inputOperation = nullptr;
@@ -308,3 +310,5 @@ void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2],
resolution[0] = this->m_newWidth;
resolution[1] = this->m_newHeight;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ScaleOperation.h b/source/blender/compositor/operations/COM_ScaleOperation.h
index f28b8237485..dc3de3602bf 100644
--- a/source/blender/compositor/operations/COM_ScaleOperation.h
+++ b/source/blender/compositor/operations/COM_ScaleOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class BaseScaleOperation : public NodeOperation {
public:
void setSampler(PixelSampler sampler)
@@ -55,11 +57,11 @@ class ScaleOperation : public BaseScaleOperation {
ScaleOperation();
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ rcti *output) override;
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
};
class ScaleAbsoluteOperation : public BaseScaleOperation {
@@ -73,11 +75,11 @@ class ScaleAbsoluteOperation : public BaseScaleOperation {
ScaleAbsoluteOperation();
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ rcti *output) override;
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
};
class ScaleFixedSizeOperation : public BaseScaleOperation {
@@ -100,12 +102,13 @@ class ScaleFixedSizeOperation : public BaseScaleOperation {
ScaleFixedSizeOperation();
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ rcti *output) override;
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setNewWidth(int width)
{
this->m_newWidth = width;
@@ -128,3 +131,5 @@ class ScaleFixedSizeOperation : public BaseScaleOperation {
this->m_offsetY = y;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cc b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cc
index d5918dfa6f5..634fe66b0dd 100644
--- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cc
+++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cc
@@ -24,13 +24,15 @@
#include "PIL_time.h"
+namespace blender::compositor {
+
ScreenLensDistortionOperation::ScreenLensDistortionOperation()
{
this->addInputSocket(DataType::Color);
this->addInputSocket(DataType::Value);
this->addInputSocket(DataType::Value);
this->addOutputSocket(DataType::Color);
- this->setComplex(true);
+ this->flags.complex = true;
this->m_inputProgram = nullptr;
this->m_distortion = 0.0f;
this->m_dispersion = 0.0f;
@@ -83,12 +85,12 @@ void *ScreenLensDistortionOperation::initializeTileData(rcti * /*rect*/)
if (!m_distortion_const) {
float result[4];
- getInputSocketReader(1)->readSampled(result, 0, 0, COM_PS_NEAREST);
+ getInputSocketReader(1)->readSampled(result, 0, 0, PixelSampler::Nearest);
m_distortion = result[0];
}
if (!m_dispersion_const) {
float result[4];
- getInputSocketReader(2)->readSampled(result, 0, 0, COM_PS_NEAREST);
+ getInputSocketReader(2)->readSampled(result, 0, 0, PixelSampler::Nearest);
m_dispersion = result[0];
}
@@ -351,3 +353,5 @@ void ScreenLensDistortionOperation::updateVariables(float distortion, float disp
mul_v3_v3fl(m_k4, m_k, 4.0f);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h
index 35d2bccce68..98872bfe142 100644
--- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h
+++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h
@@ -21,6 +21,10 @@
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
+struct RNG;
+
+namespace blender::compositor {
+
class ScreenLensDistortionOperation : public NodeOperation {
private:
/**
@@ -49,18 +53,18 @@ class ScreenLensDistortionOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setFit(bool fit)
{
@@ -78,7 +82,7 @@ class ScreenLensDistortionOperation : public NodeOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
private:
void determineUV(float result[6], float x, float y) const;
@@ -96,3 +100,5 @@ class ScreenLensDistortionOperation : public NodeOperation {
float sum[4],
int count[3]) const;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.cc b/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.cc
index 3151bad5e4a..24edbc61d40 100644
--- a/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.cc
+++ b/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.cc
@@ -18,6 +18,8 @@
#include "COM_SetAlphaMultiplyOperation.h"
+namespace blender::compositor {
+
SetAlphaMultiplyOperation::SetAlphaMultiplyOperation()
{
this->addInputSocket(DataType::Color);
@@ -53,3 +55,5 @@ void SetAlphaMultiplyOperation::deinitExecution()
this->m_inputColor = nullptr;
this->m_inputAlpha = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.h b/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.h
index db58b18688a..b4eea659fa2 100644
--- a/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.h
+++ b/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* This operation will apply a mask to its input image.
*
@@ -33,8 +35,10 @@ class SetAlphaMultiplyOperation : public NodeOperation {
public:
SetAlphaMultiplyOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.cc b/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.cc
index cd9bf039f3e..90bfc814b09 100644
--- a/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.cc
+++ b/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.cc
@@ -18,6 +18,8 @@
#include "COM_SetAlphaReplaceOperation.h"
+namespace blender::compositor {
+
SetAlphaReplaceOperation::SetAlphaReplaceOperation()
{
this->addInputSocket(DataType::Color);
@@ -51,3 +53,5 @@ void SetAlphaReplaceOperation::deinitExecution()
this->m_inputColor = nullptr;
this->m_inputAlpha = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.h b/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.h
index b4cab82855b..c84299b6d82 100644
--- a/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.h
+++ b/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -38,8 +40,10 @@ class SetAlphaReplaceOperation : public NodeOperation {
/**
* the inner loop of this program
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetColorOperation.cc b/source/blender/compositor/operations/COM_SetColorOperation.cc
index b08381963fd..dbe45fa60db 100644
--- a/source/blender/compositor/operations/COM_SetColorOperation.cc
+++ b/source/blender/compositor/operations/COM_SetColorOperation.cc
@@ -18,9 +18,12 @@
#include "COM_SetColorOperation.h"
+namespace blender::compositor {
+
SetColorOperation::SetColorOperation()
{
this->addOutputSocket(DataType::Color);
+ flags.is_set_operation = true;
}
void SetColorOperation::executePixelSampled(float output[4],
@@ -37,3 +40,5 @@ void SetColorOperation::determineResolution(unsigned int resolution[2],
resolution[0] = preferredResolution[0];
resolution[1] = preferredResolution[1];
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetColorOperation.h b/source/blender/compositor/operations/COM_SetColorOperation.h
index c61a4e10ac0..4b9b80013d4 100644
--- a/source/blender/compositor/operations/COM_SetColorOperation.h
+++ b/source/blender/compositor/operations/COM_SetColorOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -74,11 +76,10 @@ class SetColorOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
- bool isSetOperation() const
- {
- return true;
- }
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetSamplerOperation.cc b/source/blender/compositor/operations/COM_SetSamplerOperation.cc
index 8272ad7583d..e68774736f3 100644
--- a/source/blender/compositor/operations/COM_SetSamplerOperation.cc
+++ b/source/blender/compositor/operations/COM_SetSamplerOperation.cc
@@ -18,6 +18,8 @@
#include "COM_SetSamplerOperation.h"
+namespace blender::compositor {
+
SetSamplerOperation::SetSamplerOperation()
{
this->addInputSocket(DataType::Color);
@@ -40,3 +42,5 @@ void SetSamplerOperation::executePixelSampled(float output[4],
{
this->m_reader->readSampled(output, x, y, this->m_sampler);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetSamplerOperation.h b/source/blender/compositor/operations/COM_SetSamplerOperation.h
index 5c1ed9b12d6..d355d937806 100644
--- a/source/blender/compositor/operations/COM_SetSamplerOperation.h
+++ b/source/blender/compositor/operations/COM_SetSamplerOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output Sampler.
* it assumes we are in sRGB color space.
@@ -43,7 +45,9 @@ class SetSamplerOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
- void initExecution();
- void deinitExecution();
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+ void initExecution() override;
+ void deinitExecution() override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetValueOperation.cc b/source/blender/compositor/operations/COM_SetValueOperation.cc
index 98d0ad630ad..ef43cf64653 100644
--- a/source/blender/compositor/operations/COM_SetValueOperation.cc
+++ b/source/blender/compositor/operations/COM_SetValueOperation.cc
@@ -18,9 +18,12 @@
#include "COM_SetValueOperation.h"
+namespace blender::compositor {
+
SetValueOperation::SetValueOperation()
{
this->addOutputSocket(DataType::Value);
+ flags.is_set_operation = true;
}
void SetValueOperation::executePixelSampled(float output[4],
@@ -37,3 +40,5 @@ void SetValueOperation::determineResolution(unsigned int resolution[2],
resolution[0] = preferredResolution[0];
resolution[1] = preferredResolution[1];
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetValueOperation.h b/source/blender/compositor/operations/COM_SetValueOperation.h
index 72cd70ec1f6..5383f3b5fd3 100644
--- a/source/blender/compositor/operations/COM_SetValueOperation.h
+++ b/source/blender/compositor/operations/COM_SetValueOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -46,11 +48,9 @@ class SetValueOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
-
- bool isSetOperation() const
- {
- return true;
- }
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetVectorOperation.cc b/source/blender/compositor/operations/COM_SetVectorOperation.cc
index 6b6bcad02f3..7152d5e61d4 100644
--- a/source/blender/compositor/operations/COM_SetVectorOperation.cc
+++ b/source/blender/compositor/operations/COM_SetVectorOperation.cc
@@ -19,9 +19,12 @@
#include "COM_SetVectorOperation.h"
#include "COM_defines.h"
+namespace blender::compositor {
+
SetVectorOperation::SetVectorOperation()
{
this->addOutputSocket(DataType::Vector);
+ flags.is_set_operation = true;
}
void SetVectorOperation::executePixelSampled(float output[4],
@@ -40,3 +43,5 @@ void SetVectorOperation::determineResolution(unsigned int resolution[2],
resolution[0] = preferredResolution[0];
resolution[1] = preferredResolution[1];
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetVectorOperation.h b/source/blender/compositor/operations/COM_SetVectorOperation.h
index 4bdd03809de..b444339fcb2 100644
--- a/source/blender/compositor/operations/COM_SetVectorOperation.h
+++ b/source/blender/compositor/operations/COM_SetVectorOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -73,13 +75,10 @@ class SetVectorOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
- bool isSetOperation() const
- {
- return true;
- }
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
void setVector(const float vector[3])
{
@@ -88,3 +87,5 @@ class SetVectorOperation : public NodeOperation {
setZ(vector[2]);
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SocketProxyOperation.cc b/source/blender/compositor/operations/COM_SocketProxyOperation.cc
index 53f5fea8795..39876439b7b 100644
--- a/source/blender/compositor/operations/COM_SocketProxyOperation.cc
+++ b/source/blender/compositor/operations/COM_SocketProxyOperation.cc
@@ -18,14 +18,19 @@
#include "COM_SocketProxyOperation.h"
+namespace blender::compositor {
+
SocketProxyOperation::SocketProxyOperation(DataType type, bool use_conversion)
- : m_use_conversion(use_conversion)
{
this->addInputSocket(type);
this->addOutputSocket(type);
+ flags.is_proxy_operation = true;
+ flags.use_datatype_conversion = use_conversion;
}
-std::unique_ptr<MetaData> SocketProxyOperation::getMetaData() const
+std::unique_ptr<MetaData> SocketProxyOperation::getMetaData()
{
return this->getInputSocket(0)->getReader()->getMetaData();
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SocketProxyOperation.h b/source/blender/compositor/operations/COM_SocketProxyOperation.h
index 712347a8ea2..1d3b76055bd 100644
--- a/source/blender/compositor/operations/COM_SocketProxyOperation.h
+++ b/source/blender/compositor/operations/COM_SocketProxyOperation.h
@@ -20,29 +20,13 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class SocketProxyOperation : public NodeOperation {
public:
SocketProxyOperation(DataType type, bool use_conversion);
- bool isProxyOperation() const override
- {
- return true;
- }
- bool useDatatypeConversion() const override
- {
- return m_use_conversion;
- }
-
- bool getUseConversion() const
- {
- return m_use_conversion;
- }
- void setUseConversion(bool use_conversion)
- {
- m_use_conversion = use_conversion;
- }
- std::unique_ptr<MetaData> getMetaData() const override;
-
- private:
- bool m_use_conversion;
+ std::unique_ptr<MetaData> getMetaData() override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SplitOperation.cc b/source/blender/compositor/operations/COM_SplitOperation.cc
index 25438259973..a4754de370d 100644
--- a/source/blender/compositor/operations/COM_SplitOperation.cc
+++ b/source/blender/compositor/operations/COM_SplitOperation.cc
@@ -27,6 +27,8 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+namespace blender::compositor {
+
SplitOperation::SplitOperation()
{
this->addInputSocket(DataType::Color);
@@ -58,10 +60,10 @@ void SplitOperation::executePixelSampled(float output[4],
this->m_splitPercentage * this->getHeight() / 100.0f;
bool image1 = this->m_xSplit ? x > perc : y > perc;
if (image1) {
- this->m_image1Input->readSampled(output, x, y, COM_PS_NEAREST);
+ this->m_image1Input->readSampled(output, x, y, PixelSampler::Nearest);
}
else {
- this->m_image2Input->readSampled(output, x, y, COM_PS_NEAREST);
+ this->m_image2Input->readSampled(output, x, y, PixelSampler::Nearest);
}
}
@@ -76,3 +78,5 @@ void SplitOperation::determineResolution(unsigned int resolution[2],
NodeOperation::determineResolution(resolution, preferredResolution);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SplitOperation.h b/source/blender/compositor/operations/COM_SplitOperation.h
index 62d41a615ff..09e48821dd0 100644
--- a/source/blender/compositor/operations/COM_SplitOperation.h
+++ b/source/blender/compositor/operations/COM_SplitOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class SplitOperation : public NodeOperation {
private:
SocketReader *m_image1Input;
@@ -30,10 +32,11 @@ class SplitOperation : public NodeOperation {
public:
SplitOperation();
- void initExecution();
- void deinitExecution();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void initExecution() override;
+ void deinitExecution() override;
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
void setSplitPercentage(float splitPercentage)
{
this->m_splitPercentage = splitPercentage;
@@ -43,3 +46,5 @@ class SplitOperation : public NodeOperation {
this->m_xSplit = xsplit;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.cc b/source/blender/compositor/operations/COM_SunBeamsOperation.cc
index 23bf5897297..839eeb9ff8f 100644
--- a/source/blender/compositor/operations/COM_SunBeamsOperation.cc
+++ b/source/blender/compositor/operations/COM_SunBeamsOperation.cc
@@ -19,13 +19,15 @@
#include "COM_SunBeamsOperation.h"
+namespace blender::compositor {
+
SunBeamsOperation::SunBeamsOperation()
{
this->addInputSocket(DataType::Color);
this->addOutputSocket(DataType::Color);
this->setResolutionInputSocketIndex(0);
- this->setComplex(true);
+ this->flags.complex = true;
}
void SunBeamsOperation::initExecution()
@@ -138,7 +140,7 @@ template<int fxu, int fxv, int fyu, int fyv> struct BufferLineAccumulator {
falloff_factor = dist_max > dist_min ? dr / (float)(dist_max - dist_min) : 0.0f;
- float *iter = input->getBuffer() + COM_NUM_CHANNELS_COLOR * (x + input->getWidth() * y);
+ float *iter = input->getBuffer() + COM_DATA_TYPE_COLOR_CHANNELS * (x + input->getWidth() * y);
return iter;
}
@@ -167,7 +169,7 @@ template<int fxu, int fxv, int fyu, int fyv> struct BufferLineAccumulator {
if ((int)(co[0] - source[0]) == 0 && (int)(co[1] - source[1]) == 0) {
copy_v4_v4(output,
- input->getBuffer() + COM_NUM_CHANNELS_COLOR *
+ input->getBuffer() + COM_DATA_TYPE_COLOR_CHANNELS *
((int)source[0] + input->getWidth() * (int)source[1]));
return;
}
@@ -208,7 +210,7 @@ template<int fxu, int fxv, int fyu, int fyv> struct BufferLineAccumulator {
/* decrement u */
x -= fxu;
y -= fyu;
- buffer -= (fxu + fyu * buffer_width) * COM_NUM_CHANNELS_COLOR;
+ buffer -= (fxu + fyu * buffer_width) * COM_DATA_TYPE_COLOR_CHANNELS;
/* decrement v (in steps of dv < 1) */
v_local -= dv;
@@ -217,7 +219,7 @@ template<int fxu, int fxv, int fyu, int fyv> struct BufferLineAccumulator {
x -= fxv;
y -= fyv;
- buffer -= (fxv + fyv * buffer_width) * COM_NUM_CHANNELS_COLOR;
+ buffer -= (fxv + fyv * buffer_width) * COM_DATA_TYPE_COLOR_CHANNELS;
}
}
@@ -353,3 +355,5 @@ bool SunBeamsOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&rect, readOperation, output);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.h b/source/blender/compositor/operations/COM_SunBeamsOperation.h
index 09bdb018cc3..d3725021cde 100644
--- a/source/blender/compositor/operations/COM_SunBeamsOperation.h
+++ b/source/blender/compositor/operations/COM_SunBeamsOperation.h
@@ -19,19 +19,21 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class SunBeamsOperation : public NodeOperation {
public:
SunBeamsOperation();
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
- void initExecution();
+ void initExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
void setData(const NodeSunBeams &data)
{
@@ -44,3 +46,5 @@ class SunBeamsOperation : public NodeOperation {
float m_source_px[2];
float m_ray_length_px;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_TextureOperation.cc b/source/blender/compositor/operations/COM_TextureOperation.cc
index 146f43dbe3a..e94c457f981 100644
--- a/source/blender/compositor/operations/COM_TextureOperation.cc
+++ b/source/blender/compositor/operations/COM_TextureOperation.cc
@@ -25,6 +25,8 @@
#include "BLI_listbase.h"
#include "BLI_threads.h"
+namespace blender::compositor {
+
TextureBaseOperation::TextureBaseOperation()
{
this->addInputSocket(DataType::Vector); // offset
@@ -35,7 +37,7 @@ TextureBaseOperation::TextureBaseOperation()
this->m_rd = nullptr;
this->m_pool = nullptr;
this->m_sceneColorManage = false;
- setComplex(true);
+ flags.complex = true;
}
TextureOperation::TextureOperation() : TextureBaseOperation()
{
@@ -155,3 +157,5 @@ void TextureBaseOperation::executePixelSampled(float output[4],
output[0] = output[1] = output[2] = output[3];
}
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_TextureOperation.h b/source/blender/compositor/operations/COM_TextureOperation.h
index a40dafd14cf..e1e04611c6c 100644
--- a/source/blender/compositor/operations/COM_TextureOperation.h
+++ b/source/blender/compositor/operations/COM_TextureOperation.h
@@ -26,6 +26,8 @@
#include "RE_pipeline.h"
#include "RE_texture.h"
+namespace blender::compositor {
+
/**
* Base class for all renderlayeroperations
*
@@ -44,7 +46,8 @@ class TextureBaseOperation : public NodeOperation {
/**
* Determine the output resolution. The resolution is retrieved from the Renderer
*/
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
/**
* Constructor
@@ -52,14 +55,14 @@ class TextureBaseOperation : public NodeOperation {
TextureBaseOperation();
public:
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
void setTexture(Tex *texture)
{
this->m_texture = texture;
}
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
void setRenderData(const RenderData *rd)
{
this->m_rd = rd;
@@ -77,5 +80,7 @@ class TextureOperation : public TextureBaseOperation {
class TextureAlphaOperation : public TextureBaseOperation {
public:
TextureAlphaOperation();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_TonemapOperation.cc b/source/blender/compositor/operations/COM_TonemapOperation.cc
index 85011171432..6bfacb0c75d 100644
--- a/source/blender/compositor/operations/COM_TonemapOperation.cc
+++ b/source/blender/compositor/operations/COM_TonemapOperation.cc
@@ -22,14 +22,16 @@
#include "IMB_colormanagement.h"
+namespace blender::compositor {
+
TonemapOperation::TonemapOperation()
{
- this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
+ this->addInputSocket(DataType::Color, ResizeMode::None);
this->addOutputSocket(DataType::Color);
this->m_imageReader = nullptr;
this->m_data = nullptr;
this->m_cachedInstance = nullptr;
- this->setComplex(true);
+ this->flags.complex = true;
}
void TonemapOperation::initExecution()
{
@@ -150,3 +152,5 @@ void TonemapOperation::deinitializeTileData(rcti * /*rect*/, void * /*data*/)
{
/* pass */
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_TonemapOperation.h b/source/blender/compositor/operations/COM_TonemapOperation.h
index cb8816b93b3..7ecb179504d 100644
--- a/source/blender/compositor/operations/COM_TonemapOperation.h
+++ b/source/blender/compositor/operations/COM_TonemapOperation.h
@@ -21,6 +21,8 @@
#include "COM_NodeOperation.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
/**
* \brief temporarily storage during execution of Tone-map
* \ingroup operation
@@ -60,20 +62,20 @@ class TonemapOperation : public NodeOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
- void *initializeTileData(rcti *rect);
- void deinitializeTileData(rcti *rect, void *data);
+ void *initializeTileData(rcti *rect) override;
+ void deinitializeTileData(rcti *rect, void *data) override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
void setData(NodeTonemap *data)
{
@@ -82,7 +84,7 @@ class TonemapOperation : public NodeOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
};
/**
@@ -96,5 +98,7 @@ class PhotoreceptorTonemapOperation : public TonemapOperation {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.cc b/source/blender/compositor/operations/COM_TrackPositionOperation.cc
index 97d602aa458..993410e3e84 100644
--- a/source/blender/compositor/operations/COM_TrackPositionOperation.cc
+++ b/source/blender/compositor/operations/COM_TrackPositionOperation.cc
@@ -28,6 +28,8 @@
#include "BKE_node.h"
#include "BKE_tracking.h"
+namespace blender::compositor {
+
TrackPositionOperation::TrackPositionOperation()
{
this->addOutputSocket(DataType::Value);
@@ -39,6 +41,7 @@ TrackPositionOperation::TrackPositionOperation()
this->m_position = CMP_TRACKPOS_ABSOLUTE;
this->m_relativeFrame = 0;
this->m_speed_output = false;
+ flags.is_set_operation = true;
}
void TrackPositionOperation::initExecution()
@@ -134,3 +137,5 @@ void TrackPositionOperation::determineResolution(unsigned int resolution[2],
resolution[0] = preferredResolution[0];
resolution[1] = preferredResolution[1];
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.h b/source/blender/compositor/operations/COM_TrackPositionOperation.h
index 7d831ec5d8d..b0b0a123bd6 100644
--- a/source/blender/compositor/operations/COM_TrackPositionOperation.h
+++ b/source/blender/compositor/operations/COM_TrackPositionOperation.h
@@ -28,6 +28,8 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
+namespace blender::compositor {
+
/**
* Class with implementation of green screen gradient rasterization
*/
@@ -49,7 +51,8 @@ class TrackPositionOperation : public NodeOperation {
/**
* Determine the output resolution. The resolution is retrieved from the Renderer
*/
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
public:
TrackPositionOperation();
@@ -87,12 +90,9 @@ class TrackPositionOperation : public NodeOperation {
this->m_speed_output = speed_output;
}
- void initExecution();
-
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void initExecution() override;
- bool isSetOperation() const
- {
- return true;
- }
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_TranslateOperation.cc b/source/blender/compositor/operations/COM_TranslateOperation.cc
index 7efd655b1df..49135f25320 100644
--- a/source/blender/compositor/operations/COM_TranslateOperation.cc
+++ b/source/blender/compositor/operations/COM_TranslateOperation.cc
@@ -18,6 +18,8 @@
#include "COM_TranslateOperation.h"
+namespace blender::compositor {
+
TranslateOperation::TranslateOperation()
{
this->addInputSocket(DataType::Color);
@@ -56,7 +58,7 @@ void TranslateOperation::executePixelSampled(float output[4],
float originalXPos = x - this->getDeltaX();
float originalYPos = y - this->getDeltaY();
- this->m_inputOperation->readSampled(output, originalXPos, originalYPos, COM_PS_BILINEAR);
+ this->m_inputOperation->readSampled(output, originalXPos, originalYPos, PixelSampler::Bilinear);
}
bool TranslateOperation::determineDependingAreaOfInterest(rcti *input,
@@ -80,3 +82,5 @@ void TranslateOperation::setFactorXY(float factorX, float factorY)
m_factorX = factorX;
m_factorY = factorY;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_TranslateOperation.h b/source/blender/compositor/operations/COM_TranslateOperation.h
index 99cfb528858..eb3a664159f 100644
--- a/source/blender/compositor/operations/COM_TranslateOperation.h
+++ b/source/blender/compositor/operations/COM_TranslateOperation.h
@@ -20,6 +20,8 @@
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class TranslateOperation : public NodeOperation {
private:
SocketReader *m_inputOperation;
@@ -35,11 +37,11 @@ class TranslateOperation : public NodeOperation {
TranslateOperation();
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ rcti *output) override;
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
float getDeltaX()
{
@@ -54,9 +56,9 @@ class TranslateOperation : public NodeOperation {
{
if (!this->m_isDeltaSet) {
float tempDelta[4];
- this->m_inputXOperation->readSampled(tempDelta, 0, 0, COM_PS_NEAREST);
+ this->m_inputXOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest);
this->m_deltaX = tempDelta[0];
- this->m_inputYOperation->readSampled(tempDelta, 0, 0, COM_PS_NEAREST);
+ this->m_inputYOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest);
this->m_deltaY = tempDelta[0];
this->m_isDeltaSet = true;
}
@@ -64,3 +66,5 @@ class TranslateOperation : public NodeOperation {
void setFactorXY(float factorX, float factorY);
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cc b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cc
index ea33f3cd787..19cd5a53084 100644
--- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cc
@@ -22,18 +22,20 @@
#include "RE_pipeline.h"
+namespace blender::compositor {
+
VariableSizeBokehBlurOperation::VariableSizeBokehBlurOperation()
{
this->addInputSocket(DataType::Color);
- this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE); // do not resize the bokeh image.
+ this->addInputSocket(DataType::Color, ResizeMode::None); // do not resize the bokeh image.
this->addInputSocket(DataType::Value); // radius
#ifdef COM_DEFOCUS_SEARCH
this->addInputSocket(DataType::Color,
- COM_SC_NO_RESIZE); // inverse search radius optimization structure.
+ ResizeMode::None); // inverse search radius optimization structure.
#endif
this->addOutputSocket(DataType::Color);
- this->setComplex(true);
- this->setOpenCL(true);
+ flags.complex = true;
+ flags.open_cl = true;
this->m_inputProgram = nullptr;
this->m_inputBokehProgram = nullptr;
@@ -135,14 +137,14 @@ void VariableSizeBokehBlurOperation::executePixel(float output[4], int x, int y,
const int addXStepValue = QualityStepHelper::getStep();
const int addYStepValue = addXStepValue;
- const int addXStepColor = addXStepValue * COM_NUM_CHANNELS_COLOR;
+ const int addXStepColor = addXStepValue * COM_DATA_TYPE_COLOR_CHANNELS;
if (size_center > this->m_threshold) {
for (int ny = miny; ny < maxy; ny += addYStepValue) {
float dy = ny - y;
int offsetValueNy = ny * inputSizeBuffer->getWidth();
int offsetValueNxNy = offsetValueNy + (minx);
- int offsetColorNxNy = offsetValueNxNy * COM_NUM_CHANNELS_COLOR;
+ int offsetColorNxNy = offsetValueNxNy * COM_DATA_TYPE_COLOR_CHANNELS;
for (int nx = minx; nx < maxx; nx += addXStepValue) {
if (nx != x || ny != y) {
float size = MIN2(inputSizeFloatBuffer[offsetValueNxNy] * scalar, size_center);
@@ -278,9 +280,9 @@ bool VariableSizeBokehBlurOperation::determineDependingAreaOfInterest(
// InverseSearchRadiusOperation
InverseSearchRadiusOperation::InverseSearchRadiusOperation()
{
- this->addInputSocket(DataType::Value, COM_SC_NO_RESIZE); // radius
+ this->addInputSocket(DataType::Value, ResizeMode::None); // radius
this->addOutputSocket(DataType::Color);
- this->setComplex(true);
+ this->flags.complex = true;
this->m_inputRadius = nullptr;
}
@@ -319,7 +321,7 @@ void *InverseSearchRadiusOperation::initializeTileData(rcti *rect)
// for (int x2 = 0 ; x2 < DIVIDER ; x2 ++) {
// for (int y2 = 0 ; y2 < DIVIDER ; y2 ++) {
- // this->m_inputRadius->read(temp, rx+x2, ry+y2, COM_PS_NEAREST);
+ // this->m_inputRadius->read(temp, rx+x2, ry+y2, PixelSampler::Nearest);
// if (radius < temp[0]) {
// radius = temp[0];
// maxx = x2;
@@ -381,3 +383,5 @@ bool InverseSearchRadiusOperation::determineDependingAreaOfInterest(
return NodeOperation::determineDependingAreaOfInterest(&newRect, readOperation, output);
}
#endif
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h
index fe927f791fa..baeab6a646e 100644
--- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h
+++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h
@@ -21,6 +21,8 @@
#include "COM_NodeOperation.h"
#include "COM_QualityStepHelper.h"
+namespace blender::compositor {
+
//#define COM_DEFOCUS_SEARCH
class VariableSizeBokehBlurOperation : public NodeOperation, public QualityStepHelper {
@@ -41,25 +43,25 @@ class VariableSizeBokehBlurOperation : public NodeOperation, public QualityStepH
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
- void deinitializeTileData(rcti *rect, void *data);
+ void deinitializeTileData(rcti *rect, void *data) override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
void setMaxBlur(int maxRadius)
{
@@ -81,7 +83,7 @@ class VariableSizeBokehBlurOperation : public NodeOperation, public QualityStepH
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
std::list<cl_mem> *clMemToCleanUp,
- std::list<cl_kernel> *clKernelsToCleanUp);
+ std::list<cl_kernel> *clKernelsToCleanUp) override;
};
#ifdef COM_DEFOCUS_SEARCH
@@ -103,19 +105,20 @@ class InverseSearchRadiusOperation : public NodeOperation {
/**
* Initialize the execution
*/
- void initExecution();
- void *initializeTileData(rcti *rect);
- void deinitializeTileData(rcti *rect, void *data);
+ void initExecution() override;
+ void *initializeTileData(rcti *rect) override;
+ void deinitializeTileData(rcti *rect, void *data) override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ rcti *output) override;
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
void setMaxBlur(int maxRadius)
{
@@ -123,3 +126,5 @@ class InverseSearchRadiusOperation : public NodeOperation {
}
};
#endif
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.cc b/source/blender/compositor/operations/COM_VectorBlurOperation.cc
index ff9eef8a7e1..fd64bda156b 100644
--- a/source/blender/compositor/operations/COM_VectorBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_VectorBlurOperation.cc
@@ -25,6 +25,8 @@
#include "COM_VectorBlurOperation.h"
+namespace blender::compositor {
+
/* Defined */
#define PASS_VECTOR_MAX 10000.0f
@@ -54,7 +56,7 @@ VectorBlurOperation::VectorBlurOperation()
this->m_inputImageProgram = nullptr;
this->m_inputSpeedProgram = nullptr;
this->m_inputZProgram = nullptr;
- setComplex(true);
+ flags.complex = true;
}
void VectorBlurOperation::initExecution()
{
@@ -69,7 +71,7 @@ void VectorBlurOperation::initExecution()
void VectorBlurOperation::executePixel(float output[4], int x, int y, void *data)
{
float *buffer = (float *)data;
- int index = (y * this->getWidth() + x) * COM_NUM_CHANNELS_COLOR;
+ int index = (y * this->getWidth() + x) * COM_DATA_TYPE_COLOR_CHANNELS;
copy_v4_v4(output, &buffer[index]);
}
@@ -897,3 +899,5 @@ void zbuf_accumulate_vecblur(NodeBlurData *nbd,
}
zbuf_free_span(&zspan);
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.h b/source/blender/compositor/operations/COM_VectorBlurOperation.h
index 222e8b26968..dfcf1fb16f7 100644
--- a/source/blender/compositor/operations/COM_VectorBlurOperation.h
+++ b/source/blender/compositor/operations/COM_VectorBlurOperation.h
@@ -22,6 +22,8 @@
#include "COM_QualityStepHelper.h"
#include "DNA_node_types.h"
+namespace blender::compositor {
+
class VectorBlurOperation : public NodeOperation, public QualityStepHelper {
private:
/**
@@ -44,19 +46,19 @@ class VectorBlurOperation : public NodeOperation, public QualityStepHelper {
/**
* The inner loop of this operation.
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixel(float output[4], int x, int y, void *data) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
- void *initializeTileData(rcti *rect);
+ void *initializeTileData(rcti *rect) override;
void setVectorBlurSettings(NodeBlurData *settings)
{
@@ -64,7 +66,7 @@ class VectorBlurOperation : public NodeOperation, public QualityStepHelper {
}
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
+ rcti *output) override;
protected:
void generateVectorBlur(float *data,
@@ -72,3 +74,5 @@ class VectorBlurOperation : public NodeOperation, public QualityStepHelper {
MemoryBuffer *inputSpeed,
MemoryBuffer *inputZ);
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_VectorCurveOperation.cc b/source/blender/compositor/operations/COM_VectorCurveOperation.cc
index a6638a78e88..9d53ed5d8ee 100644
--- a/source/blender/compositor/operations/COM_VectorCurveOperation.cc
+++ b/source/blender/compositor/operations/COM_VectorCurveOperation.cc
@@ -20,6 +20,8 @@
#include "BKE_colortools.h"
+namespace blender::compositor {
+
VectorCurveOperation::VectorCurveOperation()
{
this->addInputSocket(DataType::Vector);
@@ -50,3 +52,5 @@ void VectorCurveOperation::deinitExecution()
CurveBaseOperation::deinitExecution();
this->m_inputProgram = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_VectorCurveOperation.h b/source/blender/compositor/operations/COM_VectorCurveOperation.h
index cf0d22eca1a..8cbb80e27c7 100644
--- a/source/blender/compositor/operations/COM_VectorCurveOperation.h
+++ b/source/blender/compositor/operations/COM_VectorCurveOperation.h
@@ -21,6 +21,8 @@
#include "COM_CurveBaseOperation.h"
#include "COM_NodeOperation.h"
+namespace blender::compositor {
+
class VectorCurveOperation : public CurveBaseOperation {
private:
/**
@@ -34,15 +36,17 @@ class VectorCurveOperation : public CurveBaseOperation {
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
/**
* Initialize the execution
*/
- void initExecution();
+ void initExecution() override;
/**
* Deinitialize the execution
*/
- void deinitExecution();
+ void deinitExecution() override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cc b/source/blender/compositor/operations/COM_ViewerOperation.cc
index ea5937d8afb..1ae0fe6101f 100644
--- a/source/blender/compositor/operations/COM_ViewerOperation.cc
+++ b/source/blender/compositor/operations/COM_ViewerOperation.cc
@@ -32,6 +32,8 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+namespace blender::compositor {
+
ViewerOperation::ViewerOperation()
{
this->setImage(nullptr);
@@ -53,6 +55,8 @@ ViewerOperation::ViewerOperation()
this->m_depthInput = nullptr;
this->m_rd = nullptr;
this->m_viewName = nullptr;
+ flags.use_viewer_border = true;
+ flags.is_viewer_operation = true;
}
void ViewerOperation::initExecution()
@@ -98,12 +102,12 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
for (y = y1; y < y2 && (!breaked); y++) {
for (x = x1; x < x2; x++) {
- this->m_imageInput->readSampled(&(buffer[offset4]), x, y, COM_PS_NEAREST);
+ this->m_imageInput->readSampled(&(buffer[offset4]), x, y, PixelSampler::Nearest);
if (this->m_useAlphaInput) {
- this->m_alphaInput->readSampled(alpha, x, y, COM_PS_NEAREST);
+ this->m_alphaInput->readSampled(alpha, x, y, PixelSampler::Nearest);
buffer[offset4 + 3] = alpha[0];
}
- this->m_depthInput->readSampled(depth, x, y, COM_PS_NEAREST);
+ this->m_depthInput->readSampled(depth, x, y, PixelSampler::Nearest);
depthbuffer[offset] = depth[0];
offset++;
@@ -213,3 +217,5 @@ CompositorPriority ViewerOperation::getRenderPriority() const
return CompositorPriority::Low;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ViewerOperation.h b/source/blender/compositor/operations/COM_ViewerOperation.h
index 513c6eae487..8406ea41f20 100644
--- a/source/blender/compositor/operations/COM_ViewerOperation.h
+++ b/source/blender/compositor/operations/COM_ViewerOperation.h
@@ -23,6 +23,8 @@
#include "COM_NodeOperation.h"
#include "DNA_image_types.h"
+namespace blender::compositor {
+
class ViewerOperation : public NodeOperation {
private:
float *m_outputBuffer;
@@ -48,11 +50,12 @@ class ViewerOperation : public NodeOperation {
public:
ViewerOperation();
- void initExecution();
- void deinitExecution();
- void executeRegion(rcti *rect, unsigned int tileNumber);
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
- bool isOutputOperation(bool /*rendering*/) const
+ void initExecution() override;
+ void deinitExecution() override;
+ void executeRegion(rcti *rect, unsigned int tileNumber) override;
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
+ bool isOutputOperation(bool /*rendering*/) const override
{
if (G.background) {
return false;
@@ -67,7 +70,7 @@ class ViewerOperation : public NodeOperation {
{
this->m_imageUser = imageUser;
}
- bool isActiveViewerOutput() const
+ bool isActiveViewerOutput() const override
{
return this->m_active;
}
@@ -99,11 +102,7 @@ class ViewerOperation : public NodeOperation {
{
return this->m_chunkOrder;
}
- CompositorPriority getRenderPriority() const;
- bool isViewerOperation() const
- {
- return true;
- }
+ CompositorPriority getRenderPriority() const override;
void setUseAlphaInput(bool value)
{
this->m_useAlphaInput = value;
@@ -130,3 +129,5 @@ class ViewerOperation : public NodeOperation {
void updateImage(rcti *rect);
void initImage();
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_WrapOperation.cc b/source/blender/compositor/operations/COM_WrapOperation.cc
index a869666967e..d0d2fcac3ac 100644
--- a/source/blender/compositor/operations/COM_WrapOperation.cc
+++ b/source/blender/compositor/operations/COM_WrapOperation.cc
@@ -20,6 +20,8 @@
#include "COM_WrapOperation.h"
+namespace blender::compositor {
+
WrapOperation::WrapOperation(DataType datatype) : ReadBufferOperation(datatype)
{
this->m_wrappingType = CMP_NODE_WRAP_NONE;
@@ -115,3 +117,5 @@ void WrapOperation::setWrapping(int wrapping_type)
{
m_wrappingType = wrapping_type;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_WrapOperation.h b/source/blender/compositor/operations/COM_WrapOperation.h
index a72b90e7e94..6279129a550 100644
--- a/source/blender/compositor/operations/COM_WrapOperation.h
+++ b/source/blender/compositor/operations/COM_WrapOperation.h
@@ -20,6 +20,8 @@
#include "COM_ReadBufferOperation.h"
+namespace blender::compositor {
+
class WrapOperation : public ReadBufferOperation {
private:
int m_wrappingType;
@@ -28,8 +30,8 @@ class WrapOperation : public ReadBufferOperation {
WrapOperation(DataType datatype);
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
- rcti *output);
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ rcti *output) override;
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
void setWrapping(int wrapping_type);
float getWrappedOriginalXPos(float x);
@@ -37,3 +39,5 @@ class WrapOperation : public ReadBufferOperation {
void setFactorXY(float factorX, float factorY);
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cc b/source/blender/compositor/operations/COM_WriteBufferOperation.cc
index e426bc76ef3..1aa19f26e2b 100644
--- a/source/blender/compositor/operations/COM_WriteBufferOperation.cc
+++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cc
@@ -21,12 +21,15 @@
#include "COM_defines.h"
#include <cstdio>
+namespace blender::compositor {
+
WriteBufferOperation::WriteBufferOperation(DataType datatype)
{
this->addInputSocket(datatype);
this->m_memoryProxy = new MemoryProxy(datatype);
this->m_memoryProxy->setWriteBufferOperation(this);
this->m_memoryProxy->setExecutor(nullptr);
+ flags.is_write_buffer_operation = true;
}
WriteBufferOperation::~WriteBufferOperation()
{
@@ -61,7 +64,7 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/
MemoryBuffer *memoryBuffer = this->m_memoryProxy->getBuffer();
float *buffer = memoryBuffer->getBuffer();
const uint8_t num_channels = memoryBuffer->get_num_channels();
- if (this->m_input->isComplex()) {
+ if (this->m_input->get_flags().complex) {
void *data = this->m_input->initializeTileData(rect);
int x1 = rect->xmin;
int y1 = rect->ymin;
@@ -97,7 +100,7 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/
for (y = y1; y < y2 && (!breaked); y++) {
int offset4 = (y * memoryBuffer->getWidth() + x1) * num_channels;
for (x = x1; x < x2; x++) {
- this->m_input->readSampled(&(buffer[offset4]), x, y, COM_PS_NEAREST);
+ this->m_input->readSampled(&(buffer[offset4]), x, y, PixelSampler::Nearest);
offset4 += num_channels;
}
if (isBraked()) {
@@ -225,3 +228,5 @@ void WriteBufferOperation::readResolutionFromInputSocket()
this->setWidth(inputOperation->getWidth());
this->setHeight(inputOperation->getHeight());
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.h b/source/blender/compositor/operations/COM_WriteBufferOperation.h
index a9f90830a92..2817fbe24b9 100644
--- a/source/blender/compositor/operations/COM_WriteBufferOperation.h
+++ b/source/blender/compositor/operations/COM_WriteBufferOperation.h
@@ -20,7 +20,12 @@
#include "COM_MemoryProxy.h"
#include "COM_NodeOperation.h"
-#include "COM_SocketReader.h"
+
+namespace blender::compositor {
+
+class OpenCLDevice;
+class MemoryProxy;
+
/**
* \brief NodeOperation to write to a tile
* \ingroup Operation
@@ -37,28 +42,27 @@ class WriteBufferOperation : public NodeOperation {
{
return this->m_memoryProxy;
}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
- bool isWriteBufferOperation() const
- {
- return true;
- }
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
bool isSingleValue() const
{
return m_single_value;
}
- void executeRegion(rcti *rect, unsigned int tileNumber);
- void initExecution();
- void deinitExecution();
+ void executeRegion(rcti *rect, unsigned int tileNumber) override;
+ void initExecution() override;
+ void deinitExecution() override;
void executeOpenCLRegion(OpenCLDevice *device,
rcti *rect,
unsigned int chunkNumber,
MemoryBuffer **memoryBuffers,
- MemoryBuffer *outputBuffer);
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ MemoryBuffer *outputBuffer) override;
+ void determineResolution(unsigned int resolution[2],
+ unsigned int preferredResolution[2]) override;
void readResolutionFromInputSocket();
inline NodeOperation *getInput()
{
return m_input;
}
};
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ZCombineOperation.cc b/source/blender/compositor/operations/COM_ZCombineOperation.cc
index 8afdbcc7c2d..9d3ca7e736e 100644
--- a/source/blender/compositor/operations/COM_ZCombineOperation.cc
+++ b/source/blender/compositor/operations/COM_ZCombineOperation.cc
@@ -19,6 +19,8 @@
#include "COM_ZCombineOperation.h"
#include "BLI_utildefines.h"
+namespace blender::compositor {
+
ZCombineOperation::ZCombineOperation()
{
this->addInputSocket(DataType::Color);
@@ -158,3 +160,5 @@ void ZCombineMaskOperation::deinitExecution()
this->m_maskReader = nullptr;
this->m_image2Reader = nullptr;
}
+
+} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ZCombineOperation.h b/source/blender/compositor/operations/COM_ZCombineOperation.h
index a64e3c5b70f..d0b1aee7310 100644
--- a/source/blender/compositor/operations/COM_ZCombineOperation.h
+++ b/source/blender/compositor/operations/COM_ZCombineOperation.h
@@ -20,6 +20,8 @@
#include "COM_MixOperation.h"
+namespace blender::compositor {
+
/**
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
@@ -37,17 +39,17 @@ class ZCombineOperation : public NodeOperation {
*/
ZCombineOperation();
- void initExecution();
- void deinitExecution();
+ void initExecution() override;
+ void deinitExecution() override;
/**
* The inner loop of this operation.
*/
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ZCombineAlphaOperation : public ZCombineOperation {
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ZCombineMaskOperation : public NodeOperation {
@@ -59,10 +61,12 @@ class ZCombineMaskOperation : public NodeOperation {
public:
ZCombineMaskOperation();
- void initExecution();
- void deinitExecution();
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void initExecution() override;
+ void deinitExecution() override;
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
class ZCombineMaskAlphaOperation : public ZCombineMaskOperation {
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
};
+
+} // namespace blender::compositor
diff --git a/source/blender/depsgraph/intern/builder/pipeline.cc b/source/blender/depsgraph/intern/builder/pipeline.cc
index f7feeea9593..b96236ba2e3 100644
--- a/source/blender/depsgraph/intern/builder/pipeline.cc
+++ b/source/blender/depsgraph/intern/builder/pipeline.cc
@@ -98,7 +98,7 @@ void AbstractBuilderPipeline::build_step_finalize()
if (G.debug_value == 799) {
deg_graph_transitive_reduction(deg_graph_);
}
- /* Store pointers to commonly used valuated datablocks. */
+ /* Store pointers to commonly used evaluated datablocks. */
deg_graph_->scene_cow = (Scene *)deg_graph_->get_cow_id(&deg_graph_->scene->id);
/* Flush visibility layer and re-schedule nodes for update. */
deg_graph_build_finalize(bmain_, deg_graph_);
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index 2d5b93f4272..8a35ab2aeb9 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -118,8 +118,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
void DRW_draw_depth_loop(struct Depsgraph *depsgraph,
struct ARegion *region,
struct View3D *v3d,
- struct GPUViewport *viewport,
- bool use_opengl_context);
+ struct GPUViewport *viewport);
void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph,
struct ARegion *region,
struct View3D *v3d,
diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c
index 7042d095b56..54224071d23 100644
--- a/source/blender/draw/engines/overlay/overlay_armature.c
+++ b/source/blender/draw/engines/overlay/overlay_armature.c
@@ -1293,11 +1293,15 @@ static void draw_axes(ArmatureDrawContext *ctx,
float length = pchan->bone->length;
copy_m4_m4(axis_mat, pchan->custom_tx ? pchan->custom_tx->pose_mat : pchan->pose_mat);
rescale_m4(axis_mat, (float[3]){length, length, length});
+ translate_m4(axis_mat, 0.0, arm->axes_position - 1.0, 0.0);
drw_shgroup_bone_axes(ctx, axis_mat, final_col);
}
else {
- drw_shgroup_bone_axes(ctx, BONE_VAR(eBone, pchan, disp_mat), final_col);
+ float disp_mat[4][4];
+ copy_m4_m4(disp_mat, BONE_VAR(eBone, pchan, disp_mat));
+ translate_m4(disp_mat, 0.0, arm->axes_position - 1.0, 0.0);
+ drw_shgroup_bone_axes(ctx, disp_mat, final_col);
}
}
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index a088c27d3f3..c09b4719f3a 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -2601,8 +2601,7 @@ static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph,
void DRW_draw_depth_loop(struct Depsgraph *depsgraph,
ARegion *region,
View3D *v3d,
- GPUViewport *viewport,
- bool use_opengl_context)
+ GPUViewport *viewport)
{
/* Reset before using it. */
drw_state_prepare_clean_for_draw(&DST);
@@ -2618,7 +2617,7 @@ void DRW_draw_depth_loop(struct Depsgraph *depsgraph,
}
}
- drw_draw_depth_loop_impl(depsgraph, region, v3d, viewport, use_opengl_context);
+ drw_draw_depth_loop_impl(depsgraph, region, v3d, viewport, false);
}
/**
@@ -2634,7 +2633,7 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph,
use_drw_engine(&draw_engine_gpencil_type);
- drw_draw_depth_loop_impl(depsgraph, region, v3d, viewport, true);
+ drw_draw_depth_loop_impl(depsgraph, region, v3d, viewport, false);
}
void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, const rcti *rect)
@@ -2725,7 +2724,6 @@ void DRW_draw_depth_object(
{
RegionView3D *rv3d = region->regiondata;
- DRW_opengl_context_enable();
GPU_matrix_projection_set(rv3d->winmat);
GPU_matrix_set(rv3d->viewmat);
GPU_matrix_mul(object->obmat);
@@ -2784,7 +2782,6 @@ void DRW_draw_depth_object(
GPU_matrix_set(rv3d->viewmat);
GPU_depth_test(GPU_DEPTH_NONE);
GPU_framebuffer_restore();
- DRW_opengl_context_disable();
}
/** \} */
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 4cc0413be5b..9cbb799082c 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -3034,19 +3034,9 @@ bool ED_autokeyframe_pchan(
ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
BLI_freelistN(&dsources);
- /* clear any unkeyed tags */
- if (pchan->bone) {
- pchan->bone->flag &= ~BONE_UNKEYED;
- }
-
return true;
}
- /* add unkeyed tags */
- if (pchan->bone) {
- pchan->bone->flag |= BONE_UNKEYED;
- }
-
return false;
}
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index 8bcaf72f678..70154695dcd 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -525,8 +525,8 @@ void ARMATURE_OT_flip_names(wmOperatorType *ot)
"do_strip_numbers",
false,
"Strip Numbers",
- "Try to remove right-most dot-number from flipped names "
- "(WARNING: may result in incoherent naming in some cases)");
+ "Try to remove right-most dot-number from flipped names.\n"
+ "Warning: May result in incoherent naming in some cases");
}
/** \} */
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index e65871c0896..f5daa427149 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -593,8 +593,8 @@ void POSE_OT_flip_names(wmOperatorType *ot)
"do_strip_numbers",
false,
"Strip Numbers",
- "Try to remove right-most dot-number from flipped names "
- "(WARNING: may result in incoherent naming in some cases)");
+ "Try to remove right-most dot-number from flipped names.\n"
+ "Warning: May result in incoherent naming in some cases");
}
/* ------------------ */
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index dd90f9f2cc3..21fcbf8886b 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -1108,17 +1108,6 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData
if (autokey) {
/* Add data-source override for the PoseChannel, to be used later. */
ANIM_relative_keyingset_add_source(&dsources, &pld->ob->id, &RNA_PoseBone, pchan);
-
- /* clear any unkeyed tags */
- if (pchan->bone) {
- pchan->bone->flag &= ~BONE_UNKEYED;
- }
- }
- else {
- /* add unkeyed tags */
- if (pchan->bone) {
- pchan->bone->flag |= BONE_UNKEYED;
- }
}
}
}
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index 8d1c196e9c2..43ab20eb71c 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -172,9 +172,6 @@ static void applyarmature_transfer_properties(EditBone *curbone,
unit_qt(pchan->quat);
unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
-
- /* Set anim lock. */
- curbone->flag |= BONE_UNKEYED;
}
/* Adjust the current edit position of the bone using the pose space matrix. */
@@ -1200,10 +1197,6 @@ static int pose_clear_transform_generic_exec(bContext *C,
/* do auto-keyframing as appropriate */
if (autokeyframe_cfra_can_key(scene, &ob_iter->id)) {
- /* clear any unkeyed tags */
- if (pchan->bone) {
- pchan->bone->flag &= ~BONE_UNKEYED;
- }
/* tag for autokeying later */
ANIM_relative_keyingset_add_source(&dsources, &ob_iter->id, &RNA_PoseBone, pchan);
@@ -1212,12 +1205,6 @@ static int pose_clear_transform_generic_exec(bContext *C,
clear_func(ob_iter->pose, pchan_eval);
#endif
}
- else {
- /* add unkeyed tags */
- if (pchan->bone) {
- pchan->bone->flag |= BONE_UNKEYED;
- }
- }
}
FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c
index c75e9c9ef69..75348c2b196 100644
--- a/source/blender/editors/armature/pose_utils.c
+++ b/source/blender/editors/armature/pose_utils.c
@@ -313,11 +313,6 @@ void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, ListBase *pfLinks,
/* Add data-source override for the PoseChannel, to be used later. */
ANIM_relative_keyingset_add_source(&dsources, &pfl->ob->id, &RNA_PoseBone, pchan);
-
- /* clear any unkeyed tags */
- if (pchan->bone) {
- pchan->bone->flag &= ~BONE_UNKEYED;
- }
}
/* insert keyframes for all relevant bones in one go */
diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c
index 48a36ff276d..0d071f2e595 100644
--- a/source/blender/editors/curve/editcurve_paint.c
+++ b/source/blender/editors/curve/editcurve_paint.c
@@ -1083,13 +1083,8 @@ static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* needed or else the draw matrix can be incorrect */
view3d_operator_needs_opengl(C);
- ED_view3d_autodist_init(cdd->vc.depsgraph, cdd->vc.region, cdd->vc.v3d, 0);
-
- if (cdd->vc.rv3d->depths) {
- cdd->vc.rv3d->depths->damaged = true;
- }
-
- ED_view3d_depth_update(cdd->vc.region);
+ ED_view3d_depth_override(
+ cdd->vc.depsgraph, cdd->vc.region, cdd->vc.v3d, NULL, V3D_DEPTH_NO_GPENCIL, true);
if (cdd->vc.rv3d->depths != NULL) {
cdd->project.use_depth = true;
diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c
index d362ec23370..e3fc8b73172 100644
--- a/source/blender/editors/curve/editcurve_select.c
+++ b/source/blender/editors/curve/editcurve_select.c
@@ -578,8 +578,8 @@ static int de_select_all_exec(bContext *C, wmOperator *op)
changed = ED_curve_deselect_all(cu->editnurb);
break;
case SEL_INVERT:
- changed = ED_curve_select_swap(cu->editnurb,
- v3d->overlay.handle_display == CURVE_HANDLE_NONE);
+ changed = ED_curve_select_swap(
+ cu->editnurb, (v3d && (v3d->overlay.handle_display == CURVE_HANDLE_NONE)));
break;
}
diff --git a/source/blender/editors/geometry/geometry_attributes.c b/source/blender/editors/geometry/geometry_attributes.c
index 2807e7c4392..12f6bb90677 100644
--- a/source/blender/editors/geometry/geometry_attributes.c
+++ b/source/blender/editors/geometry/geometry_attributes.c
@@ -53,7 +53,11 @@ static const EnumPropertyItem *geometry_attribute_domain_itemf(bContext *C,
bool *r_free)
{
Object *ob = ED_object_context(C);
- return rna_enum_attribute_domain_itemf(ob->data, r_free);
+ if (ob != NULL) {
+ return rna_enum_attribute_domain_itemf(ob->data, r_free);
+ }
+
+ return DummyRNA_NULL_items;
}
static int geometry_attribute_add_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
index b8ee1722cb3..c21535de4d5 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
@@ -27,11 +27,14 @@
* \brief Snap gizmo which exposes the location, normal and index in the props.
*/
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "DNA_scene_types.h"
#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
#include "GPU_immediate.h"
#include "GPU_state.h"
@@ -57,11 +60,6 @@
typedef struct SnapGizmo3D {
wmGizmo gizmo;
- PropertyRNA *prop_prevpoint;
- PropertyRNA *prop_location;
- PropertyRNA *prop_normal;
- PropertyRNA *prop_elem_index;
- PropertyRNA *prop_snap_force;
/* We could have other snap contexts, for now only support 3D view. */
SnapObjectContext *snap_context_v3d;
@@ -78,8 +76,18 @@ typedef struct SnapGizmo3D {
int snap_on;
bool invert_snap;
#endif
+
+ /* Setup. */
+ float *prevpoint;
+ float prevpoint_stack[3];
int use_snap_override;
+ short snap_elem_force;
+
+ /* Return values. */
short snap_elem;
+ float loc[3];
+ float nor[3];
+ int elem_index[3];
/** Enabled when snap is activated, even if it didn't find anything. */
bool is_enabled;
@@ -158,6 +166,19 @@ static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm)
}
#endif
+static short snap_gizmo_snap_elements(SnapGizmo3D *snap_gizmo)
+{
+ int snap_elements = snap_gizmo->snap_elem_force;
+
+ wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(&snap_gizmo->gizmo, "snap_elements");
+ if (gz_prop->prop) {
+ snap_elements |= RNA_property_enum_get(&gz_prop->ptr, gz_prop->prop);
+ }
+ snap_elements &= (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
+ SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR);
+ return (ushort)snap_elements;
+}
+
/* -------------------------------------------------------------------- */
/** \name ED_gizmo_library specific API
* \{ */
@@ -298,9 +319,7 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz,
const ARegion *region,
const View3D *v3d,
const wmWindowManager *wm,
- const float mval_fl[2],
- float r_loc[3],
- float r_nor[3])
+ const float mval_fl[2])
{
SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
snap_gizmo->is_enabled = false;
@@ -336,19 +355,12 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz,
int snap_elem_index[3] = {-1, -1, -1};
int index = -1;
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "snap_elements");
- int snap_elements = RNA_property_enum_get(&gz_prop->ptr, gz_prop->prop);
- if (gz_prop->prop != snap_gizmo->prop_snap_force) {
- int snap_elements_force = RNA_property_enum_get(gz->ptr, snap_gizmo->prop_snap_force);
- snap_elements |= snap_elements_force;
- }
- snap_elements &= (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
- SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR);
+ ushort snap_elements = snap_gizmo_snap_elements(snap_gizmo);
if (snap_elements) {
float prev_co[3] = {0.0f};
- if (RNA_property_is_set(gz->ptr, snap_gizmo->prop_prevpoint)) {
- RNA_property_float_get_array(gz->ptr, snap_gizmo->prop_prevpoint, prev_co);
+ if (snap_gizmo->prevpoint) {
+ copy_v3_v3(prev_co, snap_gizmo->prevpoint);
}
else {
snap_elements &= ~SCE_SNAP_MODE_EDGE_PERPENDICULAR;
@@ -392,19 +404,147 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz,
}
snap_gizmo->snap_elem = snap_elem;
- RNA_property_float_set_array(gz->ptr, snap_gizmo->prop_location, co);
- RNA_property_float_set_array(gz->ptr, snap_gizmo->prop_normal, no);
- RNA_property_int_set_array(gz->ptr, snap_gizmo->prop_elem_index, snap_elem_index);
+ copy_v3_v3(snap_gizmo->loc, co);
+ copy_v3_v3(snap_gizmo->nor, no);
+ copy_v3_v3_int(snap_gizmo->elem_index, snap_elem_index);
+
+ return snap_elem;
+}
+void ED_gizmotypes_snap_3d_data_get(
+ wmGizmo *gz, float r_loc[3], float r_nor[3], int r_elem_index[3], int *r_snap_elem)
+{
+ SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
if (r_loc) {
- copy_v3_v3(r_loc, co);
+ copy_v3_v3(r_loc, snap_gizmo->loc);
}
-
if (r_nor) {
- copy_v3_v3(r_nor, no);
+ copy_v3_v3(r_nor, snap_gizmo->nor);
+ }
+ if (r_elem_index) {
+ copy_v3_v3_int(r_elem_index, snap_gizmo->elem_index);
}
+ if (r_snap_elem) {
+ *r_snap_elem = snap_gizmo->snap_elem;
+ }
+}
- return snap_elem;
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name RNA callbacks
+ * \{ */
+
+/* Based on 'rna_GizmoProperties_find_operator'. */
+static struct SnapGizmo3D *gizmo_snap_rna_find_operator(PointerRNA *ptr)
+{
+ IDProperty *properties = ptr->data;
+ for (bScreen *screen = G_MAIN->screens.first; screen; screen = screen->id.next) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ if (area->spacetype != SPACE_VIEW3D) {
+ continue;
+ }
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (region->regiontype == RGN_TYPE_WINDOW && region->gizmo_map) {
+ wmGizmoMap *gzmap = region->gizmo_map;
+ LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, WM_gizmomap_group_list(gzmap)) {
+ LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
+ if (gz->properties == properties) {
+ return (SnapGizmo3D *)gz;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+static int gizmo_snap_rna_snap_elements_force_get_fn(struct PointerRNA *ptr,
+ struct PropertyRNA *UNUSED(prop))
+{
+ SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
+ if (snap_gizmo) {
+ return snap_gizmo->snap_elem_force;
+ }
+ return 0;
+}
+
+static void gizmo_snap_rna_snap_elements_force_set_fn(struct PointerRNA *ptr,
+ struct PropertyRNA *UNUSED(prop),
+ int value)
+{
+ SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
+ if (snap_gizmo) {
+ snap_gizmo->snap_elem_force = (short)value;
+ }
+}
+
+static void gizmo_snap_rna_prevpoint_get_fn(struct PointerRNA *ptr,
+ struct PropertyRNA *UNUSED(prop),
+ float *values)
+{
+ SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
+ if (snap_gizmo) {
+ copy_v3_v3(values, snap_gizmo->prevpoint_stack);
+ }
+}
+
+static void gizmo_snap_rna_prevpoint_set_fn(struct PointerRNA *ptr,
+ struct PropertyRNA *UNUSED(prop),
+ const float *values)
+{
+ SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
+ if (snap_gizmo) {
+ if (values) {
+ copy_v3_v3(snap_gizmo->prevpoint_stack, values);
+ snap_gizmo->prevpoint = snap_gizmo->prevpoint_stack;
+ }
+ else {
+ snap_gizmo->prevpoint = NULL;
+ }
+ }
+}
+
+static void gizmo_snap_rna_location_get_fn(struct PointerRNA *ptr,
+ struct PropertyRNA *UNUSED(prop),
+ float *values)
+{
+ SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
+ if (snap_gizmo) {
+ copy_v3_v3(values, snap_gizmo->loc);
+ }
+}
+
+static void gizmo_snap_rna_location_set_fn(struct PointerRNA *ptr,
+ struct PropertyRNA *UNUSED(prop),
+ const float *values)
+{
+ SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
+ if (snap_gizmo) {
+ copy_v3_v3(snap_gizmo->loc, values);
+ }
+}
+
+static void gizmo_snap_rna_normal_get_fn(struct PointerRNA *ptr,
+ struct PropertyRNA *UNUSED(prop),
+ float *values)
+{
+ SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
+ if (snap_gizmo) {
+ copy_v3_v3(values, snap_gizmo->nor);
+ }
+}
+
+static void gizmo_snap_rna_snap_elem_index_get_fn(struct PointerRNA *ptr,
+ struct PropertyRNA *UNUSED(prop),
+ int *values)
+{
+ SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
+ if (snap_gizmo) {
+ copy_v3_v3_int(values, snap_gizmo->elem_index);
+ }
}
/** \} */
@@ -416,19 +556,8 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz,
static void snap_gizmo_setup(wmGizmo *gz)
{
SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
-
- /* For quick access to the props. */
- snap_gizmo->prop_prevpoint = RNA_struct_find_property(gz->ptr, "prev_point");
- snap_gizmo->prop_location = RNA_struct_find_property(gz->ptr, "location");
- snap_gizmo->prop_normal = RNA_struct_find_property(gz->ptr, "normal");
- snap_gizmo->prop_elem_index = RNA_struct_find_property(gz->ptr, "snap_elem_index");
- snap_gizmo->prop_snap_force = RNA_struct_find_property(gz->ptr, "snap_elements_force");
-
snap_gizmo->use_snap_override = -1;
- /* Prop fallback. */
- WM_gizmo_target_property_def_rna(gz, "snap_elements", gz->ptr, "snap_elements_force", -1);
-
/* Flags. */
gz->flag |= WM_GIZMO_NO_TOOLTIP;
}
@@ -455,26 +584,23 @@ static void snap_gizmo_draw(const bContext *C, wmGizmo *gz)
return;
}
- float location[3], prev_point_stack[3], *prev_point = NULL;
uchar color_line[4], color_point[4];
-
- RNA_property_float_get_array(gz->ptr, snap_gizmo->prop_location, location);
-
UI_GetThemeColor3ubv(TH_TRANSFORM, color_line);
color_line[3] = 128;
rgba_float_to_uchar(color_point, gz->color);
- if (RNA_property_is_set(gz->ptr, snap_gizmo->prop_prevpoint)) {
- RNA_property_float_get_array(gz->ptr, snap_gizmo->prop_prevpoint, prev_point_stack);
- prev_point = prev_point_stack;
- }
-
GPU_line_smooth(false);
GPU_line_width(1.0f);
+
+ const float *prev_point = snap_gizmo_snap_elements(snap_gizmo) &
+ SCE_SNAP_MODE_EDGE_PERPENDICULAR ?
+ snap_gizmo->prevpoint :
+ NULL;
+
ED_gizmotypes_snap_3d_draw_util(
- rv3d, prev_point, location, NULL, color_line, color_point, snap_gizmo->snap_elem);
+ rv3d, prev_point, snap_gizmo->loc, NULL, color_line, color_point, snap_gizmo->snap_elem);
}
static int snap_gizmo_test_select(bContext *C, wmGizmo *gz, const int mval[2])
@@ -490,7 +616,7 @@ static int snap_gizmo_test_select(bContext *C, wmGizmo *gz, const int mval[2])
View3D *v3d = CTX_wm_view3d(C);
const float mval_fl[2] = {UNPACK2(mval)};
short snap_elem = ED_gizmotypes_snap_3d_update(
- gz, CTX_data_ensure_evaluated_depsgraph(C), region, v3d, wm, mval_fl, NULL, NULL);
+ gz, CTX_data_ensure_evaluated_depsgraph(C), region, v3d, wm, mval_fl);
if (snap_elem) {
ED_region_tag_redraw_editor_overlays(region);
@@ -553,57 +679,74 @@ static void GIZMO_GT_snap_3d(wmGizmoType *gzt)
}
/* Setup. */
- RNA_def_enum_flag(gzt->srna,
- "snap_elements_force",
- rna_enum_snap_element_items,
- SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE,
- "Snap Elements",
- "");
-
- RNA_def_float_vector(gzt->srna,
- "prev_point",
- 3,
- NULL,
- FLT_MIN,
- FLT_MAX,
- "Previous Point",
- "Point that defines the location of the perpendicular snap",
- FLT_MIN,
- FLT_MAX);
+ PropertyRNA *prop;
+ prop = RNA_def_enum_flag(gzt->srna,
+ "snap_elements_force",
+ rna_enum_snap_element_items,
+ SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE,
+ "Snap Elements",
+ "");
+
+ RNA_def_property_enum_funcs_runtime(prop,
+ gizmo_snap_rna_snap_elements_force_get_fn,
+ gizmo_snap_rna_snap_elements_force_set_fn,
+ NULL);
+
+ prop = RNA_def_float_array(gzt->srna,
+ "prev_point",
+ 3,
+ NULL,
+ FLT_MIN,
+ FLT_MAX,
+ "Previous Point",
+ "Point that defines the location of the perpendicular snap",
+ FLT_MIN,
+ FLT_MAX);
+
+ RNA_def_property_float_array_funcs_runtime(
+ prop, gizmo_snap_rna_prevpoint_get_fn, gizmo_snap_rna_prevpoint_set_fn, NULL);
/* Returns. */
- RNA_def_float_vector(gzt->srna,
- "location",
- 3,
- NULL,
- FLT_MIN,
- FLT_MAX,
- "Location",
- "Snap Point Location",
- FLT_MIN,
- FLT_MAX);
-
- RNA_def_float_vector(gzt->srna,
- "normal",
- 3,
- NULL,
- FLT_MIN,
- FLT_MAX,
- "Normal",
- "Snap Point Normal",
- FLT_MIN,
- FLT_MAX);
-
- RNA_def_int_vector(gzt->srna,
- "snap_elem_index",
- 3,
- NULL,
- INT_MIN,
- INT_MAX,
- "Snap Element",
- "Array index of face, edge and vert snapped",
- INT_MIN,
- INT_MAX);
+ prop = RNA_def_float_translation(gzt->srna,
+ "location",
+ 3,
+ NULL,
+ FLT_MIN,
+ FLT_MAX,
+ "Location",
+ "Snap Point Location",
+ FLT_MIN,
+ FLT_MAX);
+
+ RNA_def_property_float_array_funcs_runtime(
+ prop, gizmo_snap_rna_location_get_fn, gizmo_snap_rna_location_set_fn, NULL);
+
+ prop = RNA_def_float_vector_xyz(gzt->srna,
+ "normal",
+ 3,
+ NULL,
+ FLT_MIN,
+ FLT_MAX,
+ "Normal",
+ "Snap Point Normal",
+ FLT_MIN,
+ FLT_MAX);
+
+ RNA_def_property_float_array_funcs_runtime(prop, gizmo_snap_rna_normal_get_fn, NULL, NULL);
+
+ prop = RNA_def_int_vector(gzt->srna,
+ "snap_elem_index",
+ 3,
+ NULL,
+ INT_MIN,
+ INT_MAX,
+ "Snap Element",
+ "Array index of face, edge and vert snapped",
+ INT_MIN,
+ INT_MAX);
+
+ RNA_def_property_int_array_funcs_runtime(
+ prop, gizmo_snap_rna_snap_elem_index_get_fn, NULL, NULL);
/* Read/Write. */
WM_gizmotype_target_property_def(gzt, "snap_elements", PROP_ENUM, 1);
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index e9817f82090..5c40bc8e418 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -660,10 +660,14 @@ static short annotation_stroke_addpoint(tGPsdata *p,
View3D *v3d = p->area->spacedata.first;
view3d_region_operator_needs_opengl(p->win, p->region);
- ED_view3d_autodist_init(p->depsgraph,
- p->region,
- v3d,
- (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+ ED_view3d_depth_override(p->depsgraph,
+ p->region,
+ v3d,
+ NULL,
+ (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ?
+ V3D_DEPTH_GPENCIL_ONLY :
+ V3D_DEPTH_NO_GPENCIL,
+ false);
}
/* convert screen-coordinates to appropriate coordinates (and store them) */
@@ -1222,7 +1226,7 @@ static void annotation_stroke_doeraser(tGPsdata *p)
if (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH) {
View3D *v3d = p->area->spacedata.first;
view3d_region_operator_needs_opengl(p->win, p->region);
- ED_view3d_autodist_init(p->depsgraph, p->region, v3d, 0);
+ ED_view3d_depth_override(p->depsgraph, p->region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, false);
}
}
@@ -1695,8 +1699,14 @@ static void annotation_paint_strokeend(tGPsdata *p)
/* need to restore the original projection settings before packing up */
view3d_region_operator_needs_opengl(p->win, p->region);
- ED_view3d_autodist_init(
- p->depsgraph, p->region, v3d, (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+ ED_view3d_depth_override(p->depsgraph,
+ p->region,
+ v3d,
+ NULL,
+ (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ?
+ V3D_DEPTH_GPENCIL_ONLY :
+ V3D_DEPTH_NO_GPENCIL,
+ false);
}
/* check if doing eraser or not */
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 4bbd475dd2c..66beb74d566 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -3951,7 +3951,7 @@ static void gpencil_smooth_stroke(bContext *C, wmOperator *op)
}
if (smooth_thickness) {
/* thickness need to repeat process several times */
- for (int r2 = 0; r2 < r * 20; r2++) {
+ for (int r2 = 0; r2 < 20; r2++) {
BKE_gpencil_stroke_smooth_thickness(gps, i, factor);
}
}
@@ -4979,17 +4979,27 @@ static int gpencil_cutter_lasso_select(bContext *C,
/* init space conversion stuff */
gpencil_point_conversion_init(C, &gsc);
- /* deselect all strokes first */
- CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
- int i;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- pt->flag &= ~GP_SPOINT_SELECT;
- }
+ /* Deselect all strokes. */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ int i;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
- gps->flag &= ~GP_STROKE_SELECT;
- BKE_gpencil_stroke_select_index_reset(gps);
+ gps->flag &= ~GP_STROKE_SELECT;
+ BKE_gpencil_stroke_select_index_reset(gps);
+ }
+ }
+ /* if not multiedit, exit loop. */
+ if (!is_multiedit) {
+ break;
+ }
+ }
}
- CTX_DATA_END;
/* Select points */
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 4749f40fac5..3f86e5474c5 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -1363,7 +1363,8 @@ static void gpencil_get_depth_array(tGPDfill *tgpf)
if (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_VIEW) {
/* need to restore the original projection settings before packing up */
view3d_region_operator_needs_opengl(tgpf->win, tgpf->region);
- ED_view3d_autodist_init(tgpf->depsgraph, tgpf->region, tgpf->v3d, 0);
+ ED_view3d_depth_override(
+ tgpf->depsgraph, tgpf->region, tgpf->v3d, NULL, V3D_DEPTH_NO_GPENCIL, false);
/* Since strokes are so fine, when using their depth we need a margin
* otherwise they might get missed. */
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index bfa1ee6bcaf..e6a6c65243e 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -84,7 +84,8 @@ typedef struct tGPDinterpolate_layer {
/** interpolate factor */
float factor;
- /* Hash tablets to create temp relationship between strokes. */
+ /* List of strokes and Hash tablets to create temp relationship between strokes. */
+ struct ListBase selected_strokes;
struct GHash *used_strokes;
struct GHash *pair_strokes;
@@ -282,6 +283,7 @@ static void gpencil_stroke_pair_table(bContext *C,
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
/* Create hash tablets with relationship between strokes. */
+ BLI_listbase_clear(&tgpil->selected_strokes);
tgpil->used_strokes = BLI_ghash_ptr_new(__func__);
tgpil->pair_strokes = BLI_ghash_ptr_new(__func__);
@@ -315,7 +317,8 @@ static void gpencil_stroke_pair_table(bContext *C,
if (ELEM(NULL, gps_from, gps_to)) {
continue;
}
- /* Insert the pair entry in the hash table. */
+ /* Insert the pair entry in the hash table and the list of strokes to keep order. */
+ BLI_addtail(&tgpil->selected_strokes, BLI_genericNodeN(gps_from));
BLI_ghash_insert(tgpil->pair_strokes, gps_from, gps_to);
}
}
@@ -405,10 +408,13 @@ static void gpencil_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgp
/* Clear previous interpolations. */
gpencil_interpolate_free_tagged_strokes(tgpil->interFrame);
- GHashIterator gh_iter;
- GHASH_ITER (gh_iter, tgpil->pair_strokes) {
- bGPDstroke *gps_from = (bGPDstroke *)BLI_ghashIterator_getKey(&gh_iter);
- bGPDstroke *gps_to = (bGPDstroke *)BLI_ghashIterator_getValue(&gh_iter);
+ LISTBASE_FOREACH (LinkData *, link, &tgpil->selected_strokes) {
+ bGPDstroke *gps_from = link->data;
+ if (!BLI_ghash_haskey(tgpil->pair_strokes, gps_from)) {
+ continue;
+ }
+ bGPDstroke *gps_to = (bGPDstroke *)BLI_ghash_lookup(tgpil->pair_strokes, gps_from);
+
/* Create new stroke. */
bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true);
new_stroke->flag |= GP_STROKE_TAG;
@@ -527,10 +533,12 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
gpencil_stroke_pair_table(C, tgpi, tgpil);
/* Create new strokes data with interpolated points reading original stroke. */
- GHashIterator gh_iter;
- GHASH_ITER (gh_iter, tgpil->pair_strokes) {
- bGPDstroke *gps_from = (bGPDstroke *)BLI_ghashIterator_getKey(&gh_iter);
- bGPDstroke *gps_to = (bGPDstroke *)BLI_ghashIterator_getValue(&gh_iter);
+ LISTBASE_FOREACH (LinkData *, link, &tgpil->selected_strokes) {
+ bGPDstroke *gps_from = link->data;
+ if (!BLI_ghash_haskey(tgpil->pair_strokes, gps_from)) {
+ continue;
+ }
+ bGPDstroke *gps_to = (bGPDstroke *)BLI_ghash_lookup(tgpil->pair_strokes, gps_from);
/* If destination stroke is smaller, resize new_stroke to size of gps_to stroke. */
if (gps_from->totpoints > gps_to->totpoints) {
@@ -658,6 +666,9 @@ static void gpencil_interpolate_exit(bContext *C, wmOperator *op)
MEM_SAFE_FREE(tgpil->nextFrame);
MEM_SAFE_FREE(tgpil->interFrame);
+ /* Free list of strokes. */
+ BLI_freelistN(&tgpil->selected_strokes);
+
/* Free Hash tablets. */
if (tgpil->used_strokes != NULL) {
BLI_ghash_free(tgpil->used_strokes, NULL, NULL);
@@ -1292,9 +1303,9 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
bGPDframe *nextFrame = BKE_gpencil_frame_duplicate(gpf_next, true);
/* Create a table with source and target pair of strokes. */
+ ListBase selected_strokes = {NULL};
GHash *used_strokes = BLI_ghash_ptr_new(__func__);
GHash *pair_strokes = BLI_ghash_ptr_new(__func__);
-
LISTBASE_FOREACH (bGPDstroke *, gps_from, &prevFrame->strokes) {
bGPDstroke *gps_to = NULL;
/* Only selected. */
@@ -1342,7 +1353,9 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
}
}
- /* Insert the pair entry in the hash table. */
+ /* Insert the pair entry in the hash table and in the list of strokes to keep same order.
+ */
+ BLI_addtail(&selected_strokes, BLI_genericNodeN(gps_from));
BLI_ghash_insert(pair_strokes, gps_from, gps_to);
}
@@ -1369,11 +1382,12 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
}
/* Apply the factor to all pair of strokes. */
- GHashIterator gh_iter;
- GHASH_ITER (gh_iter, pair_strokes) {
- bGPDstroke *gps_from = (bGPDstroke *)BLI_ghashIterator_getKey(&gh_iter);
- bGPDstroke *gps_to = (bGPDstroke *)BLI_ghashIterator_getValue(&gh_iter);
-
+ LISTBASE_FOREACH (LinkData *, link, &selected_strokes) {
+ bGPDstroke *gps_from = link->data;
+ if (!BLI_ghash_haskey(pair_strokes, gps_from)) {
+ continue;
+ }
+ bGPDstroke *gps_to = (bGPDstroke *)BLI_ghash_lookup(pair_strokes, gps_from);
/* Create new stroke. */
bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true);
new_stroke->flag |= GP_STROKE_TAG;
@@ -1394,6 +1408,8 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
}
}
+ BLI_freelistN(&selected_strokes);
+
/* Free Hash tablets. */
if (used_strokes != NULL) {
BLI_ghash_free(used_strokes, NULL, NULL);
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 1217a3a7e8f..d072d8a35df 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -1722,7 +1722,7 @@ static void gpencil_stroke_doeraser(tGPsdata *p)
if ((gp_settings != NULL) && (gp_settings->flag & GP_BRUSH_OCCLUDE_ERASER)) {
View3D *v3d = p->area->spacedata.first;
view3d_region_operator_needs_opengl(p->win, p->region);
- ED_view3d_autodist_init(p->depsgraph, p->region, v3d, 0);
+ ED_view3d_depth_override(p->depsgraph, p->region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, false);
}
}
@@ -2305,8 +2305,14 @@ static void gpencil_paint_strokeend(tGPsdata *p)
/* need to restore the original projection settings before packing up */
view3d_region_operator_needs_opengl(p->win, p->region);
- ED_view3d_autodist_init(
- p->depsgraph, p->region, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+ ED_view3d_depth_override(p->depsgraph,
+ p->region,
+ v3d,
+ NULL,
+ (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ?
+ V3D_DEPTH_GPENCIL_ONLY :
+ V3D_DEPTH_NO_GPENCIL,
+ false);
}
/* check if doing eraser or not */
@@ -3691,7 +3697,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* Exit painting mode (and/or end current stroke).
*
*/
- if (ELEM(event->type, EVT_RETKEY, EVT_PADENTER, EVT_ESCKEY, EVT_SPACEKEY, EVT_EKEY)) {
+ if (ELEM(event->type, EVT_RETKEY, EVT_PADENTER, EVT_ESCKEY, EVT_SPACEKEY)) {
p->status = GP_STATUS_DONE;
estate = OPERATOR_FINISHED;
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index dfff0ce639e..3d20e32ed49 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -785,10 +785,14 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
/* need to restore the original projection settings before packing up */
view3d_region_operator_needs_opengl(tgpi->win, tgpi->region);
- ED_view3d_autodist_init(tgpi->depsgraph,
- tgpi->region,
- tgpi->v3d,
- (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+ ED_view3d_depth_override(tgpi->depsgraph,
+ tgpi->region,
+ tgpi->v3d,
+ NULL,
+ (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ?
+ V3D_DEPTH_GPENCIL_ONLY :
+ V3D_DEPTH_NO_GPENCIL,
+ false);
depth_arr = MEM_mallocN(sizeof(float) * gps->totpoints, "depth_points");
tGPspoint *ptc = &points2D[0];
diff --git a/source/blender/editors/gpencil/gpencil_trace_utils.c b/source/blender/editors/gpencil/gpencil_trace_utils.c
index ada777d43f3..482f7015720 100644
--- a/source/blender/editors/gpencil/gpencil_trace_utils.c
+++ b/source/blender/editors/gpencil/gpencil_trace_utils.c
@@ -308,9 +308,16 @@ void ED_gpencil_trace_data_to_strokes(Main *bmain,
if (gps->totpoints == 0) {
add_point(gps, scalef, offset, c[n - 1][2].x, c[n - 1][2].y);
}
+ else {
+ add_point(gps, scalef, offset, last[0], last[1]);
+ }
+
add_point(gps, scalef, offset, c[i][1].x, c[i][1].y);
add_point(gps, scalef, offset, c[i][2].x, c[i][2].y);
+
+ last[0] = c[i][2].x;
+ last[1] = c[i][2].y;
break;
}
case POTRACE_CURVETO: {
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 5c041134a74..8d42024a518 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -596,6 +596,21 @@ bool ED_gpencil_stroke_material_editable(Object *ob, const bGPDlayer *gpl, const
return true;
}
+/* Check whether given stroke is visible for the current material. */
+bool ED_gpencil_stroke_material_visible(Object *ob, const bGPDstroke *gps)
+{
+ /* check if the color is editable */
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+
+ if (gp_style != NULL) {
+ if (gp_style->flag & GP_MATERIAL_HIDE) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
/* ******************************************************** */
/* Space Conversion */
@@ -633,7 +648,7 @@ void gpencil_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
view3d_operator_needs_opengl(C);
view3d_region_operator_needs_opengl(win, region);
- ED_view3d_autodist_init(depsgraph, region, v3d, 0);
+ ED_view3d_depth_override(depsgraph, region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, false);
/* for camera view set the subrect */
if (rv3d->persp == RV3D_CAMOB) {
diff --git a/source/blender/editors/include/ED_gizmo_library.h b/source/blender/editors/include/ED_gizmo_library.h
index dfc8cfea5ce..1c795896f86 100644
--- a/source/blender/editors/include/ED_gizmo_library.h
+++ b/source/blender/editors/include/ED_gizmo_library.h
@@ -271,9 +271,9 @@ short ED_gizmotypes_snap_3d_update(struct wmGizmo *gz,
const struct ARegion *region,
const struct View3D *v3d,
const struct wmWindowManager *wm,
- const float mval_fl[2],
- float r_loc[3],
- float r_nor[3]);
+ const float mval_fl[2]);
+void ED_gizmotypes_snap_3d_data_get(
+ struct wmGizmo *gz, float r_loc[3], float r_nor[3], int r_elem_index[3], int *r_snap_elem);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index f3b5abb1072..e9ac21f60cf 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -150,6 +150,7 @@ bool ED_gpencil_stroke_can_use(const struct bContext *C, const struct bGPDstroke
bool ED_gpencil_stroke_material_editable(struct Object *ob,
const struct bGPDlayer *gpl,
const struct bGPDstroke *gps);
+bool ED_gpencil_stroke_material_visible(struct Object *ob, const struct bGPDstroke *gps);
/* ----------- Grease Pencil Operators ----------------- */
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 85e7a491feb..b8e9f6e8871 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -164,16 +164,16 @@ void EDBM_select_mirrored(struct BMEditMesh *em,
int *r_totfail);
struct BMVert *EDBM_vert_find_nearest_ex(struct ViewContext *vc,
- float *r_dist,
+ float *dist_px_manhattan_p,
const bool use_select_bias,
bool use_cycle,
struct Base **bases,
uint bases_len,
uint *r_base_index);
-struct BMVert *EDBM_vert_find_nearest(struct ViewContext *vc, float *r_dist);
+struct BMVert *EDBM_vert_find_nearest(struct ViewContext *vc, float *dist_px_manhattan_p);
struct BMEdge *EDBM_edge_find_nearest_ex(struct ViewContext *vc,
- float *r_dist,
+ float *dist_px_manhattan,
float *r_dist_center,
const bool use_select_bias,
bool use_cycle,
@@ -181,18 +181,19 @@ struct BMEdge *EDBM_edge_find_nearest_ex(struct ViewContext *vc,
struct Base **bases,
uint bases_len,
uint *r_base_index);
-struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, float *r_dist);
+struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, float *dist_px_manhattan_p);
struct BMFace *EDBM_face_find_nearest_ex(struct ViewContext *vc,
- float *r_dist,
+ float *dist_px_manhattan,
float *r_dist_center,
+ const bool use_zbuf_single_px,
const bool use_select_bias,
bool use_cycle,
struct BMFace **r_efa_zbuf,
struct Base **bases,
uint bases_len,
uint *r_base_index);
-struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, float *r_dist);
+struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, float *dist_px_manhattan_p);
bool EDBM_unified_findnearest(struct ViewContext *vc,
struct Base **bases,
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 0767ce21382..b5a94bc7798 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -178,6 +178,9 @@ void ED_object_base_active_refresh(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer);
void ED_object_base_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *ob);
+void ED_object_base_free_and_unlink_no_indirect_check(struct Main *bmain,
+ struct Scene *scene,
+ struct Object *ob);
bool ED_object_base_deselect_all_ex(struct ViewLayer *view_layer,
struct View3D *v3d,
int action,
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 3b8e062ffec..d00d03abae7 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -144,7 +144,17 @@ bool ED_view3d_camera_to_view_selected(struct Main *bmain,
void ED_view3d_lastview_store(struct RegionView3D *rv3d);
/* Depth buffer */
-void ED_view3d_depth_update(struct ARegion *region);
+typedef enum {
+ V3D_DEPTH_NO_GPENCIL = 0,
+ V3D_DEPTH_GPENCIL_ONLY,
+ V3D_DEPTH_OBJECT_ONLY,
+} eV3DDepthOverrideMode;
+void ED_view3d_depth_override(struct Depsgraph *depsgraph,
+ struct ARegion *region,
+ struct View3D *v3d,
+ struct Object *obact,
+ eV3DDepthOverrideMode mode,
+ bool update_cache);
float ED_view3d_depth_read_cached(const struct ViewContext *vc, const int mval[2]);
bool ED_view3d_depth_read_cached_normal(const ViewContext *vc,
const int mval[2],
@@ -481,11 +491,6 @@ bool ED_view3d_autodist(struct Depsgraph *depsgraph,
const bool alphaoverride,
const float fallback_depth_pt[3]);
-/* Only draw so #ED_view3d_autodist_simple can be called many times after. */
-void ED_view3d_autodist_init(struct Depsgraph *depsgraph,
- struct ARegion *region,
- struct View3D *v3d,
- int mode);
bool ED_view3d_autodist_simple(struct ARegion *region,
const int mval[2],
float mouse_worldloc[3],
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 279239fcc65..6caee42ac33 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1038,7 +1038,6 @@ static bool ui_but_is_rna_undo(const uiBut *but)
if (ID_CHECK_UNDO(id) == false) {
return false;
}
- return true;
}
if (but->rnapoin.type && !RNA_struct_undo_check(but->rnapoin.type)) {
return false;
@@ -1817,9 +1816,9 @@ static void ui_but_validate(const uiBut *but)
#endif
/**
- * Check if the operator \a ot poll is successfull with the context given by \a but (optionally).
+ * Check if the operator \a ot poll is successful with the context given by \a but (optionally).
* \param but: The button that might store context. Can be NULL for convenience (e.g. if there is
- * no button to take context from, but we still want to poll the operator).
+ * no button to take context from, but we still want to poll the operator).
*/
bool ui_but_context_poll_operator(bContext *C, wmOperatorType *ot, const uiBut *but)
{
diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c
index 4ae6f66281f..d5fb0e4e744 100644
--- a/source/blender/editors/interface/interface_eyedropper_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_color.c
@@ -116,14 +116,11 @@ static bool eyedropper_init(bContext *C, wmOperator *op)
float col[4];
RNA_property_float_get_array(&eye->ptr, eye->prop, col);
- if (ELEM(eye->ptr.type, &RNA_CompositorNodeCryptomatteV2, &RNA_CompositorNodeCryptomatte)) {
+ if (eye->ptr.type == &RNA_CompositorNodeCryptomatteV2) {
eye->crypto_node = (bNode *)eye->ptr.data;
eye->cryptomatte_session = ntreeCompositCryptomatteSession(eye->crypto_node);
eye->draw_handle_sample_text = WM_draw_cb_activate(CTX_wm_window(C), eyedropper_draw_cb, eye);
}
- else {
- eye->crypto_node = NULL;
- }
if (prop_subtype != PROP_COLOR) {
Scene *scene = CTX_data_scene(C);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 7343417137a..8922babc9b8 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -2529,9 +2529,8 @@ PointerRNA *UI_region_panel_custom_data_under_cursor(const bContext *C, const wm
{
ARegion *region = CTX_wm_region(C);
- Panel *panel = NULL;
LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
- panel = block->panel;
+ Panel *panel = block->panel;
if (panel == NULL) {
continue;
}
@@ -2541,15 +2540,11 @@ PointerRNA *UI_region_panel_custom_data_under_cursor(const bContext *C, const wm
ui_window_to_block(region, block, &mx, &my);
const int mouse_state = ui_panel_mouse_state_get(block, panel, mx, my);
if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) {
- break;
+ return UI_panel_custom_data_get(panel);
}
}
- if (panel == NULL) {
- return NULL;
- }
-
- return UI_panel_custom_data_get(panel);
+ return NULL;
}
/** \} */
diff --git a/source/blender/editors/io/CMakeLists.txt b/source/blender/editors/io/CMakeLists.txt
index e7effd05d34..44b5f85050f 100644
--- a/source/blender/editors/io/CMakeLists.txt
+++ b/source/blender/editors/io/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../depsgraph
../../io/alembic
../../io/collada
+ ../../io/gpencil
../../io/usd
../../makesdna
../../makesrna
@@ -39,12 +40,16 @@ set(SRC
io_alembic.c
io_cache.c
io_collada.c
+ io_gpencil_export.c
+ io_gpencil_import.c
+ io_gpencil_utils.c
io_ops.c
io_usd.c
io_alembic.h
io_cache.h
io_collada.h
+ io_gpencil.h
io_ops.h
io_usd.h
)
@@ -79,4 +84,14 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_PUGIXML)
+ add_definitions(-DWITH_PUGIXML)
+endif()
+
+if(WITH_HARU)
+ add_definitions(-DWITH_HARU)
+endif()
+
+list(APPEND LIB bf_gpencil)
+
blender_add_lib(bf_editor_io "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/io/io_gpencil.h b/source/blender/editors/io/io_gpencil.h
new file mode 100644
index 00000000000..98cb8b13310
--- /dev/null
+++ b/source/blender/editors/io/io_gpencil.h
@@ -0,0 +1,45 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+#ifndef __IO_GPENCIL_H__
+#define __IO_GPENCIL_H__
+
+/** \file
+ * \ingroup editor/io
+ */
+
+struct ARegion;
+struct bContext;
+struct View3D;
+struct wmOperator;
+struct wmOperatorType;
+
+void WM_OT_gpencil_import_svg(struct wmOperatorType *ot);
+
+#ifdef WITH_PUGIXML
+void WM_OT_gpencil_export_svg(struct wmOperatorType *ot);
+#endif
+#ifdef WITH_HARU
+void WM_OT_gpencil_export_pdf(struct wmOperatorType *ot);
+#endif
+
+struct ARegion *get_invoke_region(struct bContext *C);
+struct View3D *get_invoke_view3d(struct bContext *C);
+
+#endif /* __IO_GPENCIL_H__ */
diff --git a/source/blender/editors/io/io_gpencil_export.c b/source/blender/editors/io/io_gpencil_export.c
new file mode 100644
index 00000000000..10e4e598bad
--- /dev/null
+++ b/source/blender/editors/io/io_gpencil_export.c
@@ -0,0 +1,432 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup editor/io
+ */
+
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_gpencil.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+#include "BKE_screen.h"
+
+#include "BLT_translation.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "io_gpencil.h"
+
+#include "gpencil_io.h"
+
+#if defined(WITH_PUGIXML) || defined(WITH_HARU)
+/* Definition of enum elements to export. */
+/* Common props for exporting. */
+static void gpencil_export_common_props_definition(wmOperatorType *ot)
+{
+ static const EnumPropertyItem select_items[] = {
+ {GP_EXPORT_ACTIVE, "ACTIVE", 0, "Active", "Include only the active object"},
+ {GP_EXPORT_SELECTED, "SELECTED", 0, "Selected", "Include selected objects"},
+ {GP_EXPORT_VISIBLE, "VISIBLE", 0, "Visible", "Include all visible objects"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ RNA_def_boolean(ot->srna, "use_fill", true, "Fill", "Export strokes with fill enabled");
+ RNA_def_enum(ot->srna,
+ "selected_object_type",
+ select_items,
+ GP_EXPORT_SELECTED,
+ "Object",
+ "Which objects to include in the export");
+ RNA_def_float(ot->srna,
+ "stroke_sample",
+ 0.0f,
+ 0.0f,
+ 100.0f,
+ "Sampling",
+ "Precision of stroke sampling. Low values mean a more precise result, and zero "
+ "disables sampling",
+ 0.0f,
+ 100.0f);
+ RNA_def_boolean(ot->srna,
+ "use_normalized_thickness",
+ false,
+ "Normalize",
+ "Export strokes with constant thickness");
+}
+
+static void set_export_filepath(bContext *C, wmOperator *op, const char *extension)
+{
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ Main *bmain = CTX_data_main(C);
+ char filepath[FILE_MAX];
+
+ if (BKE_main_blendfile_path(bmain)[0] == '\0') {
+ BLI_strncpy(filepath, "untitled", sizeof(filepath));
+ }
+ else {
+ BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
+ }
+
+ BLI_path_extension_replace(filepath, sizeof(filepath), extension);
+ RNA_string_set(op->ptr, "filepath", filepath);
+ }
+}
+#endif
+
+/* <-------- SVG single frame export. --------> */
+#ifdef WITH_PUGIXML
+static bool wm_gpencil_export_svg_common_check(bContext *UNUSED(C), wmOperator *op)
+{
+ char filepath[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filepath);
+
+ if (!BLI_path_extension_check(filepath, ".svg")) {
+ BLI_path_extension_ensure(filepath, FILE_MAX, ".svg");
+ RNA_string_set(op->ptr, "filepath", filepath);
+ return true;
+ }
+
+ return false;
+}
+
+static int wm_gpencil_export_svg_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ set_export_filepath(C, op, ".svg");
+
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int wm_gpencil_export_svg_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ BKE_report(op->reports, RPT_ERROR, "No filename given");
+ return OPERATOR_CANCELLED;
+ }
+
+ ARegion *region = get_invoke_region(C);
+ if (region == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unable to find valid 3D View area");
+ return OPERATOR_CANCELLED;
+ }
+ View3D *v3d = get_invoke_view3d(C);
+
+ char filename[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filename);
+
+ const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
+ const bool use_norm_thickness = RNA_boolean_get(op->ptr, "use_normalized_thickness");
+ const eGpencilExportSelect select_mode = RNA_enum_get(op->ptr, "selected_object_type");
+
+ const bool use_clip_camera = RNA_boolean_get(op->ptr, "use_clip_camera");
+
+ /* Set flags. */
+ int flag = 0;
+ SET_FLAG_FROM_TEST(flag, use_fill, GP_EXPORT_FILL);
+ SET_FLAG_FROM_TEST(flag, use_norm_thickness, GP_EXPORT_NORM_THICKNESS);
+ SET_FLAG_FROM_TEST(flag, use_clip_camera, GP_EXPORT_CLIP_CAMERA);
+
+ GpencilIOParams params = {.C = C,
+ .region = region,
+ .v3d = v3d,
+ .ob = ob,
+ .mode = GP_EXPORT_TO_SVG,
+ .frame_start = CFRA,
+ .frame_end = CFRA,
+ .frame_cur = CFRA,
+ .flag = flag,
+ .scale = 1.0f,
+ .select_mode = select_mode,
+ .frame_mode = GP_EXPORT_FRAME_ACTIVE,
+ .stroke_sample = RNA_float_get(op->ptr, "stroke_sample"),
+ .resolution = 1.0f};
+
+ /* Do export. */
+ WM_cursor_wait(true);
+ const bool done = gpencil_io_export(filename, &params);
+ WM_cursor_wait(false);
+
+ if (!done) {
+ BKE_report(op->reports, RPT_WARNING, "Unable to export SVG");
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void ui_gpencil_export_svg_settings(uiLayout *layout, PointerRNA *imfptr)
+{
+ uiLayout *box, *row;
+
+ uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
+
+ box = uiLayoutBox(layout);
+
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Scene Options"), ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "selected_object_type", 0, NULL, ICON_NONE);
+
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Export Options"), ICON_NONE);
+
+ uiLayout *col = uiLayoutColumn(box, false);
+ uiItemR(col, imfptr, "stroke_sample", 0, NULL, ICON_NONE);
+ uiItemR(col, imfptr, "use_fill", 0, NULL, ICON_NONE);
+ uiItemR(col, imfptr, "use_normalized_thickness", 0, NULL, ICON_NONE);
+ uiItemR(col, imfptr, "use_clip_camera", 0, NULL, ICON_NONE);
+}
+
+static void wm_gpencil_export_svg_draw(bContext *UNUSED(C), wmOperator *op)
+{
+ PointerRNA ptr;
+
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+
+ ui_gpencil_export_svg_settings(op->layout, &ptr);
+}
+
+static bool wm_gpencil_export_svg_poll(bContext *C)
+{
+ if ((CTX_wm_window(C) == NULL) || (CTX_data_mode_enum(C) != CTX_MODE_OBJECT)) {
+ return false;
+ }
+
+ return true;
+}
+
+void WM_OT_gpencil_export_svg(wmOperatorType *ot)
+{
+ ot->name = "Export to SVG";
+ ot->description = "Export grease pencil to SVG";
+ ot->idname = "WM_OT_gpencil_export_svg";
+
+ ot->invoke = wm_gpencil_export_svg_invoke;
+ ot->exec = wm_gpencil_export_svg_exec;
+ ot->poll = wm_gpencil_export_svg_poll;
+ ot->ui = wm_gpencil_export_svg_draw;
+ ot->check = wm_gpencil_export_svg_common_check;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_OBJECT_IO,
+ FILE_BLENDER,
+ FILE_SAVE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+
+ gpencil_export_common_props_definition(ot);
+
+ RNA_def_boolean(ot->srna,
+ "use_clip_camera",
+ false,
+ "Clip Camera",
+ "Clip drawings to camera size when export in camera view");
+}
+#endif
+
+/* <-------- PDF single frame export. --------> */
+#ifdef WITH_HARU
+static bool wm_gpencil_export_pdf_common_check(bContext *UNUSED(C), wmOperator *op)
+{
+
+ char filepath[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filepath);
+
+ if (!BLI_path_extension_check(filepath, ".pdf")) {
+ BLI_path_extension_ensure(filepath, FILE_MAX, ".pdf");
+ RNA_string_set(op->ptr, "filepath", filepath);
+ return true;
+ }
+
+ return false;
+}
+
+static int wm_gpencil_export_pdf_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ set_export_filepath(C, op, ".pdf");
+
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int wm_gpencil_export_pdf_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ BKE_report(op->reports, RPT_ERROR, "No filename given");
+ return OPERATOR_CANCELLED;
+ }
+
+ ARegion *region = get_invoke_region(C);
+ if (region == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unable to find valid 3D View area");
+ return OPERATOR_CANCELLED;
+ }
+ View3D *v3d = get_invoke_view3d(C);
+
+ char filename[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filename);
+
+ const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
+ const bool use_norm_thickness = RNA_boolean_get(op->ptr, "use_normalized_thickness");
+ const short select_mode = RNA_enum_get(op->ptr, "selected_object_type");
+ const short frame_mode = RNA_enum_get(op->ptr, "frame_mode");
+
+ /* Set flags. */
+ int flag = 0;
+ SET_FLAG_FROM_TEST(flag, use_fill, GP_EXPORT_FILL);
+ SET_FLAG_FROM_TEST(flag, use_norm_thickness, GP_EXPORT_NORM_THICKNESS);
+
+ GpencilIOParams params = {.C = C,
+ .region = region,
+ .v3d = v3d,
+ .ob = ob,
+ .mode = GP_EXPORT_TO_PDF,
+ .frame_start = SFRA,
+ .frame_end = EFRA,
+ .frame_cur = CFRA,
+ .flag = flag,
+ .scale = 1.0f,
+ .select_mode = select_mode,
+ .frame_mode = frame_mode,
+ .stroke_sample = RNA_float_get(op->ptr, "stroke_sample"),
+ .resolution = 1.0f};
+
+ /* Do export. */
+ WM_cursor_wait(true);
+ const bool done = gpencil_io_export(filename, &params);
+ WM_cursor_wait(false);
+
+ if (!done) {
+ BKE_report(op->reports, RPT_WARNING, "Unable to export PDF");
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void ui_gpencil_export_pdf_settings(uiLayout *layout, PointerRNA *imfptr)
+{
+ uiLayout *box, *row, *col, *sub;
+
+ uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
+
+ box = uiLayoutBox(layout);
+
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Scene Options"), ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "selected_object_type", 0, NULL, ICON_NONE);
+
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Export Options"), ICON_NONE);
+
+ col = uiLayoutColumn(box, false);
+ sub = uiLayoutColumn(col, true);
+ uiItemR(sub, imfptr, "frame_mode", 0, IFACE_("Frame"), ICON_NONE);
+
+ uiLayoutSetPropSep(box, true);
+
+ sub = uiLayoutColumn(col, true);
+ uiItemR(sub, imfptr, "stroke_sample", 0, NULL, ICON_NONE);
+ uiItemR(sub, imfptr, "use_fill", 0, NULL, ICON_NONE);
+ uiItemR(sub, imfptr, "use_normalized_thickness", 0, NULL, ICON_NONE);
+}
+
+static void wm_gpencil_export_pdf_draw(bContext *UNUSED(C), wmOperator *op)
+{
+ PointerRNA ptr;
+
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+
+ ui_gpencil_export_pdf_settings(op->layout, &ptr);
+}
+
+static bool wm_gpencil_export_pdf_poll(bContext *C)
+{
+ if ((CTX_wm_window(C) == NULL) || (CTX_data_mode_enum(C) != CTX_MODE_OBJECT)) {
+ return false;
+ }
+
+ return true;
+}
+
+void WM_OT_gpencil_export_pdf(wmOperatorType *ot)
+{
+ ot->name = "Export to PDF";
+ ot->description = "Export grease pencil to PDF";
+ ot->idname = "WM_OT_gpencil_export_pdf";
+
+ ot->invoke = wm_gpencil_export_pdf_invoke;
+ ot->exec = wm_gpencil_export_pdf_exec;
+ ot->poll = wm_gpencil_export_pdf_poll;
+ ot->ui = wm_gpencil_export_pdf_draw;
+ ot->check = wm_gpencil_export_pdf_common_check;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_OBJECT_IO,
+ FILE_BLENDER,
+ FILE_SAVE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+
+ static const EnumPropertyItem gpencil_export_frame_items[] = {
+ {GP_EXPORT_FRAME_ACTIVE, "ACTIVE", 0, "Active", "Include only active frame"},
+ {GP_EXPORT_FRAME_SELECTED, "SELECTED", 0, "Selected", "Include selected frames"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ gpencil_export_common_props_definition(ot);
+ ot->prop = RNA_def_enum(ot->srna,
+ "frame_mode",
+ gpencil_export_frame_items,
+ GP_EXPORT_ACTIVE,
+ "Frames",
+ "Which frames to include in the export");
+}
+#endif
diff --git a/source/blender/editors/io/io_gpencil_import.c b/source/blender/editors/io/io_gpencil_import.c
new file mode 100644
index 00000000000..9768da85940
--- /dev/null
+++ b/source/blender/editors/io/io_gpencil_import.c
@@ -0,0 +1,195 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup editor/io
+ */
+
+#include "BLI_path_util.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_report.h"
+
+#include "BLT_translation.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "ED_gpencil.h"
+
+#include "io_gpencil.h"
+
+#include "gpencil_io.h"
+
+/* <-------- SVG single frame import. --------> */
+static bool wm_gpencil_import_svg_common_check(bContext *UNUSED(C), wmOperator *op)
+{
+
+ char filepath[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filepath);
+
+ if (!BLI_path_extension_check(filepath, ".svg")) {
+ BLI_path_extension_ensure(filepath, FILE_MAX, ".svg");
+ RNA_string_set(op->ptr, "filepath", filepath);
+ return true;
+ }
+
+ return false;
+}
+
+static int wm_gpencil_import_svg_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int wm_gpencil_import_svg_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ BKE_report(op->reports, RPT_ERROR, "No filename given");
+ return OPERATOR_CANCELLED;
+ }
+
+ ARegion *region = get_invoke_region(C);
+ if (region == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unable to find valid 3D View area");
+ return OPERATOR_CANCELLED;
+ }
+ View3D *v3d = get_invoke_view3d(C);
+
+ char filename[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filename);
+
+ /* Set flags. */
+ int flag = 0;
+
+ const int resolution = RNA_int_get(op->ptr, "resolution");
+ const float scale = RNA_float_get(op->ptr, "scale");
+
+ GpencilIOParams params = {
+ .C = C,
+ .region = region,
+ .v3d = v3d,
+ .ob = NULL,
+ .mode = GP_IMPORT_FROM_SVG,
+ .frame_start = CFRA,
+ .frame_end = CFRA,
+ .frame_cur = CFRA,
+ .flag = flag,
+ .scale = scale,
+ .select_mode = 0,
+ .frame_mode = 0,
+ .stroke_sample = 0.0f,
+ .resolution = resolution,
+ };
+
+ /* Do Import. */
+ WM_cursor_wait(1);
+ const bool done = gpencil_io_import(filename, &params);
+ WM_cursor_wait(0);
+
+ if (!done) {
+ BKE_report(op->reports, RPT_WARNING, "Unable to import SVG");
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void ui_gpencil_import_svg_settings(uiLayout *layout, PointerRNA *imfptr)
+{
+ uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
+ uiLayout *col = uiLayoutColumn(layout, false);
+ uiItemR(col, imfptr, "resolution", 0, NULL, ICON_NONE);
+ uiItemR(col, imfptr, "scale", 0, NULL, ICON_NONE);
+}
+
+static void wm_gpencil_import_svg_draw(bContext *UNUSED(C), wmOperator *op)
+{
+ PointerRNA ptr;
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+
+ ui_gpencil_import_svg_settings(op->layout, &ptr);
+}
+
+static bool wm_gpencil_import_svg_poll(bContext *C)
+{
+ if ((CTX_wm_window(C) == NULL) || (CTX_data_mode_enum(C) != CTX_MODE_OBJECT)) {
+ return false;
+ }
+
+ return true;
+}
+
+void WM_OT_gpencil_import_svg(wmOperatorType *ot)
+{
+ ot->name = "Import SVG";
+ ot->description = "Import SVG into grease pencil";
+ ot->idname = "WM_OT_gpencil_import_svg";
+
+ ot->invoke = wm_gpencil_import_svg_invoke;
+ ot->exec = wm_gpencil_import_svg_exec;
+ ot->poll = wm_gpencil_import_svg_poll;
+ ot->ui = wm_gpencil_import_svg_draw;
+ ot->check = wm_gpencil_import_svg_common_check;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_OBJECT_IO,
+ FILE_BLENDER,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_SHOW_PROPS,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_DEFAULT);
+
+ RNA_def_int(ot->srna,
+ "resolution",
+ 10,
+ 1,
+ 30,
+ "Resolution",
+ "Resolution of the generated strokes",
+ 1,
+ 20);
+
+ RNA_def_float(ot->srna,
+ "scale",
+ 10.0f,
+ 0.001f,
+ 100.0f,
+ "Scale",
+ "Scale of the final strokes",
+ 0.001f,
+ 100.0f);
+}
diff --git a/source/blender/editors/io/io_gpencil_utils.c b/source/blender/editors/io/io_gpencil_utils.c
new file mode 100644
index 00000000000..259a669519a
--- /dev/null
+++ b/source/blender/editors/io/io_gpencil_utils.c
@@ -0,0 +1,64 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup editor/io
+ */
+
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "WM_api.h"
+
+#include "io_gpencil.h"
+
+ARegion *get_invoke_region(bContext *C)
+{
+ bScreen *screen = CTX_wm_screen(C);
+ if (screen == NULL) {
+ return NULL;
+ }
+ ScrArea *area = BKE_screen_find_big_area(screen, SPACE_VIEW3D, 0);
+ if (area == NULL) {
+ return NULL;
+ }
+
+ ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
+
+ return region;
+}
+
+View3D *get_invoke_view3d(bContext *C)
+{
+ bScreen *screen = CTX_wm_screen(C);
+ if (screen == NULL) {
+ return NULL;
+ }
+ ScrArea *area = BKE_screen_find_big_area(screen, SPACE_VIEW3D, 0);
+ if (area == NULL) {
+ return NULL;
+ }
+ if (area) {
+ return area->spacedata.first;
+ }
+
+ return NULL;
+}
diff --git a/source/blender/editors/io/io_ops.c b/source/blender/editors/io/io_ops.c
index acb511a414d..9fa34a1c55d 100644
--- a/source/blender/editors/io/io_ops.c
+++ b/source/blender/editors/io/io_ops.c
@@ -38,6 +38,7 @@
#endif
#include "io_cache.h"
+#include "io_gpencil.h"
void ED_operatortypes_io(void)
{
@@ -54,6 +55,16 @@ void ED_operatortypes_io(void)
WM_operatortype_append(WM_OT_usd_export);
#endif
+ WM_operatortype_append(WM_OT_gpencil_import_svg);
+
+#ifdef WITH_PUGIXML
+ WM_operatortype_append(WM_OT_gpencil_export_svg);
+#endif
+
+#ifdef WITH_HARU
+ WM_operatortype_append(WM_OT_gpencil_export_pdf);
+#endif
+
WM_operatortype_append(CACHEFILE_OT_open);
WM_operatortype_append(CACHEFILE_OT_reload);
}
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index 1226cc57359..36edbbe31d6 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -26,6 +26,7 @@
#include "BLI_math.h"
#include "BKE_context.h"
+#include "BKE_curve.h"
#include "BKE_mask.h"
#include "DEG_depsgraph.h"
@@ -692,6 +693,33 @@ void MASK_OT_add_feather_vertex(wmOperatorType *ot)
/******************** common primitive functions *********************/
+static BezTriple *points_to_bezier(const float (*points)[2],
+ const int num_points,
+ const char handle_type,
+ const float scale,
+ const float location[2])
+{
+ BezTriple *bezier_points = MEM_calloc_arrayN(num_points, sizeof(BezTriple), __func__);
+ for (int i = 0; i < num_points; i++) {
+ copy_v2_v2(bezier_points[i].vec[1], points[i]);
+ mul_v2_fl(bezier_points[i].vec[1], scale);
+ add_v2_v2(bezier_points[i].vec[1], location);
+
+ bezier_points[i].h1 = handle_type;
+ bezier_points[i].h2 = handle_type;
+ }
+
+ for (int i = 0; i < num_points; i++) {
+ BKE_nurb_handle_calc(&bezier_points[i],
+ &bezier_points[(i - 1 + num_points) % num_points],
+ &bezier_points[(i + 1) % num_points],
+ false,
+ false);
+ }
+
+ return bezier_points;
+}
+
static int create_primitive_from_points(
bContext *C, wmOperator *op, const float (*points)[2], int num_points, char handle_type)
{
@@ -734,25 +762,25 @@ static int create_primitive_from_points(
const int spline_index = BKE_mask_layer_shape_spline_to_index(mask_layer, new_spline);
+ BezTriple *bezier_points = points_to_bezier(points, num_points, handle_type, scale, location);
+
for (int i = 0; i < num_points; i++) {
new_spline->tot_point = i + 1;
MaskSplinePoint *new_point = &new_spline->points[i];
BKE_mask_parent_init(&new_point->parent);
- copy_v2_v2(new_point->bezt.vec[1], points[i]);
- mul_v2_fl(new_point->bezt.vec[1], scale);
- add_v2_v2(new_point->bezt.vec[1], location);
+ new_point->bezt = bezier_points[i];
- new_point->bezt.h1 = handle_type;
- new_point->bezt.h2 = handle_type;
BKE_mask_point_select_set(new_point, true);
if (mask_layer->splines_shapes.first) {
- BKE_mask_layer_shape_changed_add(mask_layer, spline_index + i, true, true);
+ BKE_mask_layer_shape_changed_add(mask_layer, spline_index + i, true, false);
}
}
+ MEM_freeN(bezier_points);
+
if (added_mask) {
WM_event_add_notifier(C, NC_MASK | NA_ADDED, NULL);
}
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index df0ca6e3cae..fb107795c2a 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -74,7 +74,7 @@
/* detect isolated holes and fill them */
#define USE_NET_ISLAND_CONNECT
-#define KMAXDIST 10 /* max mouse distance from edge before not detecting it */
+#define KMAXDIST (10 * U.dpi_fac) /* max mouse distance from edge before not detecting it */
/* WARNING: knife float precision is fragile:
* be careful before making changes here see: (T43229, T42864, T42459, T41164).
@@ -146,6 +146,8 @@ typedef struct KnifePosData {
KnifeVert *vert;
KnifeEdge *edge;
BMFace *bmface;
+
+ /** When true, the cursor isn't over a face. */
bool is_space;
float mval[2]; /* mouse screen position (may be non-integral if snapped to something) */
@@ -196,7 +198,10 @@ typedef struct KnifeTool_OpData {
KnifePosData prev; /* last added cut (a line draws from the cursor to this) */
KnifePosData init; /* the first point in the cut-list, used for closing the loop */
- int totkedge, totkvert;
+ /** Number of knife edges `kedges`. */
+ int totkedge;
+ /** Number of knife vertices, `kverts`. */
+ int totkvert;
BLI_mempool *refs;
@@ -221,7 +226,7 @@ typedef struct KnifeTool_OpData {
float clipsta, clipend;
- enum { MODE_IDLE, MODE_DRAGGING, MODE_CONNECT, MODE_PANNING } mode;
+ enum { MODE_INVOKING, MODE_IDLE, MODE_DRAGGING, MODE_CONNECT, MODE_PANNING } mode;
bool is_drag_hold;
int prevmode;
@@ -243,8 +248,8 @@ enum {
KNF_MODAL_MIDPOINT_ON,
KNF_MODAL_MIDPOINT_OFF,
KNF_MODAL_NEW_CUT,
- KNF_MODEL_IGNORE_SNAP_ON,
- KNF_MODEL_IGNORE_SNAP_OFF,
+ KNF_MODAL_IGNORE_SNAP_ON,
+ KNF_MODAL_IGNORE_SNAP_OFF,
KNF_MODAL_ADD_CUT,
KNF_MODAL_ANGLE_SNAP_TOGGLE,
KNF_MODAL_CUT_THROUGH_TOGGLE,
@@ -252,19 +257,263 @@ enum {
KNF_MODAL_ADD_CUT_CLOSED,
};
-static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f);
+/* -------------------------------------------------------------------- */
+/** \name Drawing
+ * \{ */
-static void knife_input_ray_segment(KnifeTool_OpData *kcd,
- const float mval[2],
- const float ofs,
- float r_origin[3],
- float r_origin_ofs[3]);
+static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
+{
+ float v1[3], v2[3];
+ float planes[4][4];
+
+ planes_from_projmat(
+ (const float(*)[4])kcd->projmat, planes[2], planes[0], planes[3], planes[1], NULL, NULL);
+
+ /* ray-cast all planes */
+ {
+ float ray_dir[3];
+ float ray_hit_best[2][3] = {{UNPACK3(kcd->prev.cage)}, {UNPACK3(kcd->curr.cage)}};
+ float lambda_best[2] = {-FLT_MAX, FLT_MAX};
+ int i;
+
+ /* we (sometimes) need the lines to be at the same depth before projecting */
+#if 0
+ sub_v3_v3v3(ray_dir, kcd->curr.cage, kcd->prev.cage);
+#else
+ {
+ float curr_cage_adjust[3];
+ float co_depth[3];
+
+ copy_v3_v3(co_depth, kcd->prev.cage);
+ mul_m4_v3(kcd->ob->obmat, co_depth);
+ ED_view3d_win_to_3d(kcd->vc.v3d, kcd->region, co_depth, kcd->curr.mval, curr_cage_adjust);
+ mul_m4_v3(kcd->ob->imat, curr_cage_adjust);
+
+ sub_v3_v3v3(ray_dir, curr_cage_adjust, kcd->prev.cage);
+ }
+#endif
+
+ for (i = 0; i < 4; i++) {
+ float ray_hit[3];
+ float lambda_test;
+ if (isect_ray_plane_v3(kcd->prev.cage, ray_dir, planes[i], &lambda_test, false)) {
+ madd_v3_v3v3fl(ray_hit, kcd->prev.cage, ray_dir, lambda_test);
+ if (lambda_test < 0.0f) {
+ if (lambda_test > lambda_best[0]) {
+ copy_v3_v3(ray_hit_best[0], ray_hit);
+ lambda_best[0] = lambda_test;
+ }
+ }
+ else {
+ if (lambda_test < lambda_best[1]) {
+ copy_v3_v3(ray_hit_best[1], ray_hit);
+ lambda_best[1] = lambda_test;
+ }
+ }
+ }
+ }
+
+ copy_v3_v3(v1, ray_hit_best[0]);
+ copy_v3_v3(v2, ray_hit_best[1]);
+ }
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor3(TH_TRANSFORM);
+ GPU_line_width(2.0);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immEnd();
+
+ immUnbindProgram();
+}
+
+/* modal loop selection drawing callback */
+static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *arg)
+{
+ const KnifeTool_OpData *kcd = arg;
+ GPU_depth_test(GPU_DEPTH_NONE);
+
+ GPU_matrix_push_projection();
+ GPU_polygon_offset(1.0f, 1.0f);
+
+ GPU_matrix_push();
+ GPU_matrix_mul(kcd->ob->obmat);
+
+ if (kcd->mode == MODE_DRAGGING && kcd->is_angle_snapping) {
+ knifetool_draw_angle_snapping(kcd);
+ }
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ if (kcd->mode == MODE_DRAGGING) {
+ immUniformColor3ubv(kcd->colors.line);
+ GPU_line_width(2.0);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(pos, kcd->prev.cage);
+ immVertex3fv(pos, kcd->curr.cage);
+ immEnd();
+ }
+
+ if (kcd->prev.vert) {
+ immUniformColor3ubv(kcd->colors.point);
+ GPU_point_size(11 * UI_DPI_FAC);
+
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex3fv(pos, kcd->prev.cage);
+ immEnd();
+ }
+
+ if (kcd->prev.bmface || kcd->prev.edge) {
+ immUniformColor3ubv(kcd->colors.curpoint);
+ GPU_point_size(9 * UI_DPI_FAC);
+
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex3fv(pos, kcd->prev.cage);
+ immEnd();
+ }
+
+ if (kcd->curr.vert) {
+ immUniformColor3ubv(kcd->colors.point);
+ GPU_point_size(11 * UI_DPI_FAC);
+
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex3fv(pos, kcd->curr.cage);
+ immEnd();
+ }
+ else if (kcd->curr.edge) {
+ immUniformColor3ubv(kcd->colors.edge);
+ GPU_line_width(2.0);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(pos, kcd->curr.edge->v1->cageco);
+ immVertex3fv(pos, kcd->curr.edge->v2->cageco);
+ immEnd();
+ }
+
+ if (kcd->curr.bmface || kcd->curr.edge) {
+ immUniformColor3ubv(kcd->colors.curpoint);
+ GPU_point_size(9 * UI_DPI_FAC);
+
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex3fv(pos, kcd->curr.cage);
+ immEnd();
+ }
+
+ if (kcd->totlinehit > 0) {
+ KnifeLineHit *lh;
+ int i, snapped_verts_count, other_verts_count;
+ float fcol[4];
+
+ GPU_blend(GPU_BLEND_ALPHA);
+
+ GPUVertBuf *vert = GPU_vertbuf_create_with_format(format);
+ GPU_vertbuf_data_alloc(vert, kcd->totlinehit);
+
+ lh = kcd->linehits;
+ for (i = 0, snapped_verts_count = 0, other_verts_count = 0; i < kcd->totlinehit; i++, lh++) {
+ if (lh->v) {
+ GPU_vertbuf_attr_set(vert, pos, snapped_verts_count++, lh->cagehit);
+ }
+ else {
+ GPU_vertbuf_attr_set(vert, pos, kcd->totlinehit - 1 - other_verts_count++, lh->cagehit);
+ }
+ }
+
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vert, NULL, GPU_BATCH_OWNS_VBO);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+
+ /* draw any snapped verts first */
+ rgba_uchar_to_float(fcol, kcd->colors.point_a);
+ GPU_batch_uniform_4fv(batch, "color", fcol);
+ GPU_point_size(11 * UI_DPI_FAC);
+ if (snapped_verts_count > 0) {
+ GPU_batch_draw_range(batch, 0, snapped_verts_count);
+ }
+
+ /* now draw the rest */
+ rgba_uchar_to_float(fcol, kcd->colors.curpoint_a);
+ GPU_batch_uniform_4fv(batch, "color", fcol);
+ GPU_point_size(7 * UI_DPI_FAC);
+ if (other_verts_count > 0) {
+ GPU_batch_draw_range(batch, snapped_verts_count, other_verts_count);
+ }
+
+ GPU_batch_discard(batch);
+
+ GPU_blend(GPU_BLEND_NONE);
+ }
+
+ if (kcd->totkedge > 0) {
+ BLI_mempool_iter iter;
+ KnifeEdge *kfe;
+
+ immUniformColor3ubv(kcd->colors.line);
+ GPU_line_width(1.0);
+
+ GPUBatch *batch = immBeginBatchAtMost(GPU_PRIM_LINES, BLI_mempool_len(kcd->kedges) * 2);
+
+ BLI_mempool_iternew(kcd->kedges, &iter);
+ for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
+ if (!kfe->is_cut) {
+ continue;
+ }
+
+ immVertex3fv(pos, kfe->v1->cageco);
+ immVertex3fv(pos, kfe->v2->cageco);
+ }
+
+ immEnd();
+
+ GPU_batch_draw(batch);
+ GPU_batch_discard(batch);
+ }
+
+ if (kcd->totkvert > 0) {
+ BLI_mempool_iter iter;
+ KnifeVert *kfv;
+
+ immUniformColor3ubv(kcd->colors.point);
+ GPU_point_size(5.0 * UI_DPI_FAC);
+
+ GPUBatch *batch = immBeginBatchAtMost(GPU_PRIM_POINTS, BLI_mempool_len(kcd->kverts));
+
+ BLI_mempool_iternew(kcd->kverts, &iter);
+ for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
+ if (!kfv->is_cut) {
+ continue;
+ }
-static bool knife_verts_edge_in_face(KnifeVert *v1, KnifeVert *v2, BMFace *f);
+ immVertex3fv(pos, kfv->cageco);
+ }
-static void knifetool_free_bmbvh(KnifeTool_OpData *kcd);
+ immEnd();
-static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event);
+ GPU_batch_draw(batch);
+ GPU_batch_discard(batch);
+ }
+
+ immUnbindProgram();
+
+ GPU_matrix_pop();
+ GPU_matrix_pop_projection();
+
+ /* Reset default */
+ GPU_depth_test(GPU_DEPTH_LESS_EQUAL);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Header
+ * \{ */
static void knife_update_header(bContext *C, wmOperator *op, KnifeTool_OpData *kcd)
{
@@ -292,7 +541,7 @@ static void knife_update_header(bContext *C, wmOperator *op, KnifeTool_OpData *k
WM_MODALKEY(KNF_MODAL_NEW_CUT),
WM_MODALKEY(KNF_MODAL_MIDPOINT_ON),
WM_bool_as_string(kcd->snap_midpoints),
- WM_MODALKEY(KNF_MODEL_IGNORE_SNAP_ON),
+ WM_MODALKEY(KNF_MODAL_IGNORE_SNAP_ON),
WM_bool_as_string(kcd->ignore_edge_snapping),
WM_MODALKEY(KNF_MODAL_ANGLE_SNAP_TOGGLE),
WM_bool_as_string(kcd->angle_snapping),
@@ -305,51 +554,162 @@ static void knife_update_header(bContext *C, wmOperator *op, KnifeTool_OpData *k
ED_workspace_status_text(C, header);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Geometry Utils
+ * \{ */
+
static void knife_project_v2(const KnifeTool_OpData *kcd, const float co[3], float sco[2])
{
ED_view3d_project_float_v2_m4(kcd->region, co, sco, (float(*)[4])kcd->projmat);
}
-/* use when lambda is in screen-space */
-static void knife_interp_v3_v3v3(const KnifeTool_OpData *kcd,
- float r_co[3],
- const float v1[3],
- const float v2[3],
- float lambda_ss)
+static void knife_input_ray_segment(KnifeTool_OpData *kcd,
+ const float mval[2],
+ const float ofs,
+ float r_origin[3],
+ float r_origin_ofs[3])
{
- if (kcd->is_ortho) {
- interp_v3_v3v3(r_co, v1, v2, lambda_ss);
+ /* unproject to find view ray */
+ ED_view3d_unproject(kcd->vc.region, mval[0], mval[1], 0.0f, r_origin);
+ ED_view3d_unproject(kcd->vc.region, mval[0], mval[1], ofs, r_origin_ofs);
+
+ /* transform into object space */
+ invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
+
+ mul_m4_v3(kcd->ob->imat, r_origin);
+ mul_m4_v3(kcd->ob->imat, r_origin_ofs);
+}
+
+static bool knife_verts_edge_in_face(KnifeVert *v1, KnifeVert *v2, BMFace *f)
+{
+ bool v1_inside, v2_inside;
+ bool v1_inface, v2_inface;
+ BMLoop *l1, *l2;
+
+ if (!f || !v1 || !v2) {
+ return false;
}
- else {
- /* transform into screen-space, interp, then transform back */
- float v1_ss[3], v2_ss[3];
- mul_v3_project_m4_v3(v1_ss, (float(*)[4])kcd->projmat, v1);
- mul_v3_project_m4_v3(v2_ss, (float(*)[4])kcd->projmat, v2);
+ l1 = v1->v ? BM_face_vert_share_loop(f, v1->v) : NULL;
+ l2 = v2->v ? BM_face_vert_share_loop(f, v2->v) : NULL;
- interp_v3_v3v3(r_co, v1_ss, v2_ss, lambda_ss);
+ if ((l1 && l2) && BM_loop_is_adjacent(l1, l2)) {
+ /* boundary-case, always false to avoid edge-in-face checks below */
+ return false;
+ }
- mul_project_m4_v3((float(*)[4])kcd->projmat_inv, r_co);
+ /* find out if v1 and v2, if set, are part of the face */
+ v1_inface = (l1 != NULL);
+ v2_inface = (l2 != NULL);
+
+ /* BM_face_point_inside_test uses best-axis projection so this isn't most accurate test... */
+ v1_inside = v1_inface ? false : BM_face_point_inside_test(f, v1->co);
+ v2_inside = v2_inface ? false : BM_face_point_inside_test(f, v2->co);
+ if ((v1_inface && v2_inside) || (v2_inface && v1_inside) || (v1_inside && v2_inside)) {
+ return true;
+ }
+
+ if (v1_inface && v2_inface) {
+ float mid[3];
+ /* Can have case where v1 and v2 are on shared chain between two faces.
+ * BM_face_splits_check_legal does visibility and self-intersection tests,
+ * but it is expensive and maybe a bit buggy, so use a simple
+ * "is the midpoint in the face" test */
+ mid_v3_v3v3(mid, v1->co, v2->co);
+ return BM_face_point_inside_test(f, mid);
}
+ return false;
}
-static void knife_pos_data_clear(KnifePosData *kpd)
+static void knife_recalc_projmat(KnifeTool_OpData *kcd)
{
- zero_v3(kpd->co);
- zero_v3(kpd->cage);
- kpd->vert = NULL;
- kpd->edge = NULL;
- kpd->bmface = NULL;
- zero_v2(kpd->mval);
+ invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
+ ED_view3d_ob_project_mat_get(kcd->region->regiondata, kcd->ob, kcd->projmat);
+ invert_m4_m4(kcd->projmat_inv, kcd->projmat);
+
+ mul_v3_mat3_m4v3(kcd->proj_zaxis, kcd->ob->imat, kcd->vc.rv3d->viewinv[2]);
+ normalize_v3(kcd->proj_zaxis);
+
+ kcd->is_ortho = ED_view3d_clip_range_get(
+ kcd->vc.depsgraph, kcd->vc.v3d, kcd->vc.rv3d, &kcd->clipsta, &kcd->clipend, true);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Knife Element Utils
+ *
+ * Currently only used in #knife_find_line_hits.
+ * \{ */
+
+static BMElem *bm_elem_from_knife_vert(KnifeVert *kfv, KnifeEdge **r_kfe)
+{
+ BMElem *ele_test;
+ KnifeEdge *kfe = NULL;
+
+ /* vert? */
+ ele_test = (BMElem *)kfv->v;
+
+ if (r_kfe || ele_test == NULL) {
+ if (kfv->v == NULL) {
+ Ref *ref;
+ for (ref = kfv->edges.first; ref; ref = ref->next) {
+ kfe = ref->ref;
+ if (kfe->e) {
+ if (r_kfe) {
+ *r_kfe = kfe;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ /* edge? */
+ if (ele_test == NULL) {
+ if (kfe) {
+ ele_test = (BMElem *)kfe->e;
+ }
+ }
+
+ /* face? */
+ if (ele_test == NULL) {
+ if (BLI_listbase_is_single(&kfe->faces)) {
+ ele_test = ((Ref *)kfe->faces.first)->ref;
+ }
+ }
+
+ return ele_test;
}
+static BMElem *bm_elem_from_knife_edge(KnifeEdge *kfe)
+{
+ BMElem *ele_test;
+
+ ele_test = (BMElem *)kfe->e;
+
+ if (ele_test == NULL) {
+ ele_test = (BMElem *)kfe->basef;
+ }
+
+ return ele_test;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Knife Element List Utils
+ * \{ */
+
static ListBase *knife_empty_list(KnifeTool_OpData *kcd)
{
- ListBase *lst;
+ ListBase *list;
- lst = BLI_memarena_alloc(kcd->arena, sizeof(ListBase));
- BLI_listbase_clear(lst);
- return lst;
+ list = BLI_memarena_alloc(kcd->arena, sizeof(ListBase));
+ BLI_listbase_clear(list);
+ return list;
}
static void knife_append_list(KnifeTool_OpData *kcd, ListBase *lst, void *elem)
@@ -381,12 +741,6 @@ static void knife_append_list_no_dup(KnifeTool_OpData *kcd, ListBase *lst, void
}
}
-static KnifeEdge *new_knife_edge(KnifeTool_OpData *kcd)
-{
- kcd->totkedge++;
- return BLI_mempool_calloc(kcd->kedges);
-}
-
static void knife_add_to_vert_edges(KnifeTool_OpData *kcd, KnifeEdge *kfe)
{
knife_append_list(kcd, &kfe->v1->edges, kfe);
@@ -420,6 +774,12 @@ static BMFace *knife_find_common_face(ListBase *faces1, ListBase *faces2)
return NULL;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Knife Element Creation
+ * \{ */
+
static KnifeVert *new_knife_vert(KnifeTool_OpData *kcd, const float co[3], const float cageco[3])
{
KnifeVert *kfv = BLI_mempool_calloc(kcd->kverts);
@@ -432,6 +792,12 @@ static KnifeVert *new_knife_vert(KnifeTool_OpData *kcd, const float co[3], const
return kfv;
}
+static KnifeEdge *new_knife_edge(KnifeTool_OpData *kcd)
+{
+ kcd->totkedge++;
+ return BLI_mempool_calloc(kcd->kedges);
+}
+
/* get a KnifeVert wrapper for an existing BMVert */
static KnifeVert *get_bm_knife_vert(KnifeTool_OpData *kcd, BMVert *v)
{
@@ -484,92 +850,24 @@ static KnifeEdge *get_bm_knife_edge(KnifeTool_OpData *kcd, BMEdge *e)
return kfe;
}
-/* Record the index in kcd->em->looptris of first looptri triple for a given face,
- * given an index for some triple in that array.
- * This assumes that all of the triangles for a given face are contiguous
- * in that array (as they are by the current tessellation routines).
- * Actually store index + 1 in the hash, because 0 looks like "no entry"
- * to hash lookup routine; will reverse this in the get routine.
- * Doing this lazily rather than all at once for all faces.
- */
-static void set_lowest_face_tri(KnifeTool_OpData *kcd, BMFace *f, int index)
-{
- int i;
-
- if (BLI_ghash_lookup(kcd->facetrimap, f)) {
- return;
- }
-
- BLI_assert(index >= 0 && index < kcd->em->tottri);
- BLI_assert(kcd->em->looptris[index][0]->f == f);
- for (i = index - 1; i >= 0; i--) {
- if (kcd->em->looptris[i][0]->f != f) {
- i++;
- break;
- }
- }
- if (i == -1) {
- i++;
- }
-
- BLI_ghash_insert(kcd->facetrimap, f, POINTER_FROM_INT(i + 1));
-}
-
-/* This should only be called for faces that have had a lowest face tri set by previous function */
-static int get_lowest_face_tri(KnifeTool_OpData *kcd, BMFace *f)
-{
- int ans;
-
- ans = POINTER_AS_INT(BLI_ghash_lookup(kcd->facetrimap, f));
- BLI_assert(ans != 0);
- return ans - 1;
-}
-
-/* User has just clicked for first time or first time after a restart (E key).
- * Copy the current position data into prev. */
-static void knife_start_cut(KnifeTool_OpData *kcd)
-{
- kcd->prev = kcd->curr;
- kcd->curr.is_space = 0; /*TODO: why do we do this? */
-
- if (kcd->prev.vert == NULL && kcd->prev.edge == NULL) {
- float origin[3], origin_ofs[3];
- float ofs_local[3];
-
- negate_v3_v3(ofs_local, kcd->vc.rv3d->ofs);
- invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
- mul_m4_v3(kcd->ob->imat, ofs_local);
-
- knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
-
- if (!isect_line_plane_v3(kcd->prev.cage, origin, origin_ofs, ofs_local, kcd->proj_zaxis)) {
- zero_v3(kcd->prev.cage);
- }
-
- copy_v3_v3(kcd->prev.co, kcd->prev.cage); /*TODO: do we need this? */
- copy_v3_v3(kcd->curr.cage, kcd->prev.cage);
- copy_v3_v3(kcd->curr.co, kcd->prev.co);
- }
-}
-
static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f)
{
- ListBase *lst = BLI_ghash_lookup(kcd->kedgefacemap, f);
+ ListBase *list = BLI_ghash_lookup(kcd->kedgefacemap, f);
- if (!lst) {
+ if (!list) {
BMIter bmiter;
BMEdge *e;
- lst = knife_empty_list(kcd);
+ list = knife_empty_list(kcd);
BM_ITER_ELEM (e, &bmiter, f, BM_EDGES_OF_FACE) {
- knife_append_list(kcd, lst, get_bm_knife_edge(kcd, e));
+ knife_append_list(kcd, list, get_bm_knife_edge(kcd, e));
}
- BLI_ghash_insert(kcd->kedgefacemap, f, lst);
+ BLI_ghash_insert(kcd->kedgefacemap, f, list);
}
- return lst;
+ return list;
}
static void knife_edge_append_face(KnifeTool_OpData *kcd, KnifeEdge *kfe, BMFace *f)
@@ -625,6 +923,39 @@ static KnifeVert *knife_split_edge(KnifeTool_OpData *kcd,
return newkfe->v2;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Cut/Hit Utils
+ * \{ */
+
+/* User has just clicked for first time or first time after a restart (E key).
+ * Copy the current position data into prev. */
+static void knife_start_cut(KnifeTool_OpData *kcd)
+{
+ kcd->prev = kcd->curr;
+ kcd->curr.is_space = 0; /*TODO: why do we do this? */
+
+ if (kcd->prev.vert == NULL && kcd->prev.edge == NULL) {
+ float origin[3], origin_ofs[3];
+ float ofs_local[3];
+
+ negate_v3_v3(ofs_local, kcd->vc.rv3d->ofs);
+ invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
+ mul_m4_v3(kcd->ob->imat, ofs_local);
+
+ knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
+
+ if (!isect_line_plane_v3(kcd->prev.cage, origin, origin_ofs, ofs_local, kcd->proj_zaxis)) {
+ zero_v3(kcd->prev.cage);
+ }
+
+ copy_v3_v3(kcd->prev.co, kcd->prev.cage); /*TODO: do we need this? */
+ copy_v3_v3(kcd->curr.cage, kcd->prev.cage);
+ copy_v3_v3(kcd->curr.co, kcd->prev.co);
+ }
+}
+
static void linehit_to_knifepos(KnifePosData *kpos, KnifeLineHit *lh)
{
kpos->bmface = lh->f;
@@ -750,13 +1081,13 @@ static void add_hit_to_facehits(KnifeTool_OpData *kcd,
BMFace *f,
KnifeLineHit *hit)
{
- ListBase *lst = BLI_ghash_lookup(facehits, f);
+ ListBase *list = BLI_ghash_lookup(facehits, f);
- if (!lst) {
- lst = knife_empty_list(kcd);
- BLI_ghash_insert(facehits, f, lst);
+ if (!list) {
+ list = knife_empty_list(kcd);
+ BLI_ghash_insert(facehits, f, list);
}
- knife_append_list_no_dup(kcd, lst, hit);
+ knife_append_list_no_dup(kcd, list, hit);
}
/**
@@ -879,6 +1210,228 @@ static void knife_cut_face(KnifeTool_OpData *kcd, BMFace *f, ListBase *hits)
}
}
+static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfedges)
+{
+ BMesh *bm = kcd->em->bm;
+ KnifeEdge *kfe;
+ Ref *ref;
+ int edge_array_len = BLI_listbase_count(kfedges);
+ int i;
+
+ BMEdge **edge_array = BLI_array_alloca(edge_array, edge_array_len);
+
+ /* point to knife edges we've created edges in, edge_array aligned */
+ KnifeEdge **kfe_array = BLI_array_alloca(kfe_array, edge_array_len);
+
+ BLI_assert(BLI_gset_len(kcd->edgenet.edge_visit) == 0);
+
+ i = 0;
+ for (ref = kfedges->first; ref; ref = ref->next) {
+ bool is_new_edge = false;
+ kfe = ref->ref;
+
+ if (kfe->e == NULL) {
+ if (kfe->v1->v && kfe->v2->v) {
+ kfe->e = BM_edge_exists(kfe->v1->v, kfe->v2->v);
+ }
+ }
+
+ if (kfe->e) {
+ if (BM_edge_in_face(kfe->e, f)) {
+ /* shouldn't happen, but in this case - just ignore */
+ continue;
+ }
+ }
+ else {
+ if (kfe->v1->v == NULL) {
+ kfe->v1->v = BM_vert_create(bm, kfe->v1->co, NULL, 0);
+ }
+ if (kfe->v2->v == NULL) {
+ kfe->v2->v = BM_vert_create(bm, kfe->v2->co, NULL, 0);
+ }
+ BLI_assert(kfe->e == NULL);
+ kfe->e = BM_edge_create(bm, kfe->v1->v, kfe->v2->v, NULL, 0);
+ if (kfe->e) {
+ if (kcd->select_result || BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_edge_select_set(bm, kfe->e, true);
+ }
+ is_new_edge = true;
+ }
+ }
+
+ BLI_assert(kfe->e);
+
+ if (BLI_gset_add(kcd->edgenet.edge_visit, kfe->e)) {
+ kfe_array[i] = is_new_edge ? kfe : 0;
+ edge_array[i] = kfe->e;
+ i += 1;
+ }
+ }
+
+ if (i) {
+ const int edge_array_len_orig = i;
+ edge_array_len = i;
+
+#ifdef USE_NET_ISLAND_CONNECT
+ uint edge_array_holes_len;
+ BMEdge **edge_array_holes;
+ if (BM_face_split_edgenet_connect_islands(bm,
+ f,
+ edge_array,
+ edge_array_len,
+ true,
+ kcd->edgenet.arena,
+ &edge_array_holes,
+ &edge_array_holes_len)) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ for (i = edge_array_len; i < edge_array_holes_len; i++) {
+ BM_edge_select_set(bm, edge_array_holes[i], true);
+ }
+ }
+
+ edge_array_len = edge_array_holes_len;
+ edge_array = edge_array_holes; /* owned by the arena */
+ }
+#endif
+
+ {
+ BMFace **face_arr = NULL;
+ int face_arr_len;
+
+ BM_face_split_edgenet(bm, f, edge_array, edge_array_len, &face_arr, &face_arr_len);
+
+ if (face_arr) {
+ MEM_freeN(face_arr);
+ }
+ }
+
+ /* remove dangling edges, not essential - but nice for users */
+ for (i = 0; i < edge_array_len_orig; i++) {
+ if (kfe_array[i]) {
+ if (BM_edge_is_wire(kfe_array[i]->e)) {
+ BM_edge_kill(bm, kfe_array[i]->e);
+ kfe_array[i]->e = NULL;
+ }
+ }
+ }
+
+#ifdef USE_NET_ISLAND_CONNECT
+ BLI_memarena_clear(kcd->edgenet.arena);
+#endif
+ }
+
+ BLI_gset_clear(kcd->edgenet.edge_visit, NULL);
+}
+
+static int sort_verts_by_dist_cb(void *co_p, const void *cur_a_p, const void *cur_b_p)
+{
+ const KnifeVert *cur_a = ((const Ref *)cur_a_p)->ref;
+ const KnifeVert *cur_b = ((const Ref *)cur_b_p)->ref;
+ const float *co = co_p;
+ const float a_sq = len_squared_v3v3(co, cur_a->co);
+ const float b_sq = len_squared_v3v3(co, cur_b->co);
+
+ if (a_sq < b_sq) {
+ return -1;
+ }
+ if (a_sq > b_sq) {
+ return 1;
+ }
+ return 0;
+}
+
+/* Use the network of KnifeEdges and KnifeVerts accumulated to make real BMVerts and BMEdedges */
+static void knife_make_cuts(KnifeTool_OpData *kcd)
+{
+ BMesh *bm = kcd->em->bm;
+ KnifeEdge *kfe;
+ KnifeVert *kfv;
+ BMFace *f;
+ BMEdge *e, *enew;
+ ListBase *list;
+ Ref *ref;
+ float pct;
+ SmallHashIter hiter;
+ BLI_mempool_iter iter;
+ SmallHash fhash_, *fhash = &fhash_;
+ SmallHash ehash_, *ehash = &ehash_;
+
+ BLI_smallhash_init(fhash);
+ BLI_smallhash_init(ehash);
+
+ /* put list of cutting edges for a face into fhash, keyed by face */
+ BLI_mempool_iternew(kcd->kedges, &iter);
+ for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
+
+ /* select edges that lie directly on the cut */
+ if (kcd->select_result) {
+ if (kfe->e && kfe->is_cut) {
+ BM_edge_select_set(bm, kfe->e, true);
+ }
+ }
+
+ f = kfe->basef;
+ if (!f || kfe->e) {
+ continue;
+ }
+ list = BLI_smallhash_lookup(fhash, (uintptr_t)f);
+ if (!list) {
+ list = knife_empty_list(kcd);
+ BLI_smallhash_insert(fhash, (uintptr_t)f, list);
+ }
+ knife_append_list(kcd, list, kfe);
+ }
+
+ /* put list of splitting vertices for an edge into ehash, keyed by edge */
+ BLI_mempool_iternew(kcd->kverts, &iter);
+ for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
+ if (kfv->v) {
+ continue; /* already have a BMVert */
+ }
+ for (ref = kfv->edges.first; ref; ref = ref->next) {
+ kfe = ref->ref;
+ e = kfe->e;
+ if (!e) {
+ continue;
+ }
+ list = BLI_smallhash_lookup(ehash, (uintptr_t)e);
+ if (!list) {
+ list = knife_empty_list(kcd);
+ BLI_smallhash_insert(ehash, (uintptr_t)e, list);
+ }
+ /* there can be more than one kfe in kfv's list with same e */
+ if (!find_ref(list, kfv)) {
+ knife_append_list(kcd, list, kfv);
+ }
+ }
+ }
+
+ /* split bmesh edges where needed */
+ for (list = BLI_smallhash_iternew(ehash, &hiter, (uintptr_t *)&e); list;
+ list = BLI_smallhash_iternext(&hiter, (uintptr_t *)&e)) {
+ BLI_listbase_sort_r(list, sort_verts_by_dist_cb, e->v1->co);
+
+ for (ref = list->first; ref; ref = ref->next) {
+ kfv = ref->ref;
+ pct = line_point_factor_v3(kfv->co, e->v1->co, e->v2->co);
+ kfv->v = BM_edge_split(bm, e, e->v1, &enew, pct);
+ }
+ }
+
+ if (kcd->only_select) {
+ EDBM_flag_disable_all(kcd->em, BM_ELEM_SELECT);
+ }
+
+ /* do cuts for each face */
+ for (list = BLI_smallhash_iternew(fhash, &hiter, (uintptr_t *)&f); list;
+ list = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f)) {
+ knife_make_face_cuts(kcd, f, list);
+ }
+
+ BLI_smallhash_release(fhash);
+ BLI_smallhash_release(ehash);
+}
+
/* User has just left-clicked after the first time.
* Add all knife cuts implied by line from prev to curr.
* If that line crossed edges then kcd->linehits will be non-NULL.
@@ -891,7 +1444,7 @@ static void knife_add_cut(KnifeTool_OpData *kcd)
BMFace *f;
Ref *r;
GHashIterator giter;
- ListBase *lst;
+ ListBase *list;
prepare_linehits_for_cut(kcd);
if (kcd->totlinehit == 0) {
@@ -926,8 +1479,8 @@ static void knife_add_cut(KnifeTool_OpData *kcd)
* the v and the kfe or f fields will be non-NULL. */
GHASH_ITER (giter, facehits) {
f = (BMFace *)BLI_ghashIterator_getKey(&giter);
- lst = (ListBase *)BLI_ghashIterator_getValue(&giter);
- knife_cut_face(kcd, f, lst);
+ list = (ListBase *)BLI_ghashIterator_getValue(&giter);
+ knife_cut_face(kcd, f, list);
}
/* set up for next cut */
@@ -960,267 +1513,51 @@ static void knife_finish_cut(KnifeTool_OpData *kcd)
}
}
-static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
-{
- float v1[3], v2[3];
- float planes[4][4];
-
- planes_from_projmat(
- (const float(*)[4])kcd->projmat, planes[2], planes[0], planes[3], planes[1], NULL, NULL);
-
- /* ray-cast all planes */
- {
- float ray_dir[3];
- float ray_hit_best[2][3] = {{UNPACK3(kcd->prev.cage)}, {UNPACK3(kcd->curr.cage)}};
- float lambda_best[2] = {-FLT_MAX, FLT_MAX};
- int i;
-
- /* we (sometimes) need the lines to be at the same depth before projecting */
-#if 0
- sub_v3_v3v3(ray_dir, kcd->curr.cage, kcd->prev.cage);
-#else
- {
- float curr_cage_adjust[3];
- float co_depth[3];
-
- copy_v3_v3(co_depth, kcd->prev.cage);
- mul_m4_v3(kcd->ob->obmat, co_depth);
- ED_view3d_win_to_3d(kcd->vc.v3d, kcd->region, co_depth, kcd->curr.mval, curr_cage_adjust);
- mul_m4_v3(kcd->ob->imat, curr_cage_adjust);
-
- sub_v3_v3v3(ray_dir, curr_cage_adjust, kcd->prev.cage);
- }
-#endif
-
- for (i = 0; i < 4; i++) {
- float ray_hit[3];
- float lambda_test;
- if (isect_ray_plane_v3(kcd->prev.cage, ray_dir, planes[i], &lambda_test, false)) {
- madd_v3_v3v3fl(ray_hit, kcd->prev.cage, ray_dir, lambda_test);
- if (lambda_test < 0.0f) {
- if (lambda_test > lambda_best[0]) {
- copy_v3_v3(ray_hit_best[0], ray_hit);
- lambda_best[0] = lambda_test;
- }
- }
- else {
- if (lambda_test < lambda_best[1]) {
- copy_v3_v3(ray_hit_best[1], ray_hit);
- lambda_best[1] = lambda_test;
- }
- }
- }
- }
-
- copy_v3_v3(v1, ray_hit_best[0]);
- copy_v3_v3(v2, ray_hit_best[1]);
- }
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+/** \} */
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformThemeColor3(TH_TRANSFORM);
- GPU_line_width(2.0);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(pos, v1);
- immVertex3fv(pos, v2);
- immEnd();
-
- immUnbindProgram();
-}
-
-static void knife_init_colors(KnifeColors *colors)
-{
- /* possible BMESH_TODO: add explicit themes or calculate these by
- * figuring out contrasting colors with grid / edges / verts
- * a la UI_make_axis_color */
- UI_GetThemeColorType3ubv(TH_NURB_VLINE, SPACE_VIEW3D, colors->line);
- UI_GetThemeColorType3ubv(TH_NURB_ULINE, SPACE_VIEW3D, colors->edge);
- UI_GetThemeColorType3ubv(TH_HANDLE_SEL_VECT, SPACE_VIEW3D, colors->curpoint);
- UI_GetThemeColorType3ubv(TH_HANDLE_SEL_VECT, SPACE_VIEW3D, colors->curpoint_a);
- colors->curpoint_a[3] = 102;
- UI_GetThemeColorType3ubv(TH_ACTIVE_SPLINE, SPACE_VIEW3D, colors->point);
- UI_GetThemeColorType3ubv(TH_ACTIVE_SPLINE, SPACE_VIEW3D, colors->point_a);
- colors->point_a[3] = 102;
-}
+/* -------------------------------------------------------------------- */
+/** \name Screen Line Hits (#knife_find_line_hits)
+ * \{ */
-/* modal loop selection drawing callback */
-static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *arg)
+/* Record the index in kcd->em->looptris of first looptri triple for a given face,
+ * given an index for some triple in that array.
+ * This assumes that all of the triangles for a given face are contiguous
+ * in that array (as they are by the current tessellation routines).
+ * Actually store index + 1 in the hash, because 0 looks like "no entry"
+ * to hash lookup routine; will reverse this in the get routine.
+ * Doing this lazily rather than all at once for all faces.
+ */
+static void set_lowest_face_tri(KnifeTool_OpData *kcd, BMFace *f, int index)
{
- const KnifeTool_OpData *kcd = arg;
- GPU_depth_test(GPU_DEPTH_NONE);
-
- GPU_matrix_push_projection();
- GPU_polygon_offset(1.0f, 1.0f);
-
- GPU_matrix_push();
- GPU_matrix_mul(kcd->ob->obmat);
-
- if (kcd->mode == MODE_DRAGGING && kcd->is_angle_snapping) {
- knifetool_draw_angle_snapping(kcd);
- }
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
-
- if (kcd->mode == MODE_DRAGGING) {
- immUniformColor3ubv(kcd->colors.line);
- GPU_line_width(2.0);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(pos, kcd->prev.cage);
- immVertex3fv(pos, kcd->curr.cage);
- immEnd();
- }
-
- if (kcd->prev.vert) {
- immUniformColor3ubv(kcd->colors.point);
- GPU_point_size(11);
-
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex3fv(pos, kcd->prev.cage);
- immEnd();
- }
-
- if (kcd->prev.bmface) {
- immUniformColor3ubv(kcd->colors.curpoint);
- GPU_point_size(9);
-
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex3fv(pos, kcd->prev.cage);
- immEnd();
- }
-
- if (kcd->curr.edge) {
- immUniformColor3ubv(kcd->colors.edge);
- GPU_line_width(2.0);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(pos, kcd->curr.edge->v1->cageco);
- immVertex3fv(pos, kcd->curr.edge->v2->cageco);
- immEnd();
- }
- else if (kcd->curr.vert) {
- immUniformColor3ubv(kcd->colors.point);
- GPU_point_size(11);
-
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex3fv(pos, kcd->curr.cage);
- immEnd();
- }
-
- if (kcd->curr.bmface) {
- immUniformColor3ubv(kcd->colors.curpoint);
- GPU_point_size(9);
-
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex3fv(pos, kcd->curr.cage);
- immEnd();
- }
-
- if (kcd->totlinehit > 0) {
- KnifeLineHit *lh;
- int i, snapped_verts_count, other_verts_count;
- float fcol[4];
-
- GPU_blend(GPU_BLEND_ALPHA);
-
- GPUVertBuf *vert = GPU_vertbuf_create_with_format(format);
- GPU_vertbuf_data_alloc(vert, kcd->totlinehit);
-
- lh = kcd->linehits;
- for (i = 0, snapped_verts_count = 0, other_verts_count = 0; i < kcd->totlinehit; i++, lh++) {
- if (lh->v) {
- GPU_vertbuf_attr_set(vert, pos, snapped_verts_count++, lh->cagehit);
- }
- else {
- GPU_vertbuf_attr_set(vert, pos, kcd->totlinehit - 1 - other_verts_count++, lh->cagehit);
- }
- }
-
- GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vert, NULL, GPU_BATCH_OWNS_VBO);
- GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
-
- /* draw any snapped verts first */
- rgba_uchar_to_float(fcol, kcd->colors.point_a);
- GPU_batch_uniform_4fv(batch, "color", fcol);
- GPU_point_size(11);
- if (snapped_verts_count > 0) {
- GPU_batch_draw_range(batch, 0, snapped_verts_count);
- }
-
- /* now draw the rest */
- rgba_uchar_to_float(fcol, kcd->colors.curpoint_a);
- GPU_batch_uniform_4fv(batch, "color", fcol);
- GPU_point_size(7);
- if (other_verts_count > 0) {
- GPU_batch_draw_range(batch, snapped_verts_count, other_verts_count);
- }
-
- GPU_batch_discard(batch);
+ int i;
- GPU_blend(GPU_BLEND_NONE);
+ if (BLI_ghash_lookup(kcd->facetrimap, f)) {
+ return;
}
- if (kcd->totkedge > 0) {
- BLI_mempool_iter iter;
- KnifeEdge *kfe;
-
- immUniformColor3ubv(kcd->colors.line);
- GPU_line_width(1.0);
-
- GPUBatch *batch = immBeginBatchAtMost(GPU_PRIM_LINES, BLI_mempool_len(kcd->kedges) * 2);
-
- BLI_mempool_iternew(kcd->kedges, &iter);
- for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
- if (!kfe->is_cut) {
- continue;
- }
-
- immVertex3fv(pos, kfe->v1->cageco);
- immVertex3fv(pos, kfe->v2->cageco);
+ BLI_assert(index >= 0 && index < kcd->em->tottri);
+ BLI_assert(kcd->em->looptris[index][0]->f == f);
+ for (i = index - 1; i >= 0; i--) {
+ if (kcd->em->looptris[i][0]->f != f) {
+ i++;
+ break;
}
-
- immEnd();
-
- GPU_batch_draw(batch);
- GPU_batch_discard(batch);
}
-
- if (kcd->totkvert > 0) {
- BLI_mempool_iter iter;
- KnifeVert *kfv;
-
- immUniformColor3ubv(kcd->colors.point);
- GPU_point_size(5.0);
-
- GPUBatch *batch = immBeginBatchAtMost(GPU_PRIM_POINTS, BLI_mempool_len(kcd->kverts));
-
- BLI_mempool_iternew(kcd->kverts, &iter);
- for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
- if (!kfv->is_cut) {
- continue;
- }
-
- immVertex3fv(pos, kfv->cageco);
- }
-
- immEnd();
-
- GPU_batch_draw(batch);
- GPU_batch_discard(batch);
+ if (i == -1) {
+ i++;
}
- immUnbindProgram();
+ BLI_ghash_insert(kcd->facetrimap, f, POINTER_FROM_INT(i + 1));
+}
- GPU_matrix_pop();
- GPU_matrix_pop_projection();
+/* This should only be called for faces that have had a lowest face tri set by previous function */
+static int get_lowest_face_tri(KnifeTool_OpData *kcd, BMFace *f)
+{
+ int ans;
- /* Reset default */
- GPU_depth_test(GPU_DEPTH_LESS_EQUAL);
+ ans = POINTER_AS_INT(BLI_ghash_lookup(kcd->facetrimap, f));
+ BLI_assert(ans != 0);
+ return ans - 1;
}
/**
@@ -1246,7 +1583,7 @@ static bool knife_ray_intersect_face(KnifeTool_OpData *kcd,
float se1[2], se2[2];
float d, lambda;
BMLoop **tri;
- ListBase *lst;
+ ListBase *list;
Ref *ref;
KnifeEdge *kfe;
@@ -1281,8 +1618,8 @@ static bool knife_ray_intersect_face(KnifeTool_OpData *kcd,
}
interp_v3_v3v3v3_uv(hit_cageco, lv1, lv2, lv3, ray_tri_uv);
/* Now check that far enough away from verts and edges */
- lst = knife_get_face_kedges(kcd, f);
- for (ref = lst->first; ref; ref = ref->next) {
+ list = knife_get_face_kedges(kcd, f);
+ for (ref = list->first; ref; ref = ref->next) {
kfe = ref->ref;
knife_project_v2(kcd, kfe->v1->cageco, se1);
knife_project_v2(kcd, kfe->v2->cageco, se2);
@@ -1323,59 +1660,6 @@ static void calc_ortho_extent(KnifeTool_OpData *kcd)
mid_v3_v3v3(kcd->ortho_extent_center, min, max);
}
-static BMElem *bm_elem_from_knife_vert(KnifeVert *kfv, KnifeEdge **r_kfe)
-{
- BMElem *ele_test;
- KnifeEdge *kfe = NULL;
-
- /* vert? */
- ele_test = (BMElem *)kfv->v;
-
- if (r_kfe || ele_test == NULL) {
- if (kfv->v == NULL) {
- Ref *ref;
- for (ref = kfv->edges.first; ref; ref = ref->next) {
- kfe = ref->ref;
- if (kfe->e) {
- if (r_kfe) {
- *r_kfe = kfe;
- }
- break;
- }
- }
- }
- }
-
- /* edge? */
- if (ele_test == NULL) {
- if (kfe) {
- ele_test = (BMElem *)kfe->e;
- }
- }
-
- /* face? */
- if (ele_test == NULL) {
- if (BLI_listbase_is_single(&kfe->faces)) {
- ele_test = ((Ref *)kfe->faces.first)->ref;
- }
- }
-
- return ele_test;
-}
-
-static BMElem *bm_elem_from_knife_edge(KnifeEdge *kfe)
-{
- BMElem *ele_test;
-
- ele_test = (BMElem *)kfe->e;
-
- if (ele_test == NULL) {
- ele_test = (BMElem *)kfe->basef;
- }
-
- return ele_test;
-}
-
/* Do edges e1 and e2 go between exactly the same coordinates? */
static bool coinciding_edges(BMEdge *e1, BMEdge *e2)
{
@@ -1546,7 +1830,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
BMFace *f;
KnifeEdge *kfe;
KnifeVert *v;
- ListBase *lst;
+ ListBase *list;
Ref *ref;
KnifeLineHit *linehits = NULL;
BLI_array_declare(linehits);
@@ -1650,8 +1934,8 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
/* don't care what the value is except that it is non-NULL, for iterator */
BLI_smallhash_insert(&faces, (uintptr_t)f, f);
- lst = knife_get_face_kedges(kcd, f);
- for (ref = lst->first; ref; ref = ref->next) {
+ list = knife_get_face_kedges(kcd, f);
+ for (ref = list->first; ref; ref = ref->next) {
kfe = ref->ref;
if (BLI_smallhash_haskey(&kfes, (uintptr_t)kfe)) {
continue;
@@ -1858,23 +2142,28 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
}
}
-static void knife_input_ray_segment(KnifeTool_OpData *kcd,
- const float mval[2],
- const float ofs,
- float r_origin[3],
- float r_origin_ofs[3])
-{
- /* unproject to find view ray */
- ED_view3d_unproject(kcd->vc.region, mval[0], mval[1], 0.0f, r_origin);
- ED_view3d_unproject(kcd->vc.region, mval[0], mval[1], ofs, r_origin_ofs);
+/** \} */
- /* transform into object space */
- invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
+/* -------------------------------------------------------------------- */
+/** \name KnifePosData Utils
+ * \{ */
- mul_m4_v3(kcd->ob->imat, r_origin);
- mul_m4_v3(kcd->ob->imat, r_origin_ofs);
+static void knife_pos_data_clear(KnifePosData *kpd)
+{
+ zero_v3(kpd->co);
+ zero_v3(kpd->cage);
+ kpd->vert = NULL;
+ kpd->edge = NULL;
+ kpd->bmface = NULL;
+ zero_v2(kpd->mval);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Snapping (#knife_snap_update_from_mval)
+ * \{ */
+
static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd,
float co[3],
float cageco[3],
@@ -1917,6 +2206,8 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd,
* of a true coordinate on the face.
* This just puts a point 1.0f in front of the view. */
add_v3_v3v3(co, origin, ray);
+ /* Use this value for the cage location too as it's used to find near edges/vertices. */
+ copy_v3_v3(cageco, co);
}
}
@@ -1926,64 +2217,119 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd,
/**
* Find the 2d screen space density of vertices within a radius.
* Used to scale snapping distance for picking edges/verts.
+ *
+ * Arguments `f` and `cageco` should be the result of a call to #knife_find_closest_face.
*/
-static int knife_sample_screen_density(KnifeTool_OpData *kcd, const float radius)
+static int knife_sample_screen_density_from_closest_face(KnifeTool_OpData *kcd,
+ const float radius,
+ BMFace *f,
+ const float cageco[3])
{
- BMFace *f;
- bool is_space;
- float co[3], cageco[3], sco[2];
-
- BLI_assert(kcd->is_interactive == true);
-
- f = knife_find_closest_face(kcd, co, cageco, &is_space);
-
- if (f && !is_space) {
- const float radius_sq = radius * radius;
- ListBase *lst;
- Ref *ref;
- float dis_sq;
- int c = 0;
+ const float radius_sq = radius * radius;
+ ListBase *list;
+ Ref *ref;
+ float sco[2];
+ float dis_sq;
+ int c = 0;
- knife_project_v2(kcd, cageco, sco);
+ knife_project_v2(kcd, cageco, sco);
- lst = knife_get_face_kedges(kcd, f);
- for (ref = lst->first; ref; ref = ref->next) {
- KnifeEdge *kfe = ref->ref;
- int i;
+ list = knife_get_face_kedges(kcd, f);
+ for (ref = list->first; ref; ref = ref->next) {
+ KnifeEdge *kfe = ref->ref;
+ int i;
- for (i = 0; i < 2; i++) {
- KnifeVert *kfv = i ? kfe->v2 : kfe->v1;
- float kfv_sco[2];
+ for (i = 0; i < 2; i++) {
+ KnifeVert *kfv = i ? kfe->v2 : kfe->v1;
+ float kfv_sco[2];
- knife_project_v2(kcd, kfv->cageco, kfv_sco);
+ knife_project_v2(kcd, kfv->cageco, kfv_sco);
- dis_sq = len_squared_v2v2(kfv_sco, sco);
- if (dis_sq < radius_sq) {
- if (RV3D_CLIPPING_ENABLED(kcd->vc.v3d, kcd->vc.rv3d)) {
- if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, true) == 0) {
- c++;
- }
- }
- else {
+ dis_sq = len_squared_v2v2(kfv_sco, sco);
+ if (dis_sq < radius_sq) {
+ if (RV3D_CLIPPING_ENABLED(kcd->vc.v3d, kcd->vc.rv3d)) {
+ if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, true) == 0) {
c++;
}
}
+ else {
+ c++;
+ }
}
}
-
- return c;
}
- return 0;
+ return c;
}
-/* returns snapping distance for edges/verts, scaled by the density of the
- * surrounding mesh (in screen space)*/
+/**
+ * \return the snapping distance for edges/verts, scaled by the density of the
+ * surrounding mesh (in screen space).
+ *
+ * \note Face values in `kcd->curr` must be up to date.
+ */
static float knife_snap_size(KnifeTool_OpData *kcd, float maxsize)
{
- float density = (float)knife_sample_screen_density(kcd, maxsize * 2.0f);
+ BLI_assert(kcd->is_interactive == true);
+ int density = 0;
+
+ if (!kcd->curr.is_space) {
+ density = (float)knife_sample_screen_density_from_closest_face(
+ kcd, maxsize * 2.0f, kcd->curr.bmface, kcd->curr.cage);
+ }
+
+ return density ? min_ff(maxsize / ((float)density * 0.5f), maxsize) : maxsize;
+}
+
+/* Snap to edge in a specified angle.
+ * Returns 'lambda' calculated (in screen-space). */
+static bool knife_snap_edge_in_angle(KnifeTool_OpData *kcd,
+ const float sco[3],
+ const float kfv1_sco[2],
+ const float kfv2_sco[2],
+ float *r_dist_sq,
+ float *r_lambda)
+{
+ /* if snapping, check we're in bounds */
+ float sco_snap[2];
+ isect_line_line_v2_point(kfv1_sco, kfv2_sco, kcd->prev.mval, kcd->curr.mval, sco_snap);
+ float lambda = line_point_factor_v2(sco_snap, kfv1_sco, kfv2_sco);
+
+ /* be strict about angle-snapping within edge */
+ if ((lambda < 0.0f - KNIFE_FLT_EPSBIG) || (lambda > 1.0f + KNIFE_FLT_EPSBIG)) {
+ return false;
+ }
+
+ float dis_sq = len_squared_v2v2(sco, sco_snap);
+ if (dis_sq < *r_dist_sq) {
+ *r_dist_sq = dis_sq;
+ *r_lambda = lambda;
+ return true;
+ }
+ return false;
+}
+
+/* use when lambda is in screen-space */
+static void knife_interp_v3_v3v3(const KnifeTool_OpData *kcd,
+ float r_co[3],
+ const float v1[3],
+ const float v2[3],
+ float lambda_ss)
+{
+ if (kcd->is_ortho) {
+ interp_v3_v3v3(r_co, v1, v2, lambda_ss);
+ }
+ else {
+ /* transform into screen-space, interp, then transform back */
+ float v1_ss[3], v2_ss[3];
+
+ mul_v3_project_m4_v3(v1_ss, (float(*)[4])kcd->projmat, v1);
+ mul_v3_project_m4_v3(v2_ss, (float(*)[4])kcd->projmat, v2);
- return min_ff(maxsize / (density * 0.5f), maxsize);
+ interp_v3_v3v3(r_co, v1_ss, v2_ss, lambda_ss);
+
+ mul_project_m4_v3((float(*)[4])kcd->projmat_inv, r_co);
+ }
}
/* p is closest point on edge to the mouse cursor */
@@ -2009,15 +2355,15 @@ static KnifeEdge *knife_find_closest_edge_of_face(KnifeTool_OpData *kcd,
const float maxdist_sq = maxdist * maxdist;
KnifeEdge *cure = NULL;
float cur_cagep[3];
- ListBase *lst;
+ ListBase *list;
Ref *ref;
- float dis_sq, curdis_sq = FLT_MAX;
+ float dis_sq, curdis_sq = maxdist_sq;
knife_project_v2(kcd, cagep, sco);
/* look through all edges associated with this face */
- lst = knife_get_face_kedges(kcd, f);
- for (ref = lst->first; ref; ref = ref->next) {
+ list = knife_get_face_kedges(kcd, f);
+ for (ref = list->first; ref; ref = ref->next) {
KnifeEdge *kfe = ref->ref;
float kfv1_sco[2], kfv2_sco[2], test_cagep[3];
float lambda;
@@ -2028,27 +2374,14 @@ static KnifeEdge *knife_find_closest_edge_of_face(KnifeTool_OpData *kcd,
/* check if we're close enough and calculate 'lambda' */
if (kcd->is_angle_snapping) {
- /* if snapping, check we're in bounds */
- float sco_snap[2];
- isect_line_line_v2_point(kfv1_sco, kfv2_sco, kcd->prev.mval, kcd->curr.mval, sco_snap);
- lambda = line_point_factor_v2(sco_snap, kfv1_sco, kfv2_sco);
-
- /* be strict about angle-snapping within edge */
- if ((lambda < 0.0f - KNIFE_FLT_EPSBIG) || (lambda > 1.0f + KNIFE_FLT_EPSBIG)) {
- continue;
- }
-
- dis_sq = len_squared_v2v2(sco, sco_snap);
- if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
- /* we already have 'lambda' */
- }
- else {
+ dis_sq = curdis_sq;
+ if (!knife_snap_edge_in_angle(kcd, sco, kfv1_sco, kfv2_sco, &dis_sq, &lambda)) {
continue;
}
}
else {
dis_sq = dist_squared_to_line_segment_v2(sco, kfv1_sco, kfv2_sco);
- if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
+ if (dis_sq < curdis_sq) {
lambda = line_point_factor_v2(sco, kfv1_sco, kfv2_sco);
}
else {
@@ -2071,36 +2404,31 @@ static KnifeEdge *knife_find_closest_edge_of_face(KnifeTool_OpData *kcd,
copy_v3_v3(cur_cagep, test_cagep);
}
- if (cure) {
- if (!kcd->ignore_edge_snapping || !(cure->e)) {
- KnifeVert *edgesnap = NULL;
+ if (cure && !kcd->ignore_edge_snapping) {
+ KnifeVert *edgesnap = NULL;
- if (kcd->snap_midpoints) {
- mid_v3_v3v3(p, cure->v1->co, cure->v2->co);
- mid_v3_v3v3(cagep, cure->v1->cageco, cure->v2->cageco);
- }
- else {
- float lambda = line_point_factor_v3(cur_cagep, cure->v1->cageco, cure->v2->cageco);
- copy_v3_v3(cagep, cur_cagep);
- interp_v3_v3v3(p, cure->v1->co, cure->v2->co, lambda);
- }
-
- /* update mouse coordinates to the snapped-to edge's screen coordinates
- * this is important for angle snap, which uses the previous mouse position */
- edgesnap = new_knife_vert(kcd, p, cagep);
- knife_project_v2(kcd, edgesnap->cageco, kcd->curr.mval);
+ if (kcd->snap_midpoints) {
+ mid_v3_v3v3(p, cure->v1->co, cure->v2->co);
+ mid_v3_v3v3(cagep, cure->v1->cageco, cure->v2->cageco);
}
else {
- return NULL;
+ float lambda = line_point_factor_v3(cur_cagep, cure->v1->cageco, cure->v2->cageco);
+ copy_v3_v3(cagep, cur_cagep);
+ interp_v3_v3v3(p, cure->v1->co, cure->v2->co, lambda);
}
+
+ /* update mouse coordinates to the snapped-to edge's screen coordinates
+ * this is important for angle snap, which uses the previous mouse position */
+ edgesnap = new_knife_vert(kcd, p, cagep);
+ knife_project_v2(kcd, edgesnap->cageco, kcd->curr.mval);
}
return cure;
}
/* find a vertex near the mouse cursor, if it exists */
-static KnifeVert *knife_find_closest_vert_of_face(KnifeTool_OpData *kcd,
- BMFace *f,
+static KnifeVert *knife_find_closest_vert_of_edge(KnifeTool_OpData *kcd,
+ KnifeEdge *kfe,
float p[3],
float cagep[3])
{
@@ -2118,60 +2446,48 @@ static KnifeVert *knife_find_closest_vert_of_face(KnifeTool_OpData *kcd,
}
const float maxdist_sq = maxdist * maxdist;
- ListBase *lst;
- Ref *ref;
KnifeVert *curv = NULL;
float cur_kfv_sco[2];
float dis_sq, curdis_sq = FLT_MAX;
knife_project_v2(kcd, cagep, sco);
- lst = knife_get_face_kedges(kcd, f);
- for (ref = lst->first; ref; ref = ref->next) {
- KnifeEdge *kfe = ref->ref;
- int i;
+ for (int i = 0; i < 2; i++) {
+ KnifeVert *kfv = i ? kfe->v2 : kfe->v1;
+ float kfv_sco[2];
- for (i = 0; i < 2; i++) {
- KnifeVert *kfv = i ? kfe->v2 : kfe->v1;
- float kfv_sco[2];
+ knife_project_v2(kcd, kfv->cageco, kfv_sco);
- knife_project_v2(kcd, kfv->cageco, kfv_sco);
-
- /* be strict about angle snapping, the vertex needs to be very close to the angle,
- * or we ignore */
- if (kcd->is_angle_snapping) {
- if (dist_squared_to_line_segment_v2(kfv_sco, kcd->prev.mval, kcd->curr.mval) >
- KNIFE_FLT_EPSBIG) {
- continue;
- }
+ /* be strict about angle snapping, the vertex needs to be very close to the angle,
+ * or we ignore */
+ if (kcd->is_angle_snapping) {
+ if (dist_squared_to_line_segment_v2(kfv_sco, kcd->prev.mval, kcd->curr.mval) >
+ KNIFE_FLT_EPSBIG) {
+ continue;
}
+ }
- dis_sq = len_squared_v2v2(kfv_sco, sco);
- if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
- if (!RV3D_CLIPPING_ENABLED(kcd->vc.v3d, kcd->vc.rv3d) ||
- !ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, true)) {
- curv = kfv;
- curdis_sq = dis_sq;
- copy_v2_v2(cur_kfv_sco, kfv_sco);
- }
+ dis_sq = len_squared_v2v2(kfv_sco, sco);
+ if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
+ if (!RV3D_CLIPPING_ENABLED(kcd->vc.v3d, kcd->vc.rv3d) ||
+ !ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, true)) {
+ curv = kfv;
+ curdis_sq = dis_sq;
+ copy_v2_v2(cur_kfv_sco, kfv_sco);
}
}
}
- if (!kcd->ignore_vert_snapping || !(curv && curv->v)) {
- if (curv) {
- copy_v3_v3(p, curv->co);
- copy_v3_v3(cagep, curv->cageco);
+ if (curv && !kcd->ignore_vert_snapping) {
+ copy_v3_v3(p, curv->co);
+ copy_v3_v3(cagep, curv->cageco);
- /* update mouse coordinates to the snapped-to vertex's screen coordinates
- * this is important for angle snap, which uses the previous mouse position */
- copy_v2_v2(kcd->curr.mval, cur_kfv_sco);
- }
-
- return curv;
+ /* update mouse coordinates to the snapped-to vertex's screen coordinates
+ * this is important for angle snap, which uses the previous mouse position */
+ copy_v2_v2(kcd->curr.mval, cur_kfv_sco);
}
- return NULL;
+ return curv;
}
/**
@@ -2215,7 +2531,15 @@ static bool knife_snap_angle(KnifeTool_OpData *kcd)
return true;
}
-static void knife_snap_update_from_mval(KnifeTool_OpData *kcd, const float mval[2])
+/**
+ * \return true when `kcd->curr.co` & `kcd->curr.cage` are set.
+ *
+ * In this case `is_space` is nearly always false.
+ * There are some situations when vertex or edge can be snapped to, when `is_space` is true.
+ * In this case the selection-buffer is used to select the face,
+ * then the closest `vert` or `edge` is set, and those will enable `is_co_set`.
+ */
+static bool knife_snap_update_from_mval(KnifeTool_OpData *kcd, const float mval[2])
{
knife_pos_data_clear(&kcd->curr);
copy_v2_v2(kcd->curr.mval, mval);
@@ -2230,410 +2554,33 @@ static void knife_snap_update_from_mval(KnifeTool_OpData *kcd, const float mval[
kcd->is_angle_snapping = false;
}
- kcd->curr.bmface = knife_find_closest_face(
- kcd, kcd->curr.co, kcd->curr.cage, &kcd->curr.is_space);
-
- if (kcd->curr.bmface) {
- kcd->curr.vert = knife_find_closest_vert_of_face(
- kcd, kcd->curr.bmface, kcd->curr.co, kcd->curr.cage);
+ {
+ kcd->curr.bmface = knife_find_closest_face(
+ kcd, kcd->curr.co, kcd->curr.cage, &kcd->curr.is_space);
- if (!kcd->curr.vert &&
- /* no edge snapping while dragging (edges are too sticky when cuts are immediate) */
- !kcd->is_drag_hold) {
+ if (kcd->curr.bmface) {
kcd->curr.edge = knife_find_closest_edge_of_face(
kcd, kcd->curr.bmface, kcd->curr.co, kcd->curr.cage);
}
- }
-}
-
-/* update active knife edge/vert pointers */
-static int knife_update_active(KnifeTool_OpData *kcd)
-{
- knife_snap_update_from_mval(kcd, kcd->mval);
-
- /* if no hits are found this would normally default to (0, 0, 0) so instead
- * get a point at the mouse ray closest to the previous point.
- * Note that drawing lines in `free-space` isn't properly supported
- * but there's no guarantee (0, 0, 0) has any geometry either - campbell */
- if (kcd->curr.vert == NULL && kcd->curr.edge == NULL && kcd->curr.bmface == NULL) {
- float origin[3];
- float origin_ofs[3];
-
- knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
-
- if (!isect_line_plane_v3(
- kcd->curr.cage, origin, origin_ofs, kcd->prev.cage, kcd->proj_zaxis)) {
- copy_v3_v3(kcd->curr.cage, kcd->prev.cage);
-
- /* should never fail! */
- BLI_assert(0);
- }
- }
-
- if (kcd->mode == MODE_DRAGGING) {
- knife_find_line_hits(kcd);
- }
- return 1;
-}
-
-static int sort_verts_by_dist_cb(void *co_p, const void *cur_a_p, const void *cur_b_p)
-{
- const KnifeVert *cur_a = ((const Ref *)cur_a_p)->ref;
- const KnifeVert *cur_b = ((const Ref *)cur_b_p)->ref;
- const float *co = co_p;
- const float a_sq = len_squared_v3v3(co, cur_a->co);
- const float b_sq = len_squared_v3v3(co, cur_b->co);
-
- if (a_sq < b_sq) {
- return -1;
- }
- if (a_sq > b_sq) {
- return 1;
- }
- return 0;
-}
-
-static bool knife_verts_edge_in_face(KnifeVert *v1, KnifeVert *v2, BMFace *f)
-{
- bool v1_inside, v2_inside;
- bool v1_inface, v2_inface;
- BMLoop *l1, *l2;
-
- if (!f || !v1 || !v2) {
- return false;
- }
-
- l1 = v1->v ? BM_face_vert_share_loop(f, v1->v) : NULL;
- l2 = v2->v ? BM_face_vert_share_loop(f, v2->v) : NULL;
-
- if ((l1 && l2) && BM_loop_is_adjacent(l1, l2)) {
- /* boundary-case, always false to avoid edge-in-face checks below */
- return false;
- }
-
- /* find out if v1 and v2, if set, are part of the face */
- v1_inface = (l1 != NULL);
- v2_inface = (l2 != NULL);
-
- /* BM_face_point_inside_test uses best-axis projection so this isn't most accurate test... */
- v1_inside = v1_inface ? false : BM_face_point_inside_test(f, v1->co);
- v2_inside = v2_inface ? false : BM_face_point_inside_test(f, v2->co);
- if ((v1_inface && v2_inside) || (v2_inface && v1_inside) || (v1_inside && v2_inside)) {
- return true;
- }
-
- if (v1_inface && v2_inface) {
- float mid[3];
- /* Can have case where v1 and v2 are on shared chain between two faces.
- * BM_face_splits_check_legal does visibility and self-intersection tests,
- * but it is expensive and maybe a bit buggy, so use a simple
- * "is the midpoint in the face" test */
- mid_v3_v3v3(mid, v1->co, v2->co);
- return BM_face_point_inside_test(f, mid);
- }
- return false;
-}
-
-static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfedges)
-{
- BMesh *bm = kcd->em->bm;
- KnifeEdge *kfe;
- Ref *ref;
- int edge_array_len = BLI_listbase_count(kfedges);
- int i;
-
- BMEdge **edge_array = BLI_array_alloca(edge_array, edge_array_len);
-
- /* point to knife edges we've created edges in, edge_array aligned */
- KnifeEdge **kfe_array = BLI_array_alloca(kfe_array, edge_array_len);
-
- BLI_assert(BLI_gset_len(kcd->edgenet.edge_visit) == 0);
-
- i = 0;
- for (ref = kfedges->first; ref; ref = ref->next) {
- bool is_new_edge = false;
- kfe = ref->ref;
-
- if (kfe->e == NULL) {
- if (kfe->v1->v && kfe->v2->v) {
- kfe->e = BM_edge_exists(kfe->v1->v, kfe->v2->v);
- }
- }
-
- if (kfe->e) {
- if (BM_edge_in_face(kfe->e, f)) {
- /* shouldn't happen, but in this case - just ignore */
- continue;
- }
- }
- else {
- if (kfe->v1->v == NULL) {
- kfe->v1->v = BM_vert_create(bm, kfe->v1->co, NULL, 0);
- }
- if (kfe->v2->v == NULL) {
- kfe->v2->v = BM_vert_create(bm, kfe->v2->co, NULL, 0);
- }
- BLI_assert(kfe->e == NULL);
- kfe->e = BM_edge_create(bm, kfe->v1->v, kfe->v2->v, NULL, 0);
- if (kfe->e) {
- if (kcd->select_result || BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_edge_select_set(bm, kfe->e, true);
- }
- is_new_edge = true;
- }
- }
-
- BLI_assert(kfe->e);
-
- if (BLI_gset_add(kcd->edgenet.edge_visit, kfe->e)) {
- kfe_array[i] = is_new_edge ? kfe : 0;
- edge_array[i] = kfe->e;
- i += 1;
- }
- }
-
- if (i) {
- const int edge_array_len_orig = i;
- edge_array_len = i;
-
-#ifdef USE_NET_ISLAND_CONNECT
- uint edge_array_holes_len;
- BMEdge **edge_array_holes;
- if (BM_face_split_edgenet_connect_islands(bm,
- f,
- edge_array,
- edge_array_len,
- true,
- kcd->edgenet.arena,
- &edge_array_holes,
- &edge_array_holes_len)) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- for (i = edge_array_len; i < edge_array_holes_len; i++) {
- BM_edge_select_set(bm, edge_array_holes[i], true);
- }
- }
-
- edge_array_len = edge_array_holes_len;
- edge_array = edge_array_holes; /* owned by the arena */
- }
-#endif
-
- {
- BMFace **face_arr = NULL;
- int face_arr_len;
- BM_face_split_edgenet(bm, f, edge_array, edge_array_len, &face_arr, &face_arr_len);
+ if (kcd->curr.edge) {
+ kcd->curr.vert = knife_find_closest_vert_of_edge(
+ kcd, kcd->curr.edge, kcd->curr.co, kcd->curr.cage);
- if (face_arr) {
- MEM_freeN(face_arr);
+ if (kcd->ignore_edge_snapping) {
+ kcd->curr.edge = NULL;
}
}
-
- /* remove dangling edges, not essential - but nice for users */
- for (i = 0; i < edge_array_len_orig; i++) {
- if (kfe_array[i]) {
- if (BM_edge_is_wire(kfe_array[i]->e)) {
- BM_edge_kill(bm, kfe_array[i]->e);
- kfe_array[i]->e = NULL;
- }
- }
- }
-
-#ifdef USE_NET_ISLAND_CONNECT
- BLI_memarena_clear(kcd->edgenet.arena);
-#endif
}
- BLI_gset_clear(kcd->edgenet.edge_visit, NULL);
+ return kcd->curr.vert || kcd->curr.edge || (kcd->curr.bmface && !kcd->curr.is_space);
}
-/* Use the network of KnifeEdges and KnifeVerts accumulated to make real BMVerts and BMEdedges */
-static void knife_make_cuts(KnifeTool_OpData *kcd)
-{
- BMesh *bm = kcd->em->bm;
- KnifeEdge *kfe;
- KnifeVert *kfv;
- BMFace *f;
- BMEdge *e, *enew;
- ListBase *lst;
- Ref *ref;
- float pct;
- SmallHashIter hiter;
- BLI_mempool_iter iter;
- SmallHash fhash_, *fhash = &fhash_;
- SmallHash ehash_, *ehash = &ehash_;
-
- BLI_smallhash_init(fhash);
- BLI_smallhash_init(ehash);
-
- /* put list of cutting edges for a face into fhash, keyed by face */
- BLI_mempool_iternew(kcd->kedges, &iter);
- for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
-
- /* select edges that lie directly on the cut */
- if (kcd->select_result) {
- if (kfe->e && kfe->is_cut) {
- BM_edge_select_set(bm, kfe->e, true);
- }
- }
-
- f = kfe->basef;
- if (!f || kfe->e) {
- continue;
- }
- lst = BLI_smallhash_lookup(fhash, (uintptr_t)f);
- if (!lst) {
- lst = knife_empty_list(kcd);
- BLI_smallhash_insert(fhash, (uintptr_t)f, lst);
- }
- knife_append_list(kcd, lst, kfe);
- }
-
- /* put list of splitting vertices for an edge into ehash, keyed by edge */
- BLI_mempool_iternew(kcd->kverts, &iter);
- for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
- if (kfv->v) {
- continue; /* already have a BMVert */
- }
- for (ref = kfv->edges.first; ref; ref = ref->next) {
- kfe = ref->ref;
- e = kfe->e;
- if (!e) {
- continue;
- }
- lst = BLI_smallhash_lookup(ehash, (uintptr_t)e);
- if (!lst) {
- lst = knife_empty_list(kcd);
- BLI_smallhash_insert(ehash, (uintptr_t)e, lst);
- }
- /* there can be more than one kfe in kfv's list with same e */
- if (!find_ref(lst, kfv)) {
- knife_append_list(kcd, lst, kfv);
- }
- }
- }
-
- /* split bmesh edges where needed */
- for (lst = BLI_smallhash_iternew(ehash, &hiter, (uintptr_t *)&e); lst;
- lst = BLI_smallhash_iternext(&hiter, (uintptr_t *)&e)) {
- BLI_listbase_sort_r(lst, sort_verts_by_dist_cb, e->v1->co);
-
- for (ref = lst->first; ref; ref = ref->next) {
- kfv = ref->ref;
- pct = line_point_factor_v3(kfv->co, e->v1->co, e->v2->co);
- kfv->v = BM_edge_split(bm, e, e->v1, &enew, pct);
- }
- }
-
- if (kcd->only_select) {
- EDBM_flag_disable_all(kcd->em, BM_ELEM_SELECT);
- }
-
- /* do cuts for each face */
- for (lst = BLI_smallhash_iternew(fhash, &hiter, (uintptr_t *)&f); lst;
- lst = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f)) {
- knife_make_face_cuts(kcd, f, lst);
- }
-
- BLI_smallhash_release(fhash);
- BLI_smallhash_release(ehash);
-}
-
-/* called on tool confirmation */
-static void knifetool_finish_ex(KnifeTool_OpData *kcd)
-{
- knife_make_cuts(kcd);
-
- EDBM_selectmode_flush(kcd->em);
- EDBM_mesh_normals_update(kcd->em);
- EDBM_update_generic(kcd->ob->data, true, true);
-
- /* Re-tessellating makes this invalid, don't use again by accident. */
- knifetool_free_bmbvh(kcd);
-}
-static void knifetool_finish(wmOperator *op)
-{
- KnifeTool_OpData *kcd = op->customdata;
- knifetool_finish_ex(kcd);
-}
-
-static void knife_recalc_projmat(KnifeTool_OpData *kcd)
-{
- invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
- ED_view3d_ob_project_mat_get(kcd->region->regiondata, kcd->ob, kcd->projmat);
- invert_m4_m4(kcd->projmat_inv, kcd->projmat);
-
- mul_v3_mat3_m4v3(kcd->proj_zaxis, kcd->ob->imat, kcd->vc.rv3d->viewinv[2]);
- normalize_v3(kcd->proj_zaxis);
-
- kcd->is_ortho = ED_view3d_clip_range_get(
- kcd->vc.depsgraph, kcd->vc.v3d, kcd->vc.rv3d, &kcd->clipsta, &kcd->clipend, true);
-}
-
-/* called when modal loop selection is done... */
-static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd)
-{
- if (!kcd) {
- return;
- }
-
- if (kcd->is_interactive) {
- WM_cursor_modal_restore(CTX_wm_window(C));
-
- /* deactivate the extra drawing stuff in 3D-View */
- ED_region_draw_cb_exit(kcd->region->type, kcd->draw_handle);
- }
-
- /* free the custom data */
- BLI_mempool_destroy(kcd->refs);
- BLI_mempool_destroy(kcd->kverts);
- BLI_mempool_destroy(kcd->kedges);
-
- BLI_ghash_free(kcd->origedgemap, NULL, NULL);
- BLI_ghash_free(kcd->origvertmap, NULL, NULL);
- BLI_ghash_free(kcd->kedgefacemap, NULL, NULL);
- BLI_ghash_free(kcd->facetrimap, NULL, NULL);
-
- BLI_memarena_free(kcd->arena);
-#ifdef USE_NET_ISLAND_CONNECT
- BLI_memarena_free(kcd->edgenet.arena);
-#endif
- BLI_gset_free(kcd->edgenet.edge_visit, NULL);
-
- /* tag for redraw */
- ED_region_tag_redraw(kcd->region);
-
- knifetool_free_bmbvh(kcd);
-
- if (kcd->linehits) {
- MEM_freeN(kcd->linehits);
- }
-
- /* destroy kcd itself */
- MEM_freeN(kcd);
-}
-static void knifetool_exit(bContext *C, wmOperator *op)
-{
- KnifeTool_OpData *kcd = op->customdata;
- knifetool_exit_ex(C, kcd);
- op->customdata = NULL;
-}
-
-static void knifetool_update_mval(KnifeTool_OpData *kcd, const float mval[2])
-{
- knife_recalc_projmat(kcd);
- copy_v2_v2(kcd->mval, mval);
-
- if (knife_update_active(kcd)) {
- ED_region_tag_redraw(kcd->region);
- }
-}
+/** \} */
-static void knifetool_update_mval_i(KnifeTool_OpData *kcd, const int mval_i[2])
-{
- const float mval[2] = {UNPACK2(mval_i)};
- knifetool_update_mval(kcd, mval);
-}
+/* -------------------------------------------------------------------- */
+/** \name #KnifeTool_OpData (#op->customdata) Init and Free
+ * \{ */
static void knifetool_init_bmbvh(KnifeTool_OpData *kcd)
{
@@ -2667,6 +2614,21 @@ static void knifetool_free_bmbvh(KnifeTool_OpData *kcd)
}
}
+static void knife_init_colors(KnifeColors *colors)
+{
+ /* possible BMESH_TODO: add explicit themes or calculate these by
+ * figuring out contrasting colors with grid / edges / verts
+ * a la UI_make_axis_color */
+ UI_GetThemeColorType3ubv(TH_NURB_VLINE, SPACE_VIEW3D, colors->line);
+ UI_GetThemeColorType3ubv(TH_NURB_ULINE, SPACE_VIEW3D, colors->edge);
+ UI_GetThemeColorType3ubv(TH_HANDLE_SEL_VECT, SPACE_VIEW3D, colors->curpoint);
+ UI_GetThemeColorType3ubv(TH_HANDLE_SEL_VECT, SPACE_VIEW3D, colors->curpoint_a);
+ colors->curpoint_a[3] = 102;
+ UI_GetThemeColorType3ubv(TH_ACTIVE_SPLINE, SPACE_VIEW3D, colors->point);
+ UI_GetThemeColorType3ubv(TH_ACTIVE_SPLINE, SPACE_VIEW3D, colors->point_a);
+ colors->point_a[3] = 102;
+}
+
/* called when modal loop selection gets set up... */
static void knifetool_init(bContext *C,
KnifeTool_OpData *kcd,
@@ -2690,6 +2652,7 @@ static void knifetool_init(bContext *C,
kcd->is_interactive = is_interactive;
kcd->cut_through = cut_through;
kcd->only_select = only_select;
+ kcd->mode = MODE_INVOKING;
knifetool_init_bmbvh(kcd);
@@ -2729,57 +2692,140 @@ static void knifetool_init(bContext *C,
}
}
-static void knifetool_cancel(bContext *C, wmOperator *op)
+/* called when modal loop selection is done... */
+static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd)
{
- /* this is just a wrapper around exit() */
- knifetool_exit(C, op);
+ if (!kcd) {
+ return;
+ }
+
+ if (kcd->is_interactive) {
+ WM_cursor_modal_restore(CTX_wm_window(C));
+
+ /* deactivate the extra drawing stuff in 3D-View */
+ ED_region_draw_cb_exit(kcd->region->type, kcd->draw_handle);
+ }
+
+ /* free the custom data */
+ BLI_mempool_destroy(kcd->refs);
+ BLI_mempool_destroy(kcd->kverts);
+ BLI_mempool_destroy(kcd->kedges);
+
+ BLI_ghash_free(kcd->origedgemap, NULL, NULL);
+ BLI_ghash_free(kcd->origvertmap, NULL, NULL);
+ BLI_ghash_free(kcd->kedgefacemap, NULL, NULL);
+ BLI_ghash_free(kcd->facetrimap, NULL, NULL);
+
+ BLI_memarena_free(kcd->arena);
+#ifdef USE_NET_ISLAND_CONNECT
+ BLI_memarena_free(kcd->edgenet.arena);
+#endif
+ BLI_gset_free(kcd->edgenet.edge_visit, NULL);
+
+ /* tag for redraw */
+ ED_region_tag_redraw(kcd->region);
+
+ knifetool_free_bmbvh(kcd);
+
+ if (kcd->linehits) {
+ MEM_freeN(kcd->linehits);
+ }
+
+ /* destroy kcd itself */
+ MEM_freeN(kcd);
+}
+static void knifetool_exit(bContext *C, wmOperator *op)
+{
+ KnifeTool_OpData *kcd = op->customdata;
+ knifetool_exit_ex(C, kcd);
+ op->customdata = NULL;
}
-static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mouse-Moving Event Updates
+ * \{ */
+
+/* update active knife edge/vert pointers */
+static int knife_update_active(KnifeTool_OpData *kcd)
{
- const bool only_select = RNA_boolean_get(op->ptr, "only_selected");
- const bool cut_through = !RNA_boolean_get(op->ptr, "use_occlude_geometry");
- const bool wait_for_input = RNA_boolean_get(op->ptr, "wait_for_input");
+ /* if no hits are found this would normally default to (0, 0, 0) so instead
+ * get a point at the mouse ray closest to the previous point.
+ * Note that drawing lines in `free-space` isn't properly supported
+ * but there's no guarantee (0, 0, 0) has any geometry either - campbell */
+ if (!knife_snap_update_from_mval(kcd, kcd->mval)) {
+ float origin[3];
+ float origin_ofs[3];
- KnifeTool_OpData *kcd;
+ knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
- if (only_select) {
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totfacesel == 0) {
- BKE_report(op->reports, RPT_ERROR, "Selected faces required");
- return OPERATOR_CANCELLED;
+ if (!isect_line_plane_v3(
+ kcd->curr.cage, origin, origin_ofs, kcd->prev.cage, kcd->proj_zaxis)) {
+ copy_v3_v3(kcd->curr.cage, kcd->prev.cage);
+
+ /* should never fail! */
+ BLI_assert(0);
}
}
- /* alloc new customdata */
- kcd = op->customdata = MEM_callocN(sizeof(KnifeTool_OpData), __func__);
+ if (kcd->mode == MODE_DRAGGING) {
+ knife_find_line_hits(kcd);
+ }
+ return 1;
+}
- knifetool_init(C, kcd, only_select, cut_through, true);
+static void knifetool_update_mval(KnifeTool_OpData *kcd, const float mval[2])
+{
+ knife_recalc_projmat(kcd);
+ copy_v2_v2(kcd->mval, mval);
- op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ if (knife_update_active(kcd)) {
+ ED_region_tag_redraw(kcd->region);
+ }
+}
- /* add a modal handler for this operator - handles loop selection */
- WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_KNIFE);
- WM_event_add_modal_handler(C, op);
+static void knifetool_update_mval_i(KnifeTool_OpData *kcd, const int mval_i[2])
+{
+ const float mval[2] = {UNPACK2(mval_i)};
+ knifetool_update_mval(kcd, mval);
+}
- knifetool_update_mval_i(kcd, event->mval);
+/** \} */
- if (wait_for_input == false) {
- /* Avoid copy-paste logic. */
- wmEvent event_modal = {
- .prevval = KM_NOTHING,
- .type = EVT_MODAL_MAP,
- .val = KNF_MODAL_ADD_CUT,
- };
- int ret = knifetool_modal(C, op, &event_modal);
- BLI_assert(ret == OPERATOR_RUNNING_MODAL);
- UNUSED_VARS_NDEBUG(ret);
- }
+/* -------------------------------------------------------------------- */
+/** \name Finalization
+ * \{ */
- knife_update_header(C, op, kcd);
+/* called on tool confirmation */
+static void knifetool_finish_ex(KnifeTool_OpData *kcd)
+{
+ knife_make_cuts(kcd);
- return OPERATOR_RUNNING_MODAL;
+ EDBM_selectmode_flush(kcd->em);
+ EDBM_mesh_normals_update(kcd->em);
+ EDBM_update_generic(kcd->ob->data, true, true);
+
+ /* Re-tessellating makes this invalid, don't use again by accident. */
+ knifetool_free_bmbvh(kcd);
+}
+
+static void knifetool_finish(wmOperator *op)
+{
+ KnifeTool_OpData *kcd = op->customdata;
+ knifetool_finish_ex(kcd);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Operator (#MESH_OT_knife_tool)
+ * \{ */
+
+static void knifetool_cancel(bContext *C, wmOperator *op)
+{
+ /* this is just a wrapper around exit() */
+ knifetool_exit(C, op);
}
wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf)
@@ -2789,8 +2835,8 @@ wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf)
{KNF_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
{KNF_MODAL_MIDPOINT_ON, "SNAP_MIDPOINTS_ON", 0, "Snap to Midpoints On", ""},
{KNF_MODAL_MIDPOINT_OFF, "SNAP_MIDPOINTS_OFF", 0, "Snap to Midpoints Off", ""},
- {KNF_MODEL_IGNORE_SNAP_ON, "IGNORE_SNAP_ON", 0, "Ignore Snapping On", ""},
- {KNF_MODEL_IGNORE_SNAP_OFF, "IGNORE_SNAP_OFF", 0, "Ignore Snapping Off", ""},
+ {KNF_MODAL_IGNORE_SNAP_ON, "IGNORE_SNAP_ON", 0, "Ignore Snapping On", ""},
+ {KNF_MODAL_IGNORE_SNAP_OFF, "IGNORE_SNAP_OFF", 0, "Ignore Snapping Off", ""},
{KNF_MODAL_ANGLE_SNAP_TOGGLE, "ANGLE_SNAP_TOGGLE", 0, "Toggle Angle Snapping", ""},
{KNF_MODAL_CUT_THROUGH_TOGGLE, "CUT_THROUGH_TOGGLE", 0, "Toggle Cut Through", ""},
{KNF_MODAL_NEW_CUT, "NEW_CUT", 0, "End Current Cut", ""},
@@ -2873,13 +2919,13 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
ED_region_tag_redraw(kcd->region);
do_refresh = true;
break;
- case KNF_MODEL_IGNORE_SNAP_ON:
+ case KNF_MODAL_IGNORE_SNAP_ON:
ED_region_tag_redraw(kcd->region);
kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = true;
knife_update_header(C, op, kcd);
do_refresh = true;
break;
- case KNF_MODEL_IGNORE_SNAP_OFF:
+ case KNF_MODAL_IGNORE_SNAP_OFF:
ED_region_tag_redraw(kcd->region);
kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = false;
knife_update_header(C, op, kcd);
@@ -2917,10 +2963,13 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* freehand drawing is incompatible with cut-through */
if (kcd->cut_through == false) {
kcd->is_drag_hold = true;
+ /* No edge snapping while dragging (edges are too sticky when cuts are immediate). */
+ kcd->ignore_edge_snapping = true;
}
}
else {
kcd->is_drag_hold = false;
+ kcd->ignore_edge_snapping = false;
/* needed because the last face 'hit' is ignored when dragging */
knifetool_update_mval(kcd, kcd->curr.mval);
@@ -3006,6 +3055,53 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
+static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ const bool only_select = RNA_boolean_get(op->ptr, "only_selected");
+ const bool cut_through = !RNA_boolean_get(op->ptr, "use_occlude_geometry");
+ const bool wait_for_input = RNA_boolean_get(op->ptr, "wait_for_input");
+
+ KnifeTool_OpData *kcd;
+
+ if (only_select) {
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ if (em->bm->totfacesel == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Selected faces required");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* alloc new customdata */
+ kcd = op->customdata = MEM_callocN(sizeof(KnifeTool_OpData), __func__);
+
+ knifetool_init(C, kcd, only_select, cut_through, true);
+
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+
+ /* add a modal handler for this operator - handles loop selection */
+ WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_KNIFE);
+ WM_event_add_modal_handler(C, op);
+
+ knifetool_update_mval_i(kcd, event->mval);
+
+ if (wait_for_input == false) {
+ /* Avoid copy-paste logic. */
+ wmEvent event_modal = {
+ .prevval = KM_NOTHING,
+ .type = EVT_MODAL_MAP,
+ .val = KNF_MODAL_ADD_CUT,
+ };
+ int ret = knifetool_modal(C, op, &event_modal);
+ BLI_assert(ret == OPERATOR_RUNNING_MODAL);
+ UNUSED_VARS_NDEBUG(ret);
+ }
+
+ knife_update_header(C, op, kcd);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
void MESH_OT_knife_tool(wmOperatorType *ot)
{
/* description */
@@ -3035,9 +3131,13 @@ void MESH_OT_knife_tool(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* Knife tool as a utility function
- * that can be used for internal slicing operations */
+/** \name Knife tool as a utility function
+ *
+ * Can be used for internal slicing operations.
+ * \{ */
static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2])
{
@@ -3212,3 +3312,5 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
kcd = NULL;
}
}
+
+/** \} */
diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c
index 2cb8da37260..b7f671a4157 100644
--- a/source/blender/editors/mesh/editmesh_path.c
+++ b/source/blender/editors/mesh/editmesh_path.c
@@ -669,18 +669,17 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE
return edbm_shortest_path_pick_exec(C, op);
}
- Base *basact = NULL;
BMVert *eve = NULL;
BMEdge *eed = NULL;
BMFace *efa = NULL;
ViewContext vc;
- BMEditMesh *em;
bool track_active = true;
em_setup_viewcontext(C, &vc);
copy_v2_v2_int(vc.mval, event->mval);
- em = vc.em;
+ Base *basact = BASACT(vc.view_layer);
+ BMEditMesh *em = vc.em;
view3d_operator_needs_opengl(C);
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 35608a4abde..4864c7de123 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -268,7 +268,8 @@ static void findnearestvert__doClosest(void *userData,
/**
* Nearest vertex under the cursor.
*
- * \param r_dist: (in/out), minimal distance to the nearest and at the end, actual distance
+ * \param dist_px_manhattan_p: (in/out), minimal distance to the nearest and at the end,
+ * actual distance.
* \param use_select_bias:
* - When true, selected vertices are given a 5 pixel bias
* to make them further than unselect verts.
@@ -276,7 +277,7 @@ static void findnearestvert__doClosest(void *userData,
* \param use_cycle: Cycle over elements within #FIND_NEAR_CYCLE_THRESHOLD_MIN in order of index.
*/
BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
- float *r_dist,
+ float *dist_px_manhattan_p,
const bool use_select_bias,
bool use_cycle,
Base **bases,
@@ -286,7 +287,8 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
uint base_index = 0;
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
- uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->region, *r_dist);
+ uint dist_px_manhattan_test = (uint)ED_view3d_backbuf_sample_size_clamp(vc->region,
+ *dist_px_manhattan_p);
uint index;
BMVert *eve;
@@ -295,7 +297,7 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
DRW_select_buffer_context_create(bases, bases_len, SCE_SELECT_VERTEX);
index = DRW_select_buffer_find_nearest_to_point(
- vc->depsgraph, vc->region, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px);
+ vc->depsgraph, vc->region, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px_manhattan_test);
if (index) {
eve = (BMVert *)edbm_select_id_bm_elem_get(bases, index, &base_index);
@@ -306,11 +308,11 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
}
if (eve) {
- if (dist_px < *r_dist) {
+ if (dist_px_manhattan_test < *dist_px_manhattan_p) {
if (r_base_index) {
*r_base_index = base_index;
}
- *r_dist = dist_px;
+ *dist_px_manhattan_p = dist_px_manhattan_test;
return eve;
}
}
@@ -348,18 +350,19 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
data.cycle_index_prev = 0;
}
- data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+ data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias =
+ *dist_px_manhattan_p;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag);
hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit;
- if (hit->dist < *r_dist) {
+ if (hit->dist < *dist_px_manhattan_p) {
if (r_base_index) {
*r_base_index = base_index;
}
- *r_dist = hit->dist;
+ *dist_px_manhattan_p = hit->dist;
prev_select_bm = vc->em->bm;
}
}
@@ -375,10 +378,10 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
return hit->vert;
}
-BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist)
+BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *dist_px_manhattan_p)
{
Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact);
- return EDBM_vert_find_nearest_ex(vc, r_dist, false, false, &base, 1, NULL);
+ return EDBM_vert_find_nearest_ex(vc, dist_px_manhattan_p, false, false, &base, 1, NULL);
}
/* find the distance to the edge we already have */
@@ -417,7 +420,7 @@ struct NearestEdgeUserData_Hit {
/* edges only, un-biased manhattan distance to which ever edge we pick
* (not used for choosing) */
- float dist_center;
+ float dist_center_px_manhattan;
};
struct NearestEdgeUserData {
@@ -477,7 +480,7 @@ static void find_nearest_edge__doClosest(
data->hit.edge = eed;
mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
- data->hit.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
+ data->hit.dist_center_px_manhattan = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
}
if (data->use_cycle) {
@@ -491,14 +494,14 @@ static void find_nearest_edge__doClosest(
data->hit_cycle.edge = eed;
mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
- data->hit_cycle.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
+ data->hit_cycle.dist_center_px_manhattan = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
}
}
}
BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
- float *r_dist,
- float *r_dist_center,
+ float *dist_px_manhattan_p,
+ float *r_dist_center_px_manhattan,
const bool use_select_bias,
bool use_cycle,
BMEdge **r_eed_zbuf,
@@ -509,7 +512,8 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
uint base_index = 0;
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
- uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->region, *r_dist);
+ uint dist_px_manhattan_test = (uint)ED_view3d_backbuf_sample_size_clamp(vc->region,
+ *dist_px_manhattan_p);
uint index;
BMEdge *eed;
@@ -518,7 +522,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
DRW_select_buffer_context_create(bases, bases_len, SCE_SELECT_EDGE);
index = DRW_select_buffer_find_nearest_to_point(
- vc->depsgraph, vc->region, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px);
+ vc->depsgraph, vc->region, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px_manhattan_test);
if (index) {
eed = (BMEdge *)edbm_select_id_bm_elem_get(bases, index, &base_index);
@@ -533,7 +537,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
}
/* exception for faces (verts don't need this) */
- if (r_dist_center && eed) {
+ if (r_dist_center_px_manhattan && eed) {
struct NearestEdgeUserData_ZBuf data;
data.mval_fl[0] = vc->mval[0];
@@ -546,16 +550,16 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
mesh_foreachScreenEdge(
vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- *r_dist_center = data.dist;
+ *r_dist_center_px_manhattan = data.dist;
}
/* end exception */
if (eed) {
- if (dist_px < *r_dist) {
+ if (dist_px_manhattan_test < *dist_px_manhattan_p) {
if (r_base_index) {
*r_base_index = base_index;
}
- *r_dist = dist_px;
+ *dist_px_manhattan_p = dist_px_manhattan_test;
return eed;
}
}
@@ -593,18 +597,19 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
data.cycle_index_prev = 0;
}
- data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+ data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias =
+ *dist_px_manhattan_p;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag);
hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit;
- if (hit->dist < *r_dist) {
+ if (hit->dist < *dist_px_manhattan_p) {
if (r_base_index) {
*r_base_index = base_index;
}
- *r_dist = hit->dist;
+ *dist_px_manhattan_p = hit->dist;
prev_select_bm = vc->em->bm;
}
}
@@ -613,8 +618,8 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
return NULL;
}
- if (r_dist_center) {
- *r_dist_center = hit->dist_center;
+ if (r_dist_center_px_manhattan) {
+ *r_dist_center_px_manhattan = hit->dist_center_px_manhattan;
}
prev_select.index = hit->index;
@@ -624,16 +629,17 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
return hit->edge;
}
-BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist)
+BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *dist_px_manhattan_p)
{
Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact);
- return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL, &base, 1, NULL);
+ return EDBM_edge_find_nearest_ex(
+ vc, dist_px_manhattan_p, NULL, false, false, NULL, &base, 1, NULL);
}
/* find the distance to the face we already have */
struct NearestFaceUserData_ZBuf {
float mval_fl[2];
- float dist;
+ float dist_px_manhattan;
const BMFace *face_test;
};
@@ -647,8 +653,8 @@ static void find_nearest_face_center__doZBuf(void *userData,
if (efa == data->face_test) {
const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
- if (dist_test < data->dist) {
- data->dist = dist_test;
+ if (dist_test < data->dist_px_manhattan) {
+ data->dist_px_manhattan = dist_test;
}
}
}
@@ -702,9 +708,17 @@ static void findnearestface__doClosest(void *userData,
}
}
+/**
+ * \param use_zbuf_single_px: Special case, when using the back-buffer selection,
+ * only use the pixel at `vc->mval` instead of using `dist_px_manhattan_p` to search over a larger
+ * region. This is needed because historically selection worked this way for a long time, however
+ * it's reasonable that some callers might want to expand the region too. So add an argument to do
+ * this,
+ */
BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
- float *r_dist,
+ float *dist_px_manhattan_p,
float *r_dist_center,
+ const bool use_zbuf_single_px,
const bool use_select_bias,
bool use_cycle,
BMFace **r_efa_zbuf,
@@ -715,14 +729,28 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
uint base_index = 0;
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
- float dist_test = 0.0f;
+ float dist_test;
uint index;
BMFace *efa;
{
+ uint dist_px_manhattan_test = 0;
+ if (*dist_px_manhattan_p != 0.0f && (use_zbuf_single_px == false)) {
+ dist_px_manhattan_test = (uint)ED_view3d_backbuf_sample_size_clamp(vc->region,
+ *dist_px_manhattan_p);
+ }
+
DRW_select_buffer_context_create(bases, bases_len, SCE_SELECT_FACE);
- index = DRW_select_buffer_sample_point(vc->depsgraph, vc->region, vc->v3d, vc->mval);
+ if (dist_px_manhattan_test == 0) {
+ index = DRW_select_buffer_sample_point(vc->depsgraph, vc->region, vc->v3d, vc->mval);
+ dist_test = 0.0f;
+ }
+ else {
+ index = DRW_select_buffer_find_nearest_to_point(
+ vc->depsgraph, vc->region, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px_manhattan_test);
+ dist_test = dist_px_manhattan_test;
+ }
if (index) {
efa = (BMFace *)edbm_select_id_bm_elem_get(bases, index, &base_index);
@@ -742,7 +770,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
- data.dist = FLT_MAX;
+ data.dist_px_manhattan = FLT_MAX;
data.face_test = efa;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
@@ -750,16 +778,16 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
mesh_foreachScreenFace(
vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- *r_dist_center = data.dist;
+ *r_dist_center = data.dist_px_manhattan;
}
/* end exception */
if (efa) {
- if (dist_test < *r_dist) {
+ if (dist_test < *dist_px_manhattan_p) {
if (r_base_index) {
*r_base_index = base_index;
}
- *r_dist = dist_test;
+ *dist_px_manhattan_p = dist_test;
return efa;
}
}
@@ -795,18 +823,19 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
data.cycle_index_prev = 0;
}
- data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+ data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias =
+ *dist_px_manhattan_p;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;
- if (hit->dist < *r_dist) {
+ if (hit->dist < *dist_px_manhattan_p) {
if (r_base_index) {
*r_base_index = base_index;
}
- *r_dist = hit->dist;
+ *dist_px_manhattan_p = hit->dist;
prev_select_bm = vc->em->bm;
}
}
@@ -826,10 +855,11 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
return hit->face;
}
-BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
+BMFace *EDBM_face_find_nearest(ViewContext *vc, float *dist_px_manhattan_p)
{
Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact);
- return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL, &base, 1, NULL);
+ return EDBM_face_find_nearest_ex(
+ vc, dist_px_manhattan_p, NULL, false, false, false, NULL, &base, 1, NULL);
}
#undef FIND_NEAR_SELECT_BIAS
@@ -883,7 +913,7 @@ static bool unified_findnearest(ViewContext *vc,
uint base_index = 0;
BMFace *efa_zbuf = NULL;
BMFace *efa_test = EDBM_face_find_nearest_ex(
- vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf, bases, bases_len, &base_index);
+ vc, &dist, dist_center_p, true, true, use_cycle, &efa_zbuf, bases, bases_len, &base_index);
if (efa_test && dist_center_p) {
dist = min_ff(dist_margin, dist_center);
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index ade21f58232..56d971ea59b 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -6886,8 +6886,8 @@ void MESH_OT_sort_elements(wmOperatorType *ot)
"SELECTED",
0,
"Selected",
- "Move all selected elements in first places, preserving their relative order "
- "(WARNING: this will affect unselected elements' indices as well!)"},
+ "Move all selected elements in first places, preserving their relative order.\n"
+ "Warning: This will affect unselected elements' indices as well"},
{SRT_RANDOMIZE, "RANDOMIZE", 0, "Randomize", "Randomize order of selected elements"},
{SRT_REVERSE, "REVERSE", 0, "Reverse", "Reverse current order of selected elements"},
{0, NULL, 0, NULL, NULL},
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 94f386e08d5..2e98f0558f3 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -785,7 +785,7 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
l = v->l;
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv = luv->uv;
- uv_vert_sel = luv->flag & MLOOPUV_VERTSEL;
+ uv_vert_sel = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
lastv = NULL;
iterv = vlist;
@@ -796,7 +796,7 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
l = iterv->l;
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv2 = luv->uv;
- uv2_vert_sel = luv->flag & MLOOPUV_VERTSEL;
+ uv2_vert_sel = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
/* Check if the uv loops share the same selection state (if not, they are not connected as
* they have been ripped or other edit commands have separated them). */
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index e4527740164..7f189abe870 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1416,6 +1416,9 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op)
/* Only created one layer and one material. */
strcpy(md->target_layer, ((bGPDlayer *)gpd->layers.first)->info);
md->target_material = BKE_gpencil_material(ob, 1);
+ if (md->target_material) {
+ id_us_plus(&md->target_material->id);
+ }
/* Stroke object is drawn in front of meshes by default. */
ob->dtx |= OB_DRAW_IN_FRONT;
@@ -1440,41 +1443,6 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static const EnumPropertyItem *object_gpencil_add_options(bContext *C,
- PointerRNA *UNUSED(ptr),
- PropertyRNA *UNUSED(prop),
- bool *r_free)
-{
- EnumPropertyItem *item = NULL;
- const EnumPropertyItem *item_ref = rna_enum_object_gpencil_type_items;
- int totitem = 0;
- int i = 0;
- int orig_count = RNA_enum_items_count(item_ref);
-
- /* Default types. */
- for (i = 0; i < orig_count; i++) {
- if (item_ref[i].value == GP_LRT_OBJECT || item_ref[i].value == GP_LRT_COLLECTION ||
- item_ref[i].value == GP_LRT_SCENE) {
- if (item_ref[i].value == GP_LRT_SCENE) {
- /* separator before line art types */
- RNA_enum_item_add_separator(&item, &totitem);
- }
- else if (item_ref[i].value == GP_LRT_OBJECT) {
- Object *ob = CTX_data_active_object(C);
- if (!ob || ob->type != OB_MESH) {
- continue;
- }
- }
- }
- RNA_enum_item_add(&item, &totitem, &item_ref[i]);
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
-}
-
void OBJECT_OT_gpencil_add(wmOperatorType *ot)
{
/* identifiers */
@@ -1495,7 +1463,6 @@ void OBJECT_OT_gpencil_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, false);
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_gpencil_type_items, 0, "Type", "");
- RNA_def_enum_funcs(ot->prop, object_gpencil_add_options);
}
/** \} */
@@ -1932,8 +1899,8 @@ void OBJECT_OT_pointcloud_add(wmOperatorType *ot)
/* note: now unlinks constraints as well */
void ED_object_base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
{
- if (BKE_library_ID_is_indirectly_used(bmain, ob) && ID_REAL_USERS(ob) <= 1 &&
- ID_EXTRA_USERS(ob) == 0) {
+ if (ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0 &&
+ BKE_library_ID_is_indirectly_used(bmain, ob)) {
/* We cannot delete indirectly used object... */
printf(
"WARNING, undeletable object '%s', should have been caught before reaching this "
@@ -1947,6 +1914,17 @@ void ED_object_base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
BKE_scene_collections_object_remove(bmain, scene, ob, true);
}
+/**
+ * Remove base from a specific scene.
+ * `ob` must not be indirectly used.
+ */
+void ED_object_base_free_and_unlink_no_indirect_check(Main *bmain, Scene *scene, Object *ob)
+{
+ BLI_assert(!BKE_library_ID_is_indirectly_used(bmain, ob));
+ DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_BASE_FLAGS);
+ BKE_scene_collections_object_remove(bmain, scene, ob, true);
+}
+
static int object_delete_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -1954,13 +1932,15 @@ static int object_delete_exec(bContext *C, wmOperator *op)
wmWindowManager *wm = CTX_wm_manager(C);
const bool use_global = RNA_boolean_get(op->ptr, "use_global");
uint changed_count = 0;
+ uint tagged_count = 0;
if (CTX_data_edit_object(C)) {
return OPERATOR_CANCELLED;
}
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+
CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
- const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, ob);
if (ob->id.tag & LIB_TAG_INDIRECT) {
/* Can this case ever happen? */
BKE_reportf(op->reports,
@@ -1969,7 +1949,9 @@ static int object_delete_exec(bContext *C, wmOperator *op)
ob->id.name + 2);
continue;
}
- if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
+
+ if (ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0 &&
+ BKE_library_ID_is_indirectly_used(bmain, ob)) {
BKE_reportf(op->reports,
RPT_WARNING,
"Cannot delete object '%s' from scene '%s', indirectly used objects need at "
@@ -1985,63 +1967,41 @@ static int object_delete_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
}
- /* This is sort of a quick hack to address T51243 -
- * Proper thing to do here would be to nuke most of all this custom scene/object/base handling,
- * and use generic lib remap/query for that.
- * But this is for later (aka 2.8, once layers & co are settled and working).
- */
- if (use_global && ob->id.lib == NULL) {
- /* We want to nuke the object, let's nuke it the easy way (not for linked data though)... */
- BKE_id_delete(bmain, &ob->id);
- changed_count += 1;
- continue;
- }
-
- /* remove from Grease Pencil parent */
- /* XXX This is likely not correct?
- * Will also remove parent from grease pencil from other scenes,
- * even when use_global is false... */
- for (bGPdata *gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
- LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
- if (gpl->parent != NULL) {
- if (gpl->parent == ob) {
- gpl->parent = NULL;
- }
- }
- }
+ /* Use multi tagged delete if `use_global=True`, or the object is used only in one scene. */
+ if (use_global || ID_REAL_USERS(ob) <= 1) {
+ ob->id.tag |= LIB_TAG_DOIT;
+ tagged_count += 1;
}
+ else {
+ /* Object is used in multiple scenes. Delete the object from the current scene only. */
+ ED_object_base_free_and_unlink_no_indirect_check(bmain, scene, ob);
+ changed_count += 1;
- /* remove from current scene only */
- ED_object_base_free_and_unlink(bmain, scene, ob);
- changed_count += 1;
-
- if (use_global) {
- Scene *scene_iter;
- for (scene_iter = bmain->scenes.first; scene_iter; scene_iter = scene_iter->id.next) {
- if (scene_iter != scene && !ID_IS_LINKED(scene_iter)) {
- if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
- BKE_reportf(op->reports,
- RPT_WARNING,
- "Cannot delete object '%s' from scene '%s', indirectly used objects need "
- "at least one user",
- ob->id.name + 2,
- scene_iter->id.name + 2);
- break;
+ /* FIXME: this will also remove parent from grease pencil from other scenes. */
+ /* Remove from Grease Pencil parent */
+ for (bGPdata *gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ if (gpl->parent != NULL) {
+ if (gpl->parent == ob) {
+ gpl->parent = NULL;
+ }
}
- ED_object_base_free_and_unlink(bmain, scene_iter, ob);
}
}
}
- /* end global */
}
CTX_DATA_END;
- BKE_reportf(op->reports, RPT_INFO, "Deleted %u object(s)", changed_count);
-
- if (changed_count == 0) {
+ if ((changed_count + tagged_count) == 0) {
return OPERATOR_CANCELLED;
}
+ if (tagged_count > 0) {
+ BKE_id_multi_tagged_delete(bmain);
+ }
+
+ BKE_reportf(op->reports, RPT_INFO, "Deleted %u object(s)", (changed_count + tagged_count));
+
/* delete has to handle all open scenes */
BKE_main_id_tag_listbase(&bmain->scenes, LIB_TAG_DOIT, true);
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
index 72ef72403cf..22c9d669ff3 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -684,7 +684,8 @@ void OBJECT_OT_data_transfer(wmOperatorType *ot)
false,
"Auto Transform",
"Automatically compute transformation to get the best possible match between source and "
- "destination meshes (WARNING: results will never be as good as manual matching of objects)");
+ "destination meshes.\n"
+ "Warning: Results will never be as good as manual matching of objects");
RNA_def_boolean(ot->srna,
"use_object_transform",
true,
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 7673649c261..b28b7478721 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -1115,6 +1115,40 @@ bool edit_modifier_invoke_properties(bContext *C, wmOperator *op)
return false;
}
+/**
+ * If the "modifier" property is not set,fill the modifier property with the name of the modifier
+ * with a UI panel below the mouse cursor, without checking the context pointer. Used in order to
+ * apply modifier operators on hover over their panels. If this checked the context pointer then it
+ * would always use the active modifier, which isn't desired.
+ */
+bool edit_modifier_invoke_properties_with_hover_no_active(bContext *C,
+ wmOperator *op,
+ const wmEvent *event,
+ int *r_retval)
+{
+ if (RNA_struct_property_is_set(op->ptr, "modifier")) {
+ return true;
+ }
+
+ PointerRNA *panel_ptr = UI_region_panel_custom_data_under_cursor(C, event);
+ if (panel_ptr == NULL || RNA_pointer_is_null(panel_ptr)) {
+ *r_retval = OPERATOR_CANCELLED;
+ return false;
+ }
+
+ if (!RNA_struct_is_a(panel_ptr->type, &RNA_Modifier)) {
+ /* Work around multiple operators using the same shortcut. The operators for the other
+ * stacks in the property editor use the same key, and will not run after these return
+ * OPERATOR_CANCELLED. */
+ *r_retval = (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED);
+ return false;
+ }
+
+ const ModifierData *md = panel_ptr->data;
+ RNA_string_set(op->ptr, "modifier", md->name);
+ return true;
+}
+
ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
{
char modifier_name[MAX_NAME];
@@ -1174,14 +1208,13 @@ static int modifier_remove_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (edit_modifier_invoke_properties(C, op)) {
+ int retval;
+ if (edit_modifier_invoke_properties_with_hover_no_active(C, op, event, &retval)) {
return modifier_remove_exec(C, op);
}
-
- /* Work around multiple operators using the same shortcut. */
- return (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED);
+ return retval;
}
void OBJECT_OT_modifier_remove(wmOperatorType *ot)
@@ -1221,13 +1254,13 @@ static int modifier_move_up_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (edit_modifier_invoke_properties(C, op)) {
+ int retval;
+ if (edit_modifier_invoke_properties_with_hover_no_active(C, op, event, &retval)) {
return modifier_move_up_exec(C, op);
}
- /* Work around multiple operators using the same shortcut. */
- return (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED);
+ return retval;
}
void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
@@ -1266,13 +1299,13 @@ static int modifier_move_down_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (edit_modifier_invoke_properties(C, op)) {
+ int retval;
+ if (edit_modifier_invoke_properties_with_hover_no_active(C, op, event, &retval)) {
return modifier_move_down_exec(C, op);
}
- /* Work around multiple operators using the same shortcut. */
- return (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED);
+ return retval;
}
void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
@@ -1309,12 +1342,13 @@ static int modifier_move_to_index_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int modifier_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int modifier_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (edit_modifier_invoke_properties(C, op)) {
+ int retval;
+ if (edit_modifier_invoke_properties_with_hover_no_active(C, op, event, &retval)) {
return modifier_move_to_index_exec(C, op);
}
- return OPERATOR_CANCELLED;
+ return retval;
}
void OBJECT_OT_modifier_move_to_index(wmOperatorType *ot)
@@ -1421,13 +1455,13 @@ static int modifier_apply_exec(bContext *C, wmOperator *op)
return modifier_apply_exec_ex(C, op, MODIFIER_APPLY_DATA, false);
}
-static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (edit_modifier_invoke_properties(C, op)) {
+ int retval;
+ if (edit_modifier_invoke_properties_with_hover_no_active(C, op, event, &retval)) {
return modifier_apply_exec(C, op);
}
- /* Work around multiple operators using the same shortcut. */
- return (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED);
+ return retval;
}
void OBJECT_OT_modifier_apply(wmOperatorType *ot)
@@ -1465,15 +1499,13 @@ static int modifier_apply_as_shapekey_exec(bContext *C, wmOperator *op)
return modifier_apply_exec_ex(C, op, MODIFIER_APPLY_SHAPE, keep);
}
-static int modifier_apply_as_shapekey_invoke(bContext *C,
- wmOperator *op,
- const wmEvent *UNUSED(event))
+static int modifier_apply_as_shapekey_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (edit_modifier_invoke_properties(C, op)) {
+ int retval;
+ if (edit_modifier_invoke_properties_with_hover_no_active(C, op, event, &retval)) {
return modifier_apply_as_shapekey_exec(C, op);
}
- /* Work around multiple operators using the same shortcut. */
- return (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED);
+ return retval;
}
static char *modifier_apply_as_shapekey_get_description(struct bContext *UNUSED(C),
@@ -1579,13 +1611,13 @@ static int modifier_copy_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (edit_modifier_invoke_properties(C, op)) {
+ int retval;
+ if (edit_modifier_invoke_properties_with_hover_no_active(C, op, event, &retval)) {
return modifier_copy_exec(C, op);
}
- /* Work around multiple operators using the same shortcut. */
- return (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED);
+ return retval;
}
void OBJECT_OT_modifier_copy(wmOperatorType *ot)
@@ -1622,54 +1654,12 @@ static int modifier_set_active_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-/**
- * Get the modifier below the mouse cursor modifier without checking the context pointer.
- * Used in order to set the active modifier on mouse click. If this checked the context
- * pointer then it would always set the active modifier to the already active modifier.
- *
- * \param event: If this isn't NULL, the operator will also look for panels underneath
- * the cursor with custom-data set to a modifier.
- * \param r_retval: This should be used if #event is used in order to return
- * #OPERATOR_PASS_THROUGH to check other operators with the same key set.
- */
-bool edit_modifier_invoke_properties_with_hover_no_active(bContext *C,
- wmOperator *op,
- const wmEvent *event,
- int *r_retval)
-{
- if (RNA_struct_property_is_set(op->ptr, "modifier")) {
- return true;
- }
-
- PointerRNA *panel_ptr = UI_region_panel_custom_data_under_cursor(C, event);
-
- if (!(panel_ptr == NULL || RNA_pointer_is_null(panel_ptr))) {
- if (RNA_struct_is_a(panel_ptr->type, &RNA_Modifier)) {
- ModifierData *md = panel_ptr->data;
- RNA_string_set(op->ptr, "modifier", md->name);
- return true;
- }
- BLI_assert(r_retval != NULL); /* We need the return value in this case. */
- if (r_retval != NULL) {
- *r_retval = (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED);
- }
- return false;
- }
-
- if (r_retval != NULL) {
- *r_retval = OPERATOR_CANCELLED;
- }
-
- return false;
-}
-
static int modifier_set_active_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int retval;
if (edit_modifier_invoke_properties_with_hover_no_active(C, op, event, &retval)) {
return modifier_set_active_exec(C, op);
}
-
return retval;
}
@@ -1756,15 +1746,13 @@ static int modifier_copy_to_selected_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int modifier_copy_to_selected_invoke(bContext *C,
- wmOperator *op,
- const wmEvent *UNUSED(event))
+static int modifier_copy_to_selected_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (edit_modifier_invoke_properties(C, op)) {
- return modifier_copy_to_selected_exec(C, op);
+ int retval;
+ if (edit_modifier_invoke_properties_with_hover_no_active(C, op, event, &retval)) {
+ return modifier_set_active_exec(C, op);
}
- /* Work around multiple operators using the same shortcut. */
- return (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED);
+ return retval;
}
static bool modifier_copy_to_selected_poll(bContext *C)
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 13c0740bce6..1d7cf61bc3a 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -1782,12 +1782,7 @@ static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, cons
vc.v3d->flag2 |= V3D_HIDE_OVERLAYS;
#endif
- ED_view3d_autodist_init(vc.depsgraph, vc.region, vc.v3d, 0);
-
- if (vc.rv3d->depths != NULL) {
- vc.rv3d->depths->damaged = true;
- }
- ED_view3d_depth_update(vc.region);
+ ED_view3d_depth_override(vc.depsgraph, vc.region, vc.v3d, NULL, V3D_DEPTH_NO_GPENCIL, true);
#ifdef USE_RENDER_OVERRIDE
vc.v3d->flag2 = flag2_prev;
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 0ec8238f741..de4ad913d6d 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -524,15 +524,13 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
ED_view3d_viewcontext_init(C, &data->vc, data->depsgraph);
if (!XRAY_ENABLED(data->vc.v3d)) {
- if (data->vc.v3d->flag & V3D_INVALID_BACKBUF) {
- /* needed or else the draw matrix can be incorrect */
- view3d_operator_needs_opengl(C);
-
- ED_view3d_backbuf_depth_validate(&data->vc);
- /* we may need to force an update here by setting the rv3d as dirty
- * for now it seems ok, but take care!:
- * rv3d->depths->dirty = 1; */
- ED_view3d_depth_update(data->vc.region);
+ if (!(data->vc.v3d->runtime.flag & V3D_RUNTIME_DEPTHBUF_OVERRIDDEN)) {
+ ED_view3d_depth_override(data->depsgraph,
+ data->vc.region,
+ data->vc.v3d,
+ data->vc.obact,
+ V3D_DEPTH_OBJECT_ONLY,
+ true);
}
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index b44f2f66d92..c5e7b2dc4d3 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -545,6 +545,7 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups,
int x,
int y,
float zoom,
+ const ePaintMode mode,
bool col,
bool primary)
{
@@ -556,6 +557,13 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups,
(brush->overlay_flags & BRUSH_OVERLAY_SECONDARY) != 0);
int overlay_alpha = (primary) ? brush->texture_overlay_alpha : brush->mask_overlay_alpha;
+ if (mode == PAINT_MODE_TEXTURE_3D) {
+ if (primary && brush->imagepaint_tool == PAINT_TOOL_DRAW) {
+ /* All non-draw tools don't use the primary texture (clone, smear, soften.. etc). */
+ return false;
+ }
+ }
+
if (!(mtex->tex) ||
!((mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) ||
(valid && ELEM(mtex->brush_map_mode, MTEX_MAP_MODE_VIEW, MTEX_MAP_MODE_TILED)))) {
@@ -785,10 +793,11 @@ static bool paint_draw_alpha_overlay(UnifiedPaintSettings *ups,
/* Colored overlay should be drawn separately. */
if (col) {
if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY)) {
- alpha_overlay_active = paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, true, true);
+ alpha_overlay_active = paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, mode, true, true);
}
if (!(flags & PAINT_OVERLAY_OVERRIDE_SECONDARY)) {
- alpha_overlay_active = paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, false);
+ alpha_overlay_active = paint_draw_tex_overlay(
+ ups, brush, vc, x, y, zoom, mode, false, false);
}
if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR)) {
alpha_overlay_active = paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
@@ -796,7 +805,7 @@ static bool paint_draw_alpha_overlay(UnifiedPaintSettings *ups,
}
else {
if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY) && (mode != PAINT_MODE_WEIGHT)) {
- alpha_overlay_active = paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, true);
+ alpha_overlay_active = paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, mode, false, true);
}
if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR)) {
alpha_overlay_active = paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 9bdca35468e..76bfb34c809 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -2543,7 +2543,7 @@ int ED_path_extension_type(const char *path)
if (BLI_path_extension_check(path, ".zip")) {
return FILE_TYPE_ARCHIVE;
}
- if (BLI_path_extension_check_n(path, ".obj", ".3ds", ".fbx", ".glb", ".gltf", NULL)) {
+ if (BLI_path_extension_check_n(path, ".obj", ".3ds", ".fbx", ".glb", ".gltf", ".svg", NULL)) {
return FILE_TYPE_OBJECT_IO;
}
if (BLI_path_extension_check_array(path, imb_ext_image)) {
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
index 0044c6072a4..d302f099772 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -50,6 +50,7 @@ void IMAGE_OT_view_all(struct wmOperatorType *ot);
void IMAGE_OT_view_pan(struct wmOperatorType *ot);
void IMAGE_OT_view_selected(struct wmOperatorType *ot);
void IMAGE_OT_view_center_cursor(struct wmOperatorType *ot);
+void IMAGE_OT_view_cursor_center(struct wmOperatorType *ot);
void IMAGE_OT_view_zoom(struct wmOperatorType *ot);
void IMAGE_OT_view_zoom_in(struct wmOperatorType *ot);
void IMAGE_OT_view_zoom_out(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 72405a51aca..48e1397601f 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -244,6 +244,70 @@ static bool image_not_packed_poll(bContext *C)
return (ima && BLI_listbase_is_empty(&ima->packedfiles));
}
+static void image_view_all(struct SpaceImage *sima, struct ARegion *region, struct wmOperator *op)
+{
+ float aspx, aspy, zoomx, zoomy, w, h;
+ int width, height;
+ const bool fit_view = RNA_boolean_get(op->ptr, "fit_view");
+
+ ED_space_image_get_size(sima, &width, &height);
+ ED_space_image_get_aspect(sima, &aspx, &aspy);
+
+ w = width * aspx;
+ h = height * aspy;
+
+ float xof = 0.0f, yof = 0.0f;
+ if ((sima->image == NULL) || (sima->image->source == IMA_SRC_TILED)) {
+ /* Extend the shown area to cover all UDIM tiles. */
+ int x_tiles, y_tiles;
+ if (sima->image == NULL) {
+ x_tiles = sima->tile_grid_shape[0];
+ y_tiles = sima->tile_grid_shape[1];
+ }
+ else {
+ x_tiles = y_tiles = 1;
+ LISTBASE_FOREACH (ImageTile *, tile, &sima->image->tiles) {
+ int tile_x = (tile->tile_number - 1001) % 10;
+ int tile_y = (tile->tile_number - 1001) / 10;
+ x_tiles = max_ii(x_tiles, tile_x + 1);
+ y_tiles = max_ii(y_tiles, tile_y + 1);
+ }
+ }
+ xof = 0.5f * (x_tiles - 1.0f) * w;
+ yof = 0.5f * (y_tiles - 1.0f) * h;
+ w *= x_tiles;
+ h *= y_tiles;
+ }
+
+ /* check if the image will fit in the image with (zoom == 1) */
+ width = BLI_rcti_size_x(&region->winrct) + 1;
+ height = BLI_rcti_size_y(&region->winrct) + 1;
+
+ if (fit_view) {
+ const int margin = 5; /* margin from border */
+
+ zoomx = (float)width / (w + 2 * margin);
+ zoomy = (float)height / (h + 2 * margin);
+
+ sima_zoom_set(sima, region, min_ff(zoomx, zoomy), NULL, false);
+ }
+ else {
+ if ((w >= width || h >= height) && (width > 0 && height > 0)) {
+ zoomx = (float)width / w;
+ zoomy = (float)height / h;
+
+ /* find the zoom value that will fit the image in the image space */
+ sima_zoom_set(sima, region, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL, false);
+ }
+ else {
+ sima_zoom_set(sima, region, 1.0f, NULL, false);
+ }
+ }
+
+ sima->xof = xof;
+ sima->yof = yof;
+}
+
bool space_image_main_region_poll(bContext *C)
{
SpaceImage *sima = CTX_wm_space_image(C);
@@ -736,70 +800,12 @@ static int image_view_all_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima;
ARegion *region;
- float aspx, aspy, zoomx, zoomy, w, h;
- int width, height;
- const bool fit_view = RNA_boolean_get(op->ptr, "fit_view");
/* retrieve state */
sima = CTX_wm_space_image(C);
region = CTX_wm_region(C);
- ED_space_image_get_size(sima, &width, &height);
- ED_space_image_get_aspect(sima, &aspx, &aspy);
-
- w = width * aspx;
- h = height * aspy;
-
- float xof = 0.0f, yof = 0.0f;
- if ((sima->image == NULL) || (sima->image->source == IMA_SRC_TILED)) {
- /* Extend the shown area to cover all UDIM tiles. */
- int x_tiles, y_tiles;
- if (sima->image == NULL) {
- x_tiles = sima->tile_grid_shape[0];
- y_tiles = sima->tile_grid_shape[1];
- }
- else {
- x_tiles = y_tiles = 1;
- LISTBASE_FOREACH (ImageTile *, tile, &sima->image->tiles) {
- int tile_x = (tile->tile_number - 1001) % 10;
- int tile_y = (tile->tile_number - 1001) / 10;
- x_tiles = max_ii(x_tiles, tile_x + 1);
- y_tiles = max_ii(y_tiles, tile_y + 1);
- }
- }
- xof = 0.5f * (x_tiles - 1.0f) * w;
- yof = 0.5f * (y_tiles - 1.0f) * h;
- w *= x_tiles;
- h *= y_tiles;
- }
-
- /* check if the image will fit in the image with (zoom == 1) */
- width = BLI_rcti_size_x(&region->winrct) + 1;
- height = BLI_rcti_size_y(&region->winrct) + 1;
-
- if (fit_view) {
- const int margin = 5; /* margin from border */
-
- zoomx = (float)width / (w + 2 * margin);
- zoomy = (float)height / (h + 2 * margin);
-
- sima_zoom_set(sima, region, min_ff(zoomx, zoomy), NULL, false);
- }
- else {
- if ((w >= width || h >= height) && (width > 0 && height > 0)) {
- zoomx = (float)width / w;
- zoomy = (float)height / h;
-
- /* find the zoom value that will fit the image in the image space */
- sima_zoom_set(sima, region, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL, false);
- }
- else {
- sima_zoom_set(sima, region, 1.0f, NULL, false);
- }
- }
-
- sima->xof = xof;
- sima->yof = yof;
+ image_view_all(sima, region, op);
ED_region_tag_redraw(region);
@@ -830,6 +836,49 @@ void IMAGE_OT_view_all(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Cursor To Center View Operator
+ * \{ */
+
+static int view_cursor_center_exec(bContext *C, wmOperator *op)
+{
+ SpaceImage *sima;
+ ARegion *region;
+
+ sima = CTX_wm_space_image(C);
+ region = CTX_wm_region(C);
+
+ image_view_all(sima, region, op);
+
+ sima->cursor[0] = 0.5f;
+ sima->cursor[1] = 0.5f;
+
+ /* Needed for updating the cursor. */
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_view_cursor_center(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Cursor To Center View";
+ ot->description = "Set 2D Cursor To Center View location";
+ ot->idname = "IMAGE_OT_view_cursor_center";
+
+ /* api callbacks */
+ ot->exec = view_cursor_center_exec;
+ ot->poll = ED_space_image_cursor_poll;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "fit_view", 0, "Fit View", "Fit frame to the viewport");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Center View To Cursor Operator
* \{ */
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index c51d2f25efd..5a03b4f6ef0 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -200,6 +200,7 @@ static void image_operatortypes(void)
WM_operatortype_append(IMAGE_OT_view_pan);
WM_operatortype_append(IMAGE_OT_view_selected);
WM_operatortype_append(IMAGE_OT_view_center_cursor);
+ WM_operatortype_append(IMAGE_OT_view_cursor_center);
WM_operatortype_append(IMAGE_OT_view_zoom);
WM_operatortype_append(IMAGE_OT_view_zoom_in);
WM_operatortype_append(IMAGE_OT_view_zoom_out);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 0110de905d5..44da4b4ab11 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -1528,6 +1528,17 @@ static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA
uiItemR(sub, ptr, "z_scale", DEFAULT_FLAGS, NULL, ICON_NONE);
}
+static void node_composit_buts_antialiasing(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiLayout *col;
+
+ col = uiLayoutColumn(layout, false);
+
+ uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "contrast_limit", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "corner_rounding", 0, NULL, ICON_NONE);
+}
+
/* qdn: glare node */
static void node_composit_buts_glare(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
@@ -2799,6 +2810,9 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_DEFOCUS:
ntype->draw_buttons = node_composit_buts_defocus;
break;
+ case CMP_NODE_ANTIALIASING:
+ ntype->draw_buttons = node_composit_buts_antialiasing;
+ break;
case CMP_NODE_GLARE:
ntype->draw_buttons = node_composit_buts_glare;
break;
@@ -3429,7 +3443,7 @@ static void std_node_socket_draw(
}
break;
case SOCK_RGBA: {
- uiLayout *row = uiLayoutSplit(layout, 0.5f, false);
+ uiLayout *row = uiLayoutSplit(layout, 0.4f, false);
uiItemL(row, text, 0);
const bNodeTree *node_tree = (const bNodeTree *)node_ptr->owner_id;
@@ -3443,7 +3457,7 @@ static void std_node_socket_draw(
break;
}
case SOCK_STRING: {
- uiLayout *row = uiLayoutSplit(layout, 0.5f, false);
+ uiLayout *row = uiLayoutSplit(layout, 0.4f, false);
uiItemL(row, text, 0);
const bNodeTree *node_tree = (const bNodeTree *)node_ptr->owner_id;
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index a646804e0fd..c4fe9e9e531 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -472,6 +472,8 @@ static int node_add_object_exec(bContext *C, wmOperator *op)
snode_notify(C, snode);
snode_dag_update(C, snode);
+ ED_node_tag_update_nodetree(bmain, ntree, object_node);
+
return OPERATOR_FINISHED;
}
@@ -496,7 +498,8 @@ static int node_add_object_invoke(bContext *C, wmOperator *op, const wmEvent *ev
static bool node_add_object_poll(bContext *C)
{
const SpaceNode *snode = CTX_wm_space_node(C);
- return ED_operator_node_editable(C) && ELEM(snode->nodetree->type, NTREE_GEOMETRY);
+ return ED_operator_node_editable(C) && ELEM(snode->nodetree->type, NTREE_GEOMETRY) &&
+ !UI_but_active_drop_name(C);
}
void NODE_OT_add_object(wmOperatorType *ot)
@@ -568,6 +571,8 @@ static int node_add_texture_exec(bContext *C, wmOperator *op)
snode_notify(C, snode);
snode_dag_update(C, snode);
+ ED_node_tag_update_nodetree(bmain, ntree, texture_node);
+
return OPERATOR_FINISHED;
}
@@ -592,7 +597,8 @@ static int node_add_texture_invoke(bContext *C, wmOperator *op, const wmEvent *e
static bool node_add_texture_poll(bContext *C)
{
const SpaceNode *snode = CTX_wm_space_node(C);
- return ED_operator_node_editable(C) && ELEM(snode->nodetree->type, NTREE_GEOMETRY);
+ return ED_operator_node_editable(C) && ELEM(snode->nodetree->type, NTREE_GEOMETRY) &&
+ !UI_but_active_drop_name(C);
}
void NODE_OT_add_texture(wmOperatorType *ot)
@@ -670,6 +676,8 @@ static int node_add_collection_exec(bContext *C, wmOperator *op)
snode_notify(C, snode);
snode_dag_update(C, snode);
+ ED_node_tag_update_nodetree(bmain, ntree, collection_node);
+
return OPERATOR_FINISHED;
}
@@ -694,7 +702,8 @@ static int node_add_collection_invoke(bContext *C, wmOperator *op, const wmEvent
static bool node_add_collection_poll(bContext *C)
{
const SpaceNode *snode = CTX_wm_space_node(C);
- return ED_operator_node_editable(C) && ELEM(snode->nodetree->type, NTREE_GEOMETRY);
+ return ED_operator_node_editable(C) && ELEM(snode->nodetree->type, NTREE_GEOMETRY) &&
+ !UI_but_active_drop_name(C);
}
void NODE_OT_add_collection(wmOperatorType *ot)
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index fa4d6997c83..eb89658857b 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -198,7 +198,7 @@ void node_buttons_register(ARegionType *art)
{
PanelType *pt = MEM_callocN(sizeof(PanelType), __func__);
strcpy(pt->idname, "NODE_PT_node_tree_interface_inputs");
- strcpy(pt->category, N_("Node"));
+ strcpy(pt->category, N_("Group"));
strcpy(pt->label, N_("Inputs"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = node_tree_interface_inputs_panel;
@@ -208,7 +208,7 @@ void node_buttons_register(ARegionType *art)
{
PanelType *pt = MEM_callocN(sizeof(PanelType), __func__);
strcpy(pt->idname, "NODE_PT_node_tree_interface_outputs");
- strcpy(pt->category, N_("Node"));
+ strcpy(pt->category, N_("Group"));
strcpy(pt->label, N_("Outputs"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = node_tree_interface_outputs_panel;
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index b72a6503749..8fdee01f78e 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -1128,10 +1128,15 @@ static bool cursor_isect_multi_input_socket(const float cursor[2], const bNodeSo
{
const float node_socket_height = node_socket_calculate_height(socket);
const rctf multi_socket_rect = {
- .xmin = socket->locx - NODE_SOCKSIZE * 4,
- .xmax = socket->locx + NODE_SOCKSIZE,
- .ymin = socket->locy - node_socket_height * 0.5 - NODE_SOCKSIZE * 2.0f,
- .ymax = socket->locy + node_socket_height * 0.5 + NODE_SOCKSIZE * 2.0f,
+ .xmin = socket->locx - NODE_SOCKSIZE * 4.0f,
+ .xmax = socket->locx + NODE_SOCKSIZE * 2.0f,
+ /*.xmax = socket->locx + NODE_SOCKSIZE * 5.5f
+ * would be the same behavior as for regular sockets.
+ * But keep it smaller because for multi-input socket you
+ * sometimes want to drag the link to the other side, if you may
+ * accidentally pick the wrong link otherwise. */
+ .ymin = socket->locy - node_socket_height * 0.5 - NODE_SOCKSIZE,
+ .ymax = socket->locy + node_socket_height * 0.5 + NODE_SOCKSIZE,
};
if (BLI_rctf_isect_pt(&multi_socket_rect, cursor[0], cursor[1])) {
return true;
@@ -1141,7 +1146,7 @@ static bool cursor_isect_multi_input_socket(const float cursor[2], const bNodeSo
/* type is SOCK_IN and/or SOCK_OUT */
int node_find_indicated_socket(
- SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, float cursor[2], int in_out)
+ SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, const float cursor[2], int in_out)
{
rctf rect;
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index fbf9d8869ac..ff37496148f 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -262,7 +262,7 @@ int node_render_changed_exec(bContext *, struct wmOperator *);
int node_find_indicated_socket(struct SpaceNode *snode,
struct bNode **nodep,
struct bNodeSocket **sockp,
- float cursor[2],
+ const float cursor[2],
int in_out);
void NODE_OT_duplicate(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 4b2290c094b..95584847d6e 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -245,18 +245,8 @@ static void pick_input_link_by_link_intersect(const bContext *C,
bNodeSocket *socket;
node_find_indicated_socket(snode, &node, &socket, drag_start, SOCK_IN);
- const float trigger_drag_distance = 25.0f;
- const float cursor_link_touch_distance = 25.0f;
-
- const float socket_height = node_socket_calculate_height(socket);
-
- float cursor_to_socket_relative[2];
- float socket_position[2] = {socket->locx, socket->locy};
- sub_v2_v2v2(cursor_to_socket_relative, cursor, socket_position);
- float distance_from_socket_v2[2] = {
- max_ff(0, fabs(cursor_to_socket_relative[0]) - NODE_SOCKSIZE * 0.5),
- max_ff(0, fabs(cursor_to_socket_relative[1]) - socket_height)};
- const float distance_from_socket = len_v2(distance_from_socket_v2);
+ /* Distance to test overlapping of cursor on link. */
+ const float cursor_link_touch_distance = 12.5f * UI_DPI_FAC;
const int resolution = NODE_LINK_RESOL;
@@ -301,7 +291,7 @@ static void pick_input_link_by_link_intersect(const bContext *C,
link_to_pick->flag |= NODE_LINK_TEMP_HIGHLIGHT;
ED_area_tag_redraw(CTX_wm_area(C));
- if (distance_from_socket > trigger_drag_distance) {
+ if (!node_find_indicated_socket(snode, &node, &socket, cursor, SOCK_IN)) {
pick_link(C, op, nldrag, snode, node, link_to_pick);
}
}
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index 1da79671c8e..6548f6f5775 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -568,11 +568,19 @@ static int node_mouse_select(bContext *C,
}
}
else if (deselect_all && node == NULL) {
- /* Deselect in empty space. */
- for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
- nodeSetSelected(tnode, false);
+ /* Rather than deselecting others, users may want to drag to box-select (drag from empty
+ * space) or tweak-translate an already selected item. If these cases may apply, delay
+ * deselection. */
+ if (wait_to_deselect_others) {
+ ret_value = OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ /* Deselect in empty space. */
+ for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
+ nodeSetSelected(tnode, false);
+ }
+ ret_value = OPERATOR_FINISHED;
}
- ret_value = OPERATOR_FINISHED;
}
else if (node != NULL) {
/* When clicking on an already selected node, we want to wait to deselect
diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c
index b3b36811411..83f71292232 100644
--- a/source/blender/editors/space_outliner/outliner_dragdrop.c
+++ b/source/blender/editors/space_outliner/outliner_dragdrop.c
@@ -1104,9 +1104,7 @@ static bool collection_drop_init(bContext *C,
const wmEvent *event,
CollectionDrop *data)
{
- SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
-
- /* Get collection to drop into. */
+/* Get collection to drop into. */
TreeElementInsertType insert_type;
TreeElement *te = outliner_drop_insert_collection_find(C, event, &insert_type);
if (!te) {
@@ -1140,7 +1138,7 @@ static bool collection_drop_init(bContext *C,
/* Get collection to drag out of. */
ID *parent = drag_id->from_parent;
Collection *from_collection = collection_parent_from_ID(parent);
- if (event->ctrl || space_outliner->outlinevis == SO_SCENES) {
+ if (event->ctrl) {
from_collection = NULL;
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 278162c4338..0916e106abf 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -63,6 +63,7 @@
#include "ED_screen.h"
#include "WM_api.h"
+#include "WM_message.h"
#include "WM_types.h"
#include "GPU_immediate.h"
@@ -663,6 +664,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
{
Main *bmain = CTX_data_main(C);
SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
BLI_mempool *ts = space_outliner->treestore;
TreeStoreElem *tselem = tsep;
@@ -672,6 +674,8 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
if (tselem->type == TSE_SOME_ID) {
BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
+ WM_msg_publish_rna_prop(mbus, tselem->id, tselem->id, ID, name);
+
switch (GS(tselem->id->name)) {
case ID_MA:
WM_event_add_notifier(C, NC_MATERIAL, NULL);
@@ -724,12 +728,19 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
}
else {
switch (tselem->type) {
- case TSE_DEFGROUP:
- BKE_object_defgroup_unique_name(te->directdata, (Object *)tselem->id); /* id = object. */
+ case TSE_DEFGROUP: {
+ Object *ob = (Object *)tselem->id;
+ bDeformGroup *vg = te->directdata;
+ BKE_object_defgroup_unique_name(vg, ob);
+ WM_msg_publish_rna_prop(mbus, &ob->id, vg, VertexGroup, name);
break;
- case TSE_NLA_ACTION:
- BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
+ }
+ case TSE_NLA_ACTION: {
+ bAction *act = (bAction *)tselem->id;
+ BLI_libblock_ensure_unique_name(bmain, act->id.name);
+ WM_msg_publish_rna_prop(mbus, &act->id, &act->id, ID, name);
break;
+ }
case TSE_EBONE: {
bArmature *arm = (bArmature *)tselem->id;
if (arm->edbo) {
@@ -740,6 +751,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
BLI_strncpy(newname, ebone->name, sizeof(ebone->name));
BLI_strncpy(ebone->name, oldname, sizeof(ebone->name));
ED_armature_bone_rename(bmain, arm, oldname, newname);
+ WM_msg_publish_rna_prop(mbus, &arm->id, ebone, EditBone, name);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
}
break;
@@ -760,6 +772,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
BLI_strncpy(newname, bone->name, sizeof(bone->name));
BLI_strncpy(bone->name, oldname, sizeof(bone->name));
ED_armature_bone_rename(bmain, arm, oldname, newname);
+ WM_msg_publish_rna_prop(mbus, &arm->id, bone, Bone, name);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
break;
}
@@ -768,6 +781,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
outliner_viewcontext_init(C, &tvc);
Object *ob = (Object *)tselem->id;
+ bArmature *arm = (bArmature *)ob->data;
bPoseChannel *pchan = te->directdata;
char newname[sizeof(pchan->name)];
@@ -780,6 +794,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
BLI_strncpy(newname, pchan->name, sizeof(pchan->name));
BLI_strncpy(pchan->name, oldname, sizeof(pchan->name));
ED_armature_bone_rename(bmain, ob->data, oldname, newname);
+ WM_msg_publish_rna_prop(mbus, &arm->id, pchan->bone, Bone, name);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
break;
}
@@ -793,6 +808,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
'.',
offsetof(bActionGroup, name),
sizeof(grp->name));
+ WM_msg_publish_rna_prop(mbus, &ob->id, grp, ActionGroup, name);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
break;
}
@@ -807,6 +823,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
BLI_uniquename(
&gpd->layers, gpl, "GP Layer", '.', offsetof(bGPDlayer, info), sizeof(gpl->info));
+ WM_msg_publish_rna_prop(mbus, &gpd->id, gpl, GPencilLayer, info);
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, gpd);
break;
@@ -822,11 +839,15 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
/* Rename, preserving animation and compositing data. */
BKE_view_layer_rename(bmain, scene, view_layer, newname);
+ WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, ViewLayer, name);
WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL);
break;
}
case TSE_LAYER_COLLECTION: {
- BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
+ /* The ID is a #Collection, not a #LayerCollection */
+ Collection *collection = (Collection *)tselem->id;
+ BLI_libblock_ensure_unique_name(bmain, collection->id.name);
+ WM_msg_publish_rna_prop(mbus, &collection->id, &collection->id, ID, name);
WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL);
break;
}
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 681f7fab18a..7fe66b017a4 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -466,7 +466,7 @@ static void id_delete(bContext *C, ReportList *reports, TreeElement *te, TreeSto
BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked id '%s'", id->name);
return;
}
- if (BKE_library_ID_is_indirectly_used(bmain, id) && ID_REAL_USERS(id) <= 1) {
+ if (ID_REAL_USERS(id) <= 1 && BKE_library_ID_is_indirectly_used(bmain, id)) {
BKE_reportf(reports,
RPT_WARNING,
"Cannot delete id '%s', indirectly used data-blocks need at least one user",
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index dc9205106ab..66eb6ab15dc 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -699,8 +699,8 @@ static void outliner_object_delete_fn(bContext *C, ReportList *reports, Scene *s
reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2);
return;
}
- if (BKE_library_ID_is_indirectly_used(bmain, ob) && ID_REAL_USERS(ob) <= 1 &&
- ID_EXTRA_USERS(ob) == 0) {
+ if (ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0 &&
+ BKE_library_ID_is_indirectly_used(bmain, ob)) {
BKE_reportf(reports,
RPT_WARNING,
"Cannot delete object '%s' from scene '%s', indirectly used objects need at "
@@ -1422,8 +1422,8 @@ static Base *outline_batch_delete_hierarchy(
base->object->id.name + 2);
return base_next;
}
- if (BKE_library_ID_is_indirectly_used(bmain, object) && ID_REAL_USERS(object) <= 1 &&
- ID_EXTRA_USERS(object) == 0) {
+ if (ID_REAL_USERS(object) <= 1 && ID_EXTRA_USERS(object) == 0 &&
+ BKE_library_ID_is_indirectly_used(bmain, object)) {
BKE_reportf(reports,
RPT_WARNING,
"Cannot delete object '%s' from scene '%s', indirectly used objects need at least "
@@ -1873,7 +1873,7 @@ static bool outliner_id_operation_item_poll(bContext *C,
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY:
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY_ENFORCE:
case OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY:
- if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id)) {
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id) && !ID_IS_LINKED(tselem->id)) {
return true;
}
return false;
@@ -2263,7 +2263,8 @@ static const EnumPropertyItem outliner_lib_op_type_items[] = {
"DELETE",
ICON_X,
"Delete",
- "Delete this library and all its item from Blender - WARNING: no undo"},
+ "Delete this library and all its item.\n"
+ "Warning: No undo"},
{OL_LIB_RELOCATE,
"RELOCATE",
0,
diff --git a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc
index 89c9960a24f..f00cf3c34c0 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc
@@ -148,6 +148,14 @@ void TreeDisplayViewLayer::add_layer_collections_recursive(ListBase &tree,
if (!exclude && show_objects_) {
add_layer_collection_objects(ten->subtree, *lc, *ten);
}
+
+ const bool lib_overrides_visible = !SUPPORT_FILTER_OUTLINER(&space_outliner_) ||
+ ((space_outliner_.filter & SO_FILTER_NO_LIB_OVERRIDE) == 0);
+
+ if (lib_overrides_visible && ID_IS_OVERRIDE_LIBRARY_REAL(&lc->collection->id)) {
+ outliner_add_element(
+ &space_outliner_, &ten->subtree, &lc->collection->id, ten, TSE_LIBRARY_OVERRIDE_BASE, 0);
+ }
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index a6e7903d1b1..2df8dce0b3c 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -228,7 +228,6 @@ static void load_data_init_from_operator(SeqLoadData *load_data, bContext *C, wm
PropertyRNA *prop;
const bool relative = (prop = RNA_struct_find_property(op->ptr, "relative_path")) &&
RNA_property_boolean_get(op->ptr, prop);
- int is_file = -1;
memset(load_data, 0, sizeof(SeqLoadData));
load_data->start_frame = RNA_int_get(op->ptr, "frame_start");
@@ -242,17 +241,26 @@ static void load_data_init_from_operator(SeqLoadData *load_data, bContext *C, wm
}
if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
- /* Full path, file is set by the caller. */
RNA_property_string_get(op->ptr, prop, load_data->path);
- is_file = 1;
+ BLI_strncpy(load_data->name, BLI_path_basename(load_data->path), sizeof(load_data->name));
}
else if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
- /* Full path, file is set by the caller. */
- RNA_property_string_get(op->ptr, prop, load_data->path);
- is_file = 0;
+ char *directory = RNA_string_get_alloc(op->ptr, "directory", NULL, 0);
+
+ if ((prop = RNA_struct_find_property(op->ptr, "files"))) {
+ RNA_PROP_BEGIN (op->ptr, itemptr, prop) {
+ char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ BLI_strncpy(load_data->name, filename, sizeof(load_data->name));
+ BLI_snprintf(load_data->path, sizeof(load_data->path), "%s%s", directory, filename);
+ MEM_freeN(filename);
+ break;
+ }
+ RNA_PROP_END;
+ }
+ MEM_freeN(directory);
}
- if ((is_file != -1) && relative) {
+ if (relative) {
BLI_path_rel(load_data->path, BKE_main_blendfile_path(bmain));
}
@@ -276,19 +284,6 @@ static void load_data_init_from_operator(SeqLoadData *load_data, bContext *C, wm
load_data->flags |= SEQ_LOAD_MOVIE_SYNC_FPS;
}
- if (is_file == 1) {
- BLI_strncpy(load_data->name, BLI_path_basename(load_data->path), sizeof(load_data->name));
- }
- else if ((prop = RNA_struct_find_property(op->ptr, "files"))) {
- RNA_PROP_BEGIN (op->ptr, itemptr, prop) {
- char *name = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
- BLI_strncpy(load_data->name, name, sizeof(load_data->name));
- MEM_freeN(name);
- break;
- }
- RNA_PROP_END;
- }
-
if ((prop = RNA_struct_find_property(op->ptr, "use_multiview")) &&
RNA_property_boolean_get(op->ptr, prop)) {
if (op->customdata) {
@@ -990,8 +985,10 @@ static void sequencer_add_image_strip_load_files(
wmOperator *op, Sequence *seq, SeqLoadData *load_data, const int minframe, const int numdigits)
{
const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
-
- SEQ_add_image_set_directory(seq, load_data->path);
+ /* size of Strip->dir. */
+ char directory[768];
+ BLI_split_dir_part(load_data->path, directory, sizeof(directory));
+ SEQ_add_image_set_directory(seq, directory);
if (use_placeholders) {
sequencer_image_seq_reserve_frames(
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index e4afb27dd2e..7beb61e48d2 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -105,8 +105,6 @@
* it messes up transform. */
#undef SEQ_ALL_BEGIN
#undef SEQ_ALL_END
-#undef SEQ_CURRENT_BEGIN
-#undef SEQ_CURRENT_END
static Sequence *special_seq_update = NULL;
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 78d263dffad..40a0af18b18 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -312,8 +312,7 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
}
}
- /* Test for effects and overlap.
- * Don't use SEQ_CURRENT_BEGIN since that would be recursive. */
+ /* Test for effects and overlap. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK)) {
seq->flag &= ~SEQ_OVERLAP;
@@ -1411,28 +1410,25 @@ static int sequencer_split_exec(bContext *C, wmOperator *op)
}
if (changed) { /* Got new strips? */
- Sequence *seq;
if (ignore_selection) {
if (use_cursor_position) {
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (seq->enddisp == split_frame && seq->machine == split_channel) {
seq_selected = seq->flag & SEQ_ALLSEL;
}
}
- SEQ_CURRENT_END;
if (!seq_selected) {
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (seq->startdisp == split_frame && seq->machine == split_channel) {
seq->flag &= ~SEQ_ALLSEL;
}
}
- SEQ_CURRENT_END;
}
}
}
else {
if (split_side != SEQ_SIDE_BOTH) {
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (split_side == SEQ_SIDE_LEFT) {
if (seq->startdisp >= split_frame) {
seq->flag &= ~SEQ_ALLSEL;
@@ -1444,7 +1440,6 @@ static int sequencer_split_exec(bContext *C, wmOperator *op)
}
}
}
- SEQ_CURRENT_END;
}
}
@@ -1652,16 +1647,14 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene, false);
- Sequence *seq;
SEQ_prefetch_stop(scene);
- SEQ_CURRENT_BEGIN (scene->ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (seq->flag & SELECT) {
SEQ_edit_flag_for_removal(scene, ed->seqbasep, seq);
}
}
- SEQ_CURRENT_END;
SEQ_edit_remove_flagged_sequences(scene, ed->seqbasep);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
@@ -2418,17 +2411,15 @@ void SEQUENCER_OT_copy(wmOperatorType *ot)
void ED_sequencer_deselect_all(Scene *scene)
{
- Sequence *seq;
Editing *ed = SEQ_editing_get(scene, false);
if (ed == NULL) {
return;
}
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
seq->flag &= ~SEQ_ALLSEL;
}
- SEQ_CURRENT_END;
}
static int sequencer_paste_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c
index f11a879912c..9b3ecacceb9 100644
--- a/source/blender/editors/space_sequencer/sequencer_modifier.c
+++ b/source/blender/editors/space_sequencer/sequencer_modifier.c
@@ -230,14 +230,13 @@ static int strip_modifier_copy_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Editing *ed = scene->ed;
Sequence *seq = SEQ_select_active_get(scene);
- Sequence *seq_iter;
const int type = RNA_enum_get(op->ptr, "type");
if (!seq || !seq->modifiers.first) {
return OPERATOR_CANCELLED;
}
- SEQ_CURRENT_BEGIN (ed, seq_iter) {
+ LISTBASE_FOREACH (Sequence *, seq_iter, SEQ_active_seqbase_get(ed)) {
if (seq_iter->flag & SELECT) {
if (seq_iter == seq) {
continue;
@@ -259,7 +258,6 @@ static int strip_modifier_copy_exec(bContext *C, wmOperator *op)
SEQ_modifier_list_copy(seq_iter, seq);
}
}
- SEQ_CURRENT_END;
SEQ_relations_invalidate_cache_preprocessed(scene, seq);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
diff --git a/source/blender/editors/space_sequencer/sequencer_proxy.c b/source/blender/editors/space_sequencer/sequencer_proxy.c
index e44afde371a..df84772aa8c 100644
--- a/source/blender/editors/space_sequencer/sequencer_proxy.c
+++ b/source/blender/editors/space_sequencer/sequencer_proxy.c
@@ -58,7 +58,6 @@ static void seq_proxy_build_job(const bContext *C, ReportList *reports)
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene, false);
ScrArea *area = CTX_wm_area(C);
- Sequence *seq;
if (ed == NULL) {
return;
@@ -70,7 +69,7 @@ static void seq_proxy_build_job(const bContext *C, ReportList *reports)
GSet *file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
bool selected = false; /* Check for no selected strips */
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (!ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE) || (seq->flag & SELECT) == 0) {
continue;
}
@@ -92,7 +91,6 @@ static void seq_proxy_build_job(const bContext *C, ReportList *reports)
BKE_reportf(reports, RPT_WARNING, "Overwrite is not checked for %s, skipping", seq->name);
}
}
- SEQ_CURRENT_END;
BLI_gset_free(file_list, MEM_freeN);
@@ -124,7 +122,6 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene, false);
- Sequence *seq;
GSet *file_list;
if (ed == NULL) {
@@ -133,7 +130,7 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if ((seq->flag & SELECT)) {
ListBase queue = {NULL, NULL};
LinkData *link;
@@ -150,7 +147,6 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
SEQ_relations_free_imbuf(scene, &ed->seqbase, false);
}
}
- SEQ_CURRENT_END;
BLI_gset_free(file_list, MEM_freeN);
@@ -189,7 +185,6 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene, false);
- Sequence *seq;
bool proxy_25 = RNA_boolean_get(op->ptr, "proxy_25");
bool proxy_50 = RNA_boolean_get(op->ptr, "proxy_50");
bool proxy_75 = RNA_boolean_get(op->ptr, "proxy_75");
@@ -201,7 +196,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
turnon = false;
}
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if ((seq->flag & SELECT)) {
if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE)) {
SEQ_proxy_set(seq, turnon);
@@ -246,7 +241,6 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
}
}
}
- SEQ_CURRENT_END;
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 5f0a18fbd0b..a9f8a70d61e 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -548,14 +548,14 @@ static int sequencer_select_exec(bContext *C, wmOperator *op)
const float x = UI_view2d_region_to_view_x(v2d, mval[0]);
- SEQ_CURRENT_BEGIN (ed, seq) {
- if (((x < CFRA) && (seq->enddisp <= CFRA)) || ((x >= CFRA) && (seq->startdisp >= CFRA))) {
+ LISTBASE_FOREACH (Sequence *, seq_iter, SEQ_active_seqbase_get(ed)) {
+ if (((x < CFRA) && (seq_iter->enddisp <= CFRA)) ||
+ ((x >= CFRA) && (seq_iter->startdisp >= CFRA))) {
/* Select left or right. */
- seq->flag |= SELECT;
- recurs_sel_seq(seq);
+ seq_iter->flag |= SELECT;
+ recurs_sel_seq(seq_iter);
}
}
- SEQ_CURRENT_END;
{
SpaceSeq *sseq = CTX_wm_space_seq(C);
@@ -1170,7 +1170,6 @@ static int sequencer_select_side_of_frame_exec(bContext *C, wmOperator *op)
Editing *ed = SEQ_editing_get(scene, false);
const bool extend = RNA_boolean_get(op->ptr, "extend");
const int side = RNA_enum_get(op->ptr, "side");
- Sequence *seq;
if (ed == NULL) {
return OPERATOR_CANCELLED;
@@ -1179,7 +1178,7 @@ static int sequencer_select_side_of_frame_exec(bContext *C, wmOperator *op)
ED_sequencer_deselect_all(scene);
}
const int timeline_frame = CFRA;
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
bool test = false;
switch (side) {
case -1:
@@ -1198,7 +1197,6 @@ static int sequencer_select_side_of_frame_exec(bContext *C, wmOperator *op)
recurs_sel_seq(seq);
}
}
- SEQ_CURRENT_END;
ED_outliner_select_sync_from_sequence_tag(C);
@@ -1483,58 +1481,51 @@ static const EnumPropertyItem sequencer_prop_select_grouped_types[] = {
static bool select_grouped_type(Editing *ed, Sequence *actseq, const int channel)
{
- Sequence *seq;
bool changed = false;
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == actseq->type) {
seq->flag |= SELECT;
changed = true;
}
}
- SEQ_CURRENT_END;
return changed;
}
static bool select_grouped_type_basic(Editing *ed, Sequence *actseq, const int channel)
{
- Sequence *seq;
bool changed = false;
const bool is_sound = SEQ_IS_SOUND(actseq);
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (SEQ_CHANNEL_CHECK(seq, channel) && (is_sound ? SEQ_IS_SOUND(seq) : !SEQ_IS_SOUND(seq))) {
seq->flag |= SELECT;
changed = true;
}
}
- SEQ_CURRENT_END;
return changed;
}
static bool select_grouped_type_effect(Editing *ed, Sequence *actseq, const int channel)
{
- Sequence *seq;
bool changed = false;
const bool is_effect = SEQ_IS_EFFECT(actseq);
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (SEQ_CHANNEL_CHECK(seq, channel) &&
(is_effect ? SEQ_IS_EFFECT(seq) : !SEQ_IS_EFFECT(seq))) {
seq->flag |= SELECT;
changed = true;
}
}
- SEQ_CURRENT_END;
return changed;
}
static bool select_grouped_data(Editing *ed, Sequence *actseq, const int channel)
{
- Sequence *seq;
bool changed = false;
const char *dir = actseq->strip ? actseq->strip->dir : NULL;
@@ -1543,45 +1534,41 @@ static bool select_grouped_data(Editing *ed, Sequence *actseq, const int channel
}
if (SEQ_HAS_PATH(actseq) && dir) {
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (SEQ_CHANNEL_CHECK(seq, channel) && SEQ_HAS_PATH(seq) && seq->strip &&
STREQ(seq->strip->dir, dir)) {
seq->flag |= SELECT;
changed = true;
}
}
- SEQ_CURRENT_END;
}
else if (actseq->type == SEQ_TYPE_SCENE) {
Scene *sce = actseq->scene;
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_SCENE && seq->scene == sce) {
seq->flag |= SELECT;
changed = true;
}
}
- SEQ_CURRENT_END;
}
else if (actseq->type == SEQ_TYPE_MOVIECLIP) {
MovieClip *clip = actseq->clip;
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_MOVIECLIP &&
seq->clip == clip) {
seq->flag |= SELECT;
changed = true;
}
}
- SEQ_CURRENT_END;
}
else if (actseq->type == SEQ_TYPE_MASK) {
struct Mask *mask = actseq->mask;
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_MASK && seq->mask == mask) {
seq->flag |= SELECT;
changed = true;
}
}
- SEQ_CURRENT_END;
}
return changed;
@@ -1589,7 +1576,6 @@ static bool select_grouped_data(Editing *ed, Sequence *actseq, const int channel
static bool select_grouped_effect(Editing *ed, Sequence *actseq, const int channel)
{
- Sequence *seq;
bool changed = false;
bool effects[SEQ_TYPE_MAX + 1];
@@ -1597,15 +1583,14 @@ static bool select_grouped_effect(Editing *ed, Sequence *actseq, const int chann
effects[i] = false;
}
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (SEQ_CHANNEL_CHECK(seq, channel) && (seq->type & SEQ_TYPE_EFFECT) &&
ELEM(actseq, seq->seq1, seq->seq2, seq->seq3)) {
effects[seq->type] = true;
}
}
- SEQ_CURRENT_END;
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (SEQ_CHANNEL_CHECK(seq, channel) && effects[seq->type]) {
if (seq->seq1) {
seq->seq1->flag |= SELECT;
@@ -1619,30 +1604,26 @@ static bool select_grouped_effect(Editing *ed, Sequence *actseq, const int chann
changed = true;
}
}
- SEQ_CURRENT_END;
return changed;
}
static bool select_grouped_time_overlap(Editing *ed, Sequence *actseq)
{
- Sequence *seq;
bool changed = false;
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if (seq->startdisp < actseq->enddisp && seq->enddisp > actseq->startdisp) {
seq->flag |= SELECT;
changed = true;
}
}
- SEQ_CURRENT_END;
return changed;
}
static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int channel)
{
- Sequence *seq = NULL;
bool changed = false;
const bool is_audio = ((actseq->type == SEQ_TYPE_META) || SEQ_IS_SOUND(actseq));
int startdisp = actseq->startdisp;
@@ -1650,13 +1631,13 @@ static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int
int machine = actseq->machine;
SeqIterator iter;
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
seq->tmp = NULL;
}
- SEQ_CURRENT_END;
actseq->tmp = POINTER_FROM_INT(true);
+ Sequence *seq = NULL;
for (SEQ_iterator_begin(ed, &iter, true); iter.valid; SEQ_iterator_next(&iter)) {
seq = iter.seq;
@@ -1711,7 +1692,7 @@ static int sequencer_select_grouped_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene, false);
- Sequence *seq, *actseq = SEQ_select_active_get(scene);
+ Sequence *actseq = SEQ_select_active_get(scene);
if (actseq == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active sequence!");
@@ -1725,11 +1706,10 @@ static int sequencer_select_grouped_exec(bContext *C, wmOperator *op)
bool changed = false;
if (!extend) {
- SEQ_CURRENT_BEGIN (ed, seq) {
+ LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
seq->flag &= ~SELECT;
changed = true;
}
- SEQ_CURRENT_END;
}
switch (type) {
diff --git a/source/blender/editors/space_spreadsheet/CMakeLists.txt b/source/blender/editors/space_spreadsheet/CMakeLists.txt
index a77e74ffd93..1343ab8d851 100644
--- a/source/blender/editors/space_spreadsheet/CMakeLists.txt
+++ b/source/blender/editors/space_spreadsheet/CMakeLists.txt
@@ -17,9 +17,9 @@
set(INC
../include
+ ../../blenfont
../../blenkernel
../../blenlib
- ../../blenfont
../../bmesh
../../depsgraph
../../functions
@@ -38,8 +38,8 @@ set(SRC
spreadsheet_from_geometry.cc
spreadsheet_ops.cc
- spreadsheet_draw.hh
spreadsheet_column_layout.hh
+ spreadsheet_draw.hh
spreadsheet_from_geometry.hh
spreadsheet_intern.hh
)
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_column_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_column_layout.cc
index 46760c0dd4e..396767e96d9 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_column_layout.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_column_layout.cc
@@ -41,7 +41,7 @@ class ColumnLayoutDrawer : public SpreadsheetDrawer {
const int fontid = UI_style_get()->widget.uifont_id;
/* Use a consistent font size for the width calculation. */
- BLF_size(fontid, 11 * U.pixelsize, U.dpi);
+ BLF_size(fontid, UI_style_get_dpi()->widget.points * U.pixelsize, U.dpi);
/* The width of the index column depends on the maximum row index. */
left_column_width = std::to_string(std::max(0, column_layout_.tot_rows - 1)).size() *
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc
index 590fbfb5024..910bc0a34ec 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc
@@ -275,9 +275,9 @@ static void get_selected_corner_indices(const Mesh &mesh,
}
}
-static void get_selected_polygon_indices(const Mesh &mesh,
- const IsVertexSelectedFn is_vertex_selected_fn,
- Vector<int64_t> &r_polygon_indices)
+static void get_selected_face_indices(const Mesh &mesh,
+ const IsVertexSelectedFn is_vertex_selected_fn,
+ Vector<int64_t> &r_face_indices)
{
for (const int poly_index : IndexRange(mesh.totpoly)) {
const MPoly &poly = mesh.mpoly[poly_index];
@@ -290,7 +290,7 @@ static void get_selected_polygon_indices(const Mesh &mesh,
}
}
if (is_selected) {
- r_polygon_indices.append(poly_index);
+ r_face_indices.append(poly_index);
}
}
}
@@ -315,8 +315,8 @@ static void get_selected_indices_on_domain(const Mesh &mesh,
switch (domain) {
case ATTR_DOMAIN_POINT:
return get_selected_vertex_indices(mesh, is_vertex_selected_fn, r_indices);
- case ATTR_DOMAIN_POLYGON:
- return get_selected_polygon_indices(mesh, is_vertex_selected_fn, r_indices);
+ case ATTR_DOMAIN_FACE:
+ return get_selected_face_indices(mesh, is_vertex_selected_fn, r_indices);
case ATTR_DOMAIN_CORNER:
return get_selected_corner_indices(mesh, is_vertex_selected_fn, r_indices);
case ATTR_DOMAIN_EDGE:
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index a46d093c039..0b30ca2771d 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -832,52 +832,6 @@ static void drawrenderborder(ARegion *region, View3D *v3d)
immUnbindProgram();
}
-void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *region, View3D *v3d, bool alphaoverride)
-{
- struct bThemeState theme_state;
- Scene *scene = DEG_get_evaluated_scene(depsgraph);
- RegionView3D *rv3d = region->regiondata;
-
- short flag = v3d->flag;
- float glalphaclip = U.glalphaclip;
- /* temp set drawtype to solid */
- /* Setting these temporarily is not nice */
- v3d->flag &= ~V3D_SELECT_OUTLINE;
-
- /* not that nice but means we wont zoom into billboards */
- U.glalphaclip = alphaoverride ? 0.5f : glalphaclip;
-
- /* Tools may request depth outside of regular drawing code. */
- UI_Theme_Store(&theme_state);
- UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
-
- ED_view3d_draw_setup_view(
- G_MAIN->wm.first, NULL, depsgraph, scene, region, v3d, NULL, NULL, NULL);
-
- /* get surface depth without bias */
- rv3d->rflag |= RV3D_ZOFFSET_DISABLED;
-
- /* Needed in cases the 3D Viewport isn't already setup. */
- WM_draw_region_viewport_ensure(region, SPACE_VIEW3D);
- WM_draw_region_viewport_bind(region);
-
- GPUViewport *viewport = WM_draw_region_get_viewport(region);
- /* When Blender is starting, a click event can trigger a depth test while the viewport is not
- * yet available. */
- if (viewport != NULL) {
- DRW_draw_depth_loop(depsgraph, region, v3d, viewport, false);
- }
-
- WM_draw_region_viewport_unbind(region);
-
- rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED;
-
- U.glalphaclip = glalphaclip;
- v3d->flag = flag;
-
- UI_Theme_Restore(&theme_state);
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -1634,7 +1588,8 @@ void view3d_main_region_draw(const bContext *C, ARegion *region)
/* No depth test for drawing action zones afterwards. */
GPU_depth_test(GPU_DEPTH_NONE);
- v3d->flag |= V3D_INVALID_BACKBUF;
+ v3d->runtime.flag &= ~V3D_RUNTIME_DEPTHBUF_OVERRIDDEN;
+ /* TODO: Clear cache? */
}
/** \} */
@@ -2146,8 +2101,15 @@ static bool view3d_clipping_test(const float co[3], const float clip[6][4])
return true;
}
-/* For 'local' ED_view3d_clipping_local must run first
- * then all comparisons can be done in localspace. */
+/**
+ * Return true when `co` is hidden by the 3D views clipping planes.
+ *
+ * \param local: When true use local (object-space) #ED_view3d_clipping_local must run first,
+ * then all comparisons can be done in local-space.
+ * \return True when `co` is outside all clipping planes.
+ *
+ * \note Callers should check #RV3D_CLIPPING_ENABLED first.
+ */
bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local)
{
return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip);
@@ -2168,6 +2130,10 @@ static void validate_object_select_id(struct Depsgraph *depsgraph,
View3D *v3d,
Object *obact)
{
+ /* TODO: Use a flag in the selection engine itself. */
+ if (v3d->runtime.flag & V3D_RUNTIME_DEPTHBUF_OVERRIDDEN) {
+ return;
+ }
Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
BLI_assert(region->regiontype == RGN_TYPE_WINDOW);
@@ -2186,11 +2152,7 @@ static void validate_object_select_id(struct Depsgraph *depsgraph,
/* do nothing */
}
else {
- v3d->flag &= ~V3D_INVALID_BACKBUF;
- return;
- }
-
- if (!(v3d->flag & V3D_INVALID_BACKBUF)) {
+ v3d->runtime.flag |= V3D_RUNTIME_DEPTHBUF_OVERRIDDEN;
return;
}
@@ -2199,9 +2161,7 @@ static void validate_object_select_id(struct Depsgraph *depsgraph,
DRW_select_buffer_context_create(&base, 1, -1);
}
- /* TODO: Create a flag in `DRW_manager` because the drawing is no longer
- * made on the back-buffer in this case. */
- v3d->flag &= ~V3D_INVALID_BACKBUF;
+ v3d->runtime.flag |= V3D_RUNTIME_DEPTHBUF_OVERRIDDEN;
}
/* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow.
@@ -2228,26 +2188,7 @@ static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void
void ED_view3d_select_id_validate(ViewContext *vc)
{
- /* TODO: Create a flag in `DRW_manager` because the drawing is no longer
- * made on the back-buffer in this case. */
- if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
- validate_object_select_id(vc->depsgraph, vc->view_layer, vc->region, vc->v3d, vc->obact);
- }
-}
-
-void ED_view3d_backbuf_depth_validate(ViewContext *vc)
-{
- if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
- ARegion *region = vc->region;
- Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
-
- if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) {
- GPUViewport *viewport = WM_draw_region_get_viewport(region);
- DRW_draw_depth_object(vc->scene, vc->region, vc->v3d, viewport, obact_eval);
- }
-
- vc->v3d->flag &= ~V3D_INVALID_BACKBUF;
- }
+ validate_object_select_id(vc->depsgraph, vc->view_layer, vc->region, vc->v3d, vc->obact);
}
/**
@@ -2319,7 +2260,7 @@ void view3d_update_depths_rect(ARegion *region, ViewDepths *d, rcti *rect)
}
/* Note, with nouveau drivers the glReadPixels() is very slow. T24339. */
-void ED_view3d_depth_update(ARegion *region)
+static void view3d_depth_cache_update(ARegion *region)
{
RegionView3D *rv3d = region->regiondata;
@@ -2341,13 +2282,9 @@ void ED_view3d_depth_update(ARegion *region)
if (d->damaged) {
GPUViewport *viewport = WM_draw_region_get_viewport(region);
- rcti r = {
- .xmin = 0,
- .xmax = d->w,
- .ymin = 0,
- .ymax = d->h,
- };
- view3d_opengl_read_Z_pixels(viewport, &r, d->depths);
+ DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport);
+ GPU_framebuffer_read_depth(fbl->depth_only_fb, 0, 0, d->w, d->h, GPU_DATA_FLOAT, d->depths);
+
/* Assumed to be this as they are never changed. */
d->depth_range[0] = 0.0;
d->depth_range[1] = 1.0;
@@ -2380,19 +2317,81 @@ float view3d_depth_near(ViewDepths *d)
return far == far_real ? FLT_MAX : far;
}
-void ED_view3d_draw_depth_gpencil(Depsgraph *depsgraph, Scene *scene, ARegion *region, View3D *v3d)
+/**
+ * Redraw the viewport depth buffer.
+ *
+ * \param mode: V3D_DEPTH_NO_GPENCIL - Redraw viewport without Grease Pencil and Annotations.
+ * V3D_DEPTH_GPENCIL_ONLY - Redraw viewport with Grease Pencil and Annotations only.
+ * V3D_DEPTH_OBJECT_ONLY - Redraw viewport with active object only.
+ * \param update_cache: If true, store the entire depth buffer in #rv3d->depths.
+ */
+void ED_view3d_depth_override(Depsgraph *depsgraph,
+ ARegion *region,
+ View3D *v3d,
+ Object *obact,
+ eV3DDepthOverrideMode mode,
+ bool update_cache)
{
- /* Setup view matrix. */
- ED_view3d_draw_setup_view(NULL, NULL, depsgraph, scene, region, v3d, NULL, NULL, NULL);
+ if (v3d->runtime.flag & V3D_RUNTIME_DEPTHBUF_OVERRIDDEN) {
+ return;
+ }
+ struct bThemeState theme_state;
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ RegionView3D *rv3d = region->regiondata;
+
+ short flag = v3d->flag;
+ /* temp set drawtype to solid */
+ /* Setting these temporarily is not nice */
+ v3d->flag &= ~V3D_SELECT_OUTLINE;
+
+ /* Tools may request depth outside of regular drawing code. */
+ UI_Theme_Store(&theme_state);
+ UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
+
+ ED_view3d_draw_setup_view(
+ G_MAIN->wm.first, NULL, depsgraph, scene, region, v3d, NULL, NULL, NULL);
- GPU_clear_depth(1.0f);
+ /* get surface depth without bias */
+ rv3d->rflag |= RV3D_ZOFFSET_DISABLED;
- GPU_depth_test(GPU_DEPTH_LESS_EQUAL);
+ /* Needed in cases the 3D Viewport isn't already setup. */
+ WM_draw_region_viewport_ensure(region, SPACE_VIEW3D);
+ WM_draw_region_viewport_bind(region);
GPUViewport *viewport = WM_draw_region_get_viewport(region);
- DRW_draw_depth_loop_gpencil(depsgraph, region, v3d, viewport);
+ /* When Blender is starting, a click event can trigger a depth test while the viewport is not
+ * yet available. */
+ if (viewport != NULL) {
+ switch (mode) {
+ case V3D_DEPTH_NO_GPENCIL:
+ DRW_draw_depth_loop(depsgraph, region, v3d, viewport);
+ break;
+ case V3D_DEPTH_GPENCIL_ONLY:
+ DRW_draw_depth_loop_gpencil(depsgraph, region, v3d, viewport);
+ break;
+ case V3D_DEPTH_OBJECT_ONLY:
+ DRW_draw_depth_object(
+ scene, region, v3d, viewport, DEG_get_evaluated_object(depsgraph, obact));
+ break;
+ }
- GPU_depth_test(GPU_DEPTH_NONE);
+ if (rv3d->depths != NULL) {
+ rv3d->depths->damaged = true;
+ /* TODO: Clear cache? */
+ }
+ if (update_cache) {
+ view3d_depth_cache_update(region);
+ }
+ }
+
+ WM_draw_region_viewport_unbind(region);
+
+ rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED;
+
+ v3d->flag = flag;
+ v3d->runtime.flag |= V3D_RUNTIME_DEPTHBUF_OVERRIDDEN;
+
+ UI_Theme_Restore(&theme_state);
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index dc590833368..5f3d71cc190 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -3628,9 +3628,8 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
ED_view3d_dist_range_get(v3d, dist_range);
- /* Get Z Depths, needed for perspective, nice for ortho */
- ED_view3d_draw_depth(CTX_data_ensure_evaluated_depsgraph(C), region, v3d, true);
-
+ ED_view3d_depth_override(
+ CTX_data_ensure_evaluated_depsgraph(C), region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, false);
{
/* avoid allocating the whole depth buffer */
ViewDepths depth_temp = {0};
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
index 6fa974cdb09..f11b8566690 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
@@ -67,45 +67,73 @@ enum {
GZ_INDEX_ORTHO = 4,
GZ_INDEX_CAMERA = 5,
- GZ_INDEX_TOTAL = 6,
+ /* overlaps GZ_INDEX_ORTHO (switch between) */
+ GZ_INDEX_CAMERA_LOCK = 6,
+ GZ_INDEX_CAMERA_UNLOCK = 7,
+
+ GZ_INDEX_TOTAL = 8,
};
struct NavigateGizmoInfo {
const char *opname;
const char *gizmo;
uint icon;
+ void (*op_prop_fn)(PointerRNA *ptr);
};
+static void navigate_context_toggle_camera_lock_init(PointerRNA *ptr)
+{
+ RNA_string_set(ptr, "data_path", "space_data.lock_camera");
+}
+
static struct NavigateGizmoInfo g_navigate_params[GZ_INDEX_TOTAL] = {
{
.opname = "VIEW3D_OT_move",
.gizmo = "GIZMO_GT_button_2d",
- ICON_VIEW_PAN,
+ .icon = ICON_VIEW_PAN,
+ .op_prop_fn = NULL,
},
{
.opname = "VIEW3D_OT_rotate",
.gizmo = "VIEW3D_GT_navigate_rotate",
- 0,
+ .icon = ICON_NONE,
+ .op_prop_fn = NULL,
},
{
.opname = "VIEW3D_OT_zoom",
.gizmo = "GIZMO_GT_button_2d",
- ICON_VIEW_ZOOM,
+ .icon = ICON_VIEW_ZOOM,
+ .op_prop_fn = NULL,
},
{
.opname = "VIEW3D_OT_view_persportho",
.gizmo = "GIZMO_GT_button_2d",
- ICON_VIEW_PERSPECTIVE,
+ .icon = ICON_VIEW_PERSPECTIVE,
+ .op_prop_fn = NULL,
},
{
.opname = "VIEW3D_OT_view_persportho",
.gizmo = "GIZMO_GT_button_2d",
- ICON_VIEW_ORTHO,
+ .icon = ICON_VIEW_ORTHO,
+ .op_prop_fn = NULL,
},
{
.opname = "VIEW3D_OT_view_camera",
.gizmo = "GIZMO_GT_button_2d",
- ICON_VIEW_CAMERA,
+ .icon = ICON_VIEW_CAMERA,
+ .op_prop_fn = NULL,
+ },
+ {
+ .opname = "WM_OT_context_toggle", /* GZ_INDEX_CAMERA_LOCK. Lock Camera to View. */
+ .gizmo = "GIZMO_GT_button_2d",
+ .icon = ICON_UNLOCKED,
+ .op_prop_fn = navigate_context_toggle_camera_lock_init,
+ },
+ {
+ .opname = "WM_OT_context_toggle", /* GZ_INDEX_CAMERA_UNLOCK. Unlock Camera to View. */
+ .gizmo = "GIZMO_GT_button_2d",
+ .icon = ICON_LOCKED,
+ .op_prop_fn = navigate_context_toggle_camera_lock_init,
},
};
@@ -115,8 +143,11 @@ struct NavigateWidgetGroup {
struct {
rcti rect_visible;
struct {
+ int flag2;
+ } v3d;
+ struct {
char is_persp;
- char is_camera;
+ bool is_camera;
char viewlock;
} rv3d;
} state;
@@ -177,7 +208,7 @@ static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup)
/* may be overwritten later */
gz->scale_basis = GIZMO_MINI_SIZE / 2.0f;
- if (info->icon != 0) {
+ if (info->icon != ICON_NONE) {
PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon");
RNA_property_enum_set(gz->ptr, prop, info->icon);
RNA_enum_set(
@@ -185,7 +216,10 @@ static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup)
}
wmOperatorType *ot = WM_operatortype_find(info->opname, true);
- WM_gizmo_operator_set(gz, 0, ot, NULL);
+ PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot, NULL);
+ if (info->op_prop_fn != NULL) {
+ info->op_prop_fn(ptr);
+ }
}
{
@@ -195,7 +229,13 @@ static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup)
/* Click only buttons (not modal). */
{
- int gz_ids[] = {GZ_INDEX_PERSP, GZ_INDEX_ORTHO, GZ_INDEX_CAMERA};
+ int gz_ids[] = {
+ GZ_INDEX_PERSP,
+ GZ_INDEX_ORTHO,
+ GZ_INDEX_CAMERA,
+ GZ_INDEX_CAMERA_LOCK,
+ GZ_INDEX_CAMERA_UNLOCK,
+ };
for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) {
wmGizmo *gz = navgroup->gz_array[gz_ids[i]];
RNA_boolean_set(gz->ptr, "show_drag", false);
@@ -243,6 +283,8 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g
struct NavigateWidgetGroup *navgroup = gzgroup->customdata;
ARegion *region = CTX_wm_region(C);
const RegionView3D *rv3d = region->regiondata;
+ View3D *v3d = CTX_wm_view3d(C);
+ const int v3d_flag2_test = V3D_LOCK_CAMERA;
for (int i = 0; i < 3; i++) {
copy_v3_v3(navgroup->gz_array[GZ_INDEX_ROTATE]->matrix_offset[i], rv3d->viewmat[i]);
@@ -250,8 +292,13 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g
const rcti *rect_visible = ED_region_visible_rect(region);
+ /* Ensure types match so bits are never lost on assignment. */
+ CHECK_TYPE_PAIR(navgroup->state.v3d.flag2, v3d->flag2);
+ CHECK_TYPE_PAIR(navgroup->state.rv3d.viewlock, rv3d->viewlock);
+
if ((navgroup->state.rect_visible.xmax == rect_visible->xmax) &&
(navgroup->state.rect_visible.ymax == rect_visible->ymax) &&
+ (navgroup->state.v3d.flag2 == (v3d->flag2 & v3d_flag2_test)) &&
(navgroup->state.rv3d.is_persp == rv3d->is_persp) &&
(navgroup->state.rv3d.is_camera == (rv3d->persp == RV3D_CAMOB)) &&
(navgroup->state.rv3d.viewlock == RV3D_LOCK_FLAGS(rv3d))) {
@@ -259,6 +306,7 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g
}
navgroup->state.rect_visible = *rect_visible;
+ navgroup->state.v3d.flag2 = v3d->flag2 & v3d_flag2_test;
navgroup->state.rv3d.is_persp = rv3d->is_persp;
navgroup->state.rv3d.is_camera = (rv3d->persp == RV3D_CAMOB);
navgroup->state.rv3d.viewlock = RV3D_LOCK_FLAGS(rv3d);
@@ -333,6 +381,14 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
}
}
+
+ if (navgroup->state.rv3d.is_camera == true) {
+ gz = navgroup->gz_array[(v3d->flag2 & V3D_LOCK_CAMERA) ? GZ_INDEX_CAMERA_UNLOCK :
+ GZ_INDEX_CAMERA_LOCK];
+ gz->matrix_basis[3][0] = roundf(co[0]);
+ gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+ }
}
}
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index 870996ddefa..833901b6770 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -387,7 +387,9 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
}
ED_gizmotypes_snap_3d_update(
- snap_gizmo, depsgraph, ruler_info->region, v3d, ruler_info->wm, mval_fl, co, NULL);
+ snap_gizmo, depsgraph, ruler_info->region, v3d, ruler_info->wm, mval_fl);
+
+ ED_gizmotypes_snap_3d_data_get(snap_gizmo, co, NULL, NULL, NULL);
}
return true;
}
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 118ec2425fc..e766ae96c2f 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -122,17 +122,7 @@ void VIEW3D_OT_walk(struct wmOperatorType *ot);
void view3d_main_region_draw(const struct bContext *C, struct ARegion *region);
void view3d_draw_region_info(const struct bContext *C, struct ARegion *region);
-void ED_view3d_draw_depth(struct Depsgraph *depsgraph,
- struct ARegion *region,
- View3D *v3d,
- bool alphaoverride);
-
/* view3d_draw_legacy.c */
-void ED_view3d_draw_depth_gpencil(struct Depsgraph *depsgraph,
- Scene *scene,
- struct ARegion *region,
- View3D *v3d);
-
void ED_view3d_draw_select_loop(struct Depsgraph *depsgraph,
ViewContext *vc,
Scene *scene,
diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c
index 48f274ca71b..b0dfd4af7c5 100644
--- a/source/blender/editors/space_view3d/view3d_placement.c
+++ b/source/blender/editors/space_view3d/view3d_placement.c
@@ -1058,9 +1058,7 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv
ipd->region,
ipd->v3d,
G_MAIN->wm.first,
- mval_fl,
- NULL,
- NULL);
+ mval_fl);
}
}
@@ -1507,9 +1505,8 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve
ipd->region,
ipd->v3d,
G_MAIN->wm.first,
- mval_fl,
- ipd->snap_co,
- NULL)) {
+ mval_fl)) {
+ ED_gizmotypes_snap_3d_data_get(ipd->snap_gizmo, ipd->snap_co, NULL, NULL, NULL);
ipd->is_snap_found = true;
}
ED_gizmotypes_snap_3d_toggle_clear(ipd->snap_gizmo);
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index e3acda9bffb..3b4834045f8 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -1024,6 +1024,7 @@ static float view_autodist_depth_margin(ARegion *region, const int mval[2], int
/**
* Get the world-space 3d location from a screen-space 2d point.
+ * TODO: Implement #alphaoverride. We don't want to zoom into billboards.
*
* \param mval: Input screen-space pixel location.
* \param mouse_worldloc: Output world-space location.
@@ -1034,7 +1035,7 @@ bool ED_view3d_autodist(Depsgraph *depsgraph,
View3D *v3d,
const int mval[2],
float mouse_worldloc[3],
- const bool alphaoverride,
+ const bool UNUSED(alphaoverride),
const float fallback_depth_pt[3])
{
float depth_close;
@@ -1042,7 +1043,7 @@ bool ED_view3d_autodist(Depsgraph *depsgraph,
bool depth_ok = false;
/* Get Z Depths, needed for perspective, nice for ortho */
- ED_view3d_draw_depth(depsgraph, region, v3d, alphaoverride);
+ ED_view3d_depth_override(depsgraph, region, v3d, NULL, V3D_DEPTH_NO_GPENCIL, false);
/* Attempt with low margin's first */
int i = 0;
@@ -1067,22 +1068,7 @@ bool ED_view3d_autodist(Depsgraph *depsgraph,
return false;
}
-void ED_view3d_autodist_init(Depsgraph *depsgraph, ARegion *region, View3D *v3d, int mode)
-{
- /* Get Z Depths, needed for perspective, nice for ortho */
- switch (mode) {
- case 0:
- ED_view3d_draw_depth(depsgraph, region, v3d, true);
- break;
- case 1: {
- Scene *scene = DEG_get_evaluated_scene(depsgraph);
- ED_view3d_draw_depth_gpencil(depsgraph, scene, region, v3d);
- break;
- }
- }
-}
-
-/* no 4x4 sampling, run #ED_view3d_autodist_init first */
+/* no 4x4 sampling, run #ED_view3d_depth_override first */
bool ED_view3d_autodist_simple(ARegion *region,
const int mval[2],
float mouse_worldloc[3],
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 2cc3025c3a5..c021c084a23 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -1187,10 +1187,11 @@ static eTFlag flags_from_data_type(eTConvertType data_type)
return T_EDIT;
case TC_MESH_UV:
return T_EDIT | T_POINTS | T_2D_EDIT;
+ case TC_CURSOR_IMAGE:
+ return T_2D_EDIT;
case TC_PARTICLE_VERTS:
return T_POINTS;
case TC_POSE:
- case TC_CURSOR_IMAGE:
case TC_CURSOR_VIEW3D:
case TC_OBJECT:
case TC_OBJECT_TEXSPACE:
@@ -1643,6 +1644,21 @@ void animrecord_check_state(TransInfo *t, struct Object *ob)
}
}
+static void recalcData_cursor_image(TransInfo *t)
+{
+ TransDataContainer *tc = t->data_container;
+ TransData *td = tc->data;
+ float aspect_inv[2];
+
+ aspect_inv[0] = 1.0f / t->aspect[0];
+ aspect_inv[1] = 1.0f / t->aspect[1];
+
+ td->loc[0] = td->loc[0] * aspect_inv[0];
+ td->loc[1] = td->loc[1] * aspect_inv[1];
+
+ DEG_id_tag_update(&t->scene->id, ID_RECALC_COPY_ON_WRITE);
+}
+
static void recalcData_cursor(TransInfo *t)
{
DEG_id_tag_update(&t->scene->id, ID_RECALC_COPY_ON_WRITE);
@@ -1677,6 +1693,8 @@ void recalcData(TransInfo *t)
recalcData_curve(t);
break;
case TC_CURSOR_IMAGE:
+ recalcData_cursor_image(t);
+ break;
case TC_CURSOR_VIEW3D:
recalcData_cursor(t);
break;
diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c
index a4edf51ffee..7f24a0fa5f8 100644
--- a/source/blender/editors/transform/transform_convert_armature.c
+++ b/source/blender/editors/transform/transform_convert_armature.c
@@ -99,15 +99,7 @@ static void autokeyframe_pose(
bPoseChannel *pchan;
FCurve *fcu;
- /* TODO: this should probably be done per channel instead. */
if (!autokeyframe_cfra_can_key(scene, id)) {
- /* tag channels that should have unkeyed data */
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->flag & BONE_TRANSFORM) {
- /* tag this channel */
- pchan->bone->flag |= BONE_UNKEYED;
- }
- }
return;
}
@@ -139,9 +131,6 @@ static void autokeyframe_pose(
ListBase dsources = {NULL, NULL};
- /* clear any 'unkeyed' flag it may have */
- pchan->bone->flag &= ~BONE_UNKEYED;
-
/* add datasource override for the camera object */
ANIM_relative_keyingset_add_source(&dsources, id, &RNA_PoseBone, pchan);
diff --git a/source/blender/editors/transform/transform_convert_cursor.c b/source/blender/editors/transform/transform_convert_cursor.c
index e6a972bfc7c..67d85f9610b 100644
--- a/source/blender/editors/transform/transform_convert_cursor.c
+++ b/source/blender/editors/transform/transform_convert_cursor.c
@@ -56,6 +56,13 @@ void createTransCursor_image(TransInfo *t)
}
td->flag = TD_SELECTED;
+
+ /* UV coords are scaled by aspects (see UVsToTransData). This also applies for the Cursor in the
+ * UV Editor which also means that for display and when the cursor coords are flushed
+ * (recalcData_cursor_image), these are converted each time. */
+ cursor_location[0] = cursor_location[0] * t->aspect[0];
+ cursor_location[1] = cursor_location[1] * t->aspect[1];
+
copy_v3_v3(td->center, cursor_location);
td->ob = NULL;
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index 7d7d10004a3..cf2b6ee19d5 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -18,10 +18,10 @@
set(INC
../include
../space_sequencer
+ ../../blenfont
../../blenkernel
../../blenlib
../../blentranslation
- ../../blenfont
../../bmesh
../../depsgraph
../../gpu
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index e94aaa49839..7d82884760c 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -4546,7 +4546,10 @@ void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys)
}
}
-void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool topology_from_uvs)
+void param_construct_end(ParamHandle *handle,
+ ParamBool fill,
+ ParamBool topology_from_uvs,
+ int *count_fail)
{
PHandle *phandle = (PHandle *)handle;
PChart *chart = phandle->construction_chart;
@@ -4574,6 +4577,9 @@ void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool topology
if (!topology_from_uvs && nboundaries == 0) {
p_chart_delete(chart);
+ if (count_fail != NULL) {
+ *count_fail += 1;
+ }
continue;
}
@@ -4611,12 +4617,11 @@ void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf)
}
}
-void param_lscm_solve(ParamHandle *handle)
+void param_lscm_solve(ParamHandle *handle, int *count_changed, int *count_failed)
{
PHandle *phandle = (PHandle *)handle;
PChart *chart;
int i;
- PBool result;
param_assert(phandle->state == PHANDLE_STATE_LSCM);
@@ -4624,7 +4629,7 @@ void param_lscm_solve(ParamHandle *handle)
chart = phandle->charts[i];
if (chart->u.lscm.context) {
- result = p_chart_lscm_solve(phandle, chart);
+ const PBool result = p_chart_lscm_solve(phandle, chart);
if (result && !(chart->flag & PCHART_HAS_PINS)) {
p_chart_rotate_minimum_area(chart);
@@ -4637,6 +4642,17 @@ void param_lscm_solve(ParamHandle *handle)
if (!result || !(chart->flag & PCHART_HAS_PINS)) {
p_chart_lscm_end(chart);
}
+
+ if (result) {
+ if (count_changed != NULL) {
+ *count_changed += 1;
+ }
+ }
+ else {
+ if (count_failed != NULL) {
+ *count_failed += 1;
+ }
+ }
}
}
}
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.h b/source/blender/editors/uvedit/uvedit_parametrizer.h
index 2427e589833..e69ce360e61 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.h
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.h
@@ -59,7 +59,10 @@ void param_face_add(ParamHandle *handle,
void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys);
-void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool topology_from_uvs);
+void param_construct_end(ParamHandle *handle,
+ ParamBool fill,
+ ParamBool topology_from_uvs,
+ int *count_fail);
void param_delete(ParamHandle *handle);
/* Least Squares Conformal Maps:
@@ -74,7 +77,7 @@ void param_delete(ParamHandle *handle);
*/
void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf);
-void param_lscm_solve(ParamHandle *handle);
+void param_lscm_solve(ParamHandle *handle, int *count_changed, int *count_failed);
void param_lscm_end(ParamHandle *handle);
/* Stretch */
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index fc5f41e8ed5..87ae112a237 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -165,6 +165,11 @@ typedef struct UnwrapOptions {
bool correct_aspect;
} UnwrapOptions;
+typedef struct UnwrapResultInfo {
+ int count_changed;
+ int count_failed;
+} UnwrapResultInfo;
+
static bool uvedit_have_selection(const Scene *scene, BMEditMesh *em, const UnwrapOptions *options)
{
BMFace *efa;
@@ -281,7 +286,8 @@ static void construct_param_handle_face_add(ParamHandle *handle,
static ParamHandle *construct_param_handle(const Scene *scene,
Object *ob,
BMesh *bm,
- const UnwrapOptions *options)
+ const UnwrapOptions *options,
+ UnwrapResultInfo *result_info)
{
ParamHandle *handle;
BMFace *efa;
@@ -344,7 +350,10 @@ static ParamHandle *construct_param_handle(const Scene *scene,
}
}
- param_construct_end(handle, options->fill_holes, options->topology_from_uvs);
+ param_construct_end(handle,
+ options->fill_holes,
+ options->topology_from_uvs,
+ result_info ? &result_info->count_failed : NULL);
return handle;
}
@@ -355,7 +364,8 @@ static ParamHandle *construct_param_handle(const Scene *scene,
static ParamHandle *construct_param_handle_multi(const Scene *scene,
Object **objects,
const uint objects_len,
- const UnwrapOptions *options)
+ const UnwrapOptions *options,
+ int *count_fail)
{
ParamHandle *handle;
BMFace *efa;
@@ -431,7 +441,7 @@ static ParamHandle *construct_param_handle_multi(const Scene *scene,
offset += bm->totface;
}
- param_construct_end(handle, options->fill_holes, options->topology_from_uvs);
+ param_construct_end(handle, options->fill_holes, options->topology_from_uvs, count_fail);
return handle;
}
@@ -475,7 +485,8 @@ static void texface_from_original_index(const Scene *scene,
static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
Object *ob,
BMEditMesh *em,
- const UnwrapOptions *options)
+ const UnwrapOptions *options,
+ UnwrapResultInfo *result_info)
{
ParamHandle *handle;
/* index pointers */
@@ -651,7 +662,10 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
}
}
- param_construct_end(handle, options->fill_holes, options->topology_from_uvs);
+ param_construct_end(handle,
+ options->fill_holes,
+ options->topology_from_uvs,
+ result_info ? &result_info->count_failed : NULL);
/* cleanup */
MEM_freeN(faceMap);
@@ -707,7 +721,7 @@ static bool minimize_stretch_init(bContext *C, wmOperator *op)
ms->blend = RNA_float_get(op->ptr, "blend");
ms->iterations = RNA_int_get(op->ptr, "iterations");
ms->i = 0;
- ms->handle = construct_param_handle_multi(scene, objects, objects_len, &options);
+ ms->handle = construct_param_handle_multi(scene, objects, objects_len, &options, NULL);
ms->lasttime = PIL_check_seconds_timer();
param_stretch_begin(ms->handle);
@@ -959,7 +973,7 @@ static void uvedit_pack_islands(const Scene *scene, Object *ob, BMesh *bm)
bool ignore_pinned = false;
ParamHandle *handle;
- handle = construct_param_handle(scene, ob, bm, &options);
+ handle = construct_param_handle(scene, ob, bm, &options, NULL);
param_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
param_flush(handle);
param_delete(handle);
@@ -979,7 +993,7 @@ static void uvedit_pack_islands_multi(const Scene *scene,
bool ignore_pinned)
{
ParamHandle *handle;
- handle = construct_param_handle_multi(scene, objects, objects_len, options);
+ handle = construct_param_handle_multi(scene, objects, objects_len, options, NULL);
param_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
param_flush(handle);
param_delete(handle);
@@ -1087,7 +1101,7 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
- ParamHandle *handle = construct_param_handle_multi(scene, objects, objects_len, &options);
+ ParamHandle *handle = construct_param_handle_multi(scene, objects, objects_len, &options, NULL);
param_average(handle, false);
param_flush(handle);
param_delete(handle);
@@ -1154,10 +1168,10 @@ void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
};
if (use_subsurf) {
- handle = construct_param_handle_subsurfed(scene, obedit, em, &options);
+ handle = construct_param_handle_subsurfed(scene, obedit, em, &options, NULL);
}
else {
- handle = construct_param_handle(scene, obedit, em->bm, &options);
+ handle = construct_param_handle(scene, obedit, em->bm, &options, NULL);
}
param_lscm_begin(handle, PARAM_TRUE, abf);
@@ -1182,7 +1196,7 @@ void ED_uvedit_live_unwrap_re_solve(void)
{
if (g_live_unwrap.handles) {
for (int i = 0; i < g_live_unwrap.len; i++) {
- param_lscm_solve(g_live_unwrap.handles[i]);
+ param_lscm_solve(g_live_unwrap.handles[i], NULL, NULL);
param_flush(g_live_unwrap.handles[i]);
}
}
@@ -1631,7 +1645,10 @@ static void uv_map_clip_correct(Object *ob, wmOperator *op)
* \{ */
/* Assumes UV Map exists, doesn't run update funcs. */
-static void uvedit_unwrap(const Scene *scene, Object *obedit, const UnwrapOptions *options)
+static void uvedit_unwrap(const Scene *scene,
+ Object *obedit,
+ const UnwrapOptions *options,
+ UnwrapResultInfo *result_info)
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
if (!CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) {
@@ -1643,14 +1660,16 @@ static void uvedit_unwrap(const Scene *scene, Object *obedit, const UnwrapOption
ParamHandle *handle;
if (use_subsurf) {
- handle = construct_param_handle_subsurfed(scene, obedit, em, options);
+ handle = construct_param_handle_subsurfed(scene, obedit, em, options, result_info);
}
else {
- handle = construct_param_handle(scene, obedit, em->bm, options);
+ handle = construct_param_handle(scene, obedit, em->bm, options, result_info);
}
param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
- param_lscm_solve(handle);
+ param_lscm_solve(handle,
+ result_info ? &result_info->count_changed : NULL,
+ result_info ? &result_info->count_failed : NULL);
param_lscm_end(handle);
param_average(handle, true);
@@ -1663,11 +1682,12 @@ static void uvedit_unwrap(const Scene *scene, Object *obedit, const UnwrapOption
static void uvedit_unwrap_multi(const Scene *scene,
Object **objects,
const int objects_len,
- const UnwrapOptions *options)
+ const UnwrapOptions *options,
+ UnwrapResultInfo *result_info)
{
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
- uvedit_unwrap(scene, obedit, options);
+ uvedit_unwrap(scene, obedit, options, result_info);
DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
}
@@ -1687,7 +1707,7 @@ void ED_uvedit_live_unwrap(const Scene *scene, Object **objects, int objects_len
bool rotate = true;
bool ignore_pinned = true;
- uvedit_unwrap_multi(scene, objects, objects_len, &options);
+ uvedit_unwrap_multi(scene, objects, objects_len, &options, NULL);
uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
}
}
@@ -1816,11 +1836,28 @@ static int unwrap_exec(bContext *C, wmOperator *op)
}
/* execute unwrap */
- uvedit_unwrap_multi(scene, objects, objects_len, &options);
+ UnwrapResultInfo result_info = {
+ .count_changed = 0,
+ .count_failed = 0,
+ };
+ uvedit_unwrap_multi(scene, objects, objects_len, &options, &result_info);
uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
MEM_freeN(objects);
+ if (result_info.count_failed == 0 && result_info.count_changed == 0) {
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "Unwrap could not solve any island(s), edge seams may need to be added");
+ }
+ else if (result_info.count_failed) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Unwrap failed to solve %d of %d island(s), edge seams may need to be added",
+ result_info.count_failed,
+ result_info.count_changed + result_info.count_failed);
+ }
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/functions/FN_cpp_type.hh b/source/blender/functions/FN_cpp_type.hh
index 665296f30e1..54ea0103fe5 100644
--- a/source/blender/functions/FN_cpp_type.hh
+++ b/source/blender/functions/FN_cpp_type.hh
@@ -661,7 +661,7 @@ class CPPType : NonCopyable, NonMovable {
uint64_t hash() const
{
- return DefaultHash<const CPPType *>{}(this);
+ return get_default_hash(this);
}
template<typename T> bool is() const
@@ -674,6 +674,6 @@ class CPPType : NonCopyable, NonMovable {
/* Utility for allocating an uninitialized buffer for a single value of the given #CPPType. */
#define BUFFER_FOR_CPP_TYPE_VALUE(type, variable_name) \
- blender::DynamicStackBuffer<64, 64> stack_buffer_for_##variable_name(type.size(), \
- type.alignment()); \
+ blender::DynamicStackBuffer<64, 64> stack_buffer_for_##variable_name((type).size(), \
+ (type).alignment()); \
void *variable_name = stack_buffer_for_##variable_name.buffer();
diff --git a/source/blender/functions/FN_cpp_type_make.hh b/source/blender/functions/FN_cpp_type_make.hh
index 342161d01b6..cd14fe8c078 100644
--- a/source/blender/functions/FN_cpp_type_make.hh
+++ b/source/blender/functions/FN_cpp_type_make.hh
@@ -220,7 +220,7 @@ template<typename T> bool is_equal_cb(const void *a, const void *b)
template<typename T> uint64_t hash_cb(const void *value)
{
const T &value_ = *static_cast<const T *>(value);
- return DefaultHash<T>{}(value_);
+ return get_default_hash(value_);
}
} // namespace blender::fn::cpp_type_util
diff --git a/source/blender/functions/FN_multi_function.hh b/source/blender/functions/FN_multi_function.hh
index 2ce65426245..f6c4addfb52 100644
--- a/source/blender/functions/FN_multi_function.hh
+++ b/source/blender/functions/FN_multi_function.hh
@@ -64,7 +64,7 @@ class MultiFunction {
virtual uint64_t hash() const
{
- return DefaultHash<const MultiFunction *>{}(this);
+ return get_default_hash(this);
}
virtual bool equals(const MultiFunction &UNUSED(other)) const
diff --git a/source/blender/functions/FN_multi_function_builder.hh b/source/blender/functions/FN_multi_function_builder.hh
index 95a9f52e29e..691abeb18c0 100644
--- a/source/blender/functions/FN_multi_function_builder.hh
+++ b/source/blender/functions/FN_multi_function_builder.hh
@@ -384,7 +384,7 @@ template<typename T> class CustomMF_Constant : public MultiFunction {
uint64_t hash() const override
{
- return DefaultHash<T>{}(value_);
+ return get_default_hash(value_);
}
bool equals(const MultiFunction &other) const override
diff --git a/source/blender/functions/FN_multi_function_data_type.hh b/source/blender/functions/FN_multi_function_data_type.hh
index 713f73c2b5a..c3372151a1b 100644
--- a/source/blender/functions/FN_multi_function_data_type.hh
+++ b/source/blender/functions/FN_multi_function_data_type.hh
@@ -110,7 +110,7 @@ class MFDataType {
uint64_t hash() const
{
- return DefaultHash<CPPType>{}(*type_) + static_cast<uint64_t>(category_);
+ return get_default_hash_2(*type_, category_);
}
};
diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt
index e3bb0d773a2..9690f47c862 100644
--- a/source/blender/gpencil_modifiers/CMakeLists.txt
+++ b/source/blender/gpencil_modifiers/CMakeLists.txt
@@ -53,8 +53,8 @@ set(SRC
intern/MOD_gpencilbuild.c
intern/MOD_gpencilcolor.c
intern/MOD_gpencilhook.c
- intern/MOD_gpencillineart.c
intern/MOD_gpencillattice.c
+ intern/MOD_gpencillineart.c
intern/MOD_gpencilmirror.c
intern/MOD_gpencilmultiply.c
intern/MOD_gpencilnoise.c
@@ -68,18 +68,19 @@ set(SRC
intern/MOD_gpenciltime.c
intern/MOD_gpenciltint.c
+ MOD_gpencil_lineart.h
MOD_gpencil_modifiertypes.h
intern/MOD_gpencil_ui_common.h
intern/MOD_gpencil_util.h
# Lineart code
- intern/lineart/lineart_ops.c
- intern/lineart/lineart_cpu.c
intern/lineart/lineart_chain.c
+ intern/lineart/lineart_cpu.c
+ intern/lineart/lineart_ops.c
intern/lineart/lineart_util.c
- intern/lineart/lineart_intern.h
intern/lineart/MOD_lineart.h
+ intern/lineart/lineart_intern.h
)
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
index 4efc1d9eaae..2934b89c747 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
@@ -136,36 +136,39 @@ static void bakeModifier(Main *UNUSED(bmain),
bGPdata *gpd = ob->data;
int oldframe = (int)DEG_get_ctime(depsgraph);
- if (mmd->object == NULL) {
+ if ((mmd->object == NULL) || (mmd->object->type != OB_LATTICE)) {
return;
}
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
- /* apply lattice effects on this frame
- * NOTE: this assumes that we don't want lattice animation on non-keyframed frames
+ /* Apply lattice effects on this frame
+ * NOTE: this assumes that we don't want lattice animation on non-keyframed frames.
*/
CFRA = gpf->framenum;
BKE_scene_graph_update_for_newframe(depsgraph);
- /* recalculate lattice data */
- BKE_gpencil_lattice_init(ob);
+ /* Recalculate lattice data. */
+ if (mmd->cache_data) {
+ BKE_lattice_deform_data_destroy(mmd->cache_data);
+ }
+ mmd->cache_data = BKE_lattice_deform_data_create(mmd->object, ob);
- /* compute lattice effects on this frame */
+ /* Compute lattice effects on this frame. */
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
}
- /* free lingering data */
+ /* Free lingering data. */
ldata = (struct LatticeDeformData *)mmd->cache_data;
if (ldata) {
BKE_lattice_deform_data_destroy(ldata);
mmd->cache_data = NULL;
}
- /* return frame state and DB to original state */
+ /* Return frame state and DB to original state. */
CFRA = oldframe;
BKE_scene_graph_update_for_newframe(depsgraph);
}
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index 7fb3981d9dc..2389e0c403c 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -3858,7 +3858,7 @@ static void lineart_gpencil_generate(LineartRenderBuffer *rb,
BKE_gpencil_stroke_add_points(gps, stroke_data, count, mat);
BKE_gpencil_dvert_ensure(gps);
- gps->mat_nr = material_nr;
+ gps->mat_nr = max_ii(material_nr, 0);
MEM_freeN(stroke_data);
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index d36c7bbe486..dc39af803e0 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -574,8 +574,19 @@ static int startffmpeg(struct anim *anim)
pCodecCtx->workaround_bugs = 1;
- pCodecCtx->thread_count = BLI_system_thread_count();
- pCodecCtx->thread_type = FF_THREAD_SLICE;
+ if (pCodec->capabilities & AV_CODEC_CAP_AUTO_THREADS) {
+ pCodecCtx->thread_count = 0;
+ }
+ else {
+ pCodecCtx->thread_count = BLI_system_thread_count();
+ }
+
+ if (pCodec->capabilities & AV_CODEC_CAP_FRAME_THREADS) {
+ pCodecCtx->thread_type = FF_THREAD_FRAME;
+ }
+ else if (pCodec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
+ pCodecCtx->thread_type = FF_THREAD_SLICE;
+ }
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
avformat_close_input(&pFormatCtx);
@@ -969,44 +980,6 @@ static int ffmpeg_decode_video_frame(struct anim *anim)
return (rval >= 0);
}
-static void ffmpeg_decode_video_frame_scan(struct anim *anim, int64_t pts_to_search)
-{
- /* there seem to exist *very* silly GOP lengths out in the wild... */
- int count = 1000;
-
- av_log(anim->pFormatCtx,
- AV_LOG_DEBUG,
- "SCAN start: considering pts=%" PRId64 " in search of %" PRId64 "\n",
- (int64_t)anim->next_pts,
- (int64_t)pts_to_search);
-
- while (count > 0 && anim->next_pts < pts_to_search) {
- av_log(anim->pFormatCtx,
- AV_LOG_DEBUG,
- " WHILE: pts=%" PRId64 " in search of %" PRId64 "\n",
- (int64_t)anim->next_pts,
- (int64_t)pts_to_search);
- if (!ffmpeg_decode_video_frame(anim)) {
- break;
- }
- count--;
- }
- if (count == 0) {
- av_log(anim->pFormatCtx,
- AV_LOG_ERROR,
- "SCAN failed: completely lost in stream, "
- "bailing out at PTS=%" PRId64 ", searching for PTS=%" PRId64 "\n",
- (int64_t)anim->next_pts,
- (int64_t)pts_to_search);
- }
- if (anim->next_pts == pts_to_search) {
- av_log(anim->pFormatCtx, AV_LOG_DEBUG, "SCAN HAPPY: we found our PTS!\n");
- }
- else {
- av_log(anim->pFormatCtx, AV_LOG_ERROR, "SCAN UNHAPPY: PTS not matched!\n");
- }
-}
-
static int match_format(const char *name, AVFormatContext *pFormatCtx)
{
const char *p;
@@ -1049,37 +1022,18 @@ static int ffmpeg_seek_by_byte(AVFormatContext *pFormatCtx)
return false;
}
-static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Type tc)
+static int64_t ffmpeg_get_pts_to_search(struct anim *anim,
+ struct anim_index *tc_index,
+ int position)
{
- int64_t pts_to_search = 0;
- double frame_rate;
- double pts_time_base;
- int64_t st_time;
- struct anim_index *tc_index = 0;
- AVStream *v_st;
- int new_frame_index = 0; /* To quiet gcc barking... */
- int old_frame_index = 0; /* To quiet gcc barking... */
-
- if (anim == NULL) {
- return 0;
- }
-
- av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: pos=%d\n", position);
-
- if (tc != IMB_TC_NONE) {
- tc_index = IMB_anim_open_index(anim, tc);
- }
-
- v_st = anim->pFormatCtx->streams[anim->videoStream];
-
- frame_rate = av_q2d(av_guess_frame_rate(anim->pFormatCtx, v_st, NULL));
-
- st_time = anim->pFormatCtx->start_time;
- pts_time_base = av_q2d(v_st->time_base);
+ int64_t pts_to_search;
+ int64_t st_time = anim->pFormatCtx->start_time;
+ AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
+ double frame_rate = av_q2d(av_guess_frame_rate(anim->pFormatCtx, v_st, NULL));
+ double pts_time_base = av_q2d(v_st->time_base);
if (tc_index) {
- new_frame_index = IMB_indexer_get_frame_index(tc_index, position);
- old_frame_index = IMB_indexer_get_frame_index(tc_index, anim->curposition);
+ int new_frame_index = IMB_indexer_get_frame_index(tc_index, position);
pts_to_search = IMB_indexer_get_pts(tc_index, new_frame_index);
}
else {
@@ -1089,117 +1043,259 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ
pts_to_search += st_time / pts_time_base / AV_TIME_BASE;
}
}
+ return pts_to_search;
+}
- av_log(anim->pFormatCtx,
- AV_LOG_DEBUG,
- "FETCH: looking for PTS=%" PRId64 " (pts_timebase=%g, frame_rate=%g, st_time=%" PRId64
- ")\n",
- (int64_t)pts_to_search,
- pts_time_base,
- frame_rate,
- st_time);
+static bool ffmpeg_pts_matches_last_frame(struct anim *anim, int64_t pts_to_search)
+{
+ return anim->last_frame && anim->last_pts <= pts_to_search && anim->next_pts > pts_to_search;
+}
- if (anim->last_frame && anim->last_pts <= pts_to_search && anim->next_pts > pts_to_search) {
- av_log(anim->pFormatCtx,
- AV_LOG_DEBUG,
- "FETCH: frame repeat: last: %" PRId64 " next: %" PRId64 "\n",
- (int64_t)anim->last_pts,
- (int64_t)anim->next_pts);
- IMB_refImBuf(anim->last_frame);
- anim->curposition = position;
- return anim->last_frame;
- }
+/* Requested video frame is expected to be found within different GOP as last decoded frame.
+ * Seeking to new position and scanning is fastest way to get requested frame.
+ * Check whether ffmpeg_can_scan() and ffmpeg_pts_matches_last_frame() is false before using this
+ * function. */
+static bool ffmpeg_can_seek(struct anim *anim, int position)
+{
+ return position != anim->curposition + 1;
+}
+/* Requested video frame is expected to be found within same GOP as last decoded frame.
+ * Decoding frames in sequence until frame matches requested one is fastest way to get it. */
+static bool ffmpeg_can_scan(struct anim *anim, int position, struct anim_index *tc_index)
+{
if (position > anim->curposition + 1 && anim->preseek && !tc_index &&
position - (anim->curposition + 1) < anim->preseek) {
- av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: within preseek interval (no index)\n");
+ return true;
+ }
- ffmpeg_decode_video_frame_scan(anim, pts_to_search);
+ if (tc_index == NULL) {
+ return false;
}
- else if (tc_index && IMB_indexer_can_scan(tc_index, old_frame_index, new_frame_index)) {
+
+ int new_frame_index = IMB_indexer_get_frame_index(tc_index, position);
+ int old_frame_index = IMB_indexer_get_frame_index(tc_index, anim->curposition);
+ return IMB_indexer_can_scan(tc_index, old_frame_index, new_frame_index);
+}
+
+static bool ffmpeg_is_first_frame_decode(struct anim *anim, int position)
+{
+ return position == 0 && anim->curposition == -1;
+}
+
+/* Decode frames one by one until its PTS matches pts_to_search. */
+static void ffmpeg_decode_video_frame_scan(struct anim *anim, int64_t pts_to_search)
+{
+ av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: within preseek interval\n");
+
+ /* there seem to exist *very* silly GOP lengths out in the wild... */
+ int count = 1000;
+
+ av_log(anim->pFormatCtx,
+ AV_LOG_DEBUG,
+ "SCAN start: considering pts=%" PRId64 " in search of %" PRId64 "\n",
+ (int64_t)anim->next_pts,
+ (int64_t)pts_to_search);
+
+ while (count > 0 && anim->next_pts < pts_to_search) {
av_log(anim->pFormatCtx,
AV_LOG_DEBUG,
- "FETCH: within preseek interval "
- "(index tells us)\n");
+ " WHILE: pts=%" PRId64 " in search of %" PRId64 "\n",
+ (int64_t)anim->next_pts,
+ (int64_t)pts_to_search);
+ if (!ffmpeg_decode_video_frame(anim)) {
+ break;
+ }
+ count--;
+ }
+ if (count == 0) {
+ av_log(anim->pFormatCtx,
+ AV_LOG_ERROR,
+ "SCAN failed: completely lost in stream, "
+ "bailing out at PTS=%" PRId64 ", searching for PTS=%" PRId64 "\n",
+ (int64_t)anim->next_pts,
+ (int64_t)pts_to_search);
+ }
+ if (anim->next_pts == pts_to_search) {
+ av_log(anim->pFormatCtx, AV_LOG_DEBUG, "SCAN HAPPY: we found our PTS!\n");
+ }
+ else {
+ av_log(anim->pFormatCtx, AV_LOG_ERROR, "SCAN UNHAPPY: PTS not matched!\n");
+ }
+}
- ffmpeg_decode_video_frame_scan(anim, pts_to_search);
+/* Wrapper over av_seek_frame(), for formats that doesn't have it's own read_seek() or read_seek2()
+ * functions defined. When seeking in these formats, rule to seek to last necessary I-frame is not
+ * honored. It is not even guaranteed that I-frame, that must be decoded will be read. See
+ * https://trac.ffmpeg.org/ticket/1607 and https://developer.blender.org/T86944. */
+static int ffmpeg_generic_seek_workaround(struct anim *anim, int64_t requested_pos)
+{
+ AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
+ double frame_rate = av_q2d(av_guess_frame_rate(anim->pFormatCtx, v_st, NULL));
+ int64_t current_pos = requested_pos;
+
+ /* This time offset maximum limit is arbitrary. If some files fails to decode it may be
+ * increased. Seek performance will be negatively affected. Small initial offset is necessary
+ * because encoder can re-arrange frames as it needs but within it's delay, which is usually
+ * small. */
+ for (int offset = 5; offset < 25; offset++) {
+ current_pos = requested_pos - ((int64_t)(offset)*AV_TIME_BASE / frame_rate);
+
+ /* Seek to timestamp. */
+ if (av_seek_frame(anim->pFormatCtx, -1, current_pos, AVSEEK_FLAG_BACKWARD) < 0) {
+ break;
+ }
+
+ /* Read first video stream packet. */
+ AVPacket read_packet = {0};
+ while (av_read_frame(anim->pFormatCtx, &read_packet) >= 0) {
+ if (anim->next_packet.stream_index == anim->videoStream) {
+ break;
+ }
+ }
+
+ /* If this packet contains I-frame, exit loop. This should be the frame that we need. */
+ if (read_packet.flags & AV_PKT_FLAG_KEY) {
+ break;
+ }
}
- else if (position != anim->curposition + 1) {
- int64_t pos;
- int ret;
- if (tc_index) {
- uint64_t dts;
+ /* Re-seek to timestamp that gave I-frame, so it can be read by decode function. */
+ return av_seek_frame(anim->pFormatCtx, -1, current_pos, AVSEEK_FLAG_BACKWARD);
+}
- pos = IMB_indexer_get_seek_pos(tc_index, new_frame_index);
- dts = IMB_indexer_get_seek_pos_dts(tc_index, new_frame_index);
+/* Seek to last necessary I-frame and scan-decode until requested frame is found. */
+static void ffmpeg_seek_and_decode(struct anim *anim, int position, struct anim_index *tc_index)
+{
+ AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
+ double frame_rate = av_q2d(av_guess_frame_rate(anim->pFormatCtx, v_st, NULL));
+ int64_t st_time = anim->pFormatCtx->start_time;
- av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek pos = %" PRId64 "\n", pos);
- av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek dts = %" PRIu64 "\n", dts);
+ int64_t pts_to_search = ffmpeg_get_pts_to_search(anim, tc_index, position);
- if (ffmpeg_seek_by_byte(anim->pFormatCtx)) {
- av_log(anim->pFormatCtx, AV_LOG_DEBUG, "... using BYTE pos\n");
+ int64_t pos;
+ int ret;
- ret = av_seek_frame(anim->pFormatCtx, -1, pos, AVSEEK_FLAG_BYTE);
- av_update_cur_dts(anim->pFormatCtx, v_st, dts);
- }
- else {
- av_log(anim->pFormatCtx, AV_LOG_DEBUG, "... using DTS pos\n");
- ret = av_seek_frame(anim->pFormatCtx, anim->videoStream, dts, AVSEEK_FLAG_BACKWARD);
- }
+ if (tc_index) {
+ int new_frame_index = IMB_indexer_get_frame_index(tc_index, position);
+ uint64_t dts;
+
+ pos = IMB_indexer_get_seek_pos(tc_index, new_frame_index);
+ dts = IMB_indexer_get_seek_pos_dts(tc_index, new_frame_index);
+
+ av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek pos = %" PRId64 "\n", pos);
+ av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek dts = %" PRIu64 "\n", dts);
+
+ if (ffmpeg_seek_by_byte(anim->pFormatCtx)) {
+ av_log(anim->pFormatCtx, AV_LOG_DEBUG, "... using BYTE pos\n");
+
+ ret = av_seek_frame(anim->pFormatCtx, -1, pos, AVSEEK_FLAG_BYTE);
+ av_update_cur_dts(anim->pFormatCtx, v_st, dts);
}
else {
- pos = (int64_t)position * AV_TIME_BASE / frame_rate;
+ av_log(anim->pFormatCtx, AV_LOG_DEBUG, "... using DTS pos\n");
+ ret = av_seek_frame(anim->pFormatCtx, anim->videoStream, dts, AVSEEK_FLAG_BACKWARD);
+ }
+ }
+ else {
+ pos = (int64_t)(position)*AV_TIME_BASE / frame_rate;
- av_log(anim->pFormatCtx,
- AV_LOG_DEBUG,
- "NO INDEX seek pos = %" PRId64 ", st_time = %" PRId64 "\n",
- pos,
- (st_time != AV_NOPTS_VALUE) ? st_time : 0);
+ av_log(anim->pFormatCtx,
+ AV_LOG_DEBUG,
+ "NO INDEX seek pos = %" PRId64 ", st_time = %" PRId64 "\n",
+ pos,
+ (st_time != AV_NOPTS_VALUE) ? st_time : 0);
- if (pos < 0) {
- pos = 0;
- }
+ if (pos < 0) {
+ pos = 0;
+ }
- if (st_time != AV_NOPTS_VALUE) {
- pos += st_time;
- }
+ if (st_time != AV_NOPTS_VALUE) {
+ pos += st_time;
+ }
+
+ av_log(anim->pFormatCtx, AV_LOG_DEBUG, "NO INDEX final seek pos = %" PRId64 "\n", pos);
- av_log(anim->pFormatCtx, AV_LOG_DEBUG, "NO INDEX final seek pos = %" PRId64 "\n", pos);
+ AVFormatContext *format_ctx = anim->pFormatCtx;
+ /* Condition based on av_seek_frame() code. */
+ if (format_ctx->iformat->read_seek2 && !format_ctx->iformat->read_seek) {
ret = av_seek_frame(anim->pFormatCtx, -1, pos, AVSEEK_FLAG_BACKWARD);
}
-
- if (ret < 0) {
- av_log(anim->pFormatCtx,
- AV_LOG_ERROR,
- "FETCH: "
- "error while seeking to DTS = %" PRId64 " (frameno = %d, PTS = %" PRId64
- "): errcode = %d\n",
- pos,
- position,
- (int64_t)pts_to_search,
- ret);
+ else {
+ ret = ffmpeg_generic_seek_workaround(anim, pos);
}
+ }
- avcodec_flush_buffers(anim->pCodecCtx);
+ if (ret < 0) {
+ av_log(anim->pFormatCtx,
+ AV_LOG_ERROR,
+ "FETCH: "
+ "error while seeking to DTS = %" PRId64 " (frameno = %d, PTS = %" PRId64
+ "): errcode = %d\n",
+ pos,
+ position,
+ (int64_t)pts_to_search,
+ ret);
+ }
+ avcodec_flush_buffers(anim->pCodecCtx);
- anim->next_pts = -1;
+ anim->next_pts = -1;
- if (anim->next_packet.stream_index == anim->videoStream) {
- av_free_packet(&anim->next_packet);
- anim->next_packet.stream_index = -1;
- }
+ if (anim->next_packet.stream_index == anim->videoStream) {
+ av_free_packet(&anim->next_packet);
+ anim->next_packet.stream_index = -1;
+ }
- /* memset(anim->pFrame, ...) ?? */
+ /* memset(anim->pFrame, ...) ?? */
+ if (ret < 0) {
+ /* Seek failed. */
+ return;
+ }
- if (ret >= 0) {
- ffmpeg_decode_video_frame_scan(anim, pts_to_search);
- }
+ ffmpeg_decode_video_frame_scan(anim, pts_to_search);
+}
+
+static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Type tc)
+{
+ if (anim == NULL) {
+ return NULL;
+ }
+
+ av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: pos=%d\n", position);
+
+ struct anim_index *tc_index = IMB_anim_open_index(anim, tc);
+ int64_t pts_to_search = ffmpeg_get_pts_to_search(anim, tc_index, position);
+ AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
+ double frame_rate = av_q2d(av_guess_frame_rate(anim->pFormatCtx, v_st, NULL));
+ double pts_time_base = av_q2d(v_st->time_base);
+ int64_t st_time = anim->pFormatCtx->start_time;
+
+ av_log(anim->pFormatCtx,
+ AV_LOG_DEBUG,
+ "FETCH: looking for PTS=%" PRId64 " (pts_timebase=%g, frame_rate=%g, st_time=%" PRId64
+ ")\n",
+ (int64_t)pts_to_search,
+ pts_time_base,
+ frame_rate,
+ st_time);
+
+ if (ffmpeg_pts_matches_last_frame(anim, pts_to_search)) {
+ av_log(anim->pFormatCtx,
+ AV_LOG_DEBUG,
+ "FETCH: frame repeat: last: %" PRId64 " next: %" PRId64 "\n",
+ (int64_t)anim->last_pts,
+ (int64_t)anim->next_pts);
+ IMB_refImBuf(anim->last_frame);
+ anim->curposition = position;
+ return anim->last_frame;
+ }
+
+ if (ffmpeg_can_scan(anim, position, tc_index) || ffmpeg_is_first_frame_decode(anim, position)) {
+ ffmpeg_decode_video_frame_scan(anim, pts_to_search);
}
- else if (position == 0 && anim->curposition == -1) {
- /* first frame without seeking special case... */
- ffmpeg_decode_video_frame(anim);
+ else if (ffmpeg_can_seek(anim, position)) {
+ ffmpeg_seek_and_decode(anim, position, tc_index);
}
else {
av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: no seek necessary, just continue...\n");
diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c
index de54e6dab9d..91d7b9a8b9e 100644
--- a/source/blender/imbuf/intern/cineon/cineon_dpx.c
+++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c
@@ -198,10 +198,10 @@ ImBuf *imb_load_cineon(const unsigned char *mem,
int flags,
char colorspace[IM_MAX_SPACE])
{
- if (imb_is_a_cineon(mem, size)) {
- return imb_load_dpx_cineon(mem, size, 1, flags, colorspace);
+ if (!imb_is_a_cineon(mem, size)) {
+ return NULL;
}
- return NULL;
+ return imb_load_dpx_cineon(mem, size, 1, flags, colorspace);
}
bool imb_save_dpx(struct ImBuf *buf, const char *filepath, int flags)
@@ -219,8 +219,8 @@ ImBuf *imb_load_dpx(const unsigned char *mem,
int flags,
char colorspace[IM_MAX_SPACE])
{
- if (imb_is_a_dpx(mem, size)) {
- return imb_load_dpx_cineon(mem, size, 0, flags, colorspace);
+ if (!imb_is_a_dpx(mem, size)) {
+ return NULL;
}
- return NULL;
+ return imb_load_dpx_cineon(mem, size, 0, flags, colorspace);
}
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index d331cfd533a..6496f2d05a4 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -541,8 +541,20 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
av_dict_set_int(&codec_opts, "crf", crf, 0);
/* Prefer smaller file-size. */
av_dict_set(&codec_opts, "preset", "slow", 0);
- /* Thread count. */
- av_dict_set_int(&codec_opts, "threads", BLI_system_thread_count(), 0);
+
+ if (rv->codec->capabilities & AV_CODEC_CAP_AUTO_THREADS) {
+ rv->c->thread_count = 0;
+ }
+ else {
+ rv->c->thread_count = BLI_system_thread_count();
+ }
+
+ if (rv->codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) {
+ rv->c->thread_type = FF_THREAD_FRAME;
+ }
+ else if (rv->codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
+ rv->c->thread_type = FF_THREAD_SLICE;
+ }
if (rv->of->flags & AVFMT_GLOBALHEADER) {
rv->c->flags |= CODEC_FLAG_GLOBAL_HEADER;
@@ -794,11 +806,21 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim,
context->iCodecCtx->workaround_bugs = 1;
- AVDictionary *codec_opts = NULL;
- /* Thread count. */
- av_dict_set_int(&codec_opts, "threads", BLI_system_thread_count(), 0);
+ if (context->iCodec->capabilities & AV_CODEC_CAP_AUTO_THREADS) {
+ context->iCodecCtx->thread_count = 0;
+ }
+ else {
+ context->iCodecCtx->thread_count = BLI_system_thread_count();
+ }
+
+ if (context->iCodec->capabilities & AV_CODEC_CAP_FRAME_THREADS) {
+ context->iCodecCtx->thread_type = FF_THREAD_FRAME;
+ }
+ else if (context->iCodec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
+ context->iCodecCtx->thread_type = FF_THREAD_SLICE;
+ }
- if (avcodec_open2(context->iCodecCtx, context->iCodec, &codec_opts) < 0) {
+ if (avcodec_open2(context->iCodecCtx, context->iCodec, NULL) < 0) {
avformat_close_input(&context->iFormatCtx);
MEM_freeN(context);
return NULL;
diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c
index 112b95bf1a1..547af472d73 100644
--- a/source/blender/imbuf/intern/iris.c
+++ b/source/blender/imbuf/intern/iris.c
@@ -270,11 +270,13 @@ struct ImBuf *imb_loadiris(const uchar *mem, size_t size, int flags, char colors
ImBuf *ibuf = NULL;
uchar dirty_flag = 0;
- if (size < HEADER_SIZE) {
+ if (!imb_is_a_iris(mem, size)) {
return NULL;
}
- if (!imb_is_a_iris(mem, size)) {
+ /* Could pe part of the magic check above,
+ * by convention this check only requests the size needed to read it's magic though. */
+ if (size < HEADER_SIZE) {
return NULL;
}
diff --git a/source/blender/imbuf/intern/metadata.c b/source/blender/imbuf/intern/metadata.c
index d8abd3411cb..c59997b34f5 100644
--- a/source/blender/imbuf/intern/metadata.c
+++ b/source/blender/imbuf/intern/metadata.c
@@ -38,8 +38,6 @@
#include "IMB_metadata.h"
-#define METADATA_MAX_VALUE_LENGTH 1024
-
void IMB_metadata_ensure(struct IDProperty **metadata)
{
if (*metadata != NULL) {
@@ -99,11 +97,11 @@ void IMB_metadata_set_field(struct IDProperty *metadata, const char *key, const
}
if (prop == NULL) {
- prop = IDP_NewString(value, key, METADATA_MAX_VALUE_LENGTH);
+ prop = IDP_NewString(value, key, 0);
IDP_AddToGroup(metadata, prop);
}
- IDP_AssignString(prop, value, METADATA_MAX_VALUE_LENGTH);
+ IDP_AssignString(prop, value, 0);
}
void IMB_metadata_foreach(struct ImBuf *ibuf, IMBMetadataForeachCb callback, void *userdata)
diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c
index 285b18595f7..94b2a62aa26 100644
--- a/source/blender/imbuf/intern/radiance_hdr.c
+++ b/source/blender/imbuf/intern/radiance_hdr.c
@@ -229,87 +229,89 @@ struct ImBuf *imb_loadhdr(const unsigned char *mem,
const unsigned char *ptr, *mem_eof = mem + size;
char oriY[80], oriX[80];
- if (imb_is_a_hdr(mem, size)) {
- colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT);
-
- /* find empty line, next line is resolution info */
- size_t x;
- for (x = 1; x < size; x++) {
- if ((mem[x - 1] == '\n') && (mem[x] == '\n')) {
- found = 1;
- break;
- }
+ if (!imb_is_a_hdr(mem, size)) {
+ return NULL;
+ }
+
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT);
+
+ /* find empty line, next line is resolution info */
+ size_t x;
+ for (x = 1; x < size; x++) {
+ if ((mem[x - 1] == '\n') && (mem[x] == '\n')) {
+ found = 1;
+ break;
}
- if (found && (x < (size + 2))) {
- if (sscanf((char *)&mem[x + 1],
- "%79s %d %79s %d",
- (char *)&oriY,
- &height,
- (char *)&oriX,
- &width) != 4) {
- return NULL;
- }
+ }
- /* find end of this line, data right behind it */
- ptr = (unsigned char *)strchr((char *)&mem[x + 1], '\n');
- ptr++;
+ if ((found && (x < (size + 2))) == 0) {
+ /* Data not found! */
+ return NULL;
+ }
- if (flags & IB_test) {
- ibuf = IMB_allocImBuf(width, height, 32, 0);
- }
- else {
- ibuf = IMB_allocImBuf(width, height, 32, (flags & IB_rect) | IB_rectfloat);
- }
+ if (sscanf((const char *)&mem[x + 1],
+ "%79s %d %79s %d",
+ (char *)&oriY,
+ &height,
+ (char *)&oriX,
+ &width) != 4) {
+ return NULL;
+ }
- if (UNLIKELY(ibuf == NULL)) {
- return NULL;
- }
- ibuf->ftype = IMB_FTYPE_RADHDR;
+ /* find end of this line, data right behind it */
+ ptr = (const unsigned char *)strchr((const char *)&mem[x + 1], '\n');
+ ptr++;
- if (flags & IB_alphamode_detect) {
- ibuf->flags |= IB_alphamode_premul;
- }
+ if (flags & IB_test) {
+ ibuf = IMB_allocImBuf(width, height, 32, 0);
+ }
+ else {
+ ibuf = IMB_allocImBuf(width, height, 32, (flags & IB_rect) | IB_rectfloat);
+ }
- if (flags & IB_test) {
- return ibuf;
- }
+ if (UNLIKELY(ibuf == NULL)) {
+ return NULL;
+ }
- /* read in and decode the actual data */
- sline = (RGBE *)MEM_mallocN(sizeof(*sline) * width, __func__);
- rect_float = ibuf->rect_float;
+ ibuf->ftype = IMB_FTYPE_RADHDR;
- for (size_t y = 0; y < height; y++) {
- ptr = freadcolrs(sline, ptr, width, mem_eof);
- if (ptr == NULL) {
- printf(
- "WARNING! HDR decode error, image may be just truncated, or completely wrong...\n");
- break;
- }
- for (x = 0; x < width; x++) {
- /* convert to ldr */
- RGBE2FLOAT(sline[x], fcol);
- *rect_float++ = fcol[RED];
- *rect_float++ = fcol[GRN];
- *rect_float++ = fcol[BLU];
- *rect_float++ = 1.0f;
- }
- }
- MEM_freeN(sline);
- if (oriY[0] == '-') {
- IMB_flipy(ibuf);
- }
+ if (flags & IB_alphamode_detect) {
+ ibuf->flags |= IB_alphamode_premul;
+ }
- if (flags & IB_rect) {
- IMB_rect_from_float(ibuf);
- }
+ if (flags & IB_test) {
+ return ibuf;
+ }
- return ibuf;
+ /* read in and decode the actual data */
+ sline = (RGBE *)MEM_mallocN(sizeof(*sline) * width, __func__);
+ rect_float = ibuf->rect_float;
+
+ for (size_t y = 0; y < height; y++) {
+ ptr = freadcolrs(sline, ptr, width, mem_eof);
+ if (ptr == NULL) {
+ printf("WARNING! HDR decode error, image may be just truncated, or completely wrong...\n");
+ break;
}
- // else printf("Data not found!\n");
+ for (x = 0; x < width; x++) {
+ /* convert to ldr */
+ RGBE2FLOAT(sline[x], fcol);
+ *rect_float++ = fcol[RED];
+ *rect_float++ = fcol[GRN];
+ *rect_float++ = fcol[BLU];
+ *rect_float++ = 1.0f;
+ }
+ }
+ MEM_freeN(sline);
+ if (oriY[0] == '-') {
+ IMB_flipy(ibuf);
+ }
+
+ if (flags & IB_rect) {
+ IMB_rect_from_float(ibuf);
}
- // else printf("Not a valid radiance HDR file!\n");
- return NULL;
+ return ibuf;
}
/* ImBuf write */
diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c
index 2fb14e40d9d..001cd4e1575 100644
--- a/source/blender/imbuf/intern/tiff.c
+++ b/source/blender/imbuf/intern/tiff.c
@@ -576,11 +576,7 @@ ImBuf *imb_loadtiff(const unsigned char *mem,
int ib_depth;
int found;
- /* check whether or not we have a TIFF file */
- if (size < IMB_TIFF_NCB) {
- fprintf(stderr, "imb_loadtiff: size < IMB_TIFF_NCB\n");
- return NULL;
- }
+ /* Check whether or not we have a TIFF file. */
if (imb_is_a_tiff(mem, size) == 0) {
return NULL;
}
diff --git a/source/blender/io/CMakeLists.txt b/source/blender/io/CMakeLists.txt
index 360cacc4360..f11ad7627b9 100644
--- a/source/blender/io/CMakeLists.txt
+++ b/source/blender/io/CMakeLists.txt
@@ -35,3 +35,5 @@ endif()
if(WITH_USD)
add_subdirectory(usd)
endif()
+
+add_subdirectory(gpencil)
diff --git a/source/blender/io/gpencil/CMakeLists.txt b/source/blender/io/gpencil/CMakeLists.txt
new file mode 100644
index 00000000000..be46f876129
--- /dev/null
+++ b/source/blender/io/gpencil/CMakeLists.txt
@@ -0,0 +1,98 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ ../common
+ ../../blenkernel
+ ../../blenlib
+ ../../blenloader
+ ../../bmesh
+ ../../depsgraph
+ ../../editors/include
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/clog
+ ../../../../intern/guardedalloc
+ ../../../../intern/utfconv
+)
+
+set(INC_SYS
+)
+
+set(SRC
+ intern/gpencil_io_capi.cc
+ intern/gpencil_io_base.cc
+ intern/gpencil_io_import_base.cc
+ intern/gpencil_io_import_svg.cc
+
+ # This line must be removed if NanoSVG is moved to extern
+ nanosvg/nanosvg.h
+
+ gpencil_io.h
+ intern/gpencil_io_base.hh
+ intern/gpencil_io_export_base.hh
+ intern/gpencil_io_import_base.hh
+ intern/gpencil_io_import_svg.hh
+)
+
+set(LIB
+ bf_blenkernel
+ bf_blenlib
+ bf_io_common
+)
+
+if(WITH_PUGIXML)
+ list(APPEND SRC
+ intern/gpencil_io_export_svg.cc
+
+ intern/gpencil_io_export_svg.hh
+ )
+ list(APPEND INC_SYS
+ ${PUGIXML_INCLUDE_DIR}
+ )
+ list(APPEND LIB
+ ${PUGIXML_LIBRARIES}
+ )
+ add_definitions(-DWITH_PUGIXML)
+endif()
+
+if(WITH_HARU)
+ list(APPEND SRC
+ intern/gpencil_io_export_pdf.cc
+
+ intern/gpencil_io_export_pdf.hh
+ )
+ list(APPEND INC_SYS
+ ${HARU_INCLUDE_DIRS}
+ )
+ list(APPEND LIB
+ ${HARU_LIBRARIES}
+ )
+ add_definitions(-DWITH_HARU)
+endif()
+
+
+list(APPEND LIB
+ ${BOOST_LIBRARIES}
+)
+
+blender_add_lib(bf_gpencil "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/io/gpencil/gpencil_io.h b/source/blender/io/gpencil/gpencil_io.h
new file mode 100644
index 00000000000..24b13479359
--- /dev/null
+++ b/source/blender/io/gpencil/gpencil_io.h
@@ -0,0 +1,92 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation
+ * All rights reserved.
+ */
+#pragma once
+
+/** \file
+ * \ingroup bgpencil
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ARegion;
+struct bContext;
+struct Object;
+struct View3D;
+
+typedef struct GpencilIOParams {
+ bContext *C;
+ ARegion *region;
+ View3D *v3d;
+ /** Grease pencil object. */
+ Object *ob;
+ /** Mode (see eGpencilIO_Modes). */
+ uint16_t mode;
+ int32_t frame_start;
+ int32_t frame_end;
+ int32_t frame_cur;
+ uint32_t flag;
+ float scale;
+ /** Select mode (see eGpencilExportSelect). */
+ uint16_t select_mode;
+ /** Frame mode (see eGpencilExportFrame). */
+ uint16_t frame_mode;
+ /** Stroke sampling factor. */
+ float stroke_sample;
+ int32_t resolution;
+} GpencilIOParams;
+
+/* GpencilIOParams->flag. */
+typedef enum eGpencilIOParams_Flag {
+ /* Export Filled strokes. */
+ GP_EXPORT_FILL = (1 << 0),
+ /* Export normalized thickness. */
+ GP_EXPORT_NORM_THICKNESS = (1 << 1),
+ /* Clip camera area. */
+ GP_EXPORT_CLIP_CAMERA = (1 << 2),
+} eGpencilIOParams_Flag;
+
+typedef enum eGpencilIO_Modes {
+ GP_EXPORT_TO_SVG = 0,
+ GP_EXPORT_TO_PDF = 1,
+
+ GP_IMPORT_FROM_SVG = 2,
+ /* Add new formats here. */
+} eGpencilIO_Modes;
+
+/* Object to be exported. */
+typedef enum eGpencilExportSelect {
+ GP_EXPORT_ACTIVE = 0,
+ GP_EXPORT_SELECTED = 1,
+ GP_EXPORT_VISIBLE = 2,
+} eGpencilExportSelect;
+
+/** Frame-range to be exported. */
+typedef enum eGpencilExportFrame {
+ GP_EXPORT_FRAME_ACTIVE = 0,
+ GP_EXPORT_FRAME_SELECTED = 1,
+} eGpencilExportFrame;
+
+bool gpencil_io_export(const char *filename, struct GpencilIOParams *iparams);
+bool gpencil_io_import(const char *filename, struct GpencilIOParams *iparams);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/io/gpencil/intern/gpencil_io_base.cc b/source/blender/io/gpencil/intern/gpencil_io_base.cc
new file mode 100644
index 00000000000..8da1ec27b9c
--- /dev/null
+++ b/source/blender/io/gpencil/intern/gpencil_io_base.cc
@@ -0,0 +1,396 @@
+
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bgpencil
+ */
+
+#include "BLI_float2.hh"
+#include "BLI_float3.hh"
+#include "BLI_float4x4.hh"
+#include "BLI_path_util.h"
+#include "BLI_span.hh"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_layer_types.h"
+#include "DNA_material_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_camera.h"
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+
+#include "UI_view2d.h"
+
+#include "ED_view3d.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "gpencil_io_base.hh"
+
+using blender::Span;
+
+namespace blender::io::gpencil {
+
+/* Constructor. */
+GpencilIO::GpencilIO(const GpencilIOParams *iparams)
+{
+ params_ = *iparams;
+
+ /* Easy access data. */
+ bmain_ = CTX_data_main(params_.C);
+ depsgraph_ = CTX_data_depsgraph_pointer(params_.C);
+ scene_ = CTX_data_scene(params_.C);
+ rv3d_ = (RegionView3D *)params_.region->regiondata;
+ gpd_ = (params_.ob != nullptr) ? (bGPdata *)params_.ob->data : nullptr;
+ cfra_ = iparams->frame_cur;
+
+ /* Calculate camera matrix. */
+ Object *cam_ob = params_.v3d->camera;
+ if (cam_ob != nullptr) {
+ /* Set up parameters. */
+ CameraParams params;
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_object(&params, cam_ob);
+
+ /* Compute matrix, viewplane, .. */
+ RenderData *rd = &scene_->r;
+ BKE_camera_params_compute_viewplane(&params, rd->xsch, rd->ysch, rd->xasp, rd->yasp);
+ BKE_camera_params_compute_matrix(&params);
+
+ float viewmat[4][4];
+ invert_m4_m4(viewmat, cam_ob->obmat);
+
+ mul_m4_m4m4(persmat_, params.winmat, viewmat);
+ is_ortho_ = params.is_ortho;
+ }
+ else {
+ unit_m4(persmat_);
+ is_ortho_ = false;
+ }
+
+ winx_ = params_.region->winx;
+ winy_ = params_.region->winy;
+
+ /* Camera rectangle. */
+ if (rv3d_->persp == RV3D_CAMOB) {
+ render_x_ = (scene_->r.xsch * scene_->r.size) / 100;
+ render_y_ = (scene_->r.ysch * scene_->r.size) / 100;
+
+ ED_view3d_calc_camera_border(CTX_data_scene(params_.C),
+ depsgraph_,
+ params_.region,
+ params_.v3d,
+ rv3d_,
+ &camera_rect_,
+ true);
+ is_camera_ = true;
+ camera_ratio_ = render_x_ / (camera_rect_.xmax - camera_rect_.xmin);
+ offset_.x = camera_rect_.xmin;
+ offset_.y = camera_rect_.ymin;
+ }
+ else {
+ is_camera_ = false;
+ is_ortho_ = false;
+ /* Calc selected object boundbox. Need set initial value to some variables. */
+ camera_ratio_ = 1.0f;
+ offset_.x = 0.0f;
+ offset_.y = 0.0f;
+
+ selected_objects_boundbox_calc();
+ rctf boundbox;
+ selected_objects_boundbox_get(&boundbox);
+
+ render_x_ = boundbox.xmax - boundbox.xmin;
+ render_y_ = boundbox.ymax - boundbox.ymin;
+ offset_.x = boundbox.xmin;
+ offset_.y = boundbox.ymin;
+ }
+}
+
+/** Create a list of selected objects sorted from back to front */
+void GpencilIO::create_object_list()
+{
+ ViewLayer *view_layer = CTX_data_view_layer(params_.C);
+
+ float3 camera_z_axis;
+ copy_v3_v3(camera_z_axis, rv3d_->viewinv[2]);
+ ob_list_.clear();
+
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
+ Object *object = base->object;
+
+ if (object->type != OB_GPENCIL) {
+ continue;
+ }
+ if ((params_.select_mode == GP_EXPORT_ACTIVE) && (params_.ob != object)) {
+ continue;
+ }
+
+ if ((params_.select_mode == GP_EXPORT_SELECTED) && ((base->flag & BASE_SELECTED) == 0)) {
+ continue;
+ }
+
+ /* Save z-depth from view to sort from back to front. */
+ if (is_camera_) {
+ float camera_z = dot_v3v3(camera_z_axis, object->obmat[3]);
+ ObjectZ obz = {camera_z, object};
+ ob_list_.append(obz);
+ }
+ else {
+ float zdepth = 0;
+ if (rv3d_) {
+ if (rv3d_->is_persp) {
+ zdepth = ED_view3d_calc_zfac(rv3d_, object->obmat[3], nullptr);
+ }
+ else {
+ zdepth = -dot_v3v3(rv3d_->viewinv[2], object->obmat[3]);
+ }
+ ObjectZ obz = {zdepth * -1.0f, object};
+ ob_list_.append(obz);
+ }
+ }
+ }
+ /* Sort list of objects from point of view. */
+ std::sort(ob_list_.begin(), ob_list_.end(), [](const ObjectZ &obz1, const ObjectZ &obz2) {
+ return obz1.zdepth < obz2.zdepth;
+ });
+}
+
+/**
+ * Set file input_text full path.
+ * \param filename: Path of the file provided by save dialog.
+ */
+void GpencilIO::filename_set(const char *filename)
+{
+ BLI_strncpy(filename_, filename, FILE_MAX);
+ BLI_path_abs(filename_, BKE_main_blendfile_path(bmain_));
+}
+
+/** Convert to screenspace. */
+bool GpencilIO::gpencil_3D_point_to_screen_space(const float3 co, float2 &r_co)
+{
+ float3 parent_co = diff_mat_ * co;
+ float2 screen_co;
+ eV3DProjTest test = (eV3DProjTest)(V3D_PROJ_RET_OK);
+ if (ED_view3d_project_float_global(params_.region, parent_co, screen_co, test) ==
+ V3D_PROJ_RET_OK) {
+ if (!ELEM(V2D_IS_CLIPPED, screen_co[0], screen_co[1])) {
+ copy_v2_v2(r_co, screen_co);
+ /* Invert X axis. */
+ if (invert_axis_[0]) {
+ r_co[0] = winx_ - r_co[0];
+ }
+ /* Invert Y axis. */
+ if (invert_axis_[1]) {
+ r_co[1] = winy_ - r_co[1];
+ }
+ /* Apply offset and scale. */
+ sub_v2_v2(r_co, &offset_.x);
+ mul_v2_fl(r_co, camera_ratio_);
+
+ return true;
+ }
+ }
+ r_co[0] = V2D_IS_CLIPPED;
+ r_co[1] = V2D_IS_CLIPPED;
+
+ /* Invert X axis. */
+ if (invert_axis_[0]) {
+ r_co[0] = winx_ - r_co[0];
+ }
+ /* Invert Y axis. */
+ if (invert_axis_[1]) {
+ r_co[1] = winy_ - r_co[1];
+ }
+
+ return false;
+}
+
+/** Convert to render space. */
+float2 GpencilIO::gpencil_3D_point_to_render_space(const float3 co, const bool is_ortho)
+{
+ float3 parent_co = diff_mat_ * co;
+ mul_m4_v3(persmat_, parent_co);
+
+ if (!is_ortho) {
+ parent_co.x = parent_co.x / max_ff(FLT_MIN, parent_co.z);
+ parent_co.y = parent_co.y / max_ff(FLT_MIN, parent_co.z);
+ }
+
+ float2 r_co;
+ r_co.x = (parent_co.x + 1.0f) / 2.0f * (float)render_x_;
+ r_co.y = (parent_co.y + 1.0f) / 2.0f * (float)render_y_;
+
+ /* Invert X axis. */
+ if (invert_axis_[0]) {
+ r_co.x = (float)render_x_ - r_co.x;
+ }
+ /* Invert Y axis. */
+ if (invert_axis_[1]) {
+ r_co.y = (float)render_y_ - r_co.y;
+ }
+
+ return r_co;
+}
+
+/** Convert to 2D. */
+float2 GpencilIO::gpencil_3D_point_to_2D(const float3 co)
+{
+ const bool is_camera = (bool)(rv3d_->persp == RV3D_CAMOB);
+ if (is_camera) {
+ return gpencil_3D_point_to_render_space(co, is_orthographic());
+ }
+ float2 result;
+ gpencil_3D_point_to_screen_space(co, result);
+ return result;
+}
+
+/** Get radius of point. */
+float GpencilIO::stroke_point_radius_get(bGPDlayer *gpl, bGPDstroke *gps)
+{
+ bGPDspoint *pt = &gps->points[0];
+ const float2 screen_co = gpencil_3D_point_to_2D(&pt->x);
+
+ /* Radius. */
+ bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view(
+ rv3d_, gpd_, gpl, gps, 3, diff_mat_.values);
+
+ pt = &gps_perimeter->points[0];
+ const float2 screen_ex = gpencil_3D_point_to_2D(&pt->x);
+
+ const float2 v1 = screen_co - screen_ex;
+ float radius = v1.length();
+ BKE_gpencil_free_stroke(gps_perimeter);
+
+ return MAX2(radius, 1.0f);
+}
+
+void GpencilIO::prepare_layer_export_matrix(Object *ob, bGPDlayer *gpl)
+{
+ BKE_gpencil_layer_transform_matrix_get(depsgraph_, ob, gpl, diff_mat_.values);
+ diff_mat_ = diff_mat_ * float4x4(gpl->layer_invmat);
+}
+
+void GpencilIO::prepare_stroke_export_colors(Object *ob, bGPDstroke *gps)
+{
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+
+ /* Stroke color. */
+ copy_v4_v4(stroke_color_, gp_style->stroke_rgba);
+ avg_opacity_ = 0;
+ /* Get average vertex color and apply. */
+ float avg_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ for (const bGPDspoint &pt : Span(gps->points, gps->totpoints)) {
+ add_v4_v4(avg_color, pt.vert_color);
+ avg_opacity_ += pt.strength;
+ }
+
+ mul_v4_v4fl(avg_color, avg_color, 1.0f / (float)gps->totpoints);
+ interp_v3_v3v3(stroke_color_, stroke_color_, avg_color, avg_color[3]);
+ avg_opacity_ /= (float)gps->totpoints;
+
+ /* Fill color. */
+ copy_v4_v4(fill_color_, gp_style->fill_rgba);
+ /* Apply vertex color for fill. */
+ interp_v3_v3v3(fill_color_, fill_color_, gps->vert_color_fill, gps->vert_color_fill[3]);
+}
+
+float GpencilIO::stroke_average_opacity_get()
+{
+ return avg_opacity_;
+}
+
+bool GpencilIO::is_camera_mode()
+{
+ return is_camera_;
+}
+
+bool GpencilIO::is_orthographic()
+{
+ return is_ortho_;
+}
+
+/* Calculate selected strokes boundbox. */
+void GpencilIO::selected_objects_boundbox_calc()
+{
+ const float gap = 10.0f;
+
+ float2 min, max;
+ INIT_MINMAX2(min, max);
+
+ for (ObjectZ &obz : ob_list_) {
+ Object *ob = obz.ob;
+ /* Use evaluated version to get strokes with modifiers. */
+ Object *ob_eval = (Object *)DEG_get_evaluated_id(depsgraph_, &ob->id);
+ bGPdata *gpd_eval = (bGPdata *)ob_eval->data;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_eval->layers) {
+ if (gpl->flag & GP_LAYER_HIDE) {
+ continue;
+ }
+ BKE_gpencil_layer_transform_matrix_get(depsgraph_, ob_eval, gpl, diff_mat_.values);
+
+ bGPDframe *gpf = gpl->actframe;
+ if (gpf == nullptr) {
+ continue;
+ }
+
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (gps->totpoints == 0) {
+ continue;
+ }
+ for (const bGPDspoint &pt : MutableSpan(gps->points, gps->totpoints)) {
+ const float2 screen_co = gpencil_3D_point_to_2D(&pt.x);
+ minmax_v2v2_v2(min, max, screen_co);
+ }
+ }
+ }
+ }
+ /* Add small gap. */
+ add_v2_fl(min, gap * -1.0f);
+ add_v2_fl(max, gap);
+
+ select_boundbox_.xmin = min[0];
+ select_boundbox_.ymin = min[1];
+ select_boundbox_.xmax = max[0];
+ select_boundbox_.ymax = max[1];
+}
+
+void GpencilIO::selected_objects_boundbox_get(rctf *boundbox)
+{
+ boundbox->xmin = select_boundbox_.xmin;
+ boundbox->xmax = select_boundbox_.xmax;
+ boundbox->ymin = select_boundbox_.ymin;
+ boundbox->ymax = select_boundbox_.ymax;
+}
+
+void GpencilIO::frame_number_set(const int value)
+{
+ cfra_ = value;
+}
+
+} // namespace blender::io::gpencil
diff --git a/source/blender/io/gpencil/intern/gpencil_io_base.hh b/source/blender/io/gpencil/intern/gpencil_io_base.hh
new file mode 100644
index 00000000000..cbcd35e470d
--- /dev/null
+++ b/source/blender/io/gpencil/intern/gpencil_io_base.hh
@@ -0,0 +1,118 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation
+ * All rights reserved.
+ */
+#pragma once
+
+/** \file
+ * \ingroup bgpencil
+ */
+
+#include "BLI_float2.hh"
+#include "BLI_float3.hh"
+#include "BLI_float4x4.hh"
+#include "BLI_vector.hh"
+
+#include "DNA_space_types.h" /* for FILE_MAX */
+
+#include "gpencil_io.h"
+
+struct Depsgraph;
+struct Main;
+struct Object;
+struct RegionView3D;
+struct Scene;
+
+struct bGPdata;
+struct bGPDlayer;
+struct bGPDstroke;
+
+using blender::Vector;
+
+namespace blender::io::gpencil {
+
+class GpencilIO {
+ public:
+ GpencilIO(const GpencilIOParams *iparams);
+
+ void frame_number_set(const int value);
+
+ protected:
+ GpencilIOParams params_;
+
+ bool invert_axis_[2];
+ float4x4 diff_mat_;
+ char filename_[FILE_MAX];
+
+ /* Used for sorting objects. */
+ struct ObjectZ {
+ float zdepth;
+ struct Object *ob;
+ };
+
+ /** List of included objects. */
+ blender::Vector<ObjectZ> ob_list_;
+
+ /* Data for easy access. */
+ struct Depsgraph *depsgraph_;
+ struct bGPdata *gpd_;
+ struct Main *bmain_;
+ struct Scene *scene_;
+ struct RegionView3D *rv3d_;
+
+ int16_t winx_, winy_;
+ int16_t render_x_, render_y_;
+ float camera_ratio_;
+ rctf camera_rect_;
+
+ float2 offset_;
+
+ int cfra_;
+
+ float stroke_color_[4], fill_color_[4];
+
+ /* Geometry functions. */
+ bool gpencil_3D_point_to_screen_space(const float3 co, float2 &r_co);
+ float2 gpencil_3D_point_to_render_space(const float3 co, const bool is_ortho);
+ float2 gpencil_3D_point_to_2D(const float3 co);
+
+ float stroke_point_radius_get(struct bGPDlayer *gpl, struct bGPDstroke *gps);
+ void create_object_list();
+
+ bool is_camera_mode();
+ bool is_orthographic();
+
+ float stroke_average_opacity_get();
+
+ void prepare_layer_export_matrix(struct Object *ob, struct bGPDlayer *gpl);
+ void prepare_stroke_export_colors(struct Object *ob, struct bGPDstroke *gps);
+
+ void selected_objects_boundbox_calc();
+ void selected_objects_boundbox_get(rctf *boundbox);
+ void filename_set(const char *filename);
+
+ private:
+ float avg_opacity_;
+ bool is_camera_;
+ bool is_ortho_;
+ rctf select_boundbox_;
+
+ /* Camera matrix. */
+ float persmat_[4][4];
+};
+
+} // namespace blender::io::gpencil
diff --git a/source/blender/io/gpencil/intern/gpencil_io_capi.cc b/source/blender/io/gpencil/intern/gpencil_io_capi.cc
new file mode 100644
index 00000000000..a710c175a77
--- /dev/null
+++ b/source/blender/io/gpencil/intern/gpencil_io_capi.cc
@@ -0,0 +1,204 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bgpencil
+ */
+
+#include <cstdio>
+
+#include "BLI_listbase.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "../gpencil_io.h"
+
+#ifdef WITH_HARU
+# include "gpencil_io_export_pdf.hh"
+#endif
+
+#ifdef WITH_PUGIXML
+# include "gpencil_io_export_svg.hh"
+#endif
+
+#include "gpencil_io_import_svg.hh"
+
+#ifdef WITH_HARU
+using blender::io::gpencil::GpencilExporterPDF;
+#endif
+#ifdef WITH_PUGIXML
+using blender::io::gpencil::GpencilExporterSVG;
+#endif
+using blender::io::gpencil::GpencilImporterSVG;
+
+/* Check if frame is included. */
+#ifdef WITH_HARU
+static bool is_keyframe_included(bGPdata *gpd_, const int32_t framenum, const bool use_selected)
+{
+ /* Check if exist a frame. */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_->layers) {
+ if (gpl->flag & GP_LAYER_HIDE) {
+ continue;
+ }
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ if (gpf->framenum == framenum) {
+ if ((!use_selected) || (use_selected && (gpf->flag & GP_FRAME_SELECT))) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+#endif
+
+/* Import frame. */
+static bool gpencil_io_import_frame(void *in_importer, const GpencilIOParams &iparams)
+{
+
+ bool result = false;
+ switch (iparams.mode) {
+ case GP_IMPORT_FROM_SVG: {
+ GpencilImporterSVG *importer = (GpencilImporterSVG *)in_importer;
+ result |= importer->read();
+ break;
+ }
+ /* Add new import formats here. */
+ default:
+ break;
+ }
+
+ return result;
+}
+
+/* Export frame in PDF. */
+#ifdef WITH_HARU
+static bool gpencil_io_export_pdf(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ GpencilExporterPDF *exporter,
+ const GpencilIOParams *iparams)
+{
+ bool result = false;
+ Object *ob_eval_ = (Object *)DEG_get_evaluated_id(depsgraph, &ob->id);
+ bGPdata *gpd_eval = (bGPdata *)ob_eval_->data;
+
+ exporter->frame_number_set(iparams->frame_cur);
+ result |= exporter->new_document();
+
+ const bool use_frame_selected = (iparams->frame_mode == GP_EXPORT_FRAME_SELECTED);
+ if (use_frame_selected) {
+ for (int32_t i = iparams->frame_start; i < iparams->frame_end + 1; i++) {
+ if (!is_keyframe_included(gpd_eval, i, use_frame_selected)) {
+ continue;
+ }
+
+ CFRA = i;
+ BKE_scene_graph_update_for_newframe(depsgraph);
+ exporter->frame_number_set(i);
+ exporter->add_newpage();
+ exporter->add_body();
+ }
+ result = exporter->write();
+ /* Back to original frame. */
+ exporter->frame_number_set(iparams->frame_cur);
+ CFRA = iparams->frame_cur;
+ BKE_scene_graph_update_for_newframe(depsgraph);
+ }
+ else {
+ exporter->add_newpage();
+ exporter->add_body();
+ result = exporter->write();
+ }
+
+ return result;
+}
+#endif
+
+/* Export current frame in SVG. */
+#ifdef WITH_PUGIXML
+static bool gpencil_io_export_frame_svg(GpencilExporterSVG *exporter,
+ const GpencilIOParams *iparams,
+ const bool newpage,
+ const bool body,
+ const bool savepage)
+{
+ bool result = false;
+ exporter->frame_number_set(iparams->frame_cur);
+ if (newpage) {
+ result |= exporter->add_newpage();
+ }
+ if (body) {
+ result |= exporter->add_body();
+ }
+ if (savepage) {
+ result = exporter->write();
+ }
+ return result;
+}
+#endif
+
+/* Main import entry point function. */
+bool gpencil_io_import(const char *filename, GpencilIOParams *iparams)
+{
+ GpencilImporterSVG importer = GpencilImporterSVG(filename, iparams);
+
+ return gpencil_io_import_frame(&importer, *iparams);
+}
+
+/* Main export entry point function. */
+bool gpencil_io_export(const char *filename, GpencilIOParams *iparams)
+{
+ Depsgraph *depsgraph_ = CTX_data_depsgraph_pointer(iparams->C);
+ Scene *scene_ = CTX_data_scene(iparams->C);
+ Object *ob = CTX_data_active_object(iparams->C);
+
+ UNUSED_VARS(filename, depsgraph_, scene_, ob);
+
+ switch (iparams->mode) {
+#ifdef WITH_PUGIXML
+ case GP_EXPORT_TO_SVG: {
+ GpencilExporterSVG exporter = GpencilExporterSVG(filename, iparams);
+ return gpencil_io_export_frame_svg(&exporter, iparams, true, true, true);
+ break;
+ }
+#endif
+#ifdef WITH_HARU
+ case GP_EXPORT_TO_PDF: {
+ GpencilExporterPDF exporter = GpencilExporterPDF(filename, iparams);
+ return gpencil_io_export_pdf(depsgraph_, scene_, ob, &exporter, iparams);
+ break;
+ }
+#endif
+ /* Add new export formats here. */
+ default:
+ break;
+ }
+ return false;
+}
diff --git a/source/blender/compositor/intern/COM_SocketReader.cc b/source/blender/io/gpencil/intern/gpencil_io_export_base.hh
index 93c8a143b86..ffb1c6ce262 100644
--- a/source/blender/compositor/intern/COM_SocketReader.cc
+++ b/source/blender/io/gpencil/intern/gpencil_io_export_base.hh
@@ -13,7 +13,26 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Copyright 2011, Blender Foundation.
+ * The Original Code is Copyright (C) 2020 Blender Foundation
+ * All rights reserved.
*/
+#pragma once
-#include "COM_SocketReader.h"
+/** \file
+ * \ingroup bgpencil
+ */
+#include "gpencil_io_base.hh"
+
+namespace blender::io::gpencil {
+
+class GpencilExporter : public GpencilIO {
+
+ public:
+ GpencilExporter(const struct GpencilIOParams *iparams) : GpencilIO(iparams){};
+ virtual bool write() = 0;
+
+ protected:
+ private:
+};
+
+} // namespace blender::io::gpencil
diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc
new file mode 100644
index 00000000000..9b2dc6d12a3
--- /dev/null
+++ b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc
@@ -0,0 +1,311 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bgpencil
+ */
+
+#include "BLI_math_vector.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "ED_gpencil.h"
+#include "ED_view3d.h"
+
+#ifdef WIN32
+# include "utfconv.h"
+#endif
+
+#include "UI_view2d.h"
+
+#include "gpencil_io.h"
+#include "gpencil_io_export_pdf.hh"
+
+namespace blender ::io ::gpencil {
+
+static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, void *UNUSED(user_data))
+{
+ printf("ERROR: error_no=%04X, detail_no=%u\n", (HPDF_UINT)error_no, (HPDF_UINT)detail_no);
+}
+
+/* Constructor. */
+GpencilExporterPDF::GpencilExporterPDF(const char *filename, const GpencilIOParams *iparams)
+ : GpencilExporter(iparams)
+{
+ filename_set(filename);
+
+ invert_axis_[0] = false;
+ invert_axis_[1] = false;
+
+ pdf_ = nullptr;
+ page_ = nullptr;
+ gstate_ = nullptr;
+}
+
+bool GpencilExporterPDF::new_document()
+{
+ return create_document();
+}
+
+bool GpencilExporterPDF::add_newpage()
+{
+ return add_page();
+}
+
+bool GpencilExporterPDF::add_body()
+{
+ export_gpencil_layers();
+ return true;
+}
+
+bool GpencilExporterPDF::write()
+{
+ /* Support unicode character paths on Windows. */
+ HPDF_STATUS res = 0;
+ /* TODO: It looks libharu does not support unicode. */
+ //#ifdef WIN32
+ // char filename_cstr[FILE_MAX];
+ // BLI_strncpy(filename_cstr, filename_, FILE_MAX);
+ //
+ // UTF16_ENCODE(filename_cstr);
+ // std::wstring wstr(filename_cstr_16);
+ // res = HPDF_SaveToFile(pdf_, wstr.c_str());
+ //
+ // UTF16_UN_ENCODE(filename_cstr);
+ //#else
+ res = HPDF_SaveToFile(pdf_, filename_);
+ //#endif
+
+ return (res == 0) ? true : false;
+}
+
+/* Create pdf document. */
+bool GpencilExporterPDF::create_document()
+{
+ pdf_ = HPDF_New(error_handler, nullptr);
+ if (!pdf_) {
+ std::cout << "error: cannot create PdfDoc object\n";
+ return false;
+ }
+ return true;
+}
+
+/* Add page. */
+bool GpencilExporterPDF::add_page()
+{
+ /* Add a new page object. */
+ page_ = HPDF_AddPage(pdf_);
+ if (!pdf_) {
+ std::cout << "error: cannot create PdfPage\n";
+ return false;
+ }
+
+ HPDF_Page_SetWidth(page_, render_x_);
+ HPDF_Page_SetHeight(page_, render_y_);
+
+ return true;
+}
+
+/* Main layer loop. */
+void GpencilExporterPDF::export_gpencil_layers()
+{
+ /* If is doing a set of frames, the list of objects can change for each frame. */
+ create_object_list();
+
+ const bool is_normalized = ((params_.flag & GP_EXPORT_NORM_THICKNESS) != 0);
+
+ for (ObjectZ &obz : ob_list_) {
+ Object *ob = obz.ob;
+
+ /* Use evaluated version to get strokes with modifiers. */
+ Object *ob_eval_ = (Object *)DEG_get_evaluated_id(depsgraph_, &ob->id);
+ bGPdata *gpd_eval = (bGPdata *)ob_eval_->data;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_eval->layers) {
+ if (gpl->flag & GP_LAYER_HIDE) {
+ continue;
+ }
+ prepare_layer_export_matrix(ob, gpl);
+
+ bGPDframe *gpf = gpl->actframe;
+ if ((gpf == nullptr) || (gpf->strokes.first == nullptr)) {
+ continue;
+ }
+
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (gps->totpoints < 2) {
+ continue;
+ }
+ if (!ED_gpencil_stroke_material_visible(ob, gps)) {
+ continue;
+ }
+ /* Duplicate the stroke to apply any layer thickness change. */
+ bGPDstroke *gps_duplicate = BKE_gpencil_stroke_duplicate(gps, true, false);
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob,
+ gps_duplicate->mat_nr + 1);
+
+ const bool is_stroke = ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) &&
+ (gp_style->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH));
+ const bool is_fill = ((gp_style->flag & GP_MATERIAL_FILL_SHOW) &&
+ (gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH));
+ prepare_stroke_export_colors(ob, gps_duplicate);
+
+ /* Apply layer thickness change. */
+ gps_duplicate->thickness += gpl->line_change;
+ /* Apply object scale to thickness. */
+ gps_duplicate->thickness *= mat4_to_scale(ob->obmat);
+ CLAMP_MIN(gps_duplicate->thickness, 1.0f);
+ /* Fill. */
+ if ((is_fill) && (params_.flag & GP_EXPORT_FILL)) {
+ /* Fill is exported as polygon for fill and stroke in a different shape. */
+ export_stroke_to_polyline(gpl, gps_duplicate, is_stroke, true, false);
+ }
+
+ /* Stroke. */
+ if (is_stroke) {
+ if (is_normalized) {
+ export_stroke_to_polyline(gpl, gps_duplicate, is_stroke, false, true);
+ }
+ else {
+ bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view(
+ rv3d_, gpd_, gpl, gps_duplicate, 3, diff_mat_.values);
+
+ /* Sample stroke. */
+ if (params_.stroke_sample > 0.0f) {
+ BKE_gpencil_stroke_sample(gpd_eval, gps_perimeter, params_.stroke_sample, false);
+ }
+
+ export_stroke_to_polyline(gpl, gps_perimeter, is_stroke, false, false);
+
+ BKE_gpencil_free_stroke(gps_perimeter);
+ }
+ }
+ BKE_gpencil_free_stroke(gps_duplicate);
+ }
+ }
+ }
+}
+
+/**
+ * Export a stroke using polyline or polygon
+ * \param do_fill: True if the stroke is only fill
+ */
+void GpencilExporterPDF::export_stroke_to_polyline(bGPDlayer *gpl,
+ bGPDstroke *gps,
+ const bool is_stroke,
+ const bool do_fill,
+ const bool normalize)
+{
+ const bool cyclic = ((gps->flag & GP_STROKE_CYCLIC) != 0);
+ const float avg_pressure = BKE_gpencil_stroke_average_pressure_get(gps);
+
+ /* Get the thickness in pixels using a simple 1 point stroke. */
+ bGPDstroke *gps_temp = BKE_gpencil_stroke_duplicate(gps, false, false);
+ gps_temp->totpoints = 1;
+ gps_temp->points = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint), "gp_stroke_points");
+ const bGPDspoint *pt_src = &gps->points[0];
+ bGPDspoint *pt_dst = &gps_temp->points[0];
+ copy_v3_v3(&pt_dst->x, &pt_src->x);
+ pt_dst->pressure = avg_pressure;
+
+ const float radius = stroke_point_radius_get(gpl, gps_temp);
+
+ BKE_gpencil_free_stroke(gps_temp);
+
+ color_set(gpl, do_fill);
+
+ if (is_stroke && !do_fill) {
+ HPDF_Page_SetLineJoin(page_, HPDF_ROUND_JOIN);
+ HPDF_Page_SetLineWidth(page_, MAX2((radius * 2.0f) - gpl->line_change, 1.0f));
+ }
+
+ /* Loop all points. */
+ for (const int i : IndexRange(gps->totpoints)) {
+ bGPDspoint *pt = &gps->points[i];
+ const float2 screen_co = gpencil_3D_point_to_2D(&pt->x);
+ if (i == 0) {
+ HPDF_Page_MoveTo(page_, screen_co.x, screen_co.y);
+ }
+ else {
+ HPDF_Page_LineTo(page_, screen_co.x, screen_co.y);
+ }
+ }
+ /* Close cyclic */
+ if (cyclic) {
+ HPDF_Page_ClosePath(page_);
+ }
+
+ if (do_fill || !normalize) {
+ HPDF_Page_Fill(page_);
+ }
+ else {
+ HPDF_Page_Stroke(page_);
+ }
+
+ HPDF_Page_GRestore(page_);
+}
+
+/**
+ * Set color
+ * @param do_fill: True if the stroke is only fill
+ */
+void GpencilExporterPDF::color_set(bGPDlayer *gpl, const bool do_fill)
+{
+ const float fill_opacity = fill_color_[3] * gpl->opacity;
+ const float stroke_opacity = stroke_color_[3] * stroke_average_opacity_get() * gpl->opacity;
+
+ HPDF_Page_GSave(page_);
+ gstate_ = HPDF_CreateExtGState(pdf_);
+
+ float col[3];
+ if (do_fill) {
+ interp_v3_v3v3(col, fill_color_, gpl->tintcolor, gpl->tintcolor[3]);
+ linearrgb_to_srgb_v3_v3(col, col);
+ CLAMP3(col, 0.0f, 1.0f);
+
+ HPDF_ExtGState_SetAlphaFill(gstate_, clamp_f(fill_opacity, 0.0f, 1.0f));
+ HPDF_Page_SetRGBFill(page_, col[0], col[1], col[2]);
+ }
+ else {
+ interp_v3_v3v3(col, stroke_color_, gpl->tintcolor, gpl->tintcolor[3]);
+ linearrgb_to_srgb_v3_v3(col, col);
+ CLAMP3(col, 0.0f, 1.0f);
+
+ HPDF_ExtGState_SetAlphaFill(gstate_, clamp_f(stroke_opacity, 0.0f, 1.0f));
+ HPDF_ExtGState_SetAlphaStroke(gstate_, clamp_f(stroke_opacity, 0.0f, 1.0f));
+ HPDF_Page_SetRGBFill(page_, col[0], col[1], col[2]);
+ HPDF_Page_SetRGBStroke(page_, col[0], col[1], col[2]);
+ }
+ HPDF_Page_SetExtGState(page_, gstate_);
+}
+} // namespace blender::io::gpencil
diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.hh b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.hh
new file mode 100644
index 00000000000..20970151344
--- /dev/null
+++ b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.hh
@@ -0,0 +1,67 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation
+ * All rights reserved.
+ */
+#pragma once
+
+/** \file
+ * \ingroup bgpencil
+ */
+
+#include "gpencil_io_export_base.hh"
+#include "hpdf.h"
+
+struct GpencilIOParams;
+struct bGPDlayer;
+struct bGPDstroke;
+
+#define PDF_EXPORTER_NAME "PDF Exporter for Grease Pencil"
+#define PDF_EXPORTER_VERSION "v1.0"
+
+namespace blender::io::gpencil {
+
+class GpencilExporterPDF : public GpencilExporter {
+
+ public:
+ GpencilExporterPDF(const char *filename, const struct GpencilIOParams *iparams);
+ bool new_document();
+ bool add_newpage();
+ bool add_body();
+ bool write();
+
+ protected:
+ private:
+ /* PDF document. */
+ HPDF_Doc pdf_;
+ /* PDF page. */
+ HPDF_Page page_;
+ /* State. */
+ HPDF_ExtGState gstate_;
+
+ bool create_document();
+ bool add_page();
+ void export_gpencil_layers();
+
+ void export_stroke_to_polyline(bGPDlayer *gpl,
+ bGPDstroke *gps,
+ const bool is_stroke,
+ const bool do_fill,
+ const bool normalize);
+ void color_set(bGPDlayer *gpl, const bool do_fill);
+};
+
+} // namespace blender::io::gpencil
diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc
new file mode 100644
index 00000000000..c62764cca06
--- /dev/null
+++ b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc
@@ -0,0 +1,465 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bgpencil
+ */
+
+#include "BLI_math_vector.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "ED_gpencil.h"
+#include "ED_view3d.h"
+
+#ifdef WIN32
+# include "utfconv.h"
+#endif
+
+#include "UI_view2d.h"
+
+#include "gpencil_io.h"
+#include "gpencil_io_export_svg.hh"
+
+#include "pugixml.hpp"
+
+namespace blender ::io ::gpencil {
+
+/* Constructor. */
+GpencilExporterSVG::GpencilExporterSVG(const char *filename, const GpencilIOParams *iparams)
+ : GpencilExporter(iparams)
+{
+ filename_set(filename);
+
+ invert_axis_[0] = false;
+ invert_axis_[1] = true;
+}
+
+bool GpencilExporterSVG::add_newpage()
+{
+ create_document_header();
+ return true;
+}
+
+bool GpencilExporterSVG::add_body()
+{
+ export_gpencil_layers();
+ return true;
+}
+
+bool GpencilExporterSVG::write()
+{
+ bool result = true;
+/* Support unicode character paths on Windows. */
+#ifdef WIN32
+ char filename_cstr[FILE_MAX];
+ BLI_strncpy(filename_cstr, filename_, FILE_MAX);
+
+ UTF16_ENCODE(filename_cstr);
+ std::wstring wstr(filename_cstr_16);
+ result = main_doc_.save_file(wstr.c_str());
+
+ UTF16_UN_ENCODE(filename_cstr);
+#else
+ result = main_doc_.save_file(filename_);
+#endif
+
+ return result;
+}
+
+/* Create document header and main svg node. */
+void GpencilExporterSVG::create_document_header()
+{
+ /* Add a custom document declaration node. */
+ pugi::xml_node decl = main_doc_.prepend_child(pugi::node_declaration);
+ decl.append_attribute("version") = "1.0";
+ decl.append_attribute("encoding") = "UTF-8";
+
+ pugi::xml_node comment = main_doc_.append_child(pugi::node_comment);
+ char txt[128];
+ sprintf(txt, " Generator: Blender, %s - %s ", SVG_EXPORTER_NAME, SVG_EXPORTER_VERSION);
+ comment.set_value(txt);
+
+ pugi::xml_node doctype = main_doc_.append_child(pugi::node_doctype);
+ doctype.set_value(
+ "svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" "
+ "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"");
+
+ main_node_ = main_doc_.append_child("svg");
+ main_node_.append_attribute("version").set_value("1.0");
+ main_node_.append_attribute("x").set_value("0px");
+ main_node_.append_attribute("y").set_value("0px");
+ main_node_.append_attribute("xmlns").set_value("http://www.w3.org/2000/svg");
+
+ std::string width;
+ std::string height;
+
+ width = std::to_string(render_x_);
+ height = std::to_string(render_y_);
+
+ main_node_.append_attribute("width").set_value((width + "px").c_str());
+ main_node_.append_attribute("height").set_value((height + "px").c_str());
+ std::string viewbox = "0 0 " + width + " " + height;
+ main_node_.append_attribute("viewBox").set_value(viewbox.c_str());
+}
+
+/* Main layer loop. */
+void GpencilExporterSVG::export_gpencil_layers()
+{
+ const bool is_clipping = is_camera_mode() && (params_.flag & GP_EXPORT_CLIP_CAMERA) != 0;
+
+ /* If is doing a set of frames, the list of objects can change for each frame. */
+ create_object_list();
+
+ for (ObjectZ &obz : ob_list_) {
+ Object *ob = obz.ob;
+
+ /* Camera clipping. */
+ if (is_clipping) {
+ pugi::xml_node clip_node = main_node_.append_child("clipPath");
+ clip_node.append_attribute("id").set_value(("clip-path" + std::to_string(cfra_)).c_str());
+
+ add_rect(clip_node, 0, 0, render_x_, render_y_, 0.0f, "#000000");
+ }
+
+ frame_node_ = main_node_.append_child("g");
+ std::string frametxt = "blender_frame_" + std::to_string(cfra_);
+ frame_node_.append_attribute("id").set_value(frametxt.c_str());
+
+ /* Clip area. */
+ if (is_clipping) {
+ frame_node_.append_attribute("clip-path")
+ .set_value(("url(#clip-path" + std::to_string(cfra_) + ")").c_str());
+ }
+
+ pugi::xml_node ob_node = frame_node_.append_child("g");
+
+ char obtxt[96];
+ sprintf(obtxt, "blender_object_%s", ob->id.name + 2);
+ ob_node.append_attribute("id").set_value(obtxt);
+
+ /* Use evaluated version to get strokes with modifiers. */
+ Object *ob_eval_ = (Object *)DEG_get_evaluated_id(depsgraph_, &ob->id);
+ bGPdata *gpd_eval = (bGPdata *)ob_eval_->data;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_eval->layers) {
+ if (gpl->flag & GP_LAYER_HIDE) {
+ continue;
+ }
+ prepare_layer_export_matrix(ob, gpl);
+
+ bGPDframe *gpf = gpl->actframe;
+ if ((gpf == nullptr) || (gpf->strokes.first == nullptr)) {
+ continue;
+ }
+
+ /* Layer node. */
+ std::string txt = "Layer: ";
+ txt.append(gpl->info);
+ ob_node.append_child(pugi::node_comment).set_value(txt.c_str());
+
+ pugi::xml_node node_gpl = ob_node.append_child("g");
+ node_gpl.append_attribute("id").set_value(gpl->info);
+
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (gps->totpoints < 2) {
+ continue;
+ }
+ if (!ED_gpencil_stroke_material_visible(ob, gps)) {
+ continue;
+ }
+
+ /* Duplicate the stroke to apply any layer thickness change. */
+ bGPDstroke *gps_duplicate = BKE_gpencil_stroke_duplicate(gps, true, false);
+
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob,
+ gps_duplicate->mat_nr + 1);
+
+ const bool is_stroke = ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) &&
+ (gp_style->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH));
+ const bool is_fill = ((gp_style->flag & GP_MATERIAL_FILL_SHOW) &&
+ (gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH));
+
+ prepare_stroke_export_colors(ob, gps_duplicate);
+
+ /* Apply layer thickness change. */
+ gps_duplicate->thickness += gpl->line_change;
+ /* Apply object scale to thickness. */
+ gps_duplicate->thickness *= mat4_to_scale(ob->obmat);
+ CLAMP_MIN(gps_duplicate->thickness, 1.0f);
+
+ const bool is_normalized = ((params_.flag & GP_EXPORT_NORM_THICKNESS) != 0) ||
+ BKE_gpencil_stroke_is_pressure_constant(gps);
+
+ /* Fill. */
+ if ((is_fill) && (params_.flag & GP_EXPORT_FILL)) {
+ /* Fill is always exported as polygon because the stroke of the fill is done
+ * in a different SVG command. */
+ export_stroke_to_polyline(gpl, gps_duplicate, node_gpl, is_stroke, true);
+ }
+
+ /* Stroke. */
+ if (is_stroke) {
+ if (is_normalized) {
+ export_stroke_to_polyline(gpl, gps_duplicate, node_gpl, is_stroke, false);
+ }
+ else {
+ bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view(
+ rv3d_, gpd_, gpl, gps_duplicate, 3, diff_mat_.values);
+
+ /* Sample stroke. */
+ if (params_.stroke_sample > 0.0f) {
+ BKE_gpencil_stroke_sample(gpd_eval, gps_perimeter, params_.stroke_sample, false);
+ }
+
+ export_stroke_to_path(gpl, gps_perimeter, node_gpl, false);
+
+ BKE_gpencil_free_stroke(gps_perimeter);
+ }
+ }
+
+ BKE_gpencil_free_stroke(gps_duplicate);
+ }
+ }
+ }
+}
+
+/**
+ * Export a stroke using SVG path
+ * \param node_gpl: Node of the layer.
+ * \param do_fill: True if the stroke is only fill
+ */
+void GpencilExporterSVG::export_stroke_to_path(bGPDlayer *gpl,
+ bGPDstroke *gps,
+ pugi::xml_node node_gpl,
+ const bool do_fill)
+{
+ pugi::xml_node node_gps = node_gpl.append_child("path");
+
+ float col[3];
+ std::string stroke_hex;
+ if (do_fill) {
+ node_gps.append_attribute("fill-opacity").set_value(fill_color_[3] * gpl->opacity);
+
+ interp_v3_v3v3(col, fill_color_, gpl->tintcolor, gpl->tintcolor[3]);
+ }
+ else {
+ node_gps.append_attribute("fill-opacity")
+ .set_value(stroke_color_[3] * stroke_average_opacity_get() * gpl->opacity);
+
+ interp_v3_v3v3(col, stroke_color_, gpl->tintcolor, gpl->tintcolor[3]);
+ }
+
+ linearrgb_to_srgb_v3_v3(col, col);
+ stroke_hex = rgb_to_hexstr(col);
+
+ node_gps.append_attribute("fill").set_value(stroke_hex.c_str());
+ node_gps.append_attribute("stroke").set_value("none");
+
+ std::string txt = "M";
+ for (const int i : IndexRange(gps->totpoints)) {
+ if (i > 0) {
+ txt.append("L");
+ }
+ bGPDspoint &pt = gps->points[i];
+ const float2 screen_co = gpencil_3D_point_to_2D(&pt.x);
+ txt.append(std::to_string(screen_co.x) + "," + std::to_string(screen_co.y));
+ }
+ /* Close patch (cyclic)*/
+ if (gps->flag & GP_STROKE_CYCLIC) {
+ txt.append("z");
+ }
+
+ node_gps.append_attribute("d").set_value(txt.c_str());
+}
+
+/**
+ * Export a stroke using polyline or polygon
+ * \param node_gpl: Node of the layer.
+ * \param do_fill: True if the stroke is only fill
+ */
+void GpencilExporterSVG::export_stroke_to_polyline(bGPDlayer *gpl,
+ bGPDstroke *gps,
+ pugi::xml_node node_gpl,
+ const bool is_stroke,
+ const bool do_fill)
+{
+ const bool cyclic = ((gps->flag & GP_STROKE_CYCLIC) != 0);
+ const float avg_pressure = BKE_gpencil_stroke_average_pressure_get(gps);
+
+ /* Get the thickness in pixels using a simple 1 point stroke. */
+ bGPDstroke *gps_temp = BKE_gpencil_stroke_duplicate(gps, false, false);
+ gps_temp->totpoints = 1;
+ gps_temp->points = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint), "gp_stroke_points");
+ bGPDspoint *pt_src = &gps->points[0];
+ bGPDspoint *pt_dst = &gps_temp->points[0];
+ copy_v3_v3(&pt_dst->x, &pt_src->x);
+ pt_dst->pressure = avg_pressure;
+
+ const float radius = stroke_point_radius_get(gpl, gps_temp);
+
+ BKE_gpencil_free_stroke(gps_temp);
+
+ pugi::xml_node node_gps = node_gpl.append_child(do_fill || cyclic ? "polygon" : "polyline");
+
+ color_string_set(gpl, gps, node_gps, do_fill);
+
+ if (is_stroke && !do_fill) {
+ node_gps.append_attribute("stroke-width").set_value((radius * 2.0f) - gpl->line_change);
+ }
+
+ std::string txt;
+ for (const int i : IndexRange(gps->totpoints)) {
+ if (i > 0) {
+ txt.append(" ");
+ }
+ bGPDspoint *pt = &gps->points[i];
+ const float2 screen_co = gpencil_3D_point_to_2D(&pt->x);
+ txt.append(std::to_string(screen_co.x) + "," + std::to_string(screen_co.y));
+ }
+
+ node_gps.append_attribute("points").set_value(txt.c_str());
+}
+
+/**
+ * Set color SVG string for stroke
+ * \param node_gps: Stroke node
+ * @param do_fill: True if the stroke is only fill
+ */
+void GpencilExporterSVG::color_string_set(bGPDlayer *gpl,
+ bGPDstroke *gps,
+ pugi::xml_node node_gps,
+ const bool do_fill)
+{
+ const bool round_cap = (gps->caps[0] == GP_STROKE_CAP_ROUND ||
+ gps->caps[1] == GP_STROKE_CAP_ROUND);
+
+ float col[3];
+ if (do_fill) {
+ interp_v3_v3v3(col, fill_color_, gpl->tintcolor, gpl->tintcolor[3]);
+ linearrgb_to_srgb_v3_v3(col, col);
+ std::string stroke_hex = rgb_to_hexstr(col);
+ node_gps.append_attribute("fill").set_value(stroke_hex.c_str());
+ node_gps.append_attribute("stroke").set_value("none");
+ node_gps.append_attribute("fill-opacity").set_value(fill_color_[3] * gpl->opacity);
+ }
+ else {
+ interp_v3_v3v3(col, stroke_color_, gpl->tintcolor, gpl->tintcolor[3]);
+ linearrgb_to_srgb_v3_v3(col, col);
+ std::string stroke_hex = rgb_to_hexstr(col);
+ node_gps.append_attribute("stroke").set_value(stroke_hex.c_str());
+ node_gps.append_attribute("stroke-opacity")
+ .set_value(stroke_color_[3] * stroke_average_opacity_get() * gpl->opacity);
+
+ if (gps->totpoints > 1) {
+ node_gps.append_attribute("fill").set_value("none");
+ node_gps.append_attribute("stroke-linecap").set_value(round_cap ? "round" : "square");
+ }
+ else {
+ node_gps.append_attribute("fill").set_value(stroke_hex.c_str());
+ node_gps.append_attribute("fill-opacity").set_value(fill_color_[3] * gpl->opacity);
+ }
+ }
+}
+
+/**
+ * Create a SVG rectangle
+ * \param node: Parent node
+ * \param x: X location
+ * \param y: Y location
+ * \param width: width of the rectangle
+ * \param height: Height of the rectangle
+ * \param thickness: Thickness of the line
+ * \param hexcolor: Color of the line
+ */
+void GpencilExporterSVG::add_rect(pugi::xml_node node,
+ float x,
+ float y,
+ float width,
+ float height,
+ float thickness,
+ std::string hexcolor)
+{
+ pugi::xml_node rect_node = node.append_child("rect");
+ rect_node.append_attribute("x").set_value(x);
+ rect_node.append_attribute("y").set_value(y);
+ rect_node.append_attribute("width").set_value(width);
+ rect_node.append_attribute("height").set_value(height);
+ rect_node.append_attribute("fill").set_value("none");
+ if (thickness > 0.0f) {
+ rect_node.append_attribute("stroke").set_value(hexcolor.c_str());
+ rect_node.append_attribute("stroke-width").set_value(thickness);
+ }
+}
+
+/**
+ * Create SVG text
+ * \param node: Parent node
+ * \param x: X location
+ * \param y: Y location
+ * \param text: Text to include
+ * \param size: Size of the text
+ * \param hexcolor: Color of the text
+ */
+void GpencilExporterSVG::add_text(pugi::xml_node node,
+ float x,
+ float y,
+ std::string text,
+ const float size,
+ std::string hexcolor)
+{
+ pugi::xml_node nodetxt = node.append_child("text");
+
+ nodetxt.append_attribute("x").set_value(x);
+ nodetxt.append_attribute("y").set_value(y);
+ // nodetxt.append_attribute("font-family").set_value("'system-ui'");
+ nodetxt.append_attribute("font-size").set_value(size);
+ nodetxt.append_attribute("fill").set_value(hexcolor.c_str());
+ nodetxt.text().set(text.c_str());
+}
+
+/** Convert a color to Hex value (#FFFFFF). */
+std::string GpencilExporterSVG::rgb_to_hexstr(const float color[3])
+{
+ uint8_t r = color[0] * 255.0f;
+ uint8_t g = color[1] * 255.0f;
+ uint8_t b = color[2] * 255.0f;
+ char hex_string[20];
+ sprintf(hex_string, "#%02X%02X%02X", r, g, b);
+
+ std::string hexstr = hex_string;
+
+ return hexstr;
+}
+
+} // namespace blender::io::gpencil
diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_svg.hh b/source/blender/io/gpencil/intern/gpencil_io_export_svg.hh
new file mode 100644
index 00000000000..3bff31f20bf
--- /dev/null
+++ b/source/blender/io/gpencil/intern/gpencil_io_export_svg.hh
@@ -0,0 +1,89 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation
+ * All rights reserved.
+ */
+#pragma once
+
+/** \file
+ * \ingroup bgpencil
+ */
+#include "BLI_path_util.h"
+
+#include "gpencil_io_export_base.hh"
+#include "pugixml.hpp"
+
+struct GpencilIOParams;
+
+#define SVG_EXPORTER_NAME "SVG Export for Grease Pencil"
+#define SVG_EXPORTER_VERSION "v1.0"
+
+namespace blender::io::gpencil {
+
+class GpencilExporterSVG : public GpencilExporter {
+
+ public:
+ GpencilExporterSVG(const char *filename, const struct GpencilIOParams *iparams);
+ bool add_newpage();
+ bool add_body();
+ bool write();
+
+ protected:
+ static void add_rect(pugi::xml_node node,
+ float x,
+ float y,
+ float width,
+ float height,
+ float thickness,
+ std::string hexcolor);
+
+ static void add_text(pugi::xml_node node,
+ float x,
+ float y,
+ std::string text,
+ const float size,
+ std::string hexcolor);
+
+ private:
+ /* XML doc. */
+ pugi::xml_document main_doc_;
+ /* Main document node. */
+ pugi::xml_node main_node_;
+ /** Frame node */
+ pugi::xml_node frame_node_;
+ void create_document_header();
+ void export_gpencil_layers();
+
+ void export_stroke_to_path(struct bGPDlayer *gpl,
+ struct bGPDstroke *gps,
+ pugi::xml_node node_gpl,
+ const bool do_fill);
+
+ void export_stroke_to_polyline(struct bGPDlayer *gpl,
+ struct bGPDstroke *gps,
+ pugi::xml_node node_gpl,
+ const bool is_stroke,
+ const bool do_fill);
+
+ void color_string_set(struct bGPDlayer *gpl,
+ struct bGPDstroke *gps,
+ pugi::xml_node node_gps,
+ const bool do_fill);
+
+ std::string rgb_to_hexstr(const float color[3]);
+};
+
+} // namespace blender::io::gpencil
diff --git a/source/blender/io/gpencil/intern/gpencil_io_import_base.cc b/source/blender/io/gpencil/intern/gpencil_io_import_base.cc
new file mode 100644
index 00000000000..d0b6e20bda2
--- /dev/null
+++ b/source/blender/io/gpencil/intern/gpencil_io_import_base.cc
@@ -0,0 +1,83 @@
+
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bgpencil
+ */
+#include "BLI_math_vector.h"
+
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_gpencil.h"
+#include "BKE_material.h"
+
+#include "ED_gpencil.h"
+
+#include "gpencil_io_import_base.hh"
+
+namespace blender::io::gpencil {
+
+/* Constructor. */
+GpencilImporter::GpencilImporter(const GpencilIOParams *iparams) : GpencilIO(iparams)
+{
+ /* Nothing to do yet */
+}
+
+Object *GpencilImporter::create_object()
+{
+ const float *cur = scene_->cursor.location;
+ ushort local_view_bits = (params_.v3d && params_.v3d->localvd) ? params_.v3d->local_view_uuid :
+ (ushort)0;
+ Object *ob_gpencil = ED_gpencil_add_object(params_.C, cur, local_view_bits);
+
+ return ob_gpencil;
+}
+
+int32_t GpencilImporter::create_material(const char *name, const bool stroke, const bool fill)
+{
+ const float default_stroke_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ const float default_fill_color[4] = {0.5f, 0.5f, 0.5f, 1.0f};
+ int32_t mat_index = BKE_gpencil_material_find_index_by_name_prefix(params_.ob, name);
+ /* Stroke and Fill material. */
+ if (mat_index == -1) {
+ int32_t new_idx;
+ Material *mat_gp = BKE_gpencil_object_material_new(bmain_, params_.ob, name, &new_idx);
+ MaterialGPencilStyle *gp_style = mat_gp->gp_style;
+ gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
+ gp_style->flag &= ~GP_MATERIAL_FILL_SHOW;
+
+ copy_v4_v4(gp_style->stroke_rgba, default_stroke_color);
+ copy_v4_v4(gp_style->fill_rgba, default_fill_color);
+ if (stroke) {
+ gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
+ }
+ if (fill) {
+ gp_style->flag |= GP_MATERIAL_FILL_SHOW;
+ }
+ mat_index = params_.ob->totcol - 1;
+ }
+
+ return mat_index;
+}
+
+} // namespace blender::io::gpencil
diff --git a/source/blender/io/gpencil/intern/gpencil_io_import_base.hh b/source/blender/io/gpencil/intern/gpencil_io_import_base.hh
new file mode 100644
index 00000000000..7d6fad2340b
--- /dev/null
+++ b/source/blender/io/gpencil/intern/gpencil_io_import_base.hh
@@ -0,0 +1,41 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation
+ * All rights reserved.
+ */
+#pragma once
+
+/** \file
+ * \ingroup bgpencil
+ */
+#include "gpencil_io_base.hh"
+
+namespace blender::io::gpencil {
+
+class GpencilImporter : public GpencilIO {
+
+ public:
+ GpencilImporter(const struct GpencilIOParams *iparams);
+ virtual bool read() = 0;
+
+ protected:
+ struct Object *create_object();
+ int32_t create_material(const char *name, const bool stroke, const bool fill);
+
+ private:
+};
+
+} // namespace blender::io::gpencil
diff --git a/source/blender/io/gpencil/intern/gpencil_io_import_svg.cc b/source/blender/io/gpencil/intern/gpencil_io_import_svg.cc
new file mode 100644
index 00000000000..4894cfc1ada
--- /dev/null
+++ b/source/blender/io/gpencil/intern/gpencil_io_import_svg.cc
@@ -0,0 +1,253 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bgpencil
+ */
+
+#include "BLI_float3.hh"
+#include "BLI_math.h"
+#include "BLI_span.hh"
+
+#include "DNA_gpencil_types.h"
+
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "ED_gpencil.h"
+
+#include "gpencil_io.h"
+#include "gpencil_io_import_svg.hh"
+
+/* Custom flags for NanoSVG. */
+#define NANOSVG_ALL_COLOR_KEYWORDS
+#define NANOSVG_IMPLEMENTATION
+
+#include "nanosvg/nanosvg.h"
+
+using blender::MutableSpan;
+
+namespace blender::io::gpencil {
+
+/* Constructor. */
+GpencilImporterSVG::GpencilImporterSVG(const char *filename, const GpencilIOParams *iparams)
+ : GpencilImporter(iparams)
+{
+ filename_set(filename);
+}
+
+bool GpencilImporterSVG::read()
+{
+ bool result = true;
+ NSVGimage *svg_data = nullptr;
+ svg_data = nsvgParseFromFile(filename_, "mm", 96.0f);
+ if (svg_data == nullptr) {
+ std::cout << " Could not open SVG.\n ";
+ return false;
+ }
+
+ /* Create grease pencil object. */
+ params_.ob = create_object();
+ if (params_.ob == nullptr) {
+ std::cout << "Unable to create new object.\n";
+ if (svg_data) {
+ nsvgDelete(svg_data);
+ }
+
+ return false;
+ }
+ gpd_ = (bGPdata *)params_.ob->data;
+
+ /* Grease pencil is rotated 90 degrees in X axis by default. */
+ float matrix[4][4];
+ const float3 scale = float3(params_.scale);
+ unit_m4(matrix);
+ rotate_m4(matrix, 'X', DEG2RADF(-90.0f));
+ rescale_m4(matrix, scale);
+
+ /* Loop all shapes. */
+ char prv_id[70] = {"*"};
+ int prefix = 0;
+ for (NSVGshape *shape = svg_data->shapes; shape; shape = shape->next) {
+ char *layer_id = (shape->id_parent[0] == '\0') ? BLI_sprintfN("Layer_%03d", prefix) :
+ BLI_sprintfN("%s", shape->id_parent);
+ if (!STREQ(prv_id, layer_id)) {
+ prefix++;
+ MEM_freeN(layer_id);
+ layer_id = (shape->id_parent[0] == '\0') ? BLI_sprintfN("Layer_%03d", prefix) :
+ BLI_sprintfN("%s", shape->id_parent);
+ strcpy(prv_id, layer_id);
+ }
+
+ /* Check if the layer exist and create if needed. */
+ bGPDlayer *gpl = (bGPDlayer *)BLI_findstring(
+ &gpd_->layers, layer_id, offsetof(bGPDlayer, info));
+ if (gpl == nullptr) {
+ gpl = BKE_gpencil_layer_addnew(gpd_, layer_id, true);
+ /* Disable lights. */
+ gpl->flag &= ~GP_LAYER_USE_LIGHTS;
+ }
+ MEM_freeN(layer_id);
+
+ /* Check frame. */
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, cfra_, GP_GETFRAME_ADD_NEW);
+ /* Create materials. */
+ bool is_stroke = (bool)shape->stroke.type;
+ bool is_fill = (bool)shape->fill.type;
+ if ((!is_stroke) && (!is_fill)) {
+ is_stroke = true;
+ }
+
+ /* Create_shape materials. */
+ const char *const mat_names[] = {"Stroke", "Fill"};
+ int index = 0;
+ if ((is_stroke) && (is_fill)) {
+ index = 0;
+ is_fill = false;
+ }
+ else if ((!is_stroke) && (is_fill)) {
+ index = 1;
+ }
+ int32_t mat_index = create_material(mat_names[index], is_stroke, is_fill);
+
+ /* Loop all paths to create the stroke data. */
+ for (NSVGpath *path = shape->paths; path; path = path->next) {
+ create_stroke(gpd_, gpf, shape, path, mat_index, matrix);
+ }
+ }
+
+ /* Free SVG memory. */
+ nsvgDelete(svg_data);
+
+ /* Calculate bounding box and move all points to new origin center. */
+ float gp_center[3];
+ BKE_gpencil_centroid_3d(gpd_, gp_center);
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ for (bGPDspoint &pt : MutableSpan(gps->points, gps->totpoints)) {
+ sub_v3_v3(&pt.x, gp_center);
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+void GpencilImporterSVG::create_stroke(bGPdata *gpd,
+ bGPDframe *gpf,
+ NSVGshape *shape,
+ NSVGpath *path,
+ const int32_t mat_index,
+ const float matrix[4][4])
+{
+ const bool is_stroke = (bool)shape->stroke.type;
+ const bool is_fill = (bool)shape->fill.type;
+
+ const int edges = params_.resolution;
+ const float step = 1.0f / (float)(edges - 1);
+
+ const int totpoints = (path->npts / 3) * params_.resolution;
+
+ bGPDstroke *gps = BKE_gpencil_stroke_new(mat_index, totpoints, 1.0f);
+ BLI_addtail(&gpf->strokes, gps);
+
+ if (path->closed == '1') {
+ gps->flag |= GP_STROKE_CYCLIC;
+ }
+ if (is_stroke) {
+ gps->thickness = shape->strokeWidth * params_.scale;
+ }
+ /* Apply Fill vertex color. */
+ if (is_fill) {
+ NSVGpaint fill = shape->fill;
+ convert_color(fill.color, gps->vert_color_fill);
+ gps->fill_opacity_fac = gps->vert_color_fill[3];
+ gps->vert_color_fill[3] = 1.0f;
+ }
+
+ int start_index = 0;
+ for (int i = 0; i < path->npts - 1; i += 3) {
+ float *p = &path->pts[i * 2];
+ float a = 0.0f;
+ for (int v = 0; v < edges; v++) {
+ bGPDspoint *pt = &gps->points[start_index];
+ pt->strength = shape->opacity;
+ pt->pressure = 1.0f;
+ pt->z = 0.0f;
+ /* TODO(antoniov): Can be improved loading curve data instead of loading strokes. */
+ interp_v2_v2v2v2v2_cubic(&pt->x, &p[0], &p[2], &p[4], &p[6], a);
+
+ /* Scale from millimeters. */
+ mul_v3_fl(&pt->x, 0.001f);
+ mul_m4_v3(matrix, &pt->x);
+
+ /* Apply color to vertex color. */
+ if (is_fill) {
+ NSVGpaint fill = shape->fill;
+ convert_color(fill.color, pt->vert_color);
+ }
+ if (is_stroke) {
+ NSVGpaint stroke = shape->stroke;
+ convert_color(stroke.color, pt->vert_color);
+ gps->fill_opacity_fac = pt->vert_color[3];
+ }
+ pt->vert_color[3] = 1.0f;
+
+ a += step;
+ start_index++;
+ }
+ }
+
+ /* Cleanup and recalculate geometry. */
+ BKE_gpencil_stroke_merge_distance(gpd, gpf, gps, 0.001f, true);
+ BKE_gpencil_stroke_geometry_update(gpd, gps);
+}
+
+/* Unpack internal NanoSVG color. */
+static void unpack_nano_color(const unsigned int pack, float r_col[4])
+{
+ unsigned char rgb_u[4];
+
+ rgb_u[0] = ((pack) >> 0) & 0xFF;
+ rgb_u[1] = ((pack) >> 8) & 0xFF;
+ rgb_u[2] = ((pack) >> 16) & 0xFF;
+ rgb_u[3] = ((pack) >> 24) & 0xFF;
+
+ r_col[0] = (float)rgb_u[0] / 255.0f;
+ r_col[1] = (float)rgb_u[1] / 255.0f;
+ r_col[2] = (float)rgb_u[2] / 255.0f;
+ r_col[3] = (float)rgb_u[3] / 255.0f;
+}
+
+void GpencilImporterSVG::convert_color(const int32_t color, float r_linear_rgba[4])
+{
+ float rgba[4];
+ unpack_nano_color(color, rgba);
+
+ srgb_to_linearrgb_v3_v3(r_linear_rgba, rgba);
+ r_linear_rgba[3] = rgba[3];
+}
+
+} // namespace blender::io::gpencil
diff --git a/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh b/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh
new file mode 100644
index 00000000000..0e9271dd2c6
--- /dev/null
+++ b/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh
@@ -0,0 +1,56 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation
+ * All rights reserved.
+ */
+#pragma once
+
+/** \file
+ * \ingroup bgpencil
+ */
+#include "gpencil_io_import_base.hh"
+
+struct GpencilIOParams;
+struct NSVGshape;
+struct NSVGpath;
+struct bGPdata;
+struct bGPDframe;
+
+#define SVG_IMPORTER_NAME "SVG Import for Grease Pencil"
+#define SVG_IMPORTER_VERSION "v1.0"
+
+namespace blender::io::gpencil {
+
+class GpencilImporterSVG : public GpencilImporter {
+
+ public:
+ GpencilImporterSVG(const char *filename, const struct GpencilIOParams *iparams);
+
+ bool read();
+
+ protected:
+ private:
+ void create_stroke(struct bGPdata *gpd_,
+ struct bGPDframe *gpf,
+ struct NSVGshape *shape,
+ struct NSVGpath *path,
+ const int32_t mat_index,
+ const float matrix[4][4]);
+
+ void convert_color(const int32_t color, float r_linear_rgba[4]);
+};
+
+} // namespace blender::io::gpencil
diff --git a/source/blender/io/gpencil/nanosvg/nanosvg.h b/source/blender/io/gpencil/nanosvg/nanosvg.h
new file mode 100644
index 00000000000..6db32e9f40a
--- /dev/null
+++ b/source/blender/io/gpencil/nanosvg/nanosvg.h
@@ -0,0 +1,3313 @@
+/*
+ * Copyright (c) 2013-14 `Mikko Mononen <memon@inside.org>`
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * The SVG parser is based on Anti-Grain Geometry 2.4 SVG example
+ * Copyright (C) 2002-2004 Maxim Shemanarev (McSeem) (http://www.antigrain.com/)
+ *
+ * Arc calculation code based on canvg (https://code.google.com/p/canvg/)
+ *
+ * Bounding box calculation based on
+ * http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
+ *
+ * This is a modified version for Blender used by importers.
+ *
+ */
+
+#ifndef NANOSVG_H
+#define NANOSVG_H
+
+#ifndef NANOSVG_CPLUSPLUS
+# ifdef __cplusplus
+extern "C" {
+# endif
+#endif
+
+// NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of
+// cubic bezier shapes.
+//
+// The library suits well for anything from rendering scalable icons in your editor application to
+// prototyping a game.
+//
+// NanoSVG supports a wide range of SVG features, but something may be missing, feel free to create
+// a pull request!
+//
+// The shapes in the SVG images are transformed by the viewBox and converted to specified units.
+// That is, you should get the same looking data as your designed in your favorite app.
+//
+// NanoSVG can return the paths in few different units. For example if you want to render an image,
+// you may choose to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you
+// may want to use millimeters.
+//
+// The units passed to NanoSVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'.
+// DPI (dots-per-inch) controls how the unit conversion is done.
+//
+// If you don't know or care about the units stuff, "px" and 96 should get you going.
+
+/* Example Usage:
+ // Load SVG
+ NSVGimage* image;
+ image = nsvgParseFromFile("test.svg", "px", 96);
+ printf("size: %f x %f\n", image->width, image->height);
+ // Use...
+ for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) {
+ for (NSVGpath *path = shape->paths; path != NULL; path = path->next) {
+ for (int i = 0; i < path->npts-1; i += 3) {
+ float* p = &path->pts[i*2];
+ drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);
+ }
+ }
+ }
+ // Delete
+ nsvgDelete(image);
+*/
+
+enum NSVGpaintType {
+ NSVG_PAINT_NONE = 0,
+ NSVG_PAINT_COLOR = 1,
+ NSVG_PAINT_LINEAR_GRADIENT = 2,
+ NSVG_PAINT_RADIAL_GRADIENT = 3
+};
+
+enum NSVGspreadType { NSVG_SPREAD_PAD = 0, NSVG_SPREAD_REFLECT = 1, NSVG_SPREAD_REPEAT = 2 };
+
+enum NSVGlineJoin { NSVG_JOIN_MITER = 0, NSVG_JOIN_ROUND = 1, NSVG_JOIN_BEVEL = 2 };
+
+enum NSVGlineCap { NSVG_CAP_BUTT = 0, NSVG_CAP_ROUND = 1, NSVG_CAP_SQUARE = 2 };
+
+enum NSVGfillRule { NSVG_FILLRULE_NONZERO = 0, NSVG_FILLRULE_EVENODD = 1 };
+
+enum NSVGflags { NSVG_FLAGS_VISIBLE = 0x01 };
+
+typedef struct NSVGgradientStop {
+ unsigned int color;
+ float offset;
+} NSVGgradientStop;
+
+typedef struct NSVGgradient {
+ float xform[6];
+ char spread;
+ float fx, fy;
+ int nstops;
+ NSVGgradientStop stops[1];
+} NSVGgradient;
+
+typedef struct NSVGpaint {
+ char type;
+ union {
+ unsigned int color;
+ NSVGgradient *gradient;
+ };
+} NSVGpaint;
+
+typedef struct NSVGpath {
+ float *pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ...
+ int npts; // Total number of bezier points.
+ char closed; // Flag indicating if shapes should be treated as closed.
+ float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
+ struct NSVGpath *next; // Pointer to next path, or NULL if last element.
+} NSVGpath;
+
+typedef struct NSVGshape {
+ char id[64]; // Optional 'id' attr of the shape or its group
+ /* Blender: Parent ID used for layer creation. */
+ char id_parent[64];
+ NSVGpaint fill; // Fill paint
+ NSVGpaint stroke; // Stroke paint
+ float opacity; // Opacity of the shape.
+ float strokeWidth; // Stroke width (scaled).
+ float strokeDashOffset; // Stroke dash offset (scaled).
+ float strokeDashArray[8]; // Stroke dash array (scaled).
+ char strokeDashCount; // Number of dash values in dash array.
+ char strokeLineJoin; // Stroke join type.
+ char strokeLineCap; // Stroke cap type.
+ float miterLimit; // Miter limit
+ char fillRule; // Fill rule, see NSVGfillRule.
+ unsigned char flags; // Logical or of NSVG_FLAGS_* flags
+ float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
+ NSVGpath *paths; // Linked list of paths in the image.
+ struct NSVGshape *next; // Pointer to next shape, or NULL if last element.
+} NSVGshape;
+
+typedef struct NSVGimage {
+ float width; // Width of the image.
+ float height; // Height of the image.
+ NSVGshape *shapes; // Linked list of shapes in the image.
+} NSVGimage;
+
+// Parses SVG file from a file, returns SVG image as paths.
+NSVGimage *nsvgParseFromFile(const char *filename, const char *units, float dpi);
+
+// Parses SVG file from a null terminated string, returns SVG image as paths.
+// Important note: changes the string.
+NSVGimage *nsvgParse(char *input, const char *units, float dpi);
+
+// Duplicates a path.
+NSVGpath *nsvgDuplicatePath(NSVGpath *p);
+
+// Deletes an image.
+void nsvgDelete(NSVGimage *image);
+
+#ifndef NANOSVG_CPLUSPLUS
+# ifdef __cplusplus
+}
+# endif
+#endif
+
+#endif // NANOSVG_H
+
+#ifdef NANOSVG_IMPLEMENTATION
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NSVG_PI (3.14159265358979323846264338327f)
+#define NSVG_KAPPA90 \
+ (0.5522847493f) // Length proportional to radius of a cubic bezier handle for 90deg arcs.
+
+#define NSVG_ALIGN_MIN 0
+#define NSVG_ALIGN_MID 1
+#define NSVG_ALIGN_MAX 2
+#define NSVG_ALIGN_NONE 0
+#define NSVG_ALIGN_MEET 1
+#define NSVG_ALIGN_SLICE 2
+
+#define NSVG_NOTUSED(v) \
+ do { \
+ (void)(1 ? (void)0 : ((void)(v))); \
+ } while (0)
+#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16))
+
+#ifdef _MSC_VER
+# pragma warning(disable : 4996) // Switch off security warnings
+# pragma warning(disable : 4100) // Switch off unreferenced formal parameter warnings
+# ifdef __cplusplus
+# define NSVG_INLINE inline
+# else
+# define NSVG_INLINE
+# endif
+#else
+# define NSVG_INLINE inline
+#endif
+
+static int nsvg__isspace(char c)
+{
+ return strchr(" \t\n\v\f\r", c) != 0;
+}
+
+static int nsvg__isdigit(char c)
+{
+ return c >= '0' && c <= '9';
+}
+
+static NSVG_INLINE float nsvg__minf(float a, float b)
+{
+ return a < b ? a : b;
+}
+static NSVG_INLINE float nsvg__maxf(float a, float b)
+{
+ return a > b ? a : b;
+}
+
+// Simple XML parser
+
+#define NSVG_XML_TAG 1
+#define NSVG_XML_CONTENT 2
+#define NSVG_XML_MAX_ATTRIBS 256
+
+static void nsvg__parseContent(char *s, void (*contentCb)(void *ud, const char *s), void *ud)
+{
+ // Trim start white spaces
+ while (*s && nsvg__isspace(*s))
+ s++;
+ if (!*s)
+ return;
+
+ if (contentCb)
+ (*contentCb)(ud, s);
+}
+
+static void nsvg__parseElement(char *s,
+ void (*startelCb)(void *ud, const char *el, const char **attr),
+ void (*endelCb)(void *ud, const char *el),
+ void *ud)
+{
+ const char *attr[NSVG_XML_MAX_ATTRIBS];
+ int nattr = 0;
+ char *name;
+ int start = 0;
+ int end = 0;
+ char quote;
+
+ // Skip white space after the '<'
+ while (*s && nsvg__isspace(*s))
+ s++;
+
+ // Check if the tag is end tag
+ if (*s == '/') {
+ s++;
+ end = 1;
+ }
+ else {
+ start = 1;
+ }
+
+ // Skip comments, data and preprocessor stuff.
+ if (!*s || *s == '?' || *s == '!')
+ return;
+
+ // Get tag name
+ name = s;
+ while (*s && !nsvg__isspace(*s))
+ s++;
+ if (*s) {
+ *s++ = '\0';
+ }
+
+ // Get attribs
+ while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS - 3) {
+ char *name = NULL;
+ char *value = NULL;
+
+ // Skip white space before the attrib name
+ while (*s && nsvg__isspace(*s))
+ s++;
+ if (!*s)
+ break;
+ if (*s == '/') {
+ end = 1;
+ break;
+ }
+ name = s;
+ // Find end of the attrib name.
+ while (*s && !nsvg__isspace(*s) && *s != '=')
+ s++;
+ if (*s) {
+ *s++ = '\0';
+ }
+ // Skip until the beginning of the value.
+ while (*s && *s != '\"' && *s != '\'')
+ s++;
+ if (!*s)
+ break;
+ quote = *s;
+ s++;
+ // Store value and find the end of it.
+ value = s;
+ while (*s && *s != quote)
+ s++;
+ if (*s) {
+ *s++ = '\0';
+ }
+
+ // Store only well formed attributes
+ if (name && value) {
+ attr[nattr++] = name;
+ attr[nattr++] = value;
+ }
+ }
+
+ // List terminator
+ attr[nattr++] = 0;
+ attr[nattr++] = 0;
+
+ // Call callbacks.
+ if (start && startelCb)
+ (*startelCb)(ud, name, attr);
+ if (end && endelCb)
+ (*endelCb)(ud, name);
+}
+
+static int nsvg__parseXML(char *input,
+ void (*startelCb)(void *ud, const char *el, const char **attr),
+ void (*endelCb)(void *ud, const char *el),
+ void (*contentCb)(void *ud, const char *s),
+ void *ud)
+{
+ char *s = input;
+ char *mark = s;
+ int state = NSVG_XML_CONTENT;
+ while (*s) {
+ if (*s == '<' && state == NSVG_XML_CONTENT) {
+ // Start of a tag
+ *s++ = '\0';
+ nsvg__parseContent(mark, contentCb, ud);
+ mark = s;
+ state = NSVG_XML_TAG;
+ }
+ else if (*s == '>' && state == NSVG_XML_TAG) {
+ // Start of a content or new tag.
+ *s++ = '\0';
+ nsvg__parseElement(mark, startelCb, endelCb, ud);
+ mark = s;
+ state = NSVG_XML_CONTENT;
+ }
+ else {
+ s++;
+ }
+ }
+
+ return 1;
+}
+
+/* Simple SVG parser. */
+
+#define NSVG_MAX_ATTR 128
+#define NSVG_MAX_BREADCRUMB 5
+
+enum NSVGgradientUnits { NSVG_USER_SPACE = 0, NSVG_OBJECT_SPACE = 1 };
+
+#define NSVG_MAX_DASHES 8
+
+enum NSVGunits {
+ NSVG_UNITS_USER,
+ NSVG_UNITS_PX,
+ NSVG_UNITS_PT,
+ NSVG_UNITS_PC,
+ NSVG_UNITS_MM,
+ NSVG_UNITS_CM,
+ NSVG_UNITS_IN,
+ NSVG_UNITS_PERCENT,
+ NSVG_UNITS_EM,
+ NSVG_UNITS_EX
+};
+
+typedef struct NSVGcoordinate {
+ float value;
+ int units;
+} NSVGcoordinate;
+
+typedef struct NSVGlinearData {
+ NSVGcoordinate x1, y1, x2, y2;
+} NSVGlinearData;
+
+typedef struct NSVGradialData {
+ NSVGcoordinate cx, cy, r, fx, fy;
+} NSVGradialData;
+
+typedef struct NSVGgradientData {
+ char id[64];
+ char ref[64];
+ char type;
+ union {
+ NSVGlinearData linear;
+ NSVGradialData radial;
+ };
+ char spread;
+ char units;
+ float xform[6];
+ int nstops;
+ NSVGgradientStop *stops;
+ struct NSVGgradientData *next;
+} NSVGgradientData;
+
+typedef struct NSVGattrib {
+ char id[64];
+ float xform[6];
+ unsigned int fillColor;
+ unsigned int strokeColor;
+ float opacity;
+ float fillOpacity;
+ float strokeOpacity;
+ char fillGradient[64];
+ char strokeGradient[64];
+ float strokeWidth;
+ float strokeDashOffset;
+ float strokeDashArray[NSVG_MAX_DASHES];
+ int strokeDashCount;
+ char strokeLineJoin;
+ char strokeLineCap;
+ float miterLimit;
+ char fillRule;
+ float fontSize;
+ unsigned int stopColor;
+ float stopOpacity;
+ float stopOffset;
+ char hasFill;
+ char hasStroke;
+ char visible;
+} NSVGattrib;
+
+typedef struct NSVGparser {
+ NSVGattrib attr[NSVG_MAX_ATTR];
+ int attrHead;
+ float *pts;
+ int npts;
+ int cpts;
+ NSVGpath *plist;
+ NSVGimage *image;
+ NSVGgradientData *gradients;
+ NSVGshape *shapesTail;
+ float viewMinx, viewMiny, viewWidth, viewHeight;
+ int alignX, alignY, alignType;
+ float dpi;
+ char pathFlag;
+ char defsFlag;
+ /** Blender breadcrumb for layers. */
+ char breadcrumb[NSVG_MAX_BREADCRUMB][64];
+ /** Blender number of elements in breadcrumb. */
+ int breadcrumb_len;
+} NSVGparser;
+
+static void nsvg__xformIdentity(float *t)
+{
+ t[0] = 1.0f;
+ t[1] = 0.0f;
+ t[2] = 0.0f;
+ t[3] = 1.0f;
+ t[4] = 0.0f;
+ t[5] = 0.0f;
+}
+
+static void nsvg__xformSetTranslation(float *t, float tx, float ty)
+{
+ t[0] = 1.0f;
+ t[1] = 0.0f;
+ t[2] = 0.0f;
+ t[3] = 1.0f;
+ t[4] = tx;
+ t[5] = ty;
+}
+
+static void nsvg__xformSetScale(float *t, float sx, float sy)
+{
+ t[0] = sx;
+ t[1] = 0.0f;
+ t[2] = 0.0f;
+ t[3] = sy;
+ t[4] = 0.0f;
+ t[5] = 0.0f;
+}
+
+static void nsvg__xformSetSkewX(float *t, float a)
+{
+ t[0] = 1.0f;
+ t[1] = 0.0f;
+ t[2] = tanf(a);
+ t[3] = 1.0f;
+ t[4] = 0.0f;
+ t[5] = 0.0f;
+}
+
+static void nsvg__xformSetSkewY(float *t, float a)
+{
+ t[0] = 1.0f;
+ t[1] = tanf(a);
+ t[2] = 0.0f;
+ t[3] = 1.0f;
+ t[4] = 0.0f;
+ t[5] = 0.0f;
+}
+
+static void nsvg__xformSetRotation(float *t, float a)
+{
+ float cs = cosf(a), sn = sinf(a);
+ t[0] = cs;
+ t[1] = sn;
+ t[2] = -sn;
+ t[3] = cs;
+ t[4] = 0.0f;
+ t[5] = 0.0f;
+}
+
+static void nsvg__xformMultiply(float *t, float *s)
+{
+ float t0 = t[0] * s[0] + t[1] * s[2];
+ float t2 = t[2] * s[0] + t[3] * s[2];
+ float t4 = t[4] * s[0] + t[5] * s[2] + s[4];
+ t[1] = t[0] * s[1] + t[1] * s[3];
+ t[3] = t[2] * s[1] + t[3] * s[3];
+ t[5] = t[4] * s[1] + t[5] * s[3] + s[5];
+ t[0] = t0;
+ t[2] = t2;
+ t[4] = t4;
+}
+
+static void nsvg__xformInverse(float *inv, float *t)
+{
+ double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1];
+ if (det > -1e-6 && det < 1e-6) {
+ nsvg__xformIdentity(t);
+ return;
+ }
+ invdet = 1.0 / det;
+ inv[0] = (float)(t[3] * invdet);
+ inv[2] = (float)(-t[2] * invdet);
+ inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet);
+ inv[1] = (float)(-t[1] * invdet);
+ inv[3] = (float)(t[0] * invdet);
+ inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
+}
+
+static void nsvg__xformPremultiply(float *t, float *s)
+{
+ float s2[6];
+ memcpy(s2, s, sizeof(float) * 6);
+ nsvg__xformMultiply(s2, t);
+ memcpy(t, s2, sizeof(float) * 6);
+}
+
+static void nsvg__xformPoint(float *dx, float *dy, float x, float y, float *t)
+{
+ *dx = x * t[0] + y * t[2] + t[4];
+ *dy = x * t[1] + y * t[3] + t[5];
+}
+
+static void nsvg__xformVec(float *dx, float *dy, float x, float y, float *t)
+{
+ *dx = x * t[0] + y * t[2];
+ *dy = x * t[1] + y * t[3];
+}
+
+#define NSVG_EPSILON (1e-12)
+
+static int nsvg__ptInBounds(float *pt, float *bounds)
+{
+ return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3];
+}
+
+static double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3)
+{
+ double it = 1.0 - t;
+ return it * it * it * p0 + 3.0 * it * it * t * p1 + 3.0 * it * t * t * p2 + t * t * t * p3;
+}
+
+static void nsvg__curveBounds(float *bounds, float *curve)
+{
+ int i, j, count;
+ double roots[2], a, b, c, b2ac, t, v;
+ float *v0 = &curve[0];
+ float *v1 = &curve[2];
+ float *v2 = &curve[4];
+ float *v3 = &curve[6];
+
+ // Start the bounding box by end points
+ bounds[0] = nsvg__minf(v0[0], v3[0]);
+ bounds[1] = nsvg__minf(v0[1], v3[1]);
+ bounds[2] = nsvg__maxf(v0[0], v3[0]);
+ bounds[3] = nsvg__maxf(v0[1], v3[1]);
+
+ // Bezier curve fits inside the convex hull of it's control points.
+ // If control points are inside the bounds, we're done.
+ if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds))
+ return;
+
+ // Add bezier curve inflection points in X and Y.
+ for (i = 0; i < 2; i++) {
+ a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i];
+ b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i];
+ c = 3.0 * v1[i] - 3.0 * v0[i];
+ count = 0;
+ if (fabs(a) < NSVG_EPSILON) {
+ if (fabs(b) > NSVG_EPSILON) {
+ t = -c / b;
+ if (t > NSVG_EPSILON && t < 1.0 - NSVG_EPSILON)
+ roots[count++] = t;
+ }
+ }
+ else {
+ b2ac = b * b - 4.0 * c * a;
+ if (b2ac > NSVG_EPSILON) {
+ t = (-b + sqrt(b2ac)) / (2.0 * a);
+ if (t > NSVG_EPSILON && t < 1.0 - NSVG_EPSILON)
+ roots[count++] = t;
+ t = (-b - sqrt(b2ac)) / (2.0 * a);
+ if (t > NSVG_EPSILON && t < 1.0 - NSVG_EPSILON)
+ roots[count++] = t;
+ }
+ }
+ for (j = 0; j < count; j++) {
+ v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]);
+ bounds[0 + i] = nsvg__minf(bounds[0 + i], (float)v);
+ bounds[2 + i] = nsvg__maxf(bounds[2 + i], (float)v);
+ }
+ }
+}
+
+static NSVGparser *nsvg__createParser()
+{
+ NSVGparser *p;
+ p = (NSVGparser *)malloc(sizeof(NSVGparser));
+ if (p == NULL)
+ goto error;
+ memset(p, 0, sizeof(NSVGparser));
+
+ p->image = (NSVGimage *)malloc(sizeof(NSVGimage));
+ if (p->image == NULL)
+ goto error;
+ memset(p->image, 0, sizeof(NSVGimage));
+
+ // Init style
+ nsvg__xformIdentity(p->attr[0].xform);
+ memset(p->attr[0].id, 0, sizeof p->attr[0].id);
+ p->attr[0].fillColor = NSVG_RGB(0, 0, 0);
+ p->attr[0].strokeColor = NSVG_RGB(0, 0, 0);
+ p->attr[0].opacity = 1;
+ p->attr[0].fillOpacity = 1;
+ p->attr[0].strokeOpacity = 1;
+ p->attr[0].stopOpacity = 1;
+ p->attr[0].strokeWidth = 1;
+ p->attr[0].strokeLineJoin = NSVG_JOIN_MITER;
+ p->attr[0].strokeLineCap = NSVG_CAP_BUTT;
+ p->attr[0].miterLimit = 4;
+ p->attr[0].fillRule = NSVG_FILLRULE_NONZERO;
+ p->attr[0].hasFill = 1;
+ p->attr[0].visible = 1;
+
+ return p;
+
+error:
+ if (p) {
+ if (p->image)
+ free(p->image);
+ free(p);
+ }
+ return NULL;
+}
+
+static void nsvg__deletePaths(NSVGpath *path)
+{
+ while (path) {
+ NSVGpath *next = path->next;
+ if (path->pts != NULL)
+ free(path->pts);
+ free(path);
+ path = next;
+ }
+}
+
+static void nsvg__deletePaint(NSVGpaint *paint)
+{
+ if (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT)
+ free(paint->gradient);
+}
+
+static void nsvg__deleteGradientData(NSVGgradientData *grad)
+{
+ NSVGgradientData *next;
+ while (grad != NULL) {
+ next = grad->next;
+ free(grad->stops);
+ free(grad);
+ grad = next;
+ }
+}
+
+static void nsvg__deleteParser(NSVGparser *p)
+{
+ if (p != NULL) {
+ nsvg__deletePaths(p->plist);
+ nsvg__deleteGradientData(p->gradients);
+ nsvgDelete(p->image);
+ free(p->pts);
+ free(p);
+ }
+}
+
+static void nsvg__resetPath(NSVGparser *p)
+{
+ p->npts = 0;
+}
+
+static void nsvg__addPoint(NSVGparser *p, float x, float y)
+{
+ if (p->npts + 1 > p->cpts) {
+ p->cpts = p->cpts ? p->cpts * 2 : 8;
+ p->pts = (float *)realloc(p->pts, p->cpts * 2 * sizeof(float));
+ if (!p->pts)
+ return;
+ }
+ p->pts[p->npts * 2 + 0] = x;
+ p->pts[p->npts * 2 + 1] = y;
+ p->npts++;
+}
+
+static void nsvg__moveTo(NSVGparser *p, float x, float y)
+{
+ if (p->npts > 0) {
+ p->pts[(p->npts - 1) * 2 + 0] = x;
+ p->pts[(p->npts - 1) * 2 + 1] = y;
+ }
+ else {
+ nsvg__addPoint(p, x, y);
+ }
+}
+
+static void nsvg__lineTo(NSVGparser *p, float x, float y)
+{
+ float px, py, dx, dy;
+ if (p->npts > 0) {
+ px = p->pts[(p->npts - 1) * 2 + 0];
+ py = p->pts[(p->npts - 1) * 2 + 1];
+ dx = x - px;
+ dy = y - py;
+ nsvg__addPoint(p, px + dx / 3.0f, py + dy / 3.0f);
+ nsvg__addPoint(p, x - dx / 3.0f, y - dy / 3.0f);
+ nsvg__addPoint(p, x, y);
+ }
+}
+
+static void nsvg__cubicBezTo(
+ NSVGparser *p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y)
+{
+ if (p->npts > 0) {
+ nsvg__addPoint(p, cpx1, cpy1);
+ nsvg__addPoint(p, cpx2, cpy2);
+ nsvg__addPoint(p, x, y);
+ }
+}
+
+static NSVGattrib *nsvg__getAttr(NSVGparser *p)
+{
+ return &p->attr[p->attrHead];
+}
+
+static void nsvg__pushAttr(NSVGparser *p)
+{
+ if (p->attrHead < NSVG_MAX_ATTR - 1) {
+ p->attrHead++;
+ memcpy(&p->attr[p->attrHead], &p->attr[p->attrHead - 1], sizeof(NSVGattrib));
+ }
+}
+
+static void nsvg__popAttr(NSVGparser *p)
+{
+ if (p->attrHead > 0)
+ p->attrHead--;
+}
+
+static float nsvg__actualOrigX(NSVGparser *p)
+{
+ return p->viewMinx;
+}
+
+static float nsvg__actualOrigY(NSVGparser *p)
+{
+ return p->viewMiny;
+}
+
+static float nsvg__actualWidth(NSVGparser *p)
+{
+ return p->viewWidth;
+}
+
+static float nsvg__actualHeight(NSVGparser *p)
+{
+ return p->viewHeight;
+}
+
+static float nsvg__actualLength(NSVGparser *p)
+{
+ float w = nsvg__actualWidth(p), h = nsvg__actualHeight(p);
+ return sqrtf(w * w + h * h) / sqrtf(2.0f);
+}
+
+static float nsvg__convertToPixels(NSVGparser *p, NSVGcoordinate c, float orig, float length)
+{
+ NSVGattrib *attr = nsvg__getAttr(p);
+ switch (c.units) {
+ case NSVG_UNITS_USER:
+ return c.value;
+ case NSVG_UNITS_PX:
+ return c.value;
+ case NSVG_UNITS_PT:
+ return c.value / 72.0f * p->dpi;
+ case NSVG_UNITS_PC:
+ return c.value / 6.0f * p->dpi;
+ case NSVG_UNITS_MM:
+ return c.value / 25.4f * p->dpi;
+ case NSVG_UNITS_CM:
+ return c.value / 2.54f * p->dpi;
+ case NSVG_UNITS_IN:
+ return c.value * p->dpi;
+ case NSVG_UNITS_EM:
+ return c.value * attr->fontSize;
+ case NSVG_UNITS_EX:
+ return c.value * attr->fontSize * 0.52f; // x-height of Helvetica.
+ case NSVG_UNITS_PERCENT:
+ return orig + c.value / 100.0f * length;
+ default:
+ return c.value;
+ }
+ return c.value;
+}
+
+static NSVGgradientData *nsvg__findGradientData(NSVGparser *p, const char *id)
+{
+ NSVGgradientData *grad = p->gradients;
+ if (id == NULL || *id == '\0')
+ return NULL;
+ while (grad != NULL) {
+ if (strcmp(grad->id, id) == 0)
+ return grad;
+ grad = grad->next;
+ }
+ return NULL;
+}
+
+static NSVGgradient *nsvg__createGradient(NSVGparser *p,
+ const char *id,
+ const float *localBounds,
+ char *paintType)
+{
+ NSVGattrib *attr = nsvg__getAttr(p);
+ NSVGgradientData *data = NULL;
+ NSVGgradientData *ref = NULL;
+ NSVGgradientStop *stops = NULL;
+ NSVGgradient *grad;
+ float ox, oy, sw, sh, sl;
+ int nstops = 0;
+ int refIter;
+
+ data = nsvg__findGradientData(p, id);
+ if (data == NULL)
+ return NULL;
+
+ // TODO: use ref to fill in all unset values too.
+ ref = data;
+ refIter = 0;
+ while (ref != NULL) {
+ NSVGgradientData *nextRef = NULL;
+ if (stops == NULL && ref->stops != NULL) {
+ stops = ref->stops;
+ nstops = ref->nstops;
+ break;
+ }
+ nextRef = nsvg__findGradientData(p, ref->ref);
+ if (nextRef == ref)
+ break; // prevent infite loops on malformed data
+ ref = nextRef;
+ refIter++;
+ if (refIter > 32)
+ break; // prevent infite loops on malformed data
+ }
+ if (stops == NULL)
+ return NULL;
+
+ grad = (NSVGgradient *)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop) * (nstops - 1));
+ if (grad == NULL)
+ return NULL;
+
+ // The shape width and height.
+ if (data->units == NSVG_OBJECT_SPACE) {
+ ox = localBounds[0];
+ oy = localBounds[1];
+ sw = localBounds[2] - localBounds[0];
+ sh = localBounds[3] - localBounds[1];
+ }
+ else {
+ ox = nsvg__actualOrigX(p);
+ oy = nsvg__actualOrigY(p);
+ sw = nsvg__actualWidth(p);
+ sh = nsvg__actualHeight(p);
+ }
+ sl = sqrtf(sw * sw + sh * sh) / sqrtf(2.0f);
+
+ if (data->type == NSVG_PAINT_LINEAR_GRADIENT) {
+ float x1, y1, x2, y2, dx, dy;
+ x1 = nsvg__convertToPixels(p, data->linear.x1, ox, sw);
+ y1 = nsvg__convertToPixels(p, data->linear.y1, oy, sh);
+ x2 = nsvg__convertToPixels(p, data->linear.x2, ox, sw);
+ y2 = nsvg__convertToPixels(p, data->linear.y2, oy, sh);
+ // Calculate transform aligned to the line
+ dx = x2 - x1;
+ dy = y2 - y1;
+ grad->xform[0] = dy;
+ grad->xform[1] = -dx;
+ grad->xform[2] = dx;
+ grad->xform[3] = dy;
+ grad->xform[4] = x1;
+ grad->xform[5] = y1;
+ }
+ else {
+ float cx, cy, fx, fy, r;
+ cx = nsvg__convertToPixels(p, data->radial.cx, ox, sw);
+ cy = nsvg__convertToPixels(p, data->radial.cy, oy, sh);
+ fx = nsvg__convertToPixels(p, data->radial.fx, ox, sw);
+ fy = nsvg__convertToPixels(p, data->radial.fy, oy, sh);
+ r = nsvg__convertToPixels(p, data->radial.r, 0, sl);
+ // Calculate transform aligned to the circle
+ grad->xform[0] = r;
+ grad->xform[1] = 0;
+ grad->xform[2] = 0;
+ grad->xform[3] = r;
+ grad->xform[4] = cx;
+ grad->xform[5] = cy;
+ grad->fx = fx / r;
+ grad->fy = fy / r;
+ }
+
+ nsvg__xformMultiply(grad->xform, data->xform);
+ nsvg__xformMultiply(grad->xform, attr->xform);
+
+ grad->spread = data->spread;
+ memcpy(grad->stops, stops, nstops * sizeof(NSVGgradientStop));
+ grad->nstops = nstops;
+
+ *paintType = data->type;
+
+ return grad;
+}
+
+static float nsvg__getAverageScale(float *t)
+{
+ float sx = sqrtf(t[0] * t[0] + t[2] * t[2]);
+ float sy = sqrtf(t[1] * t[1] + t[3] * t[3]);
+ return (sx + sy) * 0.5f;
+}
+
+static void nsvg__getLocalBounds(float *bounds, NSVGshape *shape, float *xform)
+{
+ NSVGpath *path;
+ float curve[4 * 2], curveBounds[4];
+ int i, first = 1;
+ for (path = shape->paths; path != NULL; path = path->next) {
+ nsvg__xformPoint(&curve[0], &curve[1], path->pts[0], path->pts[1], xform);
+ for (i = 0; i < path->npts - 1; i += 3) {
+ nsvg__xformPoint(
+ &curve[2], &curve[3], path->pts[(i + 1) * 2], path->pts[(i + 1) * 2 + 1], xform);
+ nsvg__xformPoint(
+ &curve[4], &curve[5], path->pts[(i + 2) * 2], path->pts[(i + 2) * 2 + 1], xform);
+ nsvg__xformPoint(
+ &curve[6], &curve[7], path->pts[(i + 3) * 2], path->pts[(i + 3) * 2 + 1], xform);
+ nsvg__curveBounds(curveBounds, curve);
+ if (first) {
+ bounds[0] = curveBounds[0];
+ bounds[1] = curveBounds[1];
+ bounds[2] = curveBounds[2];
+ bounds[3] = curveBounds[3];
+ first = 0;
+ }
+ else {
+ bounds[0] = nsvg__minf(bounds[0], curveBounds[0]);
+ bounds[1] = nsvg__minf(bounds[1], curveBounds[1]);
+ bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]);
+ bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]);
+ }
+ curve[0] = curve[6];
+ curve[1] = curve[7];
+ }
+ }
+}
+
+static void nsvg__addShape(NSVGparser *p)
+{
+ NSVGattrib *attr = nsvg__getAttr(p);
+ float scale = 1.0f;
+ NSVGshape *shape;
+ NSVGpath *path;
+ int i;
+
+ if (p->plist == NULL)
+ return;
+
+ shape = (NSVGshape *)malloc(sizeof(NSVGshape));
+ if (shape == NULL)
+ goto error;
+ memset(shape, 0, sizeof(NSVGshape));
+
+ memcpy(shape->id, attr->id, sizeof shape->id);
+ /* Copy parent id from breadcrumb. */
+ if (p->breadcrumb_len > 0) {
+ memcpy(shape->id_parent, p->breadcrumb[0], sizeof shape->id_parent);
+ }
+ else {
+ memcpy(shape->id_parent, attr->id, sizeof shape->id_parent);
+ }
+
+ scale = nsvg__getAverageScale(attr->xform);
+ shape->strokeWidth = attr->strokeWidth * scale;
+ shape->strokeDashOffset = attr->strokeDashOffset * scale;
+ shape->strokeDashCount = (char)attr->strokeDashCount;
+ for (i = 0; i < attr->strokeDashCount; i++)
+ shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale;
+ shape->strokeLineJoin = attr->strokeLineJoin;
+ shape->strokeLineCap = attr->strokeLineCap;
+ shape->miterLimit = attr->miterLimit;
+ shape->fillRule = attr->fillRule;
+ shape->opacity = attr->opacity;
+
+ shape->paths = p->plist;
+ p->plist = NULL;
+
+ // Calculate shape bounds
+ shape->bounds[0] = shape->paths->bounds[0];
+ shape->bounds[1] = shape->paths->bounds[1];
+ shape->bounds[2] = shape->paths->bounds[2];
+ shape->bounds[3] = shape->paths->bounds[3];
+ for (path = shape->paths->next; path != NULL; path = path->next) {
+ shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]);
+ shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]);
+ shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]);
+ shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]);
+ }
+
+ // Set fill
+ if (attr->hasFill == 0) {
+ shape->fill.type = NSVG_PAINT_NONE;
+ }
+ else if (attr->hasFill == 1) {
+ shape->fill.type = NSVG_PAINT_COLOR;
+ shape->fill.color = attr->fillColor;
+ shape->fill.color |= (unsigned int)(attr->fillOpacity * 255) << 24;
+ }
+ else if (attr->hasFill == 2) {
+ float inv[6], localBounds[4];
+ nsvg__xformInverse(inv, attr->xform);
+ nsvg__getLocalBounds(localBounds, shape, inv);
+ shape->fill.gradient = nsvg__createGradient(
+ p, attr->fillGradient, localBounds, &shape->fill.type);
+ if (shape->fill.gradient == NULL) {
+ shape->fill.type = NSVG_PAINT_NONE;
+ }
+ }
+
+ // Set stroke
+ if (attr->hasStroke == 0) {
+ shape->stroke.type = NSVG_PAINT_NONE;
+ }
+ else if (attr->hasStroke == 1) {
+ shape->stroke.type = NSVG_PAINT_COLOR;
+ shape->stroke.color = attr->strokeColor;
+ shape->stroke.color |= (unsigned int)(attr->strokeOpacity * 255) << 24;
+ }
+ else if (attr->hasStroke == 2) {
+ float inv[6], localBounds[4];
+ nsvg__xformInverse(inv, attr->xform);
+ nsvg__getLocalBounds(localBounds, shape, inv);
+ shape->stroke.gradient = nsvg__createGradient(
+ p, attr->strokeGradient, localBounds, &shape->stroke.type);
+ if (shape->stroke.gradient == NULL)
+ shape->stroke.type = NSVG_PAINT_NONE;
+ }
+
+ // Set flags
+ shape->flags = (attr->visible ? NSVG_FLAGS_VISIBLE : 0x00);
+
+ // Add to tail
+ if (p->image->shapes == NULL)
+ p->image->shapes = shape;
+ else
+ p->shapesTail->next = shape;
+ p->shapesTail = shape;
+
+ return;
+
+error:
+ if (shape)
+ free(shape);
+}
+
+static void nsvg__addPath(NSVGparser *p, char closed)
+{
+ NSVGattrib *attr = nsvg__getAttr(p);
+ NSVGpath *path = NULL;
+ float bounds[4];
+ float *curve;
+ int i;
+
+ if (p->npts < 4)
+ return;
+
+ if (closed)
+ nsvg__lineTo(p, p->pts[0], p->pts[1]);
+
+ // Expect 1 + N*3 points (N = number of cubic bezier segments).
+ if ((p->npts % 3) != 1)
+ return;
+
+ path = (NSVGpath *)malloc(sizeof(NSVGpath));
+ if (path == NULL)
+ goto error;
+ memset(path, 0, sizeof(NSVGpath));
+
+ path->pts = (float *)malloc(p->npts * 2 * sizeof(float));
+ if (path->pts == NULL)
+ goto error;
+ path->closed = closed;
+ path->npts = p->npts;
+
+ // Transform path.
+ for (i = 0; i < p->npts; ++i)
+ nsvg__xformPoint(
+ &path->pts[i * 2], &path->pts[i * 2 + 1], p->pts[i * 2], p->pts[i * 2 + 1], attr->xform);
+
+ // Find bounds
+ for (i = 0; i < path->npts - 1; i += 3) {
+ curve = &path->pts[i * 2];
+ nsvg__curveBounds(bounds, curve);
+ if (i == 0) {
+ path->bounds[0] = bounds[0];
+ path->bounds[1] = bounds[1];
+ path->bounds[2] = bounds[2];
+ path->bounds[3] = bounds[3];
+ }
+ else {
+ path->bounds[0] = nsvg__minf(path->bounds[0], bounds[0]);
+ path->bounds[1] = nsvg__minf(path->bounds[1], bounds[1]);
+ path->bounds[2] = nsvg__maxf(path->bounds[2], bounds[2]);
+ path->bounds[3] = nsvg__maxf(path->bounds[3], bounds[3]);
+ }
+ }
+
+ path->next = p->plist;
+ p->plist = path;
+
+ return;
+
+error:
+ if (path != NULL) {
+ if (path->pts != NULL)
+ free(path->pts);
+ free(path);
+ }
+}
+
+// We roll our own string to float because the std library one uses locale and messes things up.
+static double nsvg__atof(const char *s)
+{
+ char *cur = (char *)s;
+ char *end = NULL;
+ double res = 0.0, sign = 1.0;
+ long long intPart = 0, fracPart = 0;
+ char hasIntPart = 0, hasFracPart = 0;
+
+ // Parse optional sign
+ if (*cur == '+') {
+ cur++;
+ }
+ else if (*cur == '-') {
+ sign = -1;
+ cur++;
+ }
+
+ // Parse integer part
+ if (nsvg__isdigit(*cur)) {
+ // Parse digit sequence
+ intPart = strtoll(cur, &end, 10);
+ if (cur != end) {
+ res = (double)intPart;
+ hasIntPart = 1;
+ cur = end;
+ }
+ }
+
+ // Parse fractional part.
+ if (*cur == '.') {
+ cur++; // Skip '.'
+ if (nsvg__isdigit(*cur)) {
+ // Parse digit sequence
+ fracPart = strtoll(cur, &end, 10);
+ if (cur != end) {
+ res += (double)fracPart / pow(10.0, (double)(end - cur));
+ hasFracPart = 1;
+ cur = end;
+ }
+ }
+ }
+
+ // A valid number should have integer or fractional part.
+ if (!hasIntPart && !hasFracPart)
+ return 0.0;
+
+ // Parse optional exponent
+ if (*cur == 'e' || *cur == 'E') {
+ long expPart = 0;
+ cur++; // skip 'E'
+ expPart = strtol(cur, &end, 10); // Parse digit sequence with sign
+ if (cur != end) {
+ res *= pow(10.0, (double)expPart);
+ }
+ }
+
+ return res * sign;
+}
+
+static const char *nsvg__parseNumber(const char *s, char *it, const int size)
+{
+ const int last = size - 1;
+ int i = 0;
+
+ // sign
+ if (*s == '-' || *s == '+') {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ }
+ // integer part
+ while (*s && nsvg__isdigit(*s)) {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ }
+ if (*s == '.') {
+ // decimal point
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ // fraction part
+ while (*s && nsvg__isdigit(*s)) {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ }
+ }
+ // exponent
+ if ((*s == 'e' || *s == 'E') && (s[1] != 'm' && s[1] != 'x')) {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ if (*s == '-' || *s == '+') {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ }
+ while (*s && nsvg__isdigit(*s)) {
+ if (i < last)
+ it[i++] = *s;
+ s++;
+ }
+ }
+ it[i] = '\0';
+
+ return s;
+}
+
+static const char *nsvg__getNextPathItem(const char *s, char *it)
+{
+ it[0] = '\0';
+ // Skip white spaces and commas
+ while (*s && (nsvg__isspace(*s) || *s == ','))
+ s++;
+ if (!*s)
+ return s;
+ if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) {
+ s = nsvg__parseNumber(s, it, 64);
+ }
+ else {
+ // Parse command
+ it[0] = *s++;
+ it[1] = '\0';
+ return s;
+ }
+
+ return s;
+}
+
+static unsigned int nsvg__parseColorHex(const char *str)
+{
+ unsigned int c = 0, r = 0, g = 0, b = 0;
+ int n = 0;
+ str++; // skip #
+ // Calculate number of characters.
+ while (str[n] && !nsvg__isspace(str[n]))
+ n++;
+ if (n == 6) {
+ sscanf(str, "%x", &c);
+ }
+ else if (n == 3) {
+ sscanf(str, "%x", &c);
+ c = (c & 0xf) | ((c & 0xf0) << 4) | ((c & 0xf00) << 8);
+ c |= c << 4;
+ }
+ r = (c >> 16) & 0xff;
+ g = (c >> 8) & 0xff;
+ b = c & 0xff;
+ return NSVG_RGB(r, g, b);
+}
+
+static unsigned int nsvg__parseColorRGB(const char *str)
+{
+ int r = -1, g = -1, b = -1;
+ char s1[32] = "", s2[32] = "";
+ sscanf(str + 4, "%d%[%%, \t]%d%[%%, \t]%d", &r, s1, &g, s2, &b);
+ if (strchr(s1, '%')) {
+ return NSVG_RGB((r * 255) / 100, (g * 255) / 100, (b * 255) / 100);
+ }
+ else {
+ return NSVG_RGB(r, g, b);
+ }
+}
+
+typedef struct NSVGNamedColor {
+ const char *name;
+ unsigned int color;
+} NSVGNamedColor;
+
+NSVGNamedColor nsvg__colors[] = {
+
+ {"red", NSVG_RGB(255, 0, 0)},
+ {"green", NSVG_RGB(0, 128, 0)},
+ {"blue", NSVG_RGB(0, 0, 255)},
+ {"yellow", NSVG_RGB(255, 255, 0)},
+ {"cyan", NSVG_RGB(0, 255, 255)},
+ {"magenta", NSVG_RGB(255, 0, 255)},
+ {"black", NSVG_RGB(0, 0, 0)},
+ {"grey", NSVG_RGB(128, 128, 128)},
+ {"gray", NSVG_RGB(128, 128, 128)},
+ {"white", NSVG_RGB(255, 255, 255)},
+
+#ifdef NANOSVG_ALL_COLOR_KEYWORDS
+ {"aliceblue", NSVG_RGB(240, 248, 255)},
+ {"antiquewhite", NSVG_RGB(250, 235, 215)},
+ {"aqua", NSVG_RGB(0, 255, 255)},
+ {"aquamarine", NSVG_RGB(127, 255, 212)},
+ {"azure", NSVG_RGB(240, 255, 255)},
+ {"beige", NSVG_RGB(245, 245, 220)},
+ {"bisque", NSVG_RGB(255, 228, 196)},
+ {"blanchedalmond", NSVG_RGB(255, 235, 205)},
+ {"blueviolet", NSVG_RGB(138, 43, 226)},
+ {"brown", NSVG_RGB(165, 42, 42)},
+ {"burlywood", NSVG_RGB(222, 184, 135)},
+ {"cadetblue", NSVG_RGB(95, 158, 160)},
+ {"chartreuse", NSVG_RGB(127, 255, 0)},
+ {"chocolate", NSVG_RGB(210, 105, 30)},
+ {"coral", NSVG_RGB(255, 127, 80)},
+ {"cornflowerblue", NSVG_RGB(100, 149, 237)},
+ {"cornsilk", NSVG_RGB(255, 248, 220)},
+ {"crimson", NSVG_RGB(220, 20, 60)},
+ {"darkblue", NSVG_RGB(0, 0, 139)},
+ {"darkcyan", NSVG_RGB(0, 139, 139)},
+ {"darkgoldenrod", NSVG_RGB(184, 134, 11)},
+ {"darkgray", NSVG_RGB(169, 169, 169)},
+ {"darkgreen", NSVG_RGB(0, 100, 0)},
+ {"darkgrey", NSVG_RGB(169, 169, 169)},
+ {"darkkhaki", NSVG_RGB(189, 183, 107)},
+ {"darkmagenta", NSVG_RGB(139, 0, 139)},
+ {"darkolivegreen", NSVG_RGB(85, 107, 47)},
+ {"darkorange", NSVG_RGB(255, 140, 0)},
+ {"darkorchid", NSVG_RGB(153, 50, 204)},
+ {"darkred", NSVG_RGB(139, 0, 0)},
+ {"darksalmon", NSVG_RGB(233, 150, 122)},
+ {"darkseagreen", NSVG_RGB(143, 188, 143)},
+ {"darkslateblue", NSVG_RGB(72, 61, 139)},
+ {"darkslategray", NSVG_RGB(47, 79, 79)},
+ {"darkslategrey", NSVG_RGB(47, 79, 79)},
+ {"darkturquoise", NSVG_RGB(0, 206, 209)},
+ {"darkviolet", NSVG_RGB(148, 0, 211)},
+ {"deeppink", NSVG_RGB(255, 20, 147)},
+ {"deepskyblue", NSVG_RGB(0, 191, 255)},
+ {"dimgray", NSVG_RGB(105, 105, 105)},
+ {"dimgrey", NSVG_RGB(105, 105, 105)},
+ {"dodgerblue", NSVG_RGB(30, 144, 255)},
+ {"firebrick", NSVG_RGB(178, 34, 34)},
+ {"floralwhite", NSVG_RGB(255, 250, 240)},
+ {"forestgreen", NSVG_RGB(34, 139, 34)},
+ {"fuchsia", NSVG_RGB(255, 0, 255)},
+ {"gainsboro", NSVG_RGB(220, 220, 220)},
+ {"ghostwhite", NSVG_RGB(248, 248, 255)},
+ {"gold", NSVG_RGB(255, 215, 0)},
+ {"goldenrod", NSVG_RGB(218, 165, 32)},
+ {"greenyellow", NSVG_RGB(173, 255, 47)},
+ {"honeydew", NSVG_RGB(240, 255, 240)},
+ {"hotpink", NSVG_RGB(255, 105, 180)},
+ {"indianred", NSVG_RGB(205, 92, 92)},
+ {"indigo", NSVG_RGB(75, 0, 130)},
+ {"ivory", NSVG_RGB(255, 255, 240)},
+ {"khaki", NSVG_RGB(240, 230, 140)},
+ {"lavender", NSVG_RGB(230, 230, 250)},
+ {"lavenderblush", NSVG_RGB(255, 240, 245)},
+ {"lawngreen", NSVG_RGB(124, 252, 0)},
+ {"lemonchiffon", NSVG_RGB(255, 250, 205)},
+ {"lightblue", NSVG_RGB(173, 216, 230)},
+ {"lightcoral", NSVG_RGB(240, 128, 128)},
+ {"lightcyan", NSVG_RGB(224, 255, 255)},
+ {"lightgoldenrodyellow", NSVG_RGB(250, 250, 210)},
+ {"lightgray", NSVG_RGB(211, 211, 211)},
+ {"lightgreen", NSVG_RGB(144, 238, 144)},
+ {"lightgrey", NSVG_RGB(211, 211, 211)},
+ {"lightpink", NSVG_RGB(255, 182, 193)},
+ {"lightsalmon", NSVG_RGB(255, 160, 122)},
+ {"lightseagreen", NSVG_RGB(32, 178, 170)},
+ {"lightskyblue", NSVG_RGB(135, 206, 250)},
+ {"lightslategray", NSVG_RGB(119, 136, 153)},
+ {"lightslategrey", NSVG_RGB(119, 136, 153)},
+ {"lightsteelblue", NSVG_RGB(176, 196, 222)},
+ {"lightyellow", NSVG_RGB(255, 255, 224)},
+ {"lime", NSVG_RGB(0, 255, 0)},
+ {"limegreen", NSVG_RGB(50, 205, 50)},
+ {"linen", NSVG_RGB(250, 240, 230)},
+ {"maroon", NSVG_RGB(128, 0, 0)},
+ {"mediumaquamarine", NSVG_RGB(102, 205, 170)},
+ {"mediumblue", NSVG_RGB(0, 0, 205)},
+ {"mediumorchid", NSVG_RGB(186, 85, 211)},
+ {"mediumpurple", NSVG_RGB(147, 112, 219)},
+ {"mediumseagreen", NSVG_RGB(60, 179, 113)},
+ {"mediumslateblue", NSVG_RGB(123, 104, 238)},
+ {"mediumspringgreen", NSVG_RGB(0, 250, 154)},
+ {"mediumturquoise", NSVG_RGB(72, 209, 204)},
+ {"mediumvioletred", NSVG_RGB(199, 21, 133)},
+ {"midnightblue", NSVG_RGB(25, 25, 112)},
+ {"mintcream", NSVG_RGB(245, 255, 250)},
+ {"mistyrose", NSVG_RGB(255, 228, 225)},
+ {"moccasin", NSVG_RGB(255, 228, 181)},
+ {"navajowhite", NSVG_RGB(255, 222, 173)},
+ {"navy", NSVG_RGB(0, 0, 128)},
+ {"oldlace", NSVG_RGB(253, 245, 230)},
+ {"olive", NSVG_RGB(128, 128, 0)},
+ {"olivedrab", NSVG_RGB(107, 142, 35)},
+ {"orange", NSVG_RGB(255, 165, 0)},
+ {"orangered", NSVG_RGB(255, 69, 0)},
+ {"orchid", NSVG_RGB(218, 112, 214)},
+ {"palegoldenrod", NSVG_RGB(238, 232, 170)},
+ {"palegreen", NSVG_RGB(152, 251, 152)},
+ {"paleturquoise", NSVG_RGB(175, 238, 238)},
+ {"palevioletred", NSVG_RGB(219, 112, 147)},
+ {"papayawhip", NSVG_RGB(255, 239, 213)},
+ {"peachpuff", NSVG_RGB(255, 218, 185)},
+ {"peru", NSVG_RGB(205, 133, 63)},
+ {"pink", NSVG_RGB(255, 192, 203)},
+ {"plum", NSVG_RGB(221, 160, 221)},
+ {"powderblue", NSVG_RGB(176, 224, 230)},
+ {"purple", NSVG_RGB(128, 0, 128)},
+ {"rosybrown", NSVG_RGB(188, 143, 143)},
+ {"royalblue", NSVG_RGB(65, 105, 225)},
+ {"saddlebrown", NSVG_RGB(139, 69, 19)},
+ {"salmon", NSVG_RGB(250, 128, 114)},
+ {"sandybrown", NSVG_RGB(244, 164, 96)},
+ {"seagreen", NSVG_RGB(46, 139, 87)},
+ {"seashell", NSVG_RGB(255, 245, 238)},
+ {"sienna", NSVG_RGB(160, 82, 45)},
+ {"silver", NSVG_RGB(192, 192, 192)},
+ {"skyblue", NSVG_RGB(135, 206, 235)},
+ {"slateblue", NSVG_RGB(106, 90, 205)},
+ {"slategray", NSVG_RGB(112, 128, 144)},
+ {"slategrey", NSVG_RGB(112, 128, 144)},
+ {"snow", NSVG_RGB(255, 250, 250)},
+ {"springgreen", NSVG_RGB(0, 255, 127)},
+ {"steelblue", NSVG_RGB(70, 130, 180)},
+ {"tan", NSVG_RGB(210, 180, 140)},
+ {"teal", NSVG_RGB(0, 128, 128)},
+ {"thistle", NSVG_RGB(216, 191, 216)},
+ {"tomato", NSVG_RGB(255, 99, 71)},
+ {"turquoise", NSVG_RGB(64, 224, 208)},
+ {"violet", NSVG_RGB(238, 130, 238)},
+ {"wheat", NSVG_RGB(245, 222, 179)},
+ {"whitesmoke", NSVG_RGB(245, 245, 245)},
+ {"yellowgreen", NSVG_RGB(154, 205, 50)},
+#endif
+};
+
+static unsigned int nsvg__parseColorName(const char *str)
+{
+ int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor);
+
+ for (i = 0; i < ncolors; i++) {
+ if (strcmp(nsvg__colors[i].name, str) == 0) {
+ return nsvg__colors[i].color;
+ }
+ }
+
+ return NSVG_RGB(128, 128, 128);
+}
+
+static unsigned int nsvg__parseColor(const char *str)
+{
+ size_t len = 0;
+ while (*str == ' ')
+ ++str;
+ len = strlen(str);
+ if (len >= 1 && *str == '#')
+ return nsvg__parseColorHex(str);
+ else if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(')
+ return nsvg__parseColorRGB(str);
+ return nsvg__parseColorName(str);
+}
+
+static float nsvg__parseOpacity(const char *str)
+{
+ float val = nsvg__atof(str);
+ if (val < 0.0f)
+ val = 0.0f;
+ if (val > 1.0f)
+ val = 1.0f;
+ return val;
+}
+
+static float nsvg__parseMiterLimit(const char *str)
+{
+ float val = nsvg__atof(str);
+ if (val < 0.0f)
+ val = 0.0f;
+ return val;
+}
+
+static int nsvg__parseUnits(const char *units)
+{
+ if (units[0] == 'p' && units[1] == 'x')
+ return NSVG_UNITS_PX;
+ else if (units[0] == 'p' && units[1] == 't')
+ return NSVG_UNITS_PT;
+ else if (units[0] == 'p' && units[1] == 'c')
+ return NSVG_UNITS_PC;
+ else if (units[0] == 'm' && units[1] == 'm')
+ return NSVG_UNITS_MM;
+ else if (units[0] == 'c' && units[1] == 'm')
+ return NSVG_UNITS_CM;
+ else if (units[0] == 'i' && units[1] == 'n')
+ return NSVG_UNITS_IN;
+ else if (units[0] == '%')
+ return NSVG_UNITS_PERCENT;
+ else if (units[0] == 'e' && units[1] == 'm')
+ return NSVG_UNITS_EM;
+ else if (units[0] == 'e' && units[1] == 'x')
+ return NSVG_UNITS_EX;
+ return NSVG_UNITS_USER;
+}
+
+static int nsvg__isCoordinate(const char *s)
+{
+ // optional sign
+ if (*s == '-' || *s == '+')
+ s++;
+ // must have at least one digit
+ return nsvg__isdigit(*s);
+}
+
+static NSVGcoordinate nsvg__parseCoordinateRaw(const char *str)
+{
+ NSVGcoordinate coord = {0, NSVG_UNITS_USER};
+ char buf[64];
+ coord.units = nsvg__parseUnits(nsvg__parseNumber(str, buf, 64));
+ coord.value = nsvg__atof(buf);
+ return coord;
+}
+
+static NSVGcoordinate nsvg__coord(float v, int units)
+{
+ NSVGcoordinate coord = {v, units};
+ return coord;
+}
+
+static float nsvg__parseCoordinate(NSVGparser *p, const char *str, float orig, float length)
+{
+ NSVGcoordinate coord = nsvg__parseCoordinateRaw(str);
+ return nsvg__convertToPixels(p, coord, orig, length);
+}
+
+static int nsvg__parseTransformArgs(const char *str, float *args, int maxNa, int *na)
+{
+ const char *end;
+ const char *ptr;
+ char it[64];
+
+ *na = 0;
+ ptr = str;
+ while (*ptr && *ptr != '(')
+ ++ptr;
+ if (*ptr == 0)
+ return 1;
+ end = ptr;
+ while (*end && *end != ')')
+ ++end;
+ if (*end == 0)
+ return 1;
+
+ while (ptr < end) {
+ if (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) {
+ if (*na >= maxNa)
+ return 0;
+ ptr = nsvg__parseNumber(ptr, it, 64);
+ args[(*na)++] = (float)nsvg__atof(it);
+ }
+ else {
+ ++ptr;
+ }
+ }
+ return (int)(end - str);
+}
+
+static int nsvg__parseMatrix(float *xform, const char *str)
+{
+ float t[6];
+ int na = 0;
+ int len = nsvg__parseTransformArgs(str, t, 6, &na);
+ if (na != 6)
+ return len;
+ memcpy(xform, t, sizeof(float) * 6);
+ return len;
+}
+
+static int nsvg__parseTranslate(float *xform, const char *str)
+{
+ float args[2];
+ float t[6];
+ int na = 0;
+ int len = nsvg__parseTransformArgs(str, args, 2, &na);
+ if (na == 1)
+ args[1] = 0.0;
+
+ nsvg__xformSetTranslation(t, args[0], args[1]);
+ memcpy(xform, t, sizeof(float) * 6);
+ return len;
+}
+
+static int nsvg__parseScale(float *xform, const char *str)
+{
+ float args[2];
+ int na = 0;
+ float t[6];
+ int len = nsvg__parseTransformArgs(str, args, 2, &na);
+ if (na == 1)
+ args[1] = args[0];
+ nsvg__xformSetScale(t, args[0], args[1]);
+ memcpy(xform, t, sizeof(float) * 6);
+ return len;
+}
+
+static int nsvg__parseSkewX(float *xform, const char *str)
+{
+ float args[1];
+ int na = 0;
+ float t[6];
+ int len = nsvg__parseTransformArgs(str, args, 1, &na);
+ nsvg__xformSetSkewX(t, args[0] / 180.0f * NSVG_PI);
+ memcpy(xform, t, sizeof(float) * 6);
+ return len;
+}
+
+static int nsvg__parseSkewY(float *xform, const char *str)
+{
+ float args[1];
+ int na = 0;
+ float t[6];
+ int len = nsvg__parseTransformArgs(str, args, 1, &na);
+ nsvg__xformSetSkewY(t, args[0] / 180.0f * NSVG_PI);
+ memcpy(xform, t, sizeof(float) * 6);
+ return len;
+}
+
+static int nsvg__parseRotate(float *xform, const char *str)
+{
+ float args[3];
+ int na = 0;
+ float m[6];
+ float t[6];
+ int len = nsvg__parseTransformArgs(str, args, 3, &na);
+ if (na == 1)
+ args[1] = args[2] = 0.0f;
+ nsvg__xformIdentity(m);
+
+ if (na > 1) {
+ nsvg__xformSetTranslation(t, -args[1], -args[2]);
+ nsvg__xformMultiply(m, t);
+ }
+
+ nsvg__xformSetRotation(t, args[0] / 180.0f * NSVG_PI);
+ nsvg__xformMultiply(m, t);
+
+ if (na > 1) {
+ nsvg__xformSetTranslation(t, args[1], args[2]);
+ nsvg__xformMultiply(m, t);
+ }
+
+ memcpy(xform, m, sizeof(float) * 6);
+
+ return len;
+}
+
+static void nsvg__parseTransform(float *xform, const char *str)
+{
+ float t[6];
+ int len;
+ nsvg__xformIdentity(xform);
+ while (*str) {
+ if (strncmp(str, "matrix", 6) == 0)
+ len = nsvg__parseMatrix(t, str);
+ else if (strncmp(str, "translate", 9) == 0)
+ len = nsvg__parseTranslate(t, str);
+ else if (strncmp(str, "scale", 5) == 0)
+ len = nsvg__parseScale(t, str);
+ else if (strncmp(str, "rotate", 6) == 0)
+ len = nsvg__parseRotate(t, str);
+ else if (strncmp(str, "skewX", 5) == 0)
+ len = nsvg__parseSkewX(t, str);
+ else if (strncmp(str, "skewY", 5) == 0)
+ len = nsvg__parseSkewY(t, str);
+ else {
+ ++str;
+ continue;
+ }
+ if (len != 0) {
+ str += len;
+ }
+ else {
+ ++str;
+ continue;
+ }
+
+ nsvg__xformPremultiply(xform, t);
+ }
+}
+
+static void nsvg__parseUrl(char *id, const char *str)
+{
+ int i = 0;
+ str += 4; // "url(";
+ if (*str == '#')
+ str++;
+ while (i < 63 && *str != ')') {
+ id[i] = *str++;
+ i++;
+ }
+ id[i] = '\0';
+}
+
+static char nsvg__parseLineCap(const char *str)
+{
+ if (strcmp(str, "butt") == 0)
+ return NSVG_CAP_BUTT;
+ else if (strcmp(str, "round") == 0)
+ return NSVG_CAP_ROUND;
+ else if (strcmp(str, "square") == 0)
+ return NSVG_CAP_SQUARE;
+ // TODO: handle inherit.
+ return NSVG_CAP_BUTT;
+}
+
+static char nsvg__parseLineJoin(const char *str)
+{
+ if (strcmp(str, "miter") == 0)
+ return NSVG_JOIN_MITER;
+ else if (strcmp(str, "round") == 0)
+ return NSVG_JOIN_ROUND;
+ else if (strcmp(str, "bevel") == 0)
+ return NSVG_JOIN_BEVEL;
+ // TODO: handle inherit.
+ return NSVG_JOIN_MITER;
+}
+
+static char nsvg__parseFillRule(const char *str)
+{
+ if (strcmp(str, "nonzero") == 0)
+ return NSVG_FILLRULE_NONZERO;
+ else if (strcmp(str, "evenodd") == 0)
+ return NSVG_FILLRULE_EVENODD;
+ // TODO: handle inherit.
+ return NSVG_FILLRULE_NONZERO;
+}
+
+static const char *nsvg__getNextDashItem(const char *s, char *it)
+{
+ int n = 0;
+ it[0] = '\0';
+ // Skip white spaces and commas
+ while (*s && (nsvg__isspace(*s) || *s == ','))
+ s++;
+ // Advance until whitespace, comma or end.
+ while (*s && (!nsvg__isspace(*s) && *s != ',')) {
+ if (n < 63)
+ it[n++] = *s;
+ s++;
+ }
+ it[n++] = '\0';
+ return s;
+}
+
+static int nsvg__parseStrokeDashArray(NSVGparser *p, const char *str, float *strokeDashArray)
+{
+ char item[64];
+ int count = 0, i;
+ float sum = 0.0f;
+
+ // Handle "none"
+ if (str[0] == 'n')
+ return 0;
+
+ // Parse dashes
+ while (*str) {
+ str = nsvg__getNextDashItem(str, item);
+ if (!*item)
+ break;
+ if (count < NSVG_MAX_DASHES)
+ strokeDashArray[count++] = fabsf(
+ nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p)));
+ }
+
+ for (i = 0; i < count; i++)
+ sum += strokeDashArray[i];
+ if (sum <= 1e-6f)
+ count = 0;
+
+ return count;
+}
+
+static void nsvg__parseStyle(NSVGparser *p, const char *str);
+
+static int nsvg__parseAttr(NSVGparser *p, const char *name, const char *value)
+{
+ float xform[6];
+ NSVGattrib *attr = nsvg__getAttr(p);
+ if (!attr)
+ return 0;
+
+ if (strcmp(name, "style") == 0) {
+ nsvg__parseStyle(p, value);
+ }
+ else if (strcmp(name, "display") == 0) {
+ if (strcmp(value, "none") == 0)
+ attr->visible = 0;
+ // Don't reset ->visible on display:inline, one display:none hides the whole subtree
+ }
+ else if (strcmp(name, "fill") == 0) {
+ if (strcmp(value, "none") == 0) {
+ attr->hasFill = 0;
+ }
+ else if (strncmp(value, "url(", 4) == 0) {
+ attr->hasFill = 2;
+ nsvg__parseUrl(attr->fillGradient, value);
+ }
+ else {
+ attr->hasFill = 1;
+ attr->fillColor = nsvg__parseColor(value);
+ }
+ }
+ else if (strcmp(name, "opacity") == 0) {
+ attr->opacity = nsvg__parseOpacity(value);
+ }
+ else if (strcmp(name, "fill-opacity") == 0) {
+ attr->fillOpacity = nsvg__parseOpacity(value);
+ }
+ else if (strcmp(name, "stroke") == 0) {
+ if (strcmp(value, "none") == 0) {
+ attr->hasStroke = 0;
+ }
+ else if (strncmp(value, "url(", 4) == 0) {
+ attr->hasStroke = 2;
+ nsvg__parseUrl(attr->strokeGradient, value);
+ }
+ else {
+ attr->hasStroke = 1;
+ attr->strokeColor = nsvg__parseColor(value);
+ }
+ }
+ else if (strcmp(name, "stroke-width") == 0) {
+ attr->strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
+ }
+ else if (strcmp(name, "stroke-dasharray") == 0) {
+ attr->strokeDashCount = nsvg__parseStrokeDashArray(p, value, attr->strokeDashArray);
+ }
+ else if (strcmp(name, "stroke-dashoffset") == 0) {
+ attr->strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
+ }
+ else if (strcmp(name, "stroke-opacity") == 0) {
+ attr->strokeOpacity = nsvg__parseOpacity(value);
+ }
+ else if (strcmp(name, "stroke-linecap") == 0) {
+ attr->strokeLineCap = nsvg__parseLineCap(value);
+ }
+ else if (strcmp(name, "stroke-linejoin") == 0) {
+ attr->strokeLineJoin = nsvg__parseLineJoin(value);
+ }
+ else if (strcmp(name, "stroke-miterlimit") == 0) {
+ attr->miterLimit = nsvg__parseMiterLimit(value);
+ }
+ else if (strcmp(name, "fill-rule") == 0) {
+ attr->fillRule = nsvg__parseFillRule(value);
+ }
+ else if (strcmp(name, "font-size") == 0) {
+ attr->fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
+ }
+ else if (strcmp(name, "transform") == 0) {
+ nsvg__parseTransform(xform, value);
+ nsvg__xformPremultiply(attr->xform, xform);
+ }
+ else if (strcmp(name, "stop-color") == 0) {
+ attr->stopColor = nsvg__parseColor(value);
+ }
+ else if (strcmp(name, "stop-opacity") == 0) {
+ attr->stopOpacity = nsvg__parseOpacity(value);
+ }
+ else if (strcmp(name, "offset") == 0) {
+ attr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f);
+ }
+ else if (strcmp(name, "id") == 0) {
+ strncpy(attr->id, value, 63);
+ attr->id[63] = '\0';
+ }
+ else {
+ return 0;
+ }
+ return 1;
+}
+
+static int nsvg__parseNameValue(NSVGparser *p, const char *start, const char *end)
+{
+ const char *str;
+ const char *val;
+ char name[512];
+ char value[512];
+ int n;
+
+ str = start;
+ while (str < end && *str != ':')
+ ++str;
+
+ val = str;
+
+ // Right Trim
+ while (str > start && (*str == ':' || nsvg__isspace(*str)))
+ --str;
+ ++str;
+
+ n = (int)(str - start);
+ if (n > 511)
+ n = 511;
+ if (n)
+ memcpy(name, start, n);
+ name[n] = 0;
+
+ while (val < end && (*val == ':' || nsvg__isspace(*val)))
+ ++val;
+
+ n = (int)(end - val);
+ if (n > 511)
+ n = 511;
+ if (n)
+ memcpy(value, val, n);
+ value[n] = 0;
+
+ return nsvg__parseAttr(p, name, value);
+}
+
+static void nsvg__parseStyle(NSVGparser *p, const char *str)
+{
+ const char *start;
+ const char *end;
+
+ while (*str) {
+ // Left Trim
+ while (*str && nsvg__isspace(*str))
+ ++str;
+ start = str;
+ while (*str && *str != ';')
+ ++str;
+ end = str;
+
+ // Right Trim
+ while (end > start && (*end == ';' || nsvg__isspace(*end)))
+ --end;
+ ++end;
+
+ nsvg__parseNameValue(p, start, end);
+ if (*str)
+ ++str;
+ }
+}
+
+static void nsvg__parseAttribs(NSVGparser *p, const char **attr)
+{
+ int i;
+ for (i = 0; attr[i]; i += 2) {
+ if (strcmp(attr[i], "style") == 0)
+ nsvg__parseStyle(p, attr[i + 1]);
+ else
+ nsvg__parseAttr(p, attr[i], attr[i + 1]);
+ }
+}
+
+static int nsvg__getArgsPerElement(char cmd)
+{
+ switch (cmd) {
+ case 'v':
+ case 'V':
+ case 'h':
+ case 'H':
+ return 1;
+ case 'm':
+ case 'M':
+ case 'l':
+ case 'L':
+ case 't':
+ case 'T':
+ return 2;
+ case 'q':
+ case 'Q':
+ case 's':
+ case 'S':
+ return 4;
+ case 'c':
+ case 'C':
+ return 6;
+ case 'a':
+ case 'A':
+ return 7;
+ case 'z':
+ case 'Z':
+ return 0;
+ }
+ return -1;
+}
+
+static void nsvg__pathMoveTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel)
+{
+ if (rel) {
+ *cpx += args[0];
+ *cpy += args[1];
+ }
+ else {
+ *cpx = args[0];
+ *cpy = args[1];
+ }
+ nsvg__moveTo(p, *cpx, *cpy);
+}
+
+static void nsvg__pathLineTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel)
+{
+ if (rel) {
+ *cpx += args[0];
+ *cpy += args[1];
+ }
+ else {
+ *cpx = args[0];
+ *cpy = args[1];
+ }
+ nsvg__lineTo(p, *cpx, *cpy);
+}
+
+static void nsvg__pathHLineTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel)
+{
+ if (rel)
+ *cpx += args[0];
+ else
+ *cpx = args[0];
+ nsvg__lineTo(p, *cpx, *cpy);
+}
+
+static void nsvg__pathVLineTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel)
+{
+ if (rel)
+ *cpy += args[0];
+ else
+ *cpy = args[0];
+ nsvg__lineTo(p, *cpx, *cpy);
+}
+
+static void nsvg__pathCubicBezTo(
+ NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args, int rel)
+{
+ float x2, y2, cx1, cy1, cx2, cy2;
+
+ if (rel) {
+ cx1 = *cpx + args[0];
+ cy1 = *cpy + args[1];
+ cx2 = *cpx + args[2];
+ cy2 = *cpy + args[3];
+ x2 = *cpx + args[4];
+ y2 = *cpy + args[5];
+ }
+ else {
+ cx1 = args[0];
+ cy1 = args[1];
+ cx2 = args[2];
+ cy2 = args[3];
+ x2 = args[4];
+ y2 = args[5];
+ }
+
+ nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
+
+ *cpx2 = cx2;
+ *cpy2 = cy2;
+ *cpx = x2;
+ *cpy = y2;
+}
+
+static void nsvg__pathCubicBezShortTo(
+ NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args, int rel)
+{
+ float x1, y1, x2, y2, cx1, cy1, cx2, cy2;
+
+ x1 = *cpx;
+ y1 = *cpy;
+ if (rel) {
+ cx2 = *cpx + args[0];
+ cy2 = *cpy + args[1];
+ x2 = *cpx + args[2];
+ y2 = *cpy + args[3];
+ }
+ else {
+ cx2 = args[0];
+ cy2 = args[1];
+ x2 = args[2];
+ y2 = args[3];
+ }
+
+ cx1 = 2 * x1 - *cpx2;
+ cy1 = 2 * y1 - *cpy2;
+
+ nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
+
+ *cpx2 = cx2;
+ *cpy2 = cy2;
+ *cpx = x2;
+ *cpy = y2;
+}
+
+static void nsvg__pathQuadBezTo(
+ NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args, int rel)
+{
+ float x1, y1, x2, y2, cx, cy;
+ float cx1, cy1, cx2, cy2;
+
+ x1 = *cpx;
+ y1 = *cpy;
+ if (rel) {
+ cx = *cpx + args[0];
+ cy = *cpy + args[1];
+ x2 = *cpx + args[2];
+ y2 = *cpy + args[3];
+ }
+ else {
+ cx = args[0];
+ cy = args[1];
+ x2 = args[2];
+ y2 = args[3];
+ }
+
+ // Convert to cubic bezier
+ cx1 = x1 + 2.0f / 3.0f * (cx - x1);
+ cy1 = y1 + 2.0f / 3.0f * (cy - y1);
+ cx2 = x2 + 2.0f / 3.0f * (cx - x2);
+ cy2 = y2 + 2.0f / 3.0f * (cy - y2);
+
+ nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
+
+ *cpx2 = cx;
+ *cpy2 = cy;
+ *cpx = x2;
+ *cpy = y2;
+}
+
+static void nsvg__pathQuadBezShortTo(
+ NSVGparser *p, float *cpx, float *cpy, float *cpx2, float *cpy2, float *args, int rel)
+{
+ float x1, y1, x2, y2, cx, cy;
+ float cx1, cy1, cx2, cy2;
+
+ x1 = *cpx;
+ y1 = *cpy;
+ if (rel) {
+ x2 = *cpx + args[0];
+ y2 = *cpy + args[1];
+ }
+ else {
+ x2 = args[0];
+ y2 = args[1];
+ }
+
+ cx = 2 * x1 - *cpx2;
+ cy = 2 * y1 - *cpy2;
+
+ // Convert to cubix bezier
+ cx1 = x1 + 2.0f / 3.0f * (cx - x1);
+ cy1 = y1 + 2.0f / 3.0f * (cy - y1);
+ cx2 = x2 + 2.0f / 3.0f * (cx - x2);
+ cy2 = y2 + 2.0f / 3.0f * (cy - y2);
+
+ nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2);
+
+ *cpx2 = cx;
+ *cpy2 = cy;
+ *cpx = x2;
+ *cpy = y2;
+}
+
+static float nsvg__sqr(float x)
+{
+ return x * x;
+}
+static float nsvg__vmag(float x, float y)
+{
+ return sqrtf(x * x + y * y);
+}
+
+static float nsvg__vecrat(float ux, float uy, float vx, float vy)
+{
+ return (ux * vx + uy * vy) / (nsvg__vmag(ux, uy) * nsvg__vmag(vx, vy));
+}
+
+static float nsvg__vecang(float ux, float uy, float vx, float vy)
+{
+ float r = nsvg__vecrat(ux, uy, vx, vy);
+ if (r < -1.0f)
+ r = -1.0f;
+ if (r > 1.0f)
+ r = 1.0f;
+ return ((ux * vy < uy * vx) ? -1.0f : 1.0f) * acosf(r);
+}
+
+static void nsvg__pathArcTo(NSVGparser *p, float *cpx, float *cpy, float *args, int rel)
+{
+ // Ported from canvg (https://code.google.com/p/canvg/)
+ float rx, ry, rotx;
+ float x1, y1, x2, y2, cx, cy, dx, dy, d;
+ float x1p, y1p, cxp, cyp, s, sa, sb;
+ float ux, uy, vx, vy, a1, da;
+ float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6];
+ float sinrx, cosrx;
+ int fa, fs;
+ int i, ndivs;
+ float hda, kappa;
+
+ rx = fabsf(args[0]); // y radius
+ ry = fabsf(args[1]); // x radius
+ rotx = args[2] / 180.0f * NSVG_PI; // x rotation angle
+ fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc
+ fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction
+ x1 = *cpx; // start point
+ y1 = *cpy;
+ if (rel) { // end point
+ x2 = *cpx + args[5];
+ y2 = *cpy + args[6];
+ }
+ else {
+ x2 = args[5];
+ y2 = args[6];
+ }
+
+ dx = x1 - x2;
+ dy = y1 - y2;
+ d = sqrtf(dx * dx + dy * dy);
+ if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) {
+ // The arc degenerates to a line
+ nsvg__lineTo(p, x2, y2);
+ *cpx = x2;
+ *cpy = y2;
+ return;
+ }
+
+ sinrx = sinf(rotx);
+ cosrx = cosf(rotx);
+
+ // Convert to center point parameterization.
+ // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
+ // 1) Compute x1', y1'
+ x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f;
+ y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f;
+ d = nsvg__sqr(x1p) / nsvg__sqr(rx) + nsvg__sqr(y1p) / nsvg__sqr(ry);
+ if (d > 1) {
+ d = sqrtf(d);
+ rx *= d;
+ ry *= d;
+ }
+ // 2) Compute cx', cy'
+ s = 0.0f;
+ sa = nsvg__sqr(rx) * nsvg__sqr(ry) - nsvg__sqr(rx) * nsvg__sqr(y1p) -
+ nsvg__sqr(ry) * nsvg__sqr(x1p);
+ sb = nsvg__sqr(rx) * nsvg__sqr(y1p) + nsvg__sqr(ry) * nsvg__sqr(x1p);
+ if (sa < 0.0f)
+ sa = 0.0f;
+ if (sb > 0.0f)
+ s = sqrtf(sa / sb);
+ if (fa == fs)
+ s = -s;
+ cxp = s * rx * y1p / ry;
+ cyp = s * -ry * x1p / rx;
+
+ // 3) Compute cx,cy from cx',cy'
+ cx = (x1 + x2) / 2.0f + cosrx * cxp - sinrx * cyp;
+ cy = (y1 + y2) / 2.0f + sinrx * cxp + cosrx * cyp;
+
+ // 4) Calculate theta1, and delta theta.
+ ux = (x1p - cxp) / rx;
+ uy = (y1p - cyp) / ry;
+ vx = (-x1p - cxp) / rx;
+ vy = (-y1p - cyp) / ry;
+ a1 = nsvg__vecang(1.0f, 0.0f, ux, uy); // Initial angle
+ da = nsvg__vecang(ux, uy, vx, vy); // Delta angle
+
+ // if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI;
+ // if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0;
+
+ if (fs == 0 && da > 0)
+ da -= 2 * NSVG_PI;
+ else if (fs == 1 && da < 0)
+ da += 2 * NSVG_PI;
+
+ // Approximate the arc using cubic spline segments.
+ t[0] = cosrx;
+ t[1] = sinrx;
+ t[2] = -sinrx;
+ t[3] = cosrx;
+ t[4] = cx;
+ t[5] = cy;
+
+ // Split arc into max 90 degree segments.
+ // The loop assumes an iteration per end point (including start and end), this +1.
+ ndivs = (int)(fabsf(da) / (NSVG_PI * 0.5f) + 1.0f);
+ hda = (da / (float)ndivs) / 2.0f;
+ kappa = fabsf(4.0f / 3.0f * (1.0f - cosf(hda)) / sinf(hda));
+ if (da < 0.0f)
+ kappa = -kappa;
+
+ for (i = 0; i <= ndivs; i++) {
+ a = a1 + da * ((float)i / (float)ndivs);
+ dx = cosf(a);
+ dy = sinf(a);
+ nsvg__xformPoint(&x, &y, dx * rx, dy * ry, t); // position
+ nsvg__xformVec(&tanx, &tany, -dy * rx * kappa, dx * ry * kappa, t); // tangent
+ if (i > 0)
+ nsvg__cubicBezTo(p, px + ptanx, py + ptany, x - tanx, y - tany, x, y);
+ px = x;
+ py = y;
+ ptanx = tanx;
+ ptany = tany;
+ }
+
+ *cpx = x2;
+ *cpy = y2;
+}
+
+static void nsvg__parsePath(NSVGparser *p, const char **attr)
+{
+ const char *s = NULL;
+ char cmd = '\0';
+ float args[10];
+ int nargs;
+ int rargs = 0;
+ char initPoint;
+ float cpx, cpy, cpx2, cpy2;
+ const char *tmp[4];
+ char closedFlag;
+ int i;
+ char item[64];
+
+ for (i = 0; attr[i]; i += 2) {
+ if (strcmp(attr[i], "d") == 0) {
+ s = attr[i + 1];
+ }
+ else {
+ tmp[0] = attr[i];
+ tmp[1] = attr[i + 1];
+ tmp[2] = 0;
+ tmp[3] = 0;
+ nsvg__parseAttribs(p, tmp);
+ }
+ }
+
+ if (s) {
+ nsvg__resetPath(p);
+ cpx = 0;
+ cpy = 0;
+ cpx2 = 0;
+ cpy2 = 0;
+ initPoint = 0;
+ closedFlag = 0;
+ nargs = 0;
+
+ while (*s) {
+ s = nsvg__getNextPathItem(s, item);
+ if (!*item)
+ break;
+ if (cmd != '\0' && nsvg__isCoordinate(item)) {
+ if (nargs < 10)
+ args[nargs++] = (float)nsvg__atof(item);
+ if (nargs >= rargs) {
+ switch (cmd) {
+ case 'm':
+ case 'M':
+ nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0);
+ // Moveto can be followed by multiple coordinate pairs,
+ // which should be treated as linetos.
+ cmd = (cmd == 'm') ? 'l' : 'L';
+ rargs = nsvg__getArgsPerElement(cmd);
+ cpx2 = cpx;
+ cpy2 = cpy;
+ initPoint = 1;
+ break;
+ case 'l':
+ case 'L':
+ nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0);
+ cpx2 = cpx;
+ cpy2 = cpy;
+ break;
+ case 'H':
+ case 'h':
+ nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0);
+ cpx2 = cpx;
+ cpy2 = cpy;
+ break;
+ case 'V':
+ case 'v':
+ nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0);
+ cpx2 = cpx;
+ cpy2 = cpy;
+ break;
+ case 'C':
+ case 'c':
+ nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0);
+ break;
+ case 'S':
+ case 's':
+ nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
+ break;
+ case 'Q':
+ case 'q':
+ nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0);
+ break;
+ case 'T':
+ case 't':
+ nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 't' ? 1 : 0);
+ break;
+ case 'A':
+ case 'a':
+ nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0);
+ cpx2 = cpx;
+ cpy2 = cpy;
+ break;
+ default:
+ if (nargs >= 2) {
+ cpx = args[nargs - 2];
+ cpy = args[nargs - 1];
+ cpx2 = cpx;
+ cpy2 = cpy;
+ }
+ break;
+ }
+ nargs = 0;
+ }
+ }
+ else {
+ cmd = item[0];
+ if (cmd == 'M' || cmd == 'm') {
+ // Commit path.
+ if (p->npts > 0)
+ nsvg__addPath(p, closedFlag);
+ // Start new subpath.
+ nsvg__resetPath(p);
+ closedFlag = 0;
+ nargs = 0;
+ }
+ else if (initPoint == 0) {
+ // Do not allow other commands until initial point has been set (moveTo called once).
+ cmd = '\0';
+ }
+ if (cmd == 'Z' || cmd == 'z') {
+ closedFlag = 1;
+ // Commit path.
+ if (p->npts > 0) {
+ // Move current point to first point
+ cpx = p->pts[0];
+ cpy = p->pts[1];
+ cpx2 = cpx;
+ cpy2 = cpy;
+ nsvg__addPath(p, closedFlag);
+ }
+ // Start new subpath.
+ nsvg__resetPath(p);
+ nsvg__moveTo(p, cpx, cpy);
+ closedFlag = 0;
+ nargs = 0;
+ }
+ rargs = nsvg__getArgsPerElement(cmd);
+ if (rargs == -1) {
+ // Command not recognized
+ cmd = '\0';
+ rargs = 0;
+ }
+ }
+ }
+ // Commit path.
+ if (p->npts)
+ nsvg__addPath(p, closedFlag);
+ }
+
+ nsvg__addShape(p);
+}
+
+static void nsvg__parseRect(NSVGparser *p, const char **attr)
+{
+ float x = 0.0f;
+ float y = 0.0f;
+ float w = 0.0f;
+ float h = 0.0f;
+ float rx = -1.0f; // marks not set
+ float ry = -1.0f;
+ int i;
+
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "x") == 0)
+ x = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
+ if (strcmp(attr[i], "y") == 0)
+ y = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
+ if (strcmp(attr[i], "width") == 0)
+ w = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualWidth(p));
+ if (strcmp(attr[i], "height") == 0)
+ h = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualHeight(p));
+ if (strcmp(attr[i], "rx") == 0)
+ rx = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualWidth(p)));
+ if (strcmp(attr[i], "ry") == 0)
+ ry = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualHeight(p)));
+ }
+ }
+
+ if (rx < 0.0f && ry > 0.0f)
+ rx = ry;
+ if (ry < 0.0f && rx > 0.0f)
+ ry = rx;
+ if (rx < 0.0f)
+ rx = 0.0f;
+ if (ry < 0.0f)
+ ry = 0.0f;
+ if (rx > w / 2.0f)
+ rx = w / 2.0f;
+ if (ry > h / 2.0f)
+ ry = h / 2.0f;
+
+ if (w != 0.0f && h != 0.0f) {
+ nsvg__resetPath(p);
+
+ if (rx < 0.00001f || ry < 0.0001f) {
+ nsvg__moveTo(p, x, y);
+ nsvg__lineTo(p, x + w, y);
+ nsvg__lineTo(p, x + w, y + h);
+ nsvg__lineTo(p, x, y + h);
+ }
+ else {
+ // Rounded rectangle
+ nsvg__moveTo(p, x + rx, y);
+ nsvg__lineTo(p, x + w - rx, y);
+ nsvg__cubicBezTo(p,
+ x + w - rx * (1 - NSVG_KAPPA90),
+ y,
+ x + w,
+ y + ry * (1 - NSVG_KAPPA90),
+ x + w,
+ y + ry);
+ nsvg__lineTo(p, x + w, y + h - ry);
+ nsvg__cubicBezTo(p,
+ x + w,
+ y + h - ry * (1 - NSVG_KAPPA90),
+ x + w - rx * (1 - NSVG_KAPPA90),
+ y + h,
+ x + w - rx,
+ y + h);
+ nsvg__lineTo(p, x + rx, y + h);
+ nsvg__cubicBezTo(p,
+ x + rx * (1 - NSVG_KAPPA90),
+ y + h,
+ x,
+ y + h - ry * (1 - NSVG_KAPPA90),
+ x,
+ y + h - ry);
+ nsvg__lineTo(p, x, y + ry);
+ nsvg__cubicBezTo(
+ p, x, y + ry * (1 - NSVG_KAPPA90), x + rx * (1 - NSVG_KAPPA90), y, x + rx, y);
+ }
+
+ nsvg__addPath(p, 1);
+
+ nsvg__addShape(p);
+ }
+}
+
+static void nsvg__parseCircle(NSVGparser *p, const char **attr)
+{
+ float cx = 0.0f;
+ float cy = 0.0f;
+ float r = 0.0f;
+ int i;
+
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "cx") == 0)
+ cx = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
+ if (strcmp(attr[i], "cy") == 0)
+ cy = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
+ if (strcmp(attr[i], "r") == 0)
+ r = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualLength(p)));
+ }
+ }
+
+ if (r > 0.0f) {
+ nsvg__resetPath(p);
+
+ nsvg__moveTo(p, cx + r, cy);
+ nsvg__cubicBezTo(p, cx + r, cy + r * NSVG_KAPPA90, cx + r * NSVG_KAPPA90, cy + r, cx, cy + r);
+ nsvg__cubicBezTo(p, cx - r * NSVG_KAPPA90, cy + r, cx - r, cy + r * NSVG_KAPPA90, cx - r, cy);
+ nsvg__cubicBezTo(p, cx - r, cy - r * NSVG_KAPPA90, cx - r * NSVG_KAPPA90, cy - r, cx, cy - r);
+ nsvg__cubicBezTo(p, cx + r * NSVG_KAPPA90, cy - r, cx + r, cy - r * NSVG_KAPPA90, cx + r, cy);
+
+ nsvg__addPath(p, 1);
+
+ nsvg__addShape(p);
+ }
+}
+
+static void nsvg__parseEllipse(NSVGparser *p, const char **attr)
+{
+ float cx = 0.0f;
+ float cy = 0.0f;
+ float rx = 0.0f;
+ float ry = 0.0f;
+ int i;
+
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "cx") == 0)
+ cx = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
+ if (strcmp(attr[i], "cy") == 0)
+ cy = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
+ if (strcmp(attr[i], "rx") == 0)
+ rx = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualWidth(p)));
+ if (strcmp(attr[i], "ry") == 0)
+ ry = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualHeight(p)));
+ }
+ }
+
+ if (rx > 0.0f && ry > 0.0f) {
+
+ nsvg__resetPath(p);
+
+ nsvg__moveTo(p, cx + rx, cy);
+ nsvg__cubicBezTo(
+ p, cx + rx, cy + ry * NSVG_KAPPA90, cx + rx * NSVG_KAPPA90, cy + ry, cx, cy + ry);
+ nsvg__cubicBezTo(
+ p, cx - rx * NSVG_KAPPA90, cy + ry, cx - rx, cy + ry * NSVG_KAPPA90, cx - rx, cy);
+ nsvg__cubicBezTo(
+ p, cx - rx, cy - ry * NSVG_KAPPA90, cx - rx * NSVG_KAPPA90, cy - ry, cx, cy - ry);
+ nsvg__cubicBezTo(
+ p, cx + rx * NSVG_KAPPA90, cy - ry, cx + rx, cy - ry * NSVG_KAPPA90, cx + rx, cy);
+
+ nsvg__addPath(p, 1);
+
+ nsvg__addShape(p);
+ }
+}
+
+static void nsvg__parseLine(NSVGparser *p, const char **attr)
+{
+ float x1 = 0.0;
+ float y1 = 0.0;
+ float x2 = 0.0;
+ float y2 = 0.0;
+ int i;
+
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "x1") == 0)
+ x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
+ if (strcmp(attr[i], "y1") == 0)
+ y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
+ if (strcmp(attr[i], "x2") == 0)
+ x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
+ if (strcmp(attr[i], "y2") == 0)
+ y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
+ }
+ }
+
+ nsvg__resetPath(p);
+
+ nsvg__moveTo(p, x1, y1);
+ nsvg__lineTo(p, x2, y2);
+
+ nsvg__addPath(p, 0);
+
+ nsvg__addShape(p);
+}
+
+static void nsvg__parsePoly(NSVGparser *p, const char **attr, int closeFlag)
+{
+ int i;
+ const char *s;
+ float args[2];
+ int nargs, npts = 0;
+ char item[64];
+
+ nsvg__resetPath(p);
+
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "points") == 0) {
+ s = attr[i + 1];
+ nargs = 0;
+ while (*s) {
+ s = nsvg__getNextPathItem(s, item);
+ args[nargs++] = (float)nsvg__atof(item);
+ if (nargs >= 2) {
+ if (npts == 0)
+ nsvg__moveTo(p, args[0], args[1]);
+ else
+ nsvg__lineTo(p, args[0], args[1]);
+ nargs = 0;
+ npts++;
+ }
+ }
+ }
+ }
+ }
+
+ nsvg__addPath(p, (char)closeFlag);
+
+ nsvg__addShape(p);
+}
+
+static void nsvg__parseSVG(NSVGparser *p, const char **attr)
+{
+ int i;
+ for (i = 0; attr[i]; i += 2) {
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "width") == 0) {
+ p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
+ }
+ else if (strcmp(attr[i], "height") == 0) {
+ p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
+ }
+ else if (strcmp(attr[i], "viewBox") == 0) {
+ const char *s = attr[i + 1];
+ char buf[64];
+ s = nsvg__parseNumber(s, buf, 64);
+ p->viewMinx = nsvg__atof(buf);
+ while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ','))
+ s++;
+ if (!*s)
+ return;
+ s = nsvg__parseNumber(s, buf, 64);
+ p->viewMiny = nsvg__atof(buf);
+ while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ','))
+ s++;
+ if (!*s)
+ return;
+ s = nsvg__parseNumber(s, buf, 64);
+ p->viewWidth = nsvg__atof(buf);
+ while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ','))
+ s++;
+ if (!*s)
+ return;
+ s = nsvg__parseNumber(s, buf, 64);
+ p->viewHeight = nsvg__atof(buf);
+ }
+ else if (strcmp(attr[i], "preserveAspectRatio") == 0) {
+ if (strstr(attr[i + 1], "none") != 0) {
+ // No uniform scaling
+ p->alignType = NSVG_ALIGN_NONE;
+ }
+ else {
+ // Parse X align
+ if (strstr(attr[i + 1], "xMin") != 0)
+ p->alignX = NSVG_ALIGN_MIN;
+ else if (strstr(attr[i + 1], "xMid") != 0)
+ p->alignX = NSVG_ALIGN_MID;
+ else if (strstr(attr[i + 1], "xMax") != 0)
+ p->alignX = NSVG_ALIGN_MAX;
+ // Parse X align
+ if (strstr(attr[i + 1], "yMin") != 0)
+ p->alignY = NSVG_ALIGN_MIN;
+ else if (strstr(attr[i + 1], "yMid") != 0)
+ p->alignY = NSVG_ALIGN_MID;
+ else if (strstr(attr[i + 1], "yMax") != 0)
+ p->alignY = NSVG_ALIGN_MAX;
+ // Parse meet/slice
+ p->alignType = NSVG_ALIGN_MEET;
+ if (strstr(attr[i + 1], "slice") != 0)
+ p->alignType = NSVG_ALIGN_SLICE;
+ }
+ }
+ }
+ }
+}
+
+static void nsvg__parseGradient(NSVGparser *p, const char **attr, char type)
+{
+ int i;
+ NSVGgradientData *grad = (NSVGgradientData *)malloc(sizeof(NSVGgradientData));
+ if (grad == NULL)
+ return;
+ memset(grad, 0, sizeof(NSVGgradientData));
+ grad->units = NSVG_OBJECT_SPACE;
+ grad->type = type;
+ if (grad->type == NSVG_PAINT_LINEAR_GRADIENT) {
+ grad->linear.x1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
+ grad->linear.y1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
+ grad->linear.x2 = nsvg__coord(100.0f, NSVG_UNITS_PERCENT);
+ grad->linear.y2 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
+ }
+ else if (grad->type == NSVG_PAINT_RADIAL_GRADIENT) {
+ grad->radial.cx = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
+ grad->radial.cy = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
+ grad->radial.r = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
+ }
+
+ nsvg__xformIdentity(grad->xform);
+
+ for (i = 0; attr[i]; i += 2) {
+ if (strcmp(attr[i], "id") == 0) {
+ strncpy(grad->id, attr[i + 1], 63);
+ grad->id[63] = '\0';
+ }
+ else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
+ if (strcmp(attr[i], "gradientUnits") == 0) {
+ if (strcmp(attr[i + 1], "objectBoundingBox") == 0)
+ grad->units = NSVG_OBJECT_SPACE;
+ else
+ grad->units = NSVG_USER_SPACE;
+ }
+ else if (strcmp(attr[i], "gradientTransform") == 0) {
+ nsvg__parseTransform(grad->xform, attr[i + 1]);
+ }
+ else if (strcmp(attr[i], "cx") == 0) {
+ grad->radial.cx = nsvg__parseCoordinateRaw(attr[i + 1]);
+ }
+ else if (strcmp(attr[i], "cy") == 0) {
+ grad->radial.cy = nsvg__parseCoordinateRaw(attr[i + 1]);
+ }
+ else if (strcmp(attr[i], "r") == 0) {
+ grad->radial.r = nsvg__parseCoordinateRaw(attr[i + 1]);
+ }
+ else if (strcmp(attr[i], "fx") == 0) {
+ grad->radial.fx = nsvg__parseCoordinateRaw(attr[i + 1]);
+ }
+ else if (strcmp(attr[i], "fy") == 0) {
+ grad->radial.fy = nsvg__parseCoordinateRaw(attr[i + 1]);
+ }
+ else if (strcmp(attr[i], "x1") == 0) {
+ grad->linear.x1 = nsvg__parseCoordinateRaw(attr[i + 1]);
+ }
+ else if (strcmp(attr[i], "y1") == 0) {
+ grad->linear.y1 = nsvg__parseCoordinateRaw(attr[i + 1]);
+ }
+ else if (strcmp(attr[i], "x2") == 0) {
+ grad->linear.x2 = nsvg__parseCoordinateRaw(attr[i + 1]);
+ }
+ else if (strcmp(attr[i], "y2") == 0) {
+ grad->linear.y2 = nsvg__parseCoordinateRaw(attr[i + 1]);
+ }
+ else if (strcmp(attr[i], "spreadMethod") == 0) {
+ if (strcmp(attr[i + 1], "pad") == 0)
+ grad->spread = NSVG_SPREAD_PAD;
+ else if (strcmp(attr[i + 1], "reflect") == 0)
+ grad->spread = NSVG_SPREAD_REFLECT;
+ else if (strcmp(attr[i + 1], "repeat") == 0)
+ grad->spread = NSVG_SPREAD_REPEAT;
+ }
+ else if (strcmp(attr[i], "xlink:href") == 0) {
+ const char *href = attr[i + 1];
+ strncpy(grad->ref, href + 1, 62);
+ grad->ref[62] = '\0';
+ }
+ }
+ }
+
+ grad->next = p->gradients;
+ p->gradients = grad;
+}
+
+static void nsvg__parseGradientStop(NSVGparser *p, const char **attr)
+{
+ NSVGattrib *curAttr = nsvg__getAttr(p);
+ NSVGgradientData *grad;
+ NSVGgradientStop *stop;
+ int i, idx;
+
+ curAttr->stopOffset = 0;
+ curAttr->stopColor = 0;
+ curAttr->stopOpacity = 1.0f;
+
+ for (i = 0; attr[i]; i += 2) {
+ nsvg__parseAttr(p, attr[i], attr[i + 1]);
+ }
+
+ // Add stop to the last gradient.
+ grad = p->gradients;
+ if (grad == NULL)
+ return;
+
+ grad->nstops++;
+ grad->stops = (NSVGgradientStop *)realloc(grad->stops, sizeof(NSVGgradientStop) * grad->nstops);
+ if (grad->stops == NULL)
+ return;
+
+ // Insert
+ idx = grad->nstops - 1;
+ for (i = 0; i < grad->nstops - 1; i++) {
+ if (curAttr->stopOffset < grad->stops[i].offset) {
+ idx = i;
+ break;
+ }
+ }
+ if (idx != grad->nstops - 1) {
+ for (i = grad->nstops - 1; i > idx; i--)
+ grad->stops[i] = grad->stops[i - 1];
+ }
+
+ stop = &grad->stops[idx];
+ stop->color = curAttr->stopColor;
+ stop->color |= (unsigned int)(curAttr->stopOpacity * 255) << 24;
+ stop->offset = curAttr->stopOffset;
+}
+
+static void nsvg__startElement(void *ud, const char *el, const char **attr)
+{
+ NSVGparser *p = (NSVGparser *)ud;
+
+ if (p->defsFlag) {
+ // Skip everything but gradients in defs
+ if (strcmp(el, "linearGradient") == 0) {
+ nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
+ }
+ else if (strcmp(el, "radialGradient") == 0) {
+ nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
+ }
+ else if (strcmp(el, "stop") == 0) {
+ nsvg__parseGradientStop(p, attr);
+ }
+ return;
+ }
+
+ if (strcmp(el, "g") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseAttribs(p, attr);
+
+ /* Save the breadcrumb of groups. */
+ if (p->breadcrumb_len < NSVG_MAX_BREADCRUMB) {
+ NSVGattrib *attr_id = nsvg__getAttr(p);
+ memcpy(
+ p->breadcrumb[p->breadcrumb_len], attr_id->id, sizeof(p->breadcrumb[p->breadcrumb_len]));
+ p->breadcrumb_len++;
+ }
+ }
+ else if (strcmp(el, "path") == 0) {
+ if (p->pathFlag) // Do not allow nested paths.
+ return;
+ nsvg__pushAttr(p);
+ nsvg__parsePath(p, attr);
+ nsvg__popAttr(p);
+ }
+ else if (strcmp(el, "rect") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseRect(p, attr);
+ nsvg__popAttr(p);
+ }
+ else if (strcmp(el, "circle") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseCircle(p, attr);
+ nsvg__popAttr(p);
+ }
+ else if (strcmp(el, "ellipse") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseEllipse(p, attr);
+ nsvg__popAttr(p);
+ }
+ else if (strcmp(el, "line") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseLine(p, attr);
+ nsvg__popAttr(p);
+ }
+ else if (strcmp(el, "polyline") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parsePoly(p, attr, 0);
+ nsvg__popAttr(p);
+ }
+ else if (strcmp(el, "polygon") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parsePoly(p, attr, 1);
+ nsvg__popAttr(p);
+ }
+ else if (strcmp(el, "linearGradient") == 0) {
+ nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
+ }
+ else if (strcmp(el, "radialGradient") == 0) {
+ nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
+ }
+ else if (strcmp(el, "stop") == 0) {
+ nsvg__parseGradientStop(p, attr);
+ }
+ else if (strcmp(el, "defs") == 0) {
+ p->defsFlag = 1;
+ }
+ else if (strcmp(el, "svg") == 0) {
+ nsvg__parseSVG(p, attr);
+ }
+}
+
+static void nsvg__endElement(void *ud, const char *el)
+{
+ NSVGparser *p = (NSVGparser *)ud;
+
+ if (strcmp(el, "g") == 0) {
+ /* Remove the breadcrumb level. */
+ if (p->breadcrumb_len > 0) {
+ p->breadcrumb[p->breadcrumb_len - 1][0] = '\0';
+ p->breadcrumb_len--;
+ }
+
+ nsvg__popAttr(p);
+ }
+ else if (strcmp(el, "path") == 0) {
+ p->pathFlag = 0;
+ }
+ else if (strcmp(el, "defs") == 0) {
+ p->defsFlag = 0;
+ }
+}
+
+static void nsvg__content(void *ud, const char *s)
+{
+ NSVG_NOTUSED(ud);
+ NSVG_NOTUSED(s);
+ // empty
+}
+
+static void nsvg__imageBounds(NSVGparser *p, float *bounds)
+{
+ NSVGshape *shape;
+ shape = p->image->shapes;
+ if (shape == NULL) {
+ bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0;
+ return;
+ }
+ bounds[0] = shape->bounds[0];
+ bounds[1] = shape->bounds[1];
+ bounds[2] = shape->bounds[2];
+ bounds[3] = shape->bounds[3];
+ for (shape = shape->next; shape != NULL; shape = shape->next) {
+ bounds[0] = nsvg__minf(bounds[0], shape->bounds[0]);
+ bounds[1] = nsvg__minf(bounds[1], shape->bounds[1]);
+ bounds[2] = nsvg__maxf(bounds[2], shape->bounds[2]);
+ bounds[3] = nsvg__maxf(bounds[3], shape->bounds[3]);
+ }
+}
+
+static float nsvg__viewAlign(float content, float container, int type)
+{
+ if (type == NSVG_ALIGN_MIN)
+ return 0;
+ else if (type == NSVG_ALIGN_MAX)
+ return container - content;
+ // mid
+ return (container - content) * 0.5f;
+}
+
+static void nsvg__scaleGradient(NSVGgradient *grad, float tx, float ty, float sx, float sy)
+{
+ float t[6];
+ nsvg__xformSetTranslation(t, tx, ty);
+ nsvg__xformMultiply(grad->xform, t);
+
+ nsvg__xformSetScale(t, sx, sy);
+ nsvg__xformMultiply(grad->xform, t);
+}
+
+static void nsvg__scaleToViewbox(NSVGparser *p, const char *units)
+{
+ NSVGshape *shape;
+ NSVGpath *path;
+ float tx, ty, sx, sy, us, bounds[4], t[6], avgs;
+ int i;
+ float *pt;
+
+ // Guess image size if not set completely.
+ nsvg__imageBounds(p, bounds);
+
+ if (p->viewWidth == 0) {
+ if (p->image->width > 0) {
+ p->viewWidth = p->image->width;
+ }
+ else {
+ p->viewMinx = bounds[0];
+ p->viewWidth = bounds[2] - bounds[0];
+ }
+ }
+ if (p->viewHeight == 0) {
+ if (p->image->height > 0) {
+ p->viewHeight = p->image->height;
+ }
+ else {
+ p->viewMiny = bounds[1];
+ p->viewHeight = bounds[3] - bounds[1];
+ }
+ }
+ if (p->image->width == 0)
+ p->image->width = p->viewWidth;
+ if (p->image->height == 0)
+ p->image->height = p->viewHeight;
+
+ tx = -p->viewMinx;
+ ty = -p->viewMiny;
+ sx = p->viewWidth > 0 ? p->image->width / p->viewWidth : 0;
+ sy = p->viewHeight > 0 ? p->image->height / p->viewHeight : 0;
+ // Unit scaling
+ us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f);
+
+ // Fix aspect ratio
+ if (p->alignType == NSVG_ALIGN_MEET) {
+ // fit whole image into viewbox
+ sx = sy = nsvg__minf(sx, sy);
+ tx += nsvg__viewAlign(p->viewWidth * sx, p->image->width, p->alignX) / sx;
+ ty += nsvg__viewAlign(p->viewHeight * sy, p->image->height, p->alignY) / sy;
+ }
+ else if (p->alignType == NSVG_ALIGN_SLICE) {
+ // fill whole viewbox with image
+ sx = sy = nsvg__maxf(sx, sy);
+ tx += nsvg__viewAlign(p->viewWidth * sx, p->image->width, p->alignX) / sx;
+ ty += nsvg__viewAlign(p->viewHeight * sy, p->image->height, p->alignY) / sy;
+ }
+
+ // Transform
+ sx *= us;
+ sy *= us;
+ avgs = (sx + sy) / 2.0f;
+ for (shape = p->image->shapes; shape != NULL; shape = shape->next) {
+ shape->bounds[0] = (shape->bounds[0] + tx) * sx;
+ shape->bounds[1] = (shape->bounds[1] + ty) * sy;
+ shape->bounds[2] = (shape->bounds[2] + tx) * sx;
+ shape->bounds[3] = (shape->bounds[3] + ty) * sy;
+ for (path = shape->paths; path != NULL; path = path->next) {
+ path->bounds[0] = (path->bounds[0] + tx) * sx;
+ path->bounds[1] = (path->bounds[1] + ty) * sy;
+ path->bounds[2] = (path->bounds[2] + tx) * sx;
+ path->bounds[3] = (path->bounds[3] + ty) * sy;
+ for (i = 0; i < path->npts; i++) {
+ pt = &path->pts[i * 2];
+ pt[0] = (pt[0] + tx) * sx;
+ pt[1] = (pt[1] + ty) * sy;
+ }
+ }
+
+ if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT ||
+ shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) {
+ nsvg__scaleGradient(shape->fill.gradient, tx, ty, sx, sy);
+ memcpy(t, shape->fill.gradient->xform, sizeof(float) * 6);
+ nsvg__xformInverse(shape->fill.gradient->xform, t);
+ }
+ if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT ||
+ shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) {
+ nsvg__scaleGradient(shape->stroke.gradient, tx, ty, sx, sy);
+ memcpy(t, shape->stroke.gradient->xform, sizeof(float) * 6);
+ nsvg__xformInverse(shape->stroke.gradient->xform, t);
+ }
+
+ shape->strokeWidth *= avgs;
+ shape->strokeDashOffset *= avgs;
+ for (i = 0; i < shape->strokeDashCount; i++)
+ shape->strokeDashArray[i] *= avgs;
+ }
+}
+
+NSVGimage *nsvgParse(char *input, const char *units, float dpi)
+{
+ NSVGparser *p;
+ NSVGimage *ret = 0;
+
+ p = nsvg__createParser();
+ if (p == NULL) {
+ return NULL;
+ }
+ p->dpi = dpi;
+
+ nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);
+
+ // Scale to viewBox
+ nsvg__scaleToViewbox(p, units);
+
+ ret = p->image;
+ p->image = NULL;
+
+ nsvg__deleteParser(p);
+
+ return ret;
+}
+
+NSVGimage *nsvgParseFromFile(const char *filename, const char *units, float dpi)
+{
+ FILE *fp = NULL;
+ size_t size;
+ char *data = NULL;
+ NSVGimage *image = NULL;
+
+ fp = fopen(filename, "rb");
+ if (!fp)
+ goto error;
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ data = (char *)malloc(size + 1);
+ if (data == NULL)
+ goto error;
+ if (fread(data, 1, size, fp) != size)
+ goto error;
+ data[size] = '\0'; // Must be null terminated.
+ fclose(fp);
+ image = nsvgParse(data, units, dpi);
+ free(data);
+
+ return image;
+
+error:
+ if (fp)
+ fclose(fp);
+ if (data)
+ free(data);
+ if (image)
+ nsvgDelete(image);
+ return NULL;
+}
+
+NSVGpath *nsvgDuplicatePath(NSVGpath *p)
+{
+ NSVGpath *res = NULL;
+
+ if (p == NULL)
+ return NULL;
+
+ res = (NSVGpath *)malloc(sizeof(NSVGpath));
+ if (res == NULL)
+ goto error;
+ memset(res, 0, sizeof(NSVGpath));
+
+ res->pts = (float *)malloc(p->npts * 2 * sizeof(float));
+ if (res->pts == NULL)
+ goto error;
+ memcpy(res->pts, p->pts, p->npts * sizeof(float) * 2);
+ res->npts = p->npts;
+
+ memcpy(res->bounds, p->bounds, sizeof(p->bounds));
+
+ res->closed = p->closed;
+
+ return res;
+
+error:
+ if (res != NULL) {
+ free(res->pts);
+ free(res);
+ }
+ return NULL;
+}
+
+void nsvgDelete(NSVGimage *image)
+{
+ NSVGshape *snext, *shape;
+ if (image == NULL)
+ return;
+ shape = image->shapes;
+ while (shape != NULL) {
+ snext = shape->next;
+ nsvg__deletePaths(shape->paths);
+ nsvg__deletePaint(&shape->fill);
+ nsvg__deletePaint(&shape->stroke);
+ free(shape);
+ shape = snext;
+ }
+ free(image);
+}
+
+#endif
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 077f9bf8bdc..d88db091cc2 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -763,19 +763,53 @@ typedef enum IDRecalcFlag {
* See e.g. how #BKE_library_unused_linked_data_set_tag is doing this.
*/
enum {
+ /* Special case: Library, should never ever depend on any other type. */
INDEX_ID_LI = 0,
- INDEX_ID_IP,
+
+ /* Animation types, might be used by almost all other types. */
+ INDEX_ID_IP, /* Deprecated. */
INDEX_ID_AC,
- INDEX_ID_KE,
- INDEX_ID_PAL,
+
+ /* Grease Pencil, special case, should be with the other obdata, but it can also be used by many
+ * other ID types, including node trees e.g.
+ * So there is no proper place for those, for now keep close to the lower end of the processing
+ * hierarchy, but we may want to re-evaluate that at some point. */
INDEX_ID_GD,
+
+ /* Node trees, abstraction for procedural data, potentially used by many other ID types.
+ *
+ * NOTE: While node trees can also use many other ID types, they should not /own/ any of those,
+ * while they are being owned by many other ID types. This is why they are placed here. */
INDEX_ID_NT,
+
+ /* File-wrapper types, those usually 'embed' external files in Blender, with no dependencies to
+ * other ID types. */
+ INDEX_ID_VF,
+ INDEX_ID_TXT,
+ INDEX_ID_SO,
+
+ /* Image/movie types, can be used by shading ID types, but also directly by Objects, Scenes, etc.
+ */
+ INDEX_ID_MSK,
INDEX_ID_IM,
+ INDEX_ID_MC,
+
+ /* Shading types. */
INDEX_ID_TE,
INDEX_ID_MA,
- INDEX_ID_VF,
- INDEX_ID_AR,
+ INDEX_ID_LS,
+ INDEX_ID_WO,
+
+ /* Simulation-related types. */
INDEX_ID_CF,
+ INDEX_ID_SIM,
+ INDEX_ID_PA,
+
+ /* Shape Keys snow-flake, can be used by several obdata types. */
+ INDEX_ID_KE,
+
+ /* Object data types. */
+ INDEX_ID_AR,
INDEX_ID_ME,
INDEX_ID_CU,
INDEX_ID_MB,
@@ -785,26 +819,28 @@ enum {
INDEX_ID_LT,
INDEX_ID_LA,
INDEX_ID_CA,
- INDEX_ID_TXT,
- INDEX_ID_SO,
- INDEX_ID_GR,
- INDEX_ID_PC,
- INDEX_ID_BR,
- INDEX_ID_PA,
INDEX_ID_SPK,
INDEX_ID_LP,
- INDEX_ID_WO,
- INDEX_ID_MC,
- INDEX_ID_SCR,
+
+ /* Collection and object types. */
INDEX_ID_OB,
- INDEX_ID_LS,
+ INDEX_ID_GR,
+
+ /* Preset-like, not-really-data types, can use many other ID types but should never be used by
+ * any actual data type (besides Scene, due to tool settings). */
+ INDEX_ID_PAL,
+ INDEX_ID_PC,
+ INDEX_ID_BR,
+
+ /* Scene, after preset-like ID types because of tool settings. */
INDEX_ID_SCE,
+
+ /* UI-related types, should never be used by any other data type. */
+ INDEX_ID_SCR,
INDEX_ID_WS,
INDEX_ID_WM,
- /* TODO: This should probably be tweaked, #Mask and #Simulation are rather low-level types that
- * should most likely be defined //before// #Object and geometry type indices? */
- INDEX_ID_MSK,
- INDEX_ID_SIM,
+
+ /* Special values. */
INDEX_ID_NULL,
INDEX_ID_MAX,
};
diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h
index 09304ce09f2..85780bc33c5 100644
--- a/source/blender/makesdna/DNA_armature_types.h
+++ b/source/blender/makesdna/DNA_armature_types.h
@@ -134,7 +134,7 @@ typedef struct bArmature {
/** ID data is older than edit-mode data (TODO: move to edit-mode struct). */
char needs_flush_to_id;
- char _pad0[7];
+ char _pad0[3];
int flag;
int drawtype;
@@ -146,6 +146,9 @@ typedef struct bArmature {
unsigned int layer_used;
/** For buttons to work, both variables in this order together. */
unsigned int layer, layer_protected;
+
+ /** Relative position of the axes on the bone, from head (0.0f) to tail (1.0f). */
+ float axes_position;
} bArmature;
/* armature->flag */
@@ -230,8 +233,10 @@ typedef enum eBone_Flag {
BONE_MULT_VG_ENV = (1 << 11),
/** bone doesn't deform geometry */
BONE_NO_DEFORM = (1 << 12),
+#ifdef DNA_DEPRECATED_ALLOW
/** set to prevent destruction of its unkeyframed pose (after transform) */
BONE_UNKEYED = (1 << 13),
+#endif
/** set to prevent hinge child bones from influencing the transform center */
BONE_HINGE_CHILD_TRANSFORM = (1 << 14),
#ifdef DNA_DEPRECATED_ALLOW
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 4f914089347..ff2e7fc500a 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -72,7 +72,7 @@ typedef struct BevPoint {
float sina, cosa;
/** 3D Only. */
float dir[3], tan[3], quat[4];
- short split_tag, dupe_tag;
+ short dupe_tag;
} BevPoint;
/* These two Lines with # tell makesdna this struct can be excluded. */
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index f24d0e40d19..7b4788737f8 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -715,6 +715,12 @@ typedef struct NodeBilateralBlurData {
char _pad[2];
} NodeBilateralBlurData;
+typedef struct NodeAntiAliasingData {
+ float threshold;
+ float contrast_limit;
+ float corner_rounding;
+} NodeAntiAliasingData;
+
/* NOTE: Only for do-version code. */
typedef struct NodeHueSat {
float hue, sat, val;
@@ -1108,6 +1114,14 @@ typedef struct NodeDenoise {
char hdr;
} NodeDenoise;
+typedef struct NodeAttributeClamp {
+ /* CustomDataType. */
+ uint8_t data_type;
+
+ /* NodeClampOperation. */
+ uint8_t operation;
+} NodeAttributeClamp;
+
typedef struct NodeAttributeCompare {
/* FloatCompareOperation. */
uint8_t operation;
@@ -1119,6 +1133,14 @@ typedef struct NodeAttributeCompare {
char _pad[5];
} NodeAttributeCompare;
+typedef struct NodeAttributeMapRange {
+ /* GeometryNodeAttributeDataType */
+ uint8_t data_type;
+
+ /* NodeMapRangeType. */
+ uint8_t interpolation_type;
+} NodeAttributeMapRange;
+
typedef struct NodeAttributeMath {
/* NodeMathOperation. */
uint8_t operation;
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 4595b12e9d4..334669d3433 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -646,7 +646,8 @@ typedef struct UserDef_Experimental {
char use_switch_object_operator;
char use_sculpt_tools_tilt;
char use_asset_browser;
- char _pad[6];
+ char use_override_templates;
+ char _pad[5];
/** `makesdna` does not allow empty structs. */
} UserDef_Experimental;
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index b8e2256c3c6..2f4e4e57b9f 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -367,7 +367,7 @@ typedef struct View3D {
#define V3D_LOCAL_COLLECTIONS (1 << 0)
#define V3D_FLAG_UNUSED_1 (1 << 1) /* cleared */
#define V3D_HIDE_HELPLINES (1 << 2)
-#define V3D_INVALID_BACKBUF (1 << 3)
+#define V3D_FLAG_UNUSED_2 (1 << 3) /* cleared */
#define V3D_XR_SESSION_MIRROR (1 << 4)
#define V3D_FLAG_UNUSED_10 (1 << 10) /* cleared */
@@ -380,6 +380,8 @@ typedef struct View3D {
enum {
/** The 3D view which the XR session was created in is flagged with this. */
V3D_RUNTIME_XR_SESSION_ROOT = (1 << 0),
+ /** Some operators override the depth buffer for dedicated occlusion operations. */
+ V3D_RUNTIME_DEPTHBUF_OVERRIDDEN = (1 << 1),
};
/** #RegionView3D.persp */
diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c
index 3690a1126d4..d199638710d 100644
--- a/source/blender/makesdna/intern/dna_genfile.c
+++ b/source/blender/makesdna/intern/dna_genfile.c
@@ -1194,7 +1194,10 @@ static void reconstruct_struct(const DNA_ReconstructInfo *reconstruct_info,
new_block + step->data.substruct.new_offset);
break;
case RECONSTRUCT_STEP_INIT_ZERO:
- /* Do nothing, because the memory block has been calloced. */
+ /* Do nothing, because the memory block are zeroed (from #MEM_callocN).
+ *
+ * Note that the struct could be initialized with the default struct,
+ * however this complicates versioning, especially with flags, see: D4500. */
break;
}
}
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index c4f6707dad5..78192f937e6 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -619,7 +619,7 @@ typedef enum StructFlag {
/** Indicates that this struct is an ID struct, and to use reference-counting. */
STRUCT_ID = (1 << 0),
STRUCT_ID_REFCOUNT = (1 << 1),
- /** defaults on, clear for user preferences and similar */
+ /** defaults on, indicates when changes in members of a StructRNA should trigger undo steps. */
STRUCT_UNDO = (1 << 2),
/* internal flags */
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index d51fcba410a..f750ea8f665 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -85,6 +85,47 @@ const EnumPropertyItem rna_enum_id_type_items[] = {
{0, NULL, 0, NULL, NULL},
};
+static const EnumPropertyItem rna_enum_override_library_property_operation_items[] = {
+ {IDOVERRIDE_LIBRARY_OP_NOOP,
+ "NOOP",
+ 0,
+ "No-Op",
+ "Does nothing, prevents adding actual overrides (NOT USED)"},
+ {IDOVERRIDE_LIBRARY_OP_REPLACE,
+ "REPLACE",
+ 0,
+ "Replace",
+ "Replace value of reference by overriding one"},
+ {IDOVERRIDE_LIBRARY_OP_ADD,
+ "DIFF_ADD",
+ 0,
+ "Differential",
+ "Stores and apply difference between reference and local value (NOT USED)"},
+ {IDOVERRIDE_LIBRARY_OP_SUBTRACT,
+ "DIFF_SUB",
+ 0,
+ "Differential",
+ "Stores and apply difference between reference and local value (NOT USED)"},
+ {IDOVERRIDE_LIBRARY_OP_MULTIPLY,
+ "FACT_MULTIPLY",
+ 0,
+ "Factor",
+ "Stores and apply multiplication factor between reference and local value (NOT USED)"},
+ {IDOVERRIDE_LIBRARY_OP_INSERT_AFTER,
+ "INSERT_AFTER",
+ 0,
+ "Insert After",
+ "Insert a new item into collection after the one referenced in subitem_reference_name or "
+ "_index"},
+ {IDOVERRIDE_LIBRARY_OP_INSERT_BEFORE,
+ "INSERT_BEFORE",
+ 0,
+ "Insert Before",
+ "Insert a new item into collection after the one referenced in subitem_reference_name or "
+ "_index (NOT USED)"},
+ {0, NULL, 0, NULL, NULL},
+};
+
/**
* \note Uses #IDFilterEnumPropertyItem, not EnumPropertyItem to support 64 bit items.
*/
@@ -643,6 +684,65 @@ static ID *rna_ID_override_create(ID *id, Main *bmain, bool remap_local_usages)
return local_id;
}
+static void rna_ID_override_template_create(ID *id, ReportList *reports)
+{
+ if (!U.experimental.use_override_templates) {
+ BKE_report(reports, RPT_ERROR, "Override template experimental feature is disabled");
+ return;
+ }
+ if (ID_IS_LINKED(id)) {
+ BKE_report(reports, RPT_ERROR, "Unable to create override template for linked data-blocks");
+ return;
+ }
+ if (ID_IS_OVERRIDE_LIBRARY(id)) {
+ BKE_report(
+ reports, RPT_ERROR, "Unable to create override template for overridden data-blocks");
+ return;
+ }
+ BKE_lib_override_library_template_create(id);
+}
+
+static IDOverrideLibraryProperty *rna_ID_override_library_properties_add(
+ IDOverrideLibrary *override_library, ReportList *reports, const char rna_path[])
+{
+ bool created;
+ IDOverrideLibraryProperty *result = BKE_lib_override_library_property_get(
+ override_library, rna_path, &created);
+
+ if (!created) {
+ BKE_report(reports, RPT_DEBUG, "No new override property created, property already exists");
+ }
+
+ return result;
+}
+
+static IDOverrideLibraryPropertyOperation *rna_ID_override_library_property_operations_add(
+ IDOverrideLibraryProperty *override_property,
+ ReportList *reports,
+ int operation,
+ const char *subitem_refname,
+ const char *subitem_locname,
+ int subitem_refindex,
+ int subitem_locindex)
+{
+ bool created;
+ bool strict;
+ IDOverrideLibraryPropertyOperation *result = BKE_lib_override_library_property_operation_get(
+ override_property,
+ operation,
+ subitem_refname,
+ subitem_locname,
+ subitem_refindex,
+ subitem_locindex,
+ false,
+ &strict,
+ &created);
+ if (!created) {
+ BKE_report(reports, RPT_DEBUG, "No new override operation created, operation already exists");
+ }
+ return result;
+}
+
static void rna_ID_update_tag(ID *id, Main *bmain, ReportList *reports, int flag)
{
/* XXX, new function for this! */
@@ -1358,47 +1458,6 @@ static void rna_def_ID_override_library_property_operation(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
- static const EnumPropertyItem override_library_property_operation_items[] = {
- {IDOVERRIDE_LIBRARY_OP_NOOP,
- "NOOP",
- 0,
- "No-Op",
- "Does nothing, prevents adding actual overrides (NOT USED)"},
- {IDOVERRIDE_LIBRARY_OP_REPLACE,
- "REPLACE",
- 0,
- "Replace",
- "Replace value of reference by overriding one"},
- {IDOVERRIDE_LIBRARY_OP_ADD,
- "DIFF_ADD",
- 0,
- "Differential",
- "Stores and apply difference between reference and local value (NOT USED)"},
- {IDOVERRIDE_LIBRARY_OP_SUBTRACT,
- "DIFF_SUB",
- 0,
- "Differential",
- "Stores and apply difference between reference and local value (NOT USED)"},
- {IDOVERRIDE_LIBRARY_OP_MULTIPLY,
- "FACT_MULTIPLY",
- 0,
- "Factor",
- "Stores and apply multiplication factor between reference and local value (NOT USED)"},
- {IDOVERRIDE_LIBRARY_OP_INSERT_AFTER,
- "INSERT_AFTER",
- 0,
- "Insert After",
- "Insert a new item into collection after the one referenced in subitem_reference_name or "
- "_index"},
- {IDOVERRIDE_LIBRARY_OP_INSERT_BEFORE,
- "INSERT_BEFORE",
- 0,
- "Insert Before",
- "Insert a new item into collection after the one referenced in subitem_reference_name or "
- "_index (NOT USED)"},
- {0, NULL, 0, NULL, NULL},
- };
-
static const EnumPropertyItem override_library_property_flag_items[] = {
{IDOVERRIDE_LIBRARY_FLAG_MANDATORY,
"MANDATORY",
@@ -1420,7 +1479,7 @@ static void rna_def_ID_override_library_property_operation(BlenderRNA *brna)
prop = RNA_def_enum(srna,
"operation",
- override_library_property_operation_items,
+ rna_enum_override_library_property_operation_items,
IDOVERRIDE_LIBRARY_OP_REPLACE,
"Operation",
"What override operation is performed");
@@ -1477,6 +1536,66 @@ static void rna_def_ID_override_library_property_operation(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* For now. */
}
+static void rna_def_ID_override_library_property_operations(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "IDOverrideLibraryPropertyOperations");
+ srna = RNA_def_struct(brna, "IDOverrideLibraryPropertyOperations", NULL);
+ RNA_def_struct_sdna(srna, "IDOverrideLibraryProperty");
+ RNA_def_struct_ui_text(srna, "Override Operations", "Collection of override operations");
+
+ /* Add Property */
+ func = RNA_def_function(srna, "add", "rna_ID_override_library_property_operations_add");
+ RNA_def_function_ui_description(func, "Add a new operation");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_enum(func,
+ "operation",
+ rna_enum_override_library_property_operation_items,
+ IDOVERRIDE_LIBRARY_OP_REPLACE,
+ "Operation",
+ "What override operation is performed");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_string(func,
+ "subitem_reference_name",
+ NULL,
+ INT_MAX,
+ "Subitem Reference Name",
+ "Used to handle insertions into collection");
+ parm = RNA_def_string(func,
+ "subitem_local_name",
+ NULL,
+ INT_MAX,
+ "Subitem Local Name",
+ "Used to handle insertions into collection");
+ parm = RNA_def_int(func,
+ "subitem_reference_index",
+ -1,
+ -1,
+ INT_MAX,
+ "Subitem Reference Index",
+ "Used to handle insertions into collection",
+ -1,
+ INT_MAX);
+ parm = RNA_def_int(func,
+ "subitem_local_index",
+ -1,
+ -1,
+ INT_MAX,
+ "Subitem Local Index",
+ "Used to handle insertions into collection",
+ -1,
+ INT_MAX);
+ parm = RNA_def_pointer(func,
+ "property",
+ "IDOverrideLibraryPropertyOperation",
+ "New Operation",
+ "Created operation");
+ RNA_def_function_return(func, parm);
+}
+
static void rna_def_ID_override_library_property(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1496,18 +1615,47 @@ static void rna_def_ID_override_library_property(BlenderRNA *brna)
"RNA path leading to that property, from owning ID");
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* For now. */
- RNA_def_collection(srna,
- "operations",
- "IDOverrideLibraryPropertyOperation",
- "Operations",
- "List of overriding operations for a property");
+ prop = RNA_def_collection(srna,
+ "operations",
+ "IDOverrideLibraryPropertyOperation",
+ "Operations",
+ "List of overriding operations for a property");
+ rna_def_ID_override_library_property_operations(brna, prop);
rna_def_ID_override_library_property_operation(brna);
}
+static void rna_def_ID_override_library_properties(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "IDOverrideLibraryProperties");
+ srna = RNA_def_struct(brna, "IDOverrideLibraryProperties", NULL);
+ RNA_def_struct_sdna(srna, "IDOverrideLibrary");
+ RNA_def_struct_ui_text(srna, "Override Properties", "Collection of override properties");
+
+ /* Add Property */
+ func = RNA_def_function(srna, "add", "rna_ID_override_library_properties_add");
+ RNA_def_function_ui_description(
+ func, "Add a property to the override library when it doesn't exist yet");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func,
+ "property",
+ "IDOverrideLibraryProperty",
+ "New Property",
+ "Newly created override property or existing one");
+ RNA_def_function_return(func, parm);
+ parm = RNA_def_string(
+ func, "rna_path", NULL, 256, "RNA Path", "RNA-Path of the property to add");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+}
+
static void rna_def_ID_override_library(BlenderRNA *brna)
{
StructRNA *srna;
+ PropertyRNA *prop;
srna = RNA_def_struct(brna, "IDOverrideLibrary", NULL);
RNA_def_struct_ui_text(
@@ -1516,11 +1664,12 @@ static void rna_def_ID_override_library(BlenderRNA *brna)
RNA_def_pointer(
srna, "reference", "ID", "Reference ID", "Linked ID used as reference by this override");
- RNA_def_collection(srna,
- "properties",
- "IDOverrideLibraryProperty",
- "Properties",
- "List of overridden properties");
+ prop = RNA_def_collection(srna,
+ "properties",
+ "IDOverrideLibraryProperty",
+ "Properties",
+ "List of overridden properties");
+ rna_def_ID_override_library_properties(brna, prop);
rna_def_ID_override_library_property(brna);
}
@@ -1672,6 +1821,10 @@ static void rna_def_ID(BlenderRNA *brna)
"Whether local usages of the linked ID should be remapped to the new "
"library override of it");
+ func = RNA_def_function(srna, "override_template_create", "rna_ID_override_template_create");
+ RNA_def_function_ui_description(func, "Create an override template for this ID");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+
func = RNA_def_function(srna, "user_clear", "rna_ID_user_clear");
RNA_def_function_ui_description(func,
"Clear the user count of a data-block so its not saved, "
diff --git a/source/blender/makesrna/intern/rna_access_compare_override.c b/source/blender/makesrna/intern/rna_access_compare_override.c
index 80833d4f992..39e7774e5a4 100644
--- a/source/blender/makesrna/intern/rna_access_compare_override.c
+++ b/source/blender/makesrna/intern/rna_access_compare_override.c
@@ -1098,6 +1098,10 @@ static void rna_property_override_check_resync(Main *bmain,
ID *id_dst = rna_property_override_property_real_id_owner(bmain, ptr_item_dst, NULL, NULL);
BLI_assert(id_src == NULL || ID_IS_OVERRIDE_LIBRARY_REAL(id_src));
+ /* Work around file corruption on writing, see T86853. */
+ if (id_src != NULL && !ID_IS_OVERRIDE_LIBRARY_REAL(id_src)) {
+ return;
+ }
if (/* We might be in a case where id_dst has already been processed and its usages
* remapped to its new local override. In that case overrides and linked data
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index 69ddcee60fa..fb9f5e0292e 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -407,8 +407,10 @@ static void rna_def_dopesheet(BlenderRNA *brna)
/* Multi-word fuzzy search option for name/text filters */
prop = RNA_def_property(srna, "use_multi_word_filter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ADS_FLAG_FUZZY_NAMES);
- RNA_def_property_ui_text(
- prop, "Multi-Word Fuzzy Filter", "Perform fuzzy/multi-word matching (WARNING: May be slow)");
+ RNA_def_property_ui_text(prop,
+ "Multi-Word Fuzzy Filter",
+ "Perform fuzzy/multi-word matching.\n"
+ "Warning: May be slow");
RNA_def_property_ui_icon(prop, ICON_SORTALPHA, 0);
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
diff --git a/source/blender/makesrna/intern/rna_action_api.c b/source/blender/makesrna/intern/rna_action_api.c
index 48da32afba5..308a34f9cf1 100644
--- a/source/blender/makesrna/intern/rna_action_api.c
+++ b/source/blender/makesrna/intern/rna_action_api.c
@@ -41,10 +41,32 @@
# include "DNA_anim_types.h"
# include "DNA_curve_types.h"
+static void rna_Action_flip_with_pose(bAction *act, ReportList *reports, Object *ob)
+{
+ if (ob->type != OB_ARMATURE) {
+ BKE_report(reports, RPT_ERROR, "Only armature objects are supported");
+ return;
+ }
+ BKE_action_flip_with_pose(act, ob);
+
+ /* Only for redraw. */
+ WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+}
+
#else
-void RNA_api_action(StructRNA *UNUSED(srna))
+void RNA_api_action(StructRNA *srna)
{
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ func = RNA_def_function(srna, "flip_with_pose", "rna_Action_flip_with_pose");
+ RNA_def_function_ui_description(func, "Flip the action around the X axis using a pose");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+
+ parm = RNA_def_pointer(
+ func, "object", "Object", "", "The reference armature object to use when flipping");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 554f04ca23c..c54621372ba 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -1537,6 +1537,16 @@ static void rna_def_armature(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Armature_redraw_data");
RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+ prop = RNA_def_property(srna, "axes_position", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "axes_position");
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 10, 1);
+ RNA_def_property_ui_text(prop,
+ "Axes Position",
+ "The position for the axes on the bone. Increasing the value moves it "
+ "closer to the tip; decreasing moves it closer to the root");
+ RNA_def_property_update(prop, 0, "rna_Armature_redraw_data");
+
prop = RNA_def_property(srna, "show_names", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_DRAWNAMES);
RNA_def_property_ui_text(prop, "Display Names", "Display bone names");
diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c
index 8e3d2c9b9a2..7976df3e4e4 100644
--- a/source/blender/makesrna/intern/rna_attribute.c
+++ b/source/blender/makesrna/intern/rna_attribute.c
@@ -54,8 +54,8 @@ const EnumPropertyItem rna_enum_attribute_domain_items[] = {
// {ATTR_DOMAIN_GEOMETRY, "GEOMETRY", 0, "Geometry", "Attribute on (whole) geometry"},
{ATTR_DOMAIN_POINT, "POINT", 0, "Point", "Attribute on point"},
{ATTR_DOMAIN_EDGE, "EDGE", 0, "Edge", "Attribute on mesh edge"},
- {ATTR_DOMAIN_CORNER, "CORNER", 0, "Corner", "Attribute on mesh polygon corner"},
- {ATTR_DOMAIN_POLYGON, "POLYGON", 0, "Polygon", "Attribute on mesh polygons"},
+ {ATTR_DOMAIN_FACE, "FACE", 0, "Face", "Attribute on mesh faces"},
+ {ATTR_DOMAIN_CORNER, "CORNER", 0, "Face Corner", "Attribute on mesh face corner"},
/* Not implement yet */
// {ATTR_DOMAIN_GRIDS, "GRIDS", 0, "Grids", "Attribute on mesh multires grids"},
{ATTR_DOMAIN_CURVE, "CURVE", 0, "Curve", "Attribute on hair curve"},
@@ -66,8 +66,8 @@ const EnumPropertyItem rna_enum_attribute_domain_with_auto_items[] = {
{ATTR_DOMAIN_AUTO, "AUTO", 0, "Auto", ""},
{ATTR_DOMAIN_POINT, "POINT", 0, "Point", "Attribute on point"},
{ATTR_DOMAIN_EDGE, "EDGE", 0, "Edge", "Attribute on mesh edge"},
- {ATTR_DOMAIN_CORNER, "CORNER", 0, "Corner", "Attribute on mesh polygon corner"},
- {ATTR_DOMAIN_POLYGON, "POLYGON", 0, "Polygon", "Attribute on mesh polygons"},
+ {ATTR_DOMAIN_FACE, "FACE", 0, "Face", "Attribute on mesh faces"},
+ {ATTR_DOMAIN_CORNER, "CORNER", 0, "Face Corner", "Attribute on mesh face corner"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c
index 36d39c5c201..85071e8cd19 100644
--- a/source/blender/makesrna/intern/rna_depsgraph.c
+++ b/source/blender/makesrna/intern/rna_depsgraph.c
@@ -505,11 +505,10 @@ static void rna_def_depsgraph_instance(BlenderRNA *brna)
PropertyRNA *prop;
srna = RNA_def_struct(brna, "DepsgraphObjectInstance", NULL);
- RNA_def_struct_ui_text(
- srna,
- "Dependency Graph Object Instance",
- "Extended information about dependency graph object iterator "
- "(WARNING: all data here is *evaluated* one, not original .blend IDs...)");
+ RNA_def_struct_ui_text(srna,
+ "Dependency Graph Object Instance",
+ "Extended information about dependency graph object iterator "
+ "(Warning: All data here is 'evaluated' one, not original .blend IDs)");
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Object");
@@ -773,7 +772,7 @@ static void rna_def_depsgraph(BlenderRNA *brna)
RNA_def_property_ui_text(prop,
"Object Instances",
"All object instances to display or render "
- "(WARNING: only use this as an iterator, never as a sequence, "
+ "(Warning: Only use this as an iterator, never as a sequence, "
"and do not keep any references to its items)");
prop = RNA_def_property(srna, "updates", PROP_COLLECTION, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index 0aa2e652d2d..6c6f18ab5a4 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -452,7 +452,7 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -585,7 +585,7 @@ static void rna_def_modifier_gpencilsmooth(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -698,7 +698,7 @@ static void rna_def_modifier_gpencilsubdiv(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -788,7 +788,7 @@ static void rna_def_modifier_gpencilsimplify(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -877,7 +877,7 @@ static void rna_def_modifier_gpencilthick(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -971,7 +971,7 @@ static void rna_def_modifier_gpenciloffset(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -1069,7 +1069,7 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -1273,7 +1273,7 @@ static void rna_def_modifier_gpencilcolor(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -1364,7 +1364,7 @@ static void rna_def_modifier_gpencilopacity(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -1460,7 +1460,7 @@ static void rna_def_modifier_gpencilarray(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -1759,7 +1759,7 @@ static void rna_def_modifier_gpencillattice(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -1838,7 +1838,7 @@ static void rna_def_modifier_gpencilmirror(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -1936,7 +1936,7 @@ static void rna_def_modifier_gpencilhook(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -2093,7 +2093,7 @@ static void rna_def_modifier_gpencilmultiply(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -2216,7 +2216,7 @@ static void rna_def_modifier_gpenciltexture(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -2466,7 +2466,7 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "target_material", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "Material");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 98a2b683f18..67335b81a31 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -5920,8 +5920,9 @@ static void rna_def_modifier_triangulate(BlenderRNA *brna)
RNA_def_property_ui_text(
prop,
"Keep Normals",
- "Try to preserve custom normals (WARNING: depending on chosen triangulation method, "
- "shading may not be fully preserved, 'Fixed' method usually gives the best result here)");
+ "Try to preserve custom normals.\n"
+ "Warning: Depending on chosen triangulation method, "
+ "shading may not be fully preserved, \"Fixed\" method usually gives the best result here");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
RNA_define_lib_overridable(false);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index d69a1e3dd06..277cfada44d 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -329,8 +329,12 @@ const EnumPropertyItem rna_enum_node_map_range_items[] = {
};
const EnumPropertyItem rna_enum_node_clamp_items[] = {
- {NODE_CLAMP_MINMAX, "MINMAX", 0, "Min Max", "Clamp values using Min and Max values"},
- {NODE_CLAMP_RANGE, "RANGE", 0, "Range", "Clamp values between Min and Max range"},
+ {NODE_CLAMP_MINMAX, "MINMAX", 0, "Min Max", "Constrain value between min and max"},
+ {NODE_CLAMP_RANGE,
+ "RANGE",
+ 0,
+ "Range",
+ "Constrain value between min and max, swapping arguments when min > max"},
{0, NULL, 0, NULL, NULL},
};
@@ -1886,6 +1890,19 @@ static const EnumPropertyItem *itemf_function_check(
return item_array;
}
+static bool attribute_clamp_type_supported(const EnumPropertyItem *item)
+{
+ return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3, CD_PROP_INT32, CD_PROP_COLOR);
+}
+static const EnumPropertyItem *rna_GeometryNodeAttributeClamp_type_itemf(bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ *r_free = true;
+ return itemf_function_check(rna_enum_attribute_type_items, attribute_clamp_type_supported);
+}
+
static bool attribute_random_type_supported(const EnumPropertyItem *item)
{
return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3, CD_PROP_BOOL, CD_PROP_INT32);
@@ -2065,6 +2082,17 @@ static void rna_GeometryNodeAttributeVectorMath_operation_update(Main *bmain,
rna_Node_socket_update(bmain, scene, ptr);
}
+static bool attribute_map_range_type_supported(const EnumPropertyItem *item)
+{
+ return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3);
+}
+static const EnumPropertyItem *rna_GeometryNodeAttributeMapRange_type_itemf(
+ bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ *r_free = true;
+ return itemf_function_check(rna_enum_attribute_type_items, attribute_map_range_type_supported);
+}
+
static StructRNA *rna_ShaderNode_register(Main *bmain,
ReportList *reports,
void *data,
@@ -8634,6 +8662,41 @@ static void def_cmp_denoise(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_cmp_antialiasing(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeAntiAliasingData", "storage");
+
+ prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "threshold");
+ RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+ RNA_def_property_ui_text(
+ prop,
+ "Threshold",
+ "Threshold to detect edges (smaller threshold makes more sensitive detection)");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "contrast_limit", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "contrast_limit");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+ RNA_def_property_ui_text(
+ prop,
+ "Contrast Limit",
+ "How much to eliminate spurious edges to avoid artifacts (the larger value makes less "
+ "active; the value 2.0, for example, means discard a detected edge if there is a "
+ "neighboring edge that has 2.0 times bigger contrast than the current one)");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "corner_rounding", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "corner_rounding");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+ RNA_def_property_ui_text(prop, "Corner Rounding", "How much sharp corners will be rounded");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
/* -- Texture Nodes --------------------------------------------------------- */
static void def_tex_output(StructRNA *srna)
@@ -8915,6 +8978,26 @@ static void def_geo_attribute_vector_math(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
+static void def_geo_attribute_map_range(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeAttributeMapRange", "storage");
+
+ prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "data_type");
+ RNA_def_property_enum_items(prop, rna_enum_attribute_type_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeMapRange_type_itemf");
+ RNA_def_property_ui_text(prop, "Data Type", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+
+ prop = RNA_def_property(srna, "interpolation_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "interpolation_type");
+ RNA_def_property_enum_items(prop, rna_enum_node_map_range_items);
+ RNA_def_property_ui_text(prop, "Interpolation Type", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
+}
+
static void def_geo_point_instance(StructRNA *srna)
{
static const EnumPropertyItem instance_type_items[] = {
@@ -8975,6 +9058,26 @@ static void def_geo_attribute_mix(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
+static void def_geo_attribute_clamp(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeAttributeClamp", "storage");
+
+ prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "data_type");
+ RNA_def_property_enum_items(prop, rna_enum_attribute_type_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeClamp_type_itemf");
+ RNA_def_property_ui_text(prop, "Data Type", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+
+ prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_enum_node_clamp_items);
+ RNA_def_property_enum_default(prop, NODE_CLAMP_MINMAX);
+ RNA_def_property_ui_text(prop, "Operation", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
static void def_geo_attribute_attribute_compare(StructRNA *srna)
{
PropertyRNA *prop;
@@ -9594,6 +9697,12 @@ static void rna_def_node_socket(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Linked", "True if the socket is connected");
+ prop = RNA_def_property(srna, "is_multi_input", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_MULTI_INPUT);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(
+ prop, "Multi Input", "True if the socket can accept multiple ordered input links");
+
prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SOCK_COLLAPSED);
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index b04fea11a4d..21e9328d043 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -160,6 +160,7 @@ const EnumPropertyItem rna_enum_object_gpencil_type_items[] = {
{GP_EMPTY, "EMPTY", ICON_EMPTY_AXIS, "Blank", "Create an empty grease pencil object"},
{GP_STROKE, "STROKE", ICON_STROKE, "Stroke", "Create a simple stroke with basic colors"},
{GP_MONKEY, "MONKEY", ICON_MONKEY, "Monkey", "Construct a Suzanne grease pencil object"},
+ {0, "", 0, NULL, NULL},
{GP_LRT_SCENE,
"LRT_SCENE",
ICON_SCENE_DATA,
@@ -2797,6 +2798,7 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_multi_array(prop, 2, boundbox_dimsize);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_override_clear_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
RNA_def_property_float_funcs(prop, "rna_Object_boundbox_get", NULL, NULL);
RNA_def_property_ui_text(
prop,
@@ -2967,12 +2969,11 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_float_funcs(
prop, "rna_Object_dimensions_get", "rna_Object_dimensions_set", NULL);
RNA_def_property_ui_range(prop, 0.0f, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
- RNA_def_property_ui_text(
- prop,
- "Dimensions",
- "Absolute bounding box dimensions of the object (WARNING: assigning to it or "
- "its members multiple consecutive times will not work correctly, "
- "as this needs up-to-date evaluated data)");
+ RNA_def_property_ui_text(prop,
+ "Dimensions",
+ "Absolute bounding box dimensions of the object.\n"
+ "Warning: Assigning to it or its members multiple consecutive times "
+ "will not work correctly, as this needs up-to-date evaluated data");
RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update");
/* delta transforms */
@@ -3075,8 +3076,8 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_ui_text(
prop,
"Local Matrix",
- "Parent relative transformation matrix - "
- "WARNING: Only takes into account 'Object' parenting, so e.g. in case of bone parenting "
+ "Parent relative transformation matrix.\n"
+ "Warning: Only takes into account object parenting, so e.g. in case of bone parenting "
"you get a matrix relative to the Armature object, not to the actual parent bone");
RNA_def_property_float_funcs(
prop, "rna_Object_matrix_local_get", "rna_Object_matrix_local_set", NULL);
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index d8336e79064..f7a7b745493 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -20,6 +20,8 @@
#include <stdlib.h>
+#include <CLG_log.h>
+
#include "DNA_ID.h"
#include "BLI_utildefines.h"
@@ -132,6 +134,8 @@ const EnumPropertyItem rna_enum_property_unit_items[] = {
# include "BKE_idprop.h"
# include "BKE_lib_override.h"
+static CLG_LogRef LOG_COMPARE_OVERRIDE = {"rna.rna_compare_override"};
+
/* Struct */
static void rna_Struct_identifier_get(PointerRNA *ptr, char *value)
@@ -1366,11 +1370,11 @@ static int rna_property_override_diff_propptr(Main *bmain,
/* In case one of the owner of the checked property is tagged as needing resync, do
* not change the 'match reference' status of its ID pointer properties overrides,
* since many non-matching ones are likely due to missing resync. */
- printf(
- "%s: Not checking matching ID pointer properties, since owner %s is tagged as "
- "needing resync.\n",
- __func__,
- id_a->name);
+ CLOG_INFO(&LOG_COMPARE_OVERRIDE,
+ 4,
+ "Not checking matching ID pointer properties, since owner %s is tagged as "
+ "needing resync.\n",
+ id_a->name);
}
else if (id_a->override_library != NULL && id_a->override_library->reference == id_b) {
opop->flag |= IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE;
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 3344b8c286d..65643aa92d7 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -2685,6 +2685,7 @@ static void rna_def_view3d_cursor(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_View3DCursor_path");
RNA_def_struct_ui_text(srna, "3D Cursor", "");
RNA_def_struct_ui_icon(srna, ICON_CURSOR);
+ RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_XYZ_LENGTH);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
@@ -2855,7 +2856,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_normalize", 1);
RNA_def_property_ui_text(prop,
- "WPaint Auto-Normalize",
+ "Weight Paint Auto-Normalize",
"Ensure all bone-deforming vertex groups add up "
"to 1.0 while weight painting");
RNA_def_property_update(prop, 0, "rna_Scene_update_active_object_data");
@@ -2864,7 +2865,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_boolean_sdna(prop, NULL, "wpaint_lock_relative", 1);
RNA_def_property_ui_text(prop,
- "WPaint Lock-Relative",
+ "Weight Paint Lock-Relative",
"Display bone-deforming groups as if all locked deform groups "
"were deleted, and the remaining ones were re-normalized");
RNA_def_property_update(prop, 0, "rna_Scene_update_active_object_data");
@@ -2873,7 +2874,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_boolean_sdna(prop, NULL, "multipaint", 1);
RNA_def_property_ui_text(prop,
- "WPaint Multi-Paint",
+ "Weight Paint Multi-Paint",
"Paint across the weights of all selected bones, "
"maintaining their relative influence");
RNA_def_property_update(prop, 0, "rna_Scene_update_active_object_data");
diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c
index a49a404fe6c..8aab0c079a3 100644
--- a/source/blender/makesrna/intern/rna_sequencer_api.c
+++ b/source/blender/makesrna/intern/rna_sequencer_api.c
@@ -224,13 +224,15 @@ static Sequence *rna_Sequences_new_image(ID *id,
const char *name,
const char *file,
int channel,
- int frame_start)
+ int frame_start,
+ int fit_method)
{
Scene *scene = (Scene *)id;
SeqLoadData load_data;
SEQ_add_load_data_init(&load_data, name, file, frame_start, channel);
load_data.image.len = 1;
+ load_data.fit_method = fit_method;
Sequence *seq = SEQ_add_image_strip(bmain, scene, seqbase, &load_data);
char dir[FILE_MAX], filename[FILE_MAX];
@@ -253,10 +255,11 @@ static Sequence *rna_Sequences_editing_new_image(ID *id,
const char *name,
const char *file,
int channel,
- int frame_start)
+ int frame_start,
+ int fit_method)
{
return rna_Sequences_new_image(
- id, &ed->seqbase, bmain, reports, name, file, channel, frame_start);
+ id, &ed->seqbase, bmain, reports, name, file, channel, frame_start, fit_method);
}
static Sequence *rna_Sequences_meta_new_image(ID *id,
@@ -266,10 +269,11 @@ static Sequence *rna_Sequences_meta_new_image(ID *id,
const char *name,
const char *file,
int channel,
- int frame_start)
+ int frame_start,
+ int fit_method)
{
return rna_Sequences_new_image(
- id, &seq->seqbase, bmain, reports, name, file, channel, frame_start);
+ id, &seq->seqbase, bmain, reports, name, file, channel, frame_start, fit_method);
}
static Sequence *rna_Sequences_new_movie(ID *id,
@@ -278,11 +282,13 @@ static Sequence *rna_Sequences_new_movie(ID *id,
const char *name,
const char *file,
int channel,
- int frame_start)
+ int frame_start,
+ int fit_method)
{
Scene *scene = (Scene *)id;
SeqLoadData load_data;
SEQ_add_load_data_init(&load_data, name, file, frame_start, channel);
+ load_data.fit_method = fit_method;
load_data.allow_invalid_file = true;
Sequence *seq = SEQ_add_movie_strip(bmain, scene, seqbase, &load_data);
@@ -299,9 +305,11 @@ static Sequence *rna_Sequences_editing_new_movie(ID *id,
const char *name,
const char *file,
int channel,
- int frame_start)
+ int frame_start,
+ int fit_method)
{
- return rna_Sequences_new_movie(id, &ed->seqbase, bmain, name, file, channel, frame_start);
+ return rna_Sequences_new_movie(
+ id, &ed->seqbase, bmain, name, file, channel, frame_start, fit_method);
}
static Sequence *rna_Sequences_meta_new_movie(ID *id,
@@ -310,9 +318,11 @@ static Sequence *rna_Sequences_meta_new_movie(ID *id,
const char *name,
const char *file,
int channel,
- int frame_start)
+ int frame_start,
+ int fit_method)
{
- return rna_Sequences_new_movie(id, &seq->seqbase, bmain, name, file, channel, frame_start);
+ return rna_Sequences_new_movie(
+ id, &seq->seqbase, bmain, name, file, channel, frame_start, fit_method);
}
# ifdef WITH_AUDASPACE
@@ -724,6 +734,18 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop, const bool metastri
{0, NULL, 0, NULL, NULL},
};
+ static const EnumPropertyItem scale_fit_methods[] = {
+ {SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image so fits in preview"},
+ {SEQ_SCALE_TO_FILL,
+ "FILL",
+ 0,
+ "Scale to Fill",
+ "Scale image so it fills preview completely"},
+ {SEQ_STRETCH_TO_FILL, "STRETCH", 0, "Stretch to Fill", "Stretch image so it fills preview"},
+ {SEQ_USE_ORIGINAL_SIZE, "ORIGINAL", 0, "Use Original Size", "Don't scale the image"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
const char *new_clip_func_name = "rna_Sequences_editing_new_clip";
const char *new_mask_func_name = "rna_Sequences_editing_new_mask";
const char *new_scene_func_name = "rna_Sequences_editing_new_scene";
@@ -849,6 +871,9 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop, const bool metastri
-MAXFRAME,
MAXFRAME);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_enum(
+ func, "fit_method", scale_fit_methods, SEQ_USE_ORIGINAL_SIZE, "Image Fit Method", NULL);
+ RNA_def_parameter_flags(parm, 0, PARM_PYFUNC_OPTIONAL);
/* return type */
parm = RNA_def_pointer(func, "sequence", "Sequence", "", "New Sequence");
RNA_def_function_return(func, parm);
@@ -873,6 +898,9 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop, const bool metastri
-MAXFRAME,
MAXFRAME);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_enum(
+ func, "fit_method", scale_fit_methods, SEQ_USE_ORIGINAL_SIZE, "Image Fit Method", NULL);
+ RNA_def_parameter_flags(parm, 0, PARM_PYFUNC_OPTIONAL);
/* return type */
parm = RNA_def_pointer(func, "sequence", "Sequence", "", "New Sequence");
RNA_def_function_return(func, parm);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 26ec94c2b89..cf22ff95e74 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -3083,7 +3083,7 @@ const EnumPropertyItem *rna_SpaceSpreadsheet_attribute_domain_itemf(bContext *C,
ATTR_DOMAIN_CORNER,
ATTR_DOMAIN_EDGE,
ATTR_DOMAIN_POINT,
- ATTR_DOMAIN_POLYGON)) {
+ ATTR_DOMAIN_FACE)) {
continue;
}
}
@@ -7237,7 +7237,7 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna)
"MESH",
ICON_MESH_DATA,
"Mesh",
- "Mesh component containing point, corner, edge and polygon data"},
+ "Mesh component containing point, corner, edge and face data"},
{GEO_COMPONENT_TYPE_POINT_CLOUD,
"POINTCLOUD",
ICON_POINTCLOUD_DATA,
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 4c86405a44d..baf77aae87f 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -6215,7 +6215,8 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
RNA_def_property_ui_text(prop,
"Auto Save Temporary Files",
"Automatic saving of temporary files in temp directory, "
- "uses process ID (sculpt and edit mode data won't be saved)");
+ "uses process ID.\n"
+ "Warning: Sculpt and edit mode data won't be saved");
RNA_def_property_update(prop, 0, "rna_userdef_autosave_update");
prop = RNA_def_property(srna, "auto_save_time", PROP_INT, PROP_NONE);
@@ -6304,6 +6305,11 @@ static void rna_def_userdef_experimental(BlenderRNA *brna)
prop,
"Asset Browser",
"Enable Asset Browser editor and operators to manage data-blocks as asset");
+
+ prop = RNA_def_property(srna, "use_override_templates", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "use_override_templates", 1);
+ RNA_def_property_ui_text(
+ prop, "Override Templates", "Enable library override template in the python API");
}
static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop)
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index d67d62d7af9..4a51db4e652 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -1781,41 +1781,40 @@ static void rna_Operator_bl_label_set(PointerRNA *ptr, const char *value)
}
}
-static void rna_Operator_bl_translation_context_set(PointerRNA *ptr, const char *value)
-{
- wmOperator *data = (wmOperator *)(ptr->data);
- char *str = (char *)data->type->translation_context;
- if (!str[0]) {
- BLI_strncpy(str, value, RNA_DYN_DESCR_MAX); /* utf8 already ensured */
- }
- else {
- BLI_assert(!"setting the bl_translation_context on a non-builtin operator");
- }
-}
-
-static void rna_Operator_bl_description_set(PointerRNA *ptr, const char *value)
-{
- wmOperator *data = (wmOperator *)(ptr->data);
- char *str = (char *)data->type->description;
- if (!str[0]) {
- BLI_strncpy(str, value, RNA_DYN_DESCR_MAX); /* utf8 already ensured */
- }
- else {
- BLI_assert(!"setting the bl_description on a non-builtin operator");
- }
-}
+/**
+ * Use callbacks that check for NULL instead of clearing #PROP_NEVER_NULL on the string property,
+ * so the internal value may be NULL, without allowing Python to assign `None` which doesn't
+ * make any sense in this case.
+ */
+# define OPERATOR_STR_MAYBE_NULL_GETSET(attr, len) \
+ static void rna_Operator_bl_##attr##_set(PointerRNA *ptr, const char *value) \
+ { \
+ wmOperator *data = (wmOperator *)(ptr->data); \
+ char *str = (char *)data->type->attr; \
+ if (str && !str[0]) { \
+ BLI_strncpy(str, value, len); /* utf8 already ensured */ \
+ } \
+ else { \
+ BLI_assert( \
+ !"setting the bl_" STRINGIFY(translation_context) " on a non-builtin operator"); \
+ } \
+ } \
+ static void rna_Operator_bl_##attr##_get(PointerRNA *ptr, char *value) \
+ { \
+ const wmOperator *data = (wmOperator *)(ptr->data); \
+ const char *str = data->type->attr; \
+ BLI_strncpy(value, str ? str : "", len); \
+ } \
+ static int rna_Operator_bl_##attr##_length(PointerRNA *ptr) \
+ { \
+ const wmOperator *data = (wmOperator *)(ptr->data); \
+ const char *str = data->type->attr; \
+ return BLI_strnlen(str ? str : "", len); \
+ }
-static void rna_Operator_bl_undo_group_set(PointerRNA *ptr, const char *value)
-{
- wmOperator *data = (wmOperator *)(ptr->data);
- char *str = (char *)data->type->undo_group;
- if (!str[0]) {
- BLI_strncpy(str, value, OP_MAX_TYPENAME); /* utf8 already ensured */
- }
- else {
- BLI_assert(!"setting the bl_undo_group on a non-builtin operator");
- }
-}
+OPERATOR_STR_MAYBE_NULL_GETSET(translation_context, RNA_DYN_DESCR_MAX)
+OPERATOR_STR_MAYBE_NULL_GETSET(description, RNA_DYN_DESCR_MAX)
+OPERATOR_STR_MAYBE_NULL_GETSET(undo_group, OP_MAX_TYPENAME)
static void rna_KeyMapItem_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
@@ -1930,26 +1929,32 @@ static void rna_def_operator(BlenderRNA *brna)
prop = RNA_def_property(srna, "bl_translation_context", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->translation_context");
RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Operator_bl_translation_context_set");
+ RNA_def_property_string_funcs(prop,
+ "rna_Operator_bl_translation_context_get",
+ "rna_Operator_bl_translation_context_length",
+ "rna_Operator_bl_translation_context_set");
RNA_def_property_string_default(prop, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
- RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->description");
RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Operator_bl_description_set");
+ RNA_def_property_string_funcs(prop,
+ "rna_Operator_bl_description_get",
+ "rna_Operator_bl_description_length",
+ "rna_Operator_bl_description_set");
/* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
- RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
prop = RNA_def_property(srna, "bl_undo_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->undo_group");
RNA_def_property_string_maxlength(prop, OP_MAX_TYPENAME); /* else it uses the pointer size! */
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Operator_bl_undo_group_set");
+ RNA_def_property_string_funcs(prop,
+ "rna_Operator_bl_undo_group_get",
+ "rna_Operator_bl_undo_group_length",
+ "rna_Operator_bl_undo_group_set");
/* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
- RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
prop = RNA_def_property(srna, "bl_options", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type->flag");
@@ -2022,26 +2027,32 @@ static void rna_def_macro_operator(BlenderRNA *brna)
prop = RNA_def_property(srna, "bl_translation_context", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->translation_context");
RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Operator_bl_translation_context_set");
+ RNA_def_property_string_funcs(prop,
+ "rna_Operator_bl_translation_context_get",
+ "rna_Operator_bl_translation_context_length",
+ "rna_Operator_bl_translation_context_set");
RNA_def_property_string_default(prop, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
- RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->description");
RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Operator_bl_description_set");
+ RNA_def_property_string_funcs(prop,
+ "rna_Operator_bl_description_get",
+ "rna_Operator_bl_description_length",
+ "rna_Operator_bl_description_set");
/* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
- RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
prop = RNA_def_property(srna, "bl_undo_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->undo_group");
RNA_def_property_string_maxlength(prop, OP_MAX_TYPENAME); /* else it uses the pointer size! */
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Operator_bl_undo_group_set");
+ RNA_def_property_string_funcs(prop,
+ "rna_Operator_bl_undo_group_get",
+ "rna_Operator_bl_undo_group_length",
+ "rna_Operator_bl_undo_group_set");
/* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
- RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
prop = RNA_def_property(srna, "bl_options", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type->flag");
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index fae8ac72108..ffb40bea9ba 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -660,6 +660,9 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd,
BLI_array_append(material_remaps, NULL);
if (bmd->flag & eBooleanModifierFlag_Object) {
mesh_operand = BKE_modifier_get_evaluated_mesh_from_evaluated_object(bmd->object, false);
+ if (!mesh_operand) {
+ return mesh;
+ }
BKE_mesh_wrapper_ensure_mdata(mesh_operand);
BLI_array_append(meshes, mesh_operand);
BLI_array_append(obmats, &bmd->object->obmat);
@@ -673,6 +676,9 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd,
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, ob) {
if (ob->type == OB_MESH && ob != ctx->object) {
Mesh *collection_mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob, false);
+ if (!collection_mesh) {
+ continue;
+ }
BKE_mesh_wrapper_ensure_mdata(collection_mesh);
BLI_array_append(meshes, collection_mesh);
BLI_array_append(obmats, &ob->obmat);
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index 6236dc87791..72842a1d32d 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -414,7 +414,9 @@ class GeometryNodesEvaluator {
{
const bNode &bnode = params.node();
- this->store_ui_hints(node, params);
+ if (DEG_is_active(depsgraph_)) {
+ this->store_ui_hints(node, params);
+ }
/* Use the geometry-node-execute callback if it exists. */
if (bnode.typeinfo->geometry_node_execute != nullptr) {
@@ -720,10 +722,17 @@ static const SocketPropertyType *get_socket_property_type(const bNodeSocket &bso
[](const bNodeSocket &socket) {
return (PropertyType)((bNodeSocketValueFloat *)socket.default_value)->subtype;
},
- [](const IDProperty &property) { return property.type == IDP_FLOAT; },
+ [](const IDProperty &property) { return ELEM(property.type, IDP_FLOAT, IDP_DOUBLE); },
[](const IDProperty &property,
const PersistentDataHandleMap &UNUSED(handles),
- void *r_value) { *(float *)r_value = IDP_Float(&property); },
+ void *r_value) {
+ if (property.type == IDP_FLOAT) {
+ *(float *)r_value = IDP_Float(&property);
+ }
+ else if (property.type == IDP_DOUBLE) {
+ *(float *)r_value = (float)IDP_Double(&property);
+ }
+ },
};
return &float_type;
}
@@ -1048,7 +1057,7 @@ static void reset_tree_ui_storage(Span<const blender::nodes::NodeTreeRef *> tree
* often than necessary. It's going to be replaced soon.
*/
static GeometrySet compute_geometry(const DerivedNodeTree &tree,
- Span<const OutputSocketRef *> group_input_sockets,
+ Span<const NodeRef *> group_input_nodes,
const InputSocketRef &socket_to_compute,
GeometrySet input_geometry_set,
NodesModifierData *nmd,
@@ -1064,7 +1073,12 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree,
Map<DOutputSocket, GMutablePointer> group_inputs;
const DTreeContext *root_context = &tree.root_context();
- if (group_input_sockets.size() > 0) {
+ for (const NodeRef *group_input_node : group_input_nodes) {
+ Span<const OutputSocketRef *> group_input_sockets = group_input_node->outputs().drop_back(1);
+ if (group_input_sockets.is_empty()) {
+ continue;
+ }
+
Span<const OutputSocketRef *> remaining_input_sockets = group_input_sockets;
/* If the group expects a geometry as first input, use the geometry that has been passed to
@@ -1072,7 +1086,7 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree,
const OutputSocketRef *first_input_socket = group_input_sockets[0];
if (first_input_socket->bsocket()->type == SOCK_GEOMETRY) {
GeometrySet *geometry_set_in =
- allocator.construct<GeometrySet>(std::move(input_geometry_set)).release();
+ allocator.construct<GeometrySet>(input_geometry_set).release();
group_inputs.add_new({root_context, first_input_socket}, geometry_set_in);
remaining_input_sockets = remaining_input_sockets.drop_front(1);
}
@@ -1086,6 +1100,9 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree,
}
}
+ /* Don't keep a reference to the input geometry components to avoid copies during evaluation. */
+ input_geometry_set.clear();
+
Vector<DInputSocket> group_outputs;
group_outputs.append({root_context, &socket_to_compute});
@@ -1174,18 +1191,10 @@ static void modifyGeometry(ModifierData *md,
Span<const NodeRef *> input_nodes = root_tree_ref.nodes_by_type("NodeGroupInput");
Span<const NodeRef *> output_nodes = root_tree_ref.nodes_by_type("NodeGroupOutput");
- if (input_nodes.size() > 1) {
- return;
- }
if (output_nodes.size() != 1) {
return;
}
- Span<const OutputSocketRef *> group_inputs;
- if (input_nodes.size() == 1) {
- group_inputs = input_nodes[0]->outputs().drop_back(1);
- }
-
Span<const InputSocketRef *> group_outputs = output_nodes[0]->inputs().drop_back(1);
if (group_outputs.size() == 0) {
@@ -1197,10 +1206,12 @@ static void modifyGeometry(ModifierData *md,
return;
}
- reset_tree_ui_storage(tree.used_node_tree_refs(), *ctx->object, *md);
+ if (DEG_is_active(ctx->depsgraph)) {
+ reset_tree_ui_storage(tree.used_node_tree_refs(), *ctx->object, *md);
+ }
geometry_set = compute_geometry(
- tree, group_inputs, *group_outputs[0], std::move(geometry_set), nmd, ctx);
+ tree, input_nodes, *group_outputs[0], std::move(geometry_set), nmd, ctx);
}
static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
@@ -1359,6 +1370,7 @@ static void requiredDataMask(Object *UNUSED(ob),
/* We don't know what the node tree will need. If there are vertex groups, it is likely that the
* node tree wants to access them. */
r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
+ r_cddata_masks->vmask |= CD_MASK_PROP_ALL;
}
ModifierTypeInfo modifierType_Nodes = {
diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c
index 99069919120..a77a6e595ad 100644
--- a/source/blender/modifiers/intern/MOD_solidify_extrude.c
+++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c
@@ -216,7 +216,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
numVerts, sizeof(*old_vert_arr), "old_vert_arr in solidify");
uint *edge_users = NULL;
- char *edge_order = NULL;
+ int *edge_order = NULL;
float(*vert_nors)[3] = NULL;
float(*poly_nors)[3] = NULL;
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 271f4e5c5e4..07380addaff 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -46,6 +46,7 @@ set(INC
set(SRC
composite/nodes/node_composite_alphaOver.c
+ composite/nodes/node_composite_antialiasing.c
composite/nodes/node_composite_bilateralblur.c
composite/nodes/node_composite_blur.c
composite/nodes/node_composite_bokehblur.c
@@ -139,19 +140,21 @@ set(SRC
function/node_function_util.cc
geometry/nodes/node_geo_align_rotation_to_vector.cc
+ geometry/nodes/node_geo_attribute_clamp.cc
geometry/nodes/node_geo_attribute_color_ramp.cc
geometry/nodes/node_geo_attribute_combine_xyz.cc
geometry/nodes/node_geo_attribute_compare.cc
geometry/nodes/node_geo_attribute_convert.cc
geometry/nodes/node_geo_attribute_fill.cc
+ geometry/nodes/node_geo_attribute_map_range.cc
geometry/nodes/node_geo_attribute_math.cc
geometry/nodes/node_geo_attribute_mix.cc
geometry/nodes/node_geo_attribute_proximity.cc
geometry/nodes/node_geo_attribute_randomize.cc
+ geometry/nodes/node_geo_attribute_remove.cc
geometry/nodes/node_geo_attribute_sample_texture.cc
geometry/nodes/node_geo_attribute_separate_xyz.cc
geometry/nodes/node_geo_attribute_vector_math.cc
- geometry/nodes/node_geo_attribute_remove.cc
geometry/nodes/node_geo_boolean.cc
geometry/nodes/node_geo_collection_info.cc
geometry/nodes/node_geo_common.cc
@@ -162,9 +165,9 @@ set(SRC
geometry/nodes/node_geo_mesh_primitive_cone.cc
geometry/nodes/node_geo_mesh_primitive_cube.cc
geometry/nodes/node_geo_mesh_primitive_cylinder.cc
+ geometry/nodes/node_geo_mesh_primitive_grid.cc
geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc
geometry/nodes/node_geo_mesh_primitive_line.cc
- geometry/nodes/node_geo_mesh_primitive_plane.cc
geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
geometry/nodes/node_geo_object_info.cc
geometry/nodes/node_geo_point_distribute.cc
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index b0dd0edeec5..258e4c961c9 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -79,6 +79,7 @@ void register_node_type_cmp_inpaint(void);
void register_node_type_cmp_despeckle(void);
void register_node_type_cmp_defocus(void);
void register_node_type_cmp_denoise(void);
+void register_node_type_cmp_antialiasing(void);
void register_node_type_cmp_valtorgb(void);
void register_node_type_cmp_rgbtobw(void);
diff --git a/source/blender/nodes/NOD_derived_node_tree.hh b/source/blender/nodes/NOD_derived_node_tree.hh
index e47774bb25a..c29de611e18 100644
--- a/source/blender/nodes/NOD_derived_node_tree.hh
+++ b/source/blender/nodes/NOD_derived_node_tree.hh
@@ -261,7 +261,7 @@ inline const NodeRef *DNode::operator->() const
inline uint64_t DNode::hash() const
{
- return DefaultHash<const DTreeContext *>{}(context_) ^ DefaultHash<const NodeRef *>{}(node_ref_);
+ return get_default_hash_2(context_, node_ref_);
}
/* --------------------------------------------------------------------
@@ -316,8 +316,7 @@ inline const SocketRef *DSocket::operator->() const
inline uint64_t DSocket::hash() const
{
- return DefaultHash<const DTreeContext *>{}(context_) ^
- DefaultHash<const SocketRef *>{}(socket_ref_);
+ return get_default_hash_2(context_, socket_ref_);
}
/* --------------------------------------------------------------------
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index 03115852d80..3a26f38d6ba 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -27,11 +27,13 @@ void register_node_tree_type_geo(void);
void register_node_type_geo_group(void);
void register_node_type_geo_align_rotation_to_vector(void);
+void register_node_type_geo_attribute_clamp(void);
void register_node_type_geo_attribute_color_ramp(void);
void register_node_type_geo_attribute_combine_xyz(void);
void register_node_type_geo_attribute_compare(void);
void register_node_type_geo_attribute_convert(void);
void register_node_type_geo_attribute_fill(void);
+void register_node_type_geo_attribute_map_range(void);
void register_node_type_geo_attribute_math(void);
void register_node_type_geo_attribute_mix(void);
void register_node_type_geo_attribute_proximity(void);
@@ -47,8 +49,8 @@ void register_node_type_geo_join_geometry(void);
void register_node_type_geo_mesh_primitive_circle(void);
void register_node_type_geo_mesh_primitive_cone(void);
void register_node_type_geo_mesh_primitive_cube(void);
-void register_node_type_geo_mesh_primitive_plane(void);
void register_node_type_geo_mesh_primitive_cylinder(void);
+void register_node_type_geo_mesh_primitive_grid(void);
void register_node_type_geo_mesh_primitive_ico_sphere(void);
void register_node_type_geo_mesh_primitive_line(void);
void register_node_type_geo_mesh_primitive_uv_sphere(void);
diff --git a/source/blender/nodes/NOD_math_functions.hh b/source/blender/nodes/NOD_math_functions.hh
index 08496e044c5..45de1816549 100644
--- a/source/blender/nodes/NOD_math_functions.hh
+++ b/source/blender/nodes/NOD_math_functions.hh
@@ -379,7 +379,8 @@ inline bool try_dispatch_float_math_fl3_fl3_fl_to_fl3(const NodeVectorMathOperat
switch (operation) {
case NODE_VECTOR_MATH_REFRACT:
- return dispatch([](float3 a, float3 b, float c) { return float3::refract(a, b.normalized(), c); });
+ return dispatch(
+ [](float3 a, float3 b, float c) { return float3::refract(a, b.normalized(), c); });
default:
return false;
}
diff --git a/source/blender/nodes/NOD_socket.h b/source/blender/nodes/NOD_socket.h
index 3344a25bdea..6bcfda70d04 100644
--- a/source/blender/nodes/NOD_socket.h
+++ b/source/blender/nodes/NOD_socket.h
@@ -41,7 +41,7 @@ extern "C" {
struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree,
struct bNode *node,
struct bNodeSocketTemplate *stemp,
- int in_out);
+ eNodeSocketInOut in_out);
void node_verify_socket_templates(struct bNodeTree *ntree, struct bNode *node);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index ec687ae6b70..0b1efaca502 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -224,6 +224,7 @@ DefNode(CompositorNode, CMP_NODE_CRYPTOMATTE, def_cmp_cryptomatte, "CRYPTO
DefNode(CompositorNode, CMP_NODE_CRYPTOMATTE_LEGACY, def_cmp_cryptomatte_legacy, "CRYPTOMATTE", Cryptomatte, "Cryptomatte (Legacy)", "" )
DefNode(CompositorNode, CMP_NODE_DENOISE, def_cmp_denoise, "DENOISE", Denoise, "Denoise", "" )
DefNode(CompositorNode, CMP_NODE_EXPOSURE, 0, "EXPOSURE", Exposure, "Exposure", "" )
+DefNode(CompositorNode, CMP_NODE_ANTIALIASING, def_cmp_antialiasing, "ANTIALIASING", AntiAliasing, "Anti-Aliasing", "" )
DefNode(TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" )
DefNode(TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" )
@@ -305,7 +306,9 @@ DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CYLINDER, def_geo_mesh_cylinder, "
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_ICO_SPHERE, 0, "MESH_PRIMITIVE_ICO_SPHERE", MeshIcoSphere, "Ico Sphere", "")
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CONE, def_geo_mesh_cone, "MESH_PRIMITIVE_CONE", MeshCone, "Cone", "")
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_LINE, def_geo_mesh_line, "MESH_PRIMITIVE_LINE", MeshLine, "Line", "")
-DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_PLANE, 0, "MESH_PRIMITIVE_PLANE", MeshPlane, "Plane", "")
+DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_GRID, 0, "MESH_PRIMITIVE_GRID", MeshGrid, "Grid", "")
+DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_MAP_RANGE, def_geo_attribute_map_range, "ATTRIBUTE_MAP_RANGE", AttributeMapRange, "Attribute Map Range", "")
+DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_CLAMP, def_geo_attribute_clamp, "ATTRIBUTE_CLAMP", AttributeClamp, "Attribute Clamp", "")
/* undefine macros */
#undef DefNode
diff --git a/source/blender/nodes/composite/nodes/node_composite_antialiasing.c b/source/blender/nodes/composite/nodes/node_composite_antialiasing.c
new file mode 100644
index 00000000000..7437496d878
--- /dev/null
+++ b/source/blender/nodes/composite/nodes/node_composite_antialiasing.c
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): IRIE Shinsuke
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/nodes/composite/nodes/node_composite_antialiasing.c
+ * \ingroup cmpnodes
+ */
+
+#include "node_composite_util.h"
+
+/* **************** Anti-Aliasing (SMAA 1x) ******************** */
+
+static bNodeSocketTemplate cmp_node_antialiasing_in[] = {
+ {SOCK_RGBA, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, {-1, ""}};
+
+static bNodeSocketTemplate cmp_node_antialiasing_out[] = {{SOCK_RGBA, N_("Image")}, {-1, ""}};
+
+static void node_composit_init_antialiasing(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeAntiAliasingData *data = MEM_callocN(sizeof(NodeAntiAliasingData), "node antialiasing data");
+
+ data->threshold = 1.0f;
+ data->contrast_limit = 0.2f;
+ data->corner_rounding = 0.25f;
+
+ node->storage = data;
+}
+
+void register_node_type_cmp_antialiasing(void)
+{
+ static bNodeType ntype;
+
+ cmp_node_type_base(
+ &ntype, CMP_NODE_ANTIALIASING, "Anti-Aliasing", NODE_CLASS_OP_FILTER, NODE_PREVIEW);
+ node_type_socket_templates(&ntype, cmp_node_antialiasing_in, cmp_node_antialiasing_out);
+ node_type_size(&ntype, 170, 140, 200);
+ node_type_init(&ntype, node_composit_init_antialiasing);
+ node_type_storage(
+ &ntype, "NodeAntiAliasingData", node_free_standard_storage, node_copy_standard_storage);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc
new file mode 100644
index 00000000000..93e4124bd70
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc
@@ -0,0 +1,278 @@
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "node_geometry_util.hh"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+static bNodeSocketTemplate geo_node_attribute_clamp_in[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {SOCK_STRING, N_("Attribute")},
+ {SOCK_STRING, N_("Result")},
+ {SOCK_VECTOR, N_("Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_VECTOR, N_("Max"), 1.0f, 1.0f, 1.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_FLOAT, N_("Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_FLOAT, N_("Max"), 1.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_INT, N_("Min"), 0.0f, 0.0f, 0.0f, 0.0f, -100000, 100000},
+ {SOCK_INT, N_("Max"), 100.0f, 0.0f, 0.0f, 0.0f, -100000, 100000},
+ {SOCK_RGBA, N_("Min"), 0.5, 0.5, 0.5, 1.0},
+ {SOCK_RGBA, N_("Max"), 0.5, 0.5, 0.5, 1.0},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate geo_node_attribute_clamp_out[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {-1, ""},
+};
+
+static void geo_node_attribute_clamp_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
+}
+
+static void geo_node_attribute_clamp_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeAttributeClamp *data = (NodeAttributeClamp *)MEM_callocN(sizeof(NodeAttributeClamp),
+ __func__);
+ data->data_type = CD_PROP_FLOAT;
+ data->operation = NODE_CLAMP_MINMAX;
+ node->storage = data;
+}
+
+static void geo_node_attribute_clamp_update(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sock_min_vector = (bNodeSocket *)BLI_findlink(&node->inputs, 3);
+ bNodeSocket *sock_max_vector = sock_min_vector->next;
+ bNodeSocket *sock_min_float = sock_max_vector->next;
+ bNodeSocket *sock_max_float = sock_min_float->next;
+ bNodeSocket *sock_min_int = sock_max_float->next;
+ bNodeSocket *sock_max_int = sock_min_int->next;
+ bNodeSocket *sock_min_color = sock_max_int->next;
+ bNodeSocket *sock_max_color = sock_min_color->next;
+
+ const NodeAttributeClamp &storage = *(const NodeAttributeClamp *)node->storage;
+ const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type);
+ nodeSetSocketAvailability(sock_min_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(sock_max_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(sock_min_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(sock_max_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(sock_min_int, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(sock_max_int, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(sock_min_color, data_type == CD_PROP_COLOR);
+ nodeSetSocketAvailability(sock_max_color, data_type == CD_PROP_COLOR);
+}
+
+namespace blender::nodes {
+
+template<typename T> T clamp_value(const T val, const T min, const T max);
+
+template<> inline float clamp_value(const float val, const float min, const float max)
+{
+ return std::min(std::max(val, min), max);
+}
+
+template<> inline int clamp_value(const int val, const int min, const int max)
+{
+ return std::min(std::max(val, min), max);
+}
+
+template<> inline float3 clamp_value(const float3 val, const float3 min, const float3 max)
+{
+ float3 tmp;
+ tmp.x = std::min(std::max(val.x, min.x), max.x);
+ tmp.y = std::min(std::max(val.y, min.y), max.y);
+ tmp.z = std::min(std::max(val.z, min.z), max.z);
+ return tmp;
+}
+
+template<> inline Color4f clamp_value(const Color4f val, const Color4f min, const Color4f max)
+{
+ Color4f tmp;
+ tmp.r = std::min(std::max(val.r, min.r), max.r);
+ tmp.g = std::min(std::max(val.g, min.g), max.g);
+ tmp.b = std::min(std::max(val.b, min.b), max.b);
+ tmp.a = std::min(std::max(val.a, min.a), max.a);
+ return tmp;
+}
+
+template<typename T>
+static void clamp_attribute(Span<T> read_span, MutableSpan<T> span, const T min, const T max)
+{
+ for (const int i : span.index_range()) {
+ span[i] = clamp_value<T>(read_span[i], min, max);
+ }
+}
+
+static AttributeDomain get_result_domain(const GeometryComponent &component,
+ StringRef source_name,
+ StringRef result_name)
+{
+ ReadAttributePtr result_attribute = component.attribute_try_get_for_read(result_name);
+ if (result_attribute) {
+ return result_attribute->domain();
+ }
+ ReadAttributePtr source_attribute = component.attribute_try_get_for_read(source_name);
+ if (source_attribute) {
+ return source_attribute->domain();
+ }
+ return ATTR_DOMAIN_POINT;
+}
+
+static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParams &params)
+{
+ const std::string attribute_name = params.get_input<std::string>("Attribute");
+ const std::string result_name = params.get_input<std::string>("Result");
+
+ if (attribute_name.empty() || result_name.empty()) {
+ return;
+ }
+
+ if (!component.attribute_exists(attribute_name)) {
+ params.error_message_add(NodeWarningType::Error,
+ TIP_("No attribute with name \"") + attribute_name + "\"");
+ return;
+ }
+
+ const NodeAttributeClamp &storage = *(const NodeAttributeClamp *)params.node().storage;
+ const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type);
+ const AttributeDomain domain = get_result_domain(component, attribute_name, result_name);
+ const int operation = static_cast<int>(storage.operation);
+
+ ReadAttributePtr attribute_input = component.attribute_try_get_for_read(
+ attribute_name, domain, data_type);
+
+ OutputAttributePtr attribute_result = component.attribute_try_get_for_output(
+ result_name, domain, data_type);
+
+ if (!attribute_result) {
+ params.error_message_add(NodeWarningType::Error,
+ TIP_("Could not find or create attribute with name \"") +
+ result_name + "\"");
+ return;
+ }
+
+ switch (data_type) {
+ case CD_PROP_FLOAT3: {
+ Span<float3> read_span = attribute_input->get_span<float3>();
+ MutableSpan<float3> span = attribute_result->get_span_for_write_only<float3>();
+ float3 min = params.get_input<float3>("Min");
+ float3 max = params.get_input<float3>("Max");
+ if (operation == NODE_CLAMP_RANGE) {
+ if (min.x > max.x) {
+ std::swap(min.x, max.x);
+ }
+ if (min.y > max.y) {
+ std::swap(min.y, max.y);
+ }
+ if (min.z > max.z) {
+ std::swap(min.z, max.z);
+ }
+ }
+ clamp_attribute<float3>(read_span, span, min, max);
+ break;
+ }
+ case CD_PROP_FLOAT: {
+ Span<float> read_span = attribute_input->get_span<float>();
+ MutableSpan<float> span = attribute_result->get_span_for_write_only<float>();
+ const float min = params.get_input<float>("Min_001");
+ const float max = params.get_input<float>("Max_001");
+ if (operation == NODE_CLAMP_RANGE && min > max) {
+ clamp_attribute<float>(read_span, span, max, min);
+ }
+ else {
+ clamp_attribute<float>(read_span, span, min, max);
+ }
+ break;
+ }
+ case CD_PROP_INT32: {
+ Span<int> read_span = attribute_input->get_span<int>();
+ MutableSpan<int> span = attribute_result->get_span_for_write_only<int>();
+ const int min = params.get_input<int>("Min_002");
+ const int max = params.get_input<int>("Max_002");
+ if (operation == NODE_CLAMP_RANGE && min > max) {
+ clamp_attribute<int>(read_span, span, max, min);
+ }
+ else {
+ clamp_attribute<int>(read_span, span, min, max);
+ }
+ break;
+ }
+ case CD_PROP_COLOR: {
+ Span<Color4f> read_span = attribute_input->get_span<Color4f>();
+ MutableSpan<Color4f> span = attribute_result->get_span_for_write_only<Color4f>();
+ Color4f min = params.get_input<Color4f>("Min_003");
+ Color4f max = params.get_input<Color4f>("Max_003");
+ if (operation == NODE_CLAMP_RANGE) {
+ if (min.r > max.r) {
+ std::swap(min.r, max.r);
+ }
+ if (min.g > max.g) {
+ std::swap(min.g, max.g);
+ }
+ if (min.b > max.b) {
+ std::swap(min.b, max.b);
+ }
+ if (min.a > max.a) {
+ std::swap(min.a, max.a);
+ }
+ }
+ clamp_attribute<Color4f>(read_span, span, min, max);
+ break;
+ }
+ default: {
+ BLI_assert(false);
+ break;
+ }
+ }
+
+ attribute_result.apply_span_and_save();
+}
+
+static void geo_node_attribute_clamp_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+
+ geometry_set = geometry_set_realize_instances(geometry_set);
+
+ if (geometry_set.has<MeshComponent>()) {
+ clamp_attribute(geometry_set.get_component_for_write<MeshComponent>(), params);
+ }
+ if (geometry_set.has<PointCloudComponent>()) {
+ clamp_attribute(geometry_set.get_component_for_write<PointCloudComponent>(), params);
+ }
+
+ params.set_output("Geometry", geometry_set);
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_attribute_clamp()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(&ntype, GEO_NODE_ATTRIBUTE_CLAMP, "Attribute Clamp", NODE_CLASS_ATTRIBUTE, 0);
+ node_type_socket_templates(&ntype, geo_node_attribute_clamp_in, geo_node_attribute_clamp_out);
+ node_type_init(&ntype, geo_node_attribute_clamp_init);
+ node_type_update(&ntype, geo_node_attribute_clamp_update);
+ ntype.geometry_node_execute = blender::nodes::geo_node_attribute_clamp_exec;
+ ntype.draw_buttons = geo_node_attribute_clamp_layout;
+ node_type_storage(
+ &ntype, "NodeAttributeClamp", node_free_standard_storage, node_copy_standard_storage);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_map_range.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_map_range.cc
new file mode 100644
index 00000000000..4e0dfd3a636
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_map_range.cc
@@ -0,0 +1,417 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "node_geometry_util.hh"
+
+#include "BLI_math_base_safe.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+static bNodeSocketTemplate geo_node_attribute_map_range_in[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {SOCK_STRING, N_("Attribute")},
+ {SOCK_STRING, N_("Result")},
+ {SOCK_FLOAT, N_("From Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_FLOAT, N_("From Max"), 1.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_FLOAT, N_("To Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_FLOAT, N_("To Max"), 1.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_FLOAT, N_("Steps"), 4.0f, 4.0f, 4.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_VECTOR, N_("From Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_VECTOR, N_("From Max"), 1.0f, 1.0f, 1.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_VECTOR, N_("To Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_VECTOR, N_("To Max"), 1.0f, 1.0f, 1.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_VECTOR, N_("Steps"), 4.0f, 4.0f, 4.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_BOOLEAN, N_("Clamp")},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate geo_node_attribute_map_range_out[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {-1, ""},
+};
+
+static void fn_attribute_map_range_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "interpolation_type", 0, "", ICON_NONE);
+}
+
+static void geo_node_attribute_map_range_init(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeAttributeMapRange *data = (NodeAttributeMapRange *)MEM_callocN(sizeof(NodeAttributeMapRange),
+ __func__);
+ data->data_type = CD_PROP_FLOAT;
+ data->interpolation_type = NODE_MAP_RANGE_LINEAR;
+
+ node->storage = data;
+}
+static void geo_node_attribute_map_range_update(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeAttributeMapRange &node_storage = *(NodeAttributeMapRange *)node->storage;
+
+ bNodeSocket *sock_from_min_float = (bNodeSocket *)BLI_findlink(&node->inputs, 3);
+ bNodeSocket *sock_from_max_float = sock_from_min_float->next;
+ bNodeSocket *sock_to_min_float = sock_from_max_float->next;
+ bNodeSocket *sock_to_max_float = sock_to_min_float->next;
+ bNodeSocket *sock_steps_float = sock_to_max_float->next;
+
+ bNodeSocket *sock_from_min_vector = sock_steps_float->next;
+ bNodeSocket *sock_from_max_vector = sock_from_min_vector->next;
+ bNodeSocket *sock_to_min_vector = sock_from_max_vector->next;
+ bNodeSocket *sock_to_max_vector = sock_to_min_vector->next;
+ bNodeSocket *sock_steps_vector = sock_to_max_vector->next;
+
+ bNodeSocket *sock_clamp = sock_steps_vector->next;
+
+ const CustomDataType data_type = static_cast<CustomDataType>(node_storage.data_type);
+
+ nodeSetSocketAvailability(sock_clamp,
+ node_storage.interpolation_type == NODE_MAP_RANGE_LINEAR ||
+ node_storage.interpolation_type == NODE_MAP_RANGE_STEPPED);
+
+ nodeSetSocketAvailability(sock_from_min_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(sock_from_max_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(sock_to_min_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(sock_to_max_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(sock_steps_float,
+ data_type == CD_PROP_FLOAT &&
+ node_storage.interpolation_type == NODE_MAP_RANGE_STEPPED);
+
+ nodeSetSocketAvailability(sock_from_min_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(sock_from_max_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(sock_to_min_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(sock_to_max_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(sock_steps_vector,
+ data_type == CD_PROP_FLOAT3 &&
+ node_storage.interpolation_type == NODE_MAP_RANGE_STEPPED);
+}
+
+namespace blender::nodes {
+
+static float map_linear(const float value,
+ const float min_from,
+ const float max_from,
+ const float min_to,
+ const float max_to)
+{
+ /* First we calculate a fraction that measures how far along
+ * the [min_from, max_from] interval the value lies.
+ *
+ * value
+ * min_from [------>|------------------------] max_from
+ * factor (e.g. 0.25)
+ *
+ * Then to find where the value is mapped, we add the same fraction
+ * of the [min_to, max_to] interval to min_to.
+ *
+ * min_to [--->|-----------] max_to
+ * v
+ * min_to + (max_to - min_to) * factor
+ */
+ const float factor = safe_divide(value - min_from, max_from - min_from);
+ return min_to + factor * (max_to - min_to);
+}
+
+static float map_stepped(const float value,
+ const float min_from,
+ const float max_from,
+ const float min_to,
+ const float max_to,
+ const float steps)
+{
+ /* First the factor is calculated here in the same way as for the linear mapping.
+ *
+ * Then the factor is mapped to multiples of 1.0 / steps.
+ * This is best understood with a few examples. Assume steps == 3.
+ * ____________________________________
+ * | factor | * 4.0 | floor() | / 3.0 |
+ * |--------|-------|---------|-------|
+ * | 0.0 | 0.0 | 0.0 | 0.0 |
+ * | 0.1 | 0.4 | 0.0 | 0.0 |
+ * | 0.25 | 1.0 | 1.0 | 0.333 |
+ * | 0.45 | 1.8 | 1.0 | 0.333 |
+ * | 0.5 | 2.0 | 2.0 | 0.666 |
+ * | 0.55 | 2.2 | 2.0 | 0.666 |
+ * | 0.999 | 3.999 | 3.0 | 1.0 |
+ * | 1.0 | 4.0 | 4.0 | 1.333 |
+ * ------------------------------------
+ * Note that the factor is not always mapped the closest multiple of 1.0 /steps.
+ */
+ const float factor = safe_divide(value - min_from, max_from - min_from);
+ const float factor_mapped = safe_divide(floorf(factor * (steps + 1.0f)), steps);
+ return min_to + factor_mapped * (max_to - min_to);
+}
+
+static float smoothstep_polynomial(float x)
+{
+ /* This polynomial is only meant to be used for the [0, 1] range. */
+ return (3.0f - 2.0f * x) * (x * x);
+}
+
+static float map_smoothstep(const float value,
+ const float min_from,
+ const float max_from,
+ const float min_to,
+ const float max_to)
+{
+ const float factor = safe_divide(value - min_from, max_from - min_from);
+ const float factor_clamped = std::clamp(factor, 0.0f, 1.0f);
+ const float factor_mapped = smoothstep_polynomial(factor_clamped);
+ return min_to + factor_mapped * (max_to - min_to);
+}
+
+static float smootherstep_polynomial(float x)
+{
+ /* This polynomial is only meant to be used for the [0, 1] range. */
+ return x * x * x * (x * (x * 6.0f - 15.0f) + 10.0f);
+}
+
+static float map_smootherstep(const float value,
+ const float min_from,
+ const float max_from,
+ const float min_to,
+ const float max_to)
+{
+ const float factor = safe_divide(value - min_from, max_from - min_from);
+ const float factor_clamped = std::clamp(factor, 0.0f, 1.0f);
+ const float factor_mapped = smootherstep_polynomial(factor_clamped);
+ return min_to + factor_mapped * (max_to - min_to);
+}
+
+static void map_range_float(FloatReadAttribute attribute_input,
+ FloatWriteAttribute attribute_result,
+ const GeoNodeExecParams &params)
+{
+ const bNode &node = params.node();
+ NodeAttributeMapRange &node_storage = *(NodeAttributeMapRange *)node.storage;
+ const int interpolation_type = node_storage.interpolation_type;
+ const float min_from = params.get_input<float>("From Min");
+ const float max_from = params.get_input<float>("From Max");
+ const float min_to = params.get_input<float>("To Min");
+ const float max_to = params.get_input<float>("To Max");
+
+ Span<float> span = attribute_input.get_span();
+ MutableSpan<float> result_span = attribute_result.get_span();
+
+ switch (interpolation_type) {
+ case NODE_MAP_RANGE_LINEAR: {
+ for (int i : span.index_range()) {
+ result_span[i] = map_linear(span[i], min_from, max_from, min_to, max_to);
+ }
+ break;
+ }
+ case NODE_MAP_RANGE_STEPPED: {
+ const float steps = params.get_input<float>("Steps");
+ for (int i : span.index_range()) {
+ result_span[i] = map_stepped(span[i], min_from, max_from, min_to, max_to, steps);
+ }
+ break;
+ }
+ case NODE_MAP_RANGE_SMOOTHSTEP: {
+ for (int i : span.index_range()) {
+ result_span[i] = map_smoothstep(span[i], min_from, max_from, min_to, max_to);
+ }
+ break;
+ }
+ case NODE_MAP_RANGE_SMOOTHERSTEP: {
+ for (int i : span.index_range()) {
+ result_span[i] = map_smootherstep(span[i], min_from, max_from, min_to, max_to);
+ }
+ break;
+ }
+ }
+
+ if (ELEM(interpolation_type, NODE_MAP_RANGE_LINEAR, NODE_MAP_RANGE_STEPPED) &&
+ params.get_input<bool>("Clamp")) {
+ /* Users can specify min_to > max_to, but clamping expects min < max. */
+ const float clamp_min = min_to < max_to ? min_to : max_to;
+ const float clamp_max = min_to < max_to ? max_to : min_to;
+
+ for (int i : result_span.index_range()) {
+ result_span[i] = std::clamp(result_span[i], clamp_min, clamp_max);
+ }
+ }
+}
+
+static void map_range_float3(Float3ReadAttribute attribute_input,
+ Float3WriteAttribute attribute_result,
+ const GeoNodeExecParams &params)
+{
+ const bNode &node = params.node();
+ NodeAttributeMapRange &node_storage = *(NodeAttributeMapRange *)node.storage;
+ const int interpolation_type = node_storage.interpolation_type;
+ const float3 min_from = params.get_input<float3>("From Min_001");
+ const float3 max_from = params.get_input<float3>("From Max_001");
+ const float3 min_to = params.get_input<float3>("To Min_001");
+ const float3 max_to = params.get_input<float3>("To Max_001");
+
+ Span<float3> span = attribute_input.get_span();
+ MutableSpan<float3> result_span = attribute_result.get_span();
+
+ switch (interpolation_type) {
+ case NODE_MAP_RANGE_LINEAR: {
+ for (int i : span.index_range()) {
+ result_span[i].x = map_linear(span[i].x, min_from.x, max_from.x, min_to.x, max_to.x);
+ result_span[i].y = map_linear(span[i].y, min_from.y, max_from.y, min_to.y, max_to.y);
+ result_span[i].z = map_linear(span[i].z, min_from.z, max_from.z, min_to.z, max_to.z);
+ }
+ break;
+ }
+ case NODE_MAP_RANGE_STEPPED: {
+ const float3 steps = params.get_input<float3>("Steps_001");
+ for (int i : span.index_range()) {
+ result_span[i].x = map_stepped(
+ span[i].x, min_from.x, max_from.x, min_to.x, max_to.x, steps.x);
+ result_span[i].y = map_stepped(
+ span[i].y, min_from.y, max_from.y, min_to.y, max_to.y, steps.y);
+ result_span[i].z = map_stepped(
+ span[i].z, min_from.z, max_from.z, min_to.z, max_to.z, steps.z);
+ }
+ break;
+ }
+ case NODE_MAP_RANGE_SMOOTHSTEP: {
+ for (int i : span.index_range()) {
+ result_span[i].x = map_smoothstep(span[i].x, min_from.x, max_from.x, min_to.x, max_to.x);
+ result_span[i].y = map_smoothstep(span[i].y, min_from.y, max_from.y, min_to.y, max_to.y);
+ result_span[i].z = map_smoothstep(span[i].z, min_from.z, max_from.z, min_to.z, max_to.z);
+ }
+ break;
+ }
+ case NODE_MAP_RANGE_SMOOTHERSTEP: {
+ for (int i : span.index_range()) {
+ result_span[i].x = map_smootherstep(span[i].x, min_from.x, max_from.x, min_to.x, max_to.x);
+ result_span[i].y = map_smootherstep(span[i].y, min_from.y, max_from.y, min_to.y, max_to.y);
+ result_span[i].z = map_smootherstep(span[i].z, min_from.z, max_from.z, min_to.z, max_to.z);
+ }
+ break;
+ }
+ }
+
+ if (ELEM(interpolation_type, NODE_MAP_RANGE_LINEAR, NODE_MAP_RANGE_STEPPED) &&
+ params.get_input<bool>("Clamp")) {
+ /* Users can specify min_to > max_to, but clamping expects min < max. */
+ float3 clamp_min;
+ float3 clamp_max;
+ clamp_min.x = min_to.x < max_to.x ? min_to.x : max_to.x;
+ clamp_max.x = min_to.x < max_to.x ? max_to.x : min_to.x;
+ clamp_min.y = min_to.y < max_to.y ? min_to.y : max_to.y;
+ clamp_max.y = min_to.y < max_to.y ? max_to.y : min_to.y;
+ clamp_min.z = min_to.z < max_to.z ? min_to.z : max_to.z;
+ clamp_max.z = min_to.z < max_to.z ? max_to.z : min_to.z;
+
+ for (int i : result_span.index_range()) {
+ clamp_v3_v3v3(result_span[i], clamp_min, clamp_max);
+ }
+ }
+}
+
+static AttributeDomain get_result_domain(const GeometryComponent &component,
+ StringRef source_name,
+ StringRef result_name)
+{
+ ReadAttributePtr result_attribute = component.attribute_try_get_for_read(result_name);
+ if (result_attribute) {
+ return result_attribute->domain();
+ }
+ ReadAttributePtr source_attribute = component.attribute_try_get_for_read(source_name);
+ if (source_attribute) {
+ return source_attribute->domain();
+ }
+ return ATTR_DOMAIN_POINT;
+}
+
+static void map_range_attribute(GeometryComponent &component, const GeoNodeExecParams &params)
+{
+ const std::string input_name = params.get_input<std::string>("Attribute");
+ const std::string result_name = params.get_input<std::string>("Result");
+
+ if (input_name.empty() || result_name.empty()) {
+ return;
+ }
+
+ const bNode &node = params.node();
+ NodeAttributeMapRange &node_storage = *(NodeAttributeMapRange *)node.storage;
+ const CustomDataType data_type = static_cast<CustomDataType>(node_storage.data_type);
+
+ const AttributeDomain domain = get_result_domain(component, input_name, result_name);
+
+ ReadAttributePtr attribute_input = component.attribute_try_get_for_read(
+ input_name, domain, data_type);
+
+ if (!attribute_input) {
+ params.error_message_add(NodeWarningType::Error,
+ TIP_("No attribute with name \"") + input_name + "\"");
+ return;
+ }
+
+ OutputAttributePtr attribute_result = component.attribute_try_get_for_output(
+ result_name, domain, data_type);
+ if (!attribute_result) {
+ params.error_message_add(NodeWarningType::Error,
+ TIP_("Could not find or create attribute with name \"") +
+ result_name + "\"");
+ return;
+ }
+
+ switch (data_type) {
+ case CD_PROP_FLOAT: {
+ map_range_float(*attribute_input, *attribute_result, params);
+ break;
+ }
+ case CD_PROP_FLOAT3: {
+ map_range_float3(*attribute_input, *attribute_result, params);
+ break;
+ }
+ default:
+ BLI_assert_unreachable();
+ }
+
+ attribute_result.apply_span_and_save();
+}
+
+static void geo_node_attribute_map_range_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+
+ if (geometry_set.has<MeshComponent>()) {
+ map_range_attribute(geometry_set.get_component_for_write<MeshComponent>(), params);
+ }
+ if (geometry_set.has<PointCloudComponent>()) {
+ map_range_attribute(geometry_set.get_component_for_write<PointCloudComponent>(), params);
+ }
+
+ params.set_output("Geometry", geometry_set);
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_attribute_map_range()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(
+ &ntype, GEO_NODE_ATTRIBUTE_MAP_RANGE, "Attribute Map Range", NODE_CLASS_ATTRIBUTE, 0);
+ node_type_socket_templates(
+ &ntype, geo_node_attribute_map_range_in, geo_node_attribute_map_range_out);
+ ntype.geometry_node_execute = blender::nodes::geo_node_attribute_map_range_exec;
+ node_type_init(&ntype, geo_node_attribute_map_range_init);
+ node_type_update(&ntype, geo_node_attribute_map_range_update);
+ node_type_storage(
+ &ntype, "NodeAttributeMapRange", node_free_standard_storage, node_copy_standard_storage);
+ ntype.draw_buttons = fn_attribute_map_range_layout;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc
index 9c48e7c44ba..0c970f0d2e2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc
@@ -223,8 +223,10 @@ Mesh *create_cylinder_or_cone_mesh(const float radius_top,
transform.values,
true);
+ BMeshToMeshParams params{};
+ params.calc_object_remap = false;
Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
- BM_mesh_bm_to_me_for_eval(bm, mesh, nullptr);
+ BM_mesh_bm_to_me(nullptr, bm, mesh, &params);
BM_mesh_free(bm);
return mesh;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc
index 1803a13f651..f8a9bfd2ed1 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc
@@ -50,8 +50,10 @@ static Mesh *create_cube_mesh(const float size)
size,
true);
+ BMeshToMeshParams params{};
+ params.calc_object_remap = false;
Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
- BM_mesh_bm_to_me_for_eval(bm, mesh, nullptr);
+ BM_mesh_bm_to_me(nullptr, bm, mesh, &params);
BM_mesh_free(bm);
return mesh;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_plane.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc
index eff84d7d1ad..1b9ec91a2f6 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_plane.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc
@@ -27,14 +27,14 @@
#include "node_geometry_util.hh"
-static bNodeSocketTemplate geo_node_mesh_primitive_plane_in[] = {
+static bNodeSocketTemplate geo_node_mesh_primitive_grid_in[] = {
{SOCK_FLOAT, N_("Size"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE},
- {SOCK_INT, N_("Vertices X"), 10, 0.0f, 0.0f, 0.0f, 2, 1000},
- {SOCK_INT, N_("Vertices Y"), 10, 0.0f, 0.0f, 0.0f, 2, 1000},
+ {SOCK_INT, N_("Vertices X"), 3, 0.0f, 0.0f, 0.0f, 2, 1000},
+ {SOCK_INT, N_("Vertices Y"), 3, 0.0f, 0.0f, 0.0f, 2, 1000},
{-1, ""},
};
-static bNodeSocketTemplate geo_node_mesh_primitive_plane_out[] = {
+static bNodeSocketTemplate geo_node_mesh_primitive_grid_out[] = {
{SOCK_GEOMETRY, N_("Geometry")},
{-1, ""},
};
@@ -51,14 +51,14 @@ static void calculate_uvs(Mesh *mesh, Span<MVert> verts, Span<MLoop> loops, cons
for (const int i : loops.index_range()) {
const float3 &co = verts[loops[i].v].co;
- uvs[i].x = (co.x + size) / (size * 2.0f);
- uvs[i].y = (co.y + size) / (size * 2.0f);
+ uvs[i].x = (co.x + (size * 0.5)) / size;
+ uvs[i].y = (co.y + (size * 0.5)) / size;
}
uv_attribute.apply_span_and_save();
}
-static Mesh *create_plane_mesh(const int verts_x, const int verts_y, const float size)
+static Mesh *create_grid_mesh(const int verts_x, const int verts_y, const float size)
{
const int edges_x = verts_x - 1;
const int edges_y = verts_y - 1;
@@ -75,9 +75,9 @@ static Mesh *create_plane_mesh(const int verts_x, const int verts_y, const float
{
const float dx = size / edges_x;
const float dy = size / edges_y;
- float x = -size;
+ float x = -size * 0.5;
for (const int x_index : IndexRange(verts_x)) {
- float y = -size;
+ float y = -size * 0.5;
for (const int y_index : IndexRange(verts_y)) {
const int vert_index = x_index * verts_y + y_index;
verts[vert_index].co[0] = x;
@@ -147,7 +147,7 @@ static Mesh *create_plane_mesh(const int verts_x, const int verts_y, const float
return mesh;
}
-static void geo_node_mesh_primitive_plane_exec(GeoNodeExecParams params)
+static void geo_node_mesh_primitive_grid_exec(GeoNodeExecParams params)
{
const float size = params.extract_input<float>("Size");
const int verts_x = params.extract_input<int>("Vertices X");
@@ -157,7 +157,7 @@ static void geo_node_mesh_primitive_plane_exec(GeoNodeExecParams params)
return;
}
- Mesh *mesh = create_plane_mesh(verts_x, verts_y, size);
+ Mesh *mesh = create_grid_mesh(verts_x, verts_y, size);
BLI_assert(BKE_mesh_is_valid(mesh));
params.set_output("Geometry", GeometrySet::create_with_mesh(mesh));
@@ -165,13 +165,13 @@ static void geo_node_mesh_primitive_plane_exec(GeoNodeExecParams params)
} // namespace blender::nodes
-void register_node_type_geo_mesh_primitive_plane()
+void register_node_type_geo_mesh_primitive_grid()
{
static bNodeType ntype;
- geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_PLANE, "Plane", NODE_CLASS_GEOMETRY, 0);
+ geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_GRID, "Grid", NODE_CLASS_GEOMETRY, 0);
node_type_socket_templates(
- &ntype, geo_node_mesh_primitive_plane_in, geo_node_mesh_primitive_plane_out);
- ntype.geometry_node_execute = blender::nodes::geo_node_mesh_primitive_plane_exec;
+ &ntype, geo_node_mesh_primitive_grid_in, geo_node_mesh_primitive_grid_out);
+ ntype.geometry_node_execute = blender::nodes::geo_node_mesh_primitive_grid_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc
index f16b37fe977..242cc6ed7df 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc
@@ -52,8 +52,10 @@ static Mesh *create_ico_sphere_mesh(const int subdivisions, const float radius)
transform.values,
true);
+ BMeshToMeshParams params{};
+ params.calc_object_remap = false;
Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
- BM_mesh_bm_to_me_for_eval(bm, mesh, nullptr);
+ BM_mesh_bm_to_me(nullptr, bm, mesh, &params);
BM_mesh_free(bm);
return mesh;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
index b7d249c18bc..8efba91da1a 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
@@ -85,8 +85,10 @@ static Mesh *create_uv_sphere_mesh_bmesh(const float radius, const int segments,
transform.values,
true);
+ BMeshToMeshParams params{};
+ params.calc_object_remap = false;
Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
- BM_mesh_bm_to_me_for_eval(bm, mesh, nullptr);
+ BM_mesh_bm_to_me(nullptr, bm, mesh, &params);
BM_mesh_free(bm);
return mesh;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
index 4795970377a..1e1f5e9d085 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
@@ -310,10 +310,10 @@ BLI_NOINLINE static void interpolate_attribute_corner(const Mesh &mesh,
}
template<typename T>
-BLI_NOINLINE static void interpolate_attribute_polygon(const Mesh &mesh,
- const Span<int> looptri_indices,
- const Span<T> data_in,
- MutableSpan<T> data_out)
+BLI_NOINLINE static void interpolate_attribute_face(const Mesh &mesh,
+ const Span<int> looptri_indices,
+ const Span<T> data_in,
+ MutableSpan<T> data_out)
{
BLI_assert(data_in.size() == mesh.totpoly);
Span<MLoopTri> looptris = get_mesh_looptris(mesh);
@@ -344,8 +344,8 @@ BLI_NOINLINE static void interpolate_attribute(const Mesh &mesh,
mesh, bary_coords, looptri_indices, source_span, output_span);
break;
}
- case ATTR_DOMAIN_POLYGON: {
- interpolate_attribute_polygon<T>(mesh, looptri_indices, source_span, output_span);
+ case ATTR_DOMAIN_FACE: {
+ interpolate_attribute_face<T>(mesh, looptri_indices, source_span, output_span);
break;
}
default: {
@@ -636,7 +636,8 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params)
return;
}
- Vector<GeometryInstanceGroup> set_groups = bke::geometry_set_gather_instances(geometry_set);
+ Vector<GeometryInstanceGroup> set_groups;
+ geometry_set_gather_instances(geometry_set, set_groups);
if (set_groups.is_empty()) {
params.set_output("Geometry", GeometrySet());
return;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc
index dbbb73bd36d..5d8f0a76719 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc
@@ -188,9 +188,8 @@ static void add_instances_from_geometry_component(InstancesComponent &instances,
for (const int i : IndexRange(domain_size)) {
if (instances_data[i].has_value()) {
- float transform[4][4];
- loc_eul_size_to_mat4(transform, positions[i], rotations[i], scales[i]);
- instances.add_instance(*instances_data[i], transform, ids[i]);
+ const float4x4 matrix = float4x4::from_loc_eul_scale(positions[i], rotations[i], scales[i]);
+ instances.add_instance(*instances_data[i], matrix, ids[i]);
}
}
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc
index b79ca0a6197..eb441a0a568 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc
@@ -38,7 +38,7 @@ static bNodeSocketTemplate geo_node_points_to_volume_in[] = {
{-1, ""},
};
-static bNodeSocketTemplate geo_node_point_translate_out[] = {
+static bNodeSocketTemplate geo_node_points_to_volume_out[] = {
{SOCK_GEOMETRY, N_("Geometry")},
{-1, ""},
};
@@ -262,7 +262,7 @@ void register_node_type_geo_points_to_volume()
geo_node_type_base(
&ntype, GEO_NODE_POINTS_TO_VOLUME, "Points to Volume", NODE_CLASS_GEOMETRY, 0);
- node_type_socket_templates(&ntype, geo_node_points_to_volume_in, geo_node_point_translate_out);
+ node_type_socket_templates(&ntype, geo_node_points_to_volume_in, geo_node_points_to_volume_out);
node_type_storage(&ntype,
"NodeGeometryPointsToVolume",
node_free_standard_storage,
diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc
index ef6f0be40f2..2c05c98c9ba 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_transform.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc
@@ -18,7 +18,7 @@
# include <openvdb/openvdb.h>
#endif
-#include "BLI_math_matrix.h"
+#include "BLI_float4x4.hh"
#include "DNA_pointcloud_types.h"
#include "DNA_volume_types.h"
@@ -65,13 +65,12 @@ void transform_mesh(Mesh *mesh,
/* Use only translation if rotation and scale are zero. */
if (use_translate(rotation, scale)) {
if (!translation.is_zero()) {
- BKE_mesh_translate(mesh, translation, true);
+ BKE_mesh_translate(mesh, translation, false);
}
}
else {
- float mat[4][4];
- loc_eul_size_to_mat4(mat, translation, rotation, scale);
- BKE_mesh_transform(mesh, mat, true);
+ const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, scale);
+ BKE_mesh_transform(mesh, matrix.values, false);
BKE_mesh_calc_normals(mesh);
}
}
@@ -83,15 +82,15 @@ static void transform_pointcloud(PointCloud *pointcloud,
{
/* Use only translation if rotation and scale don't apply. */
if (use_translate(rotation, scale)) {
- for (int i = 0; i < pointcloud->totpoint; i++) {
+ for (const int i : IndexRange(pointcloud->totpoint)) {
add_v3_v3(pointcloud->co[i], translation);
}
}
else {
- float mat[4][4];
- loc_eul_size_to_mat4(mat, translation, rotation, scale);
- for (int i = 0; i < pointcloud->totpoint; i++) {
- mul_m4_v3(mat, pointcloud->co[i]);
+ const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, scale);
+ for (const int i : IndexRange(pointcloud->totpoint)) {
+ float3 &co = *(float3 *)pointcloud->co[i];
+ co = matrix * co;
}
}
}
@@ -110,11 +109,9 @@ static void transform_instances(InstancesComponent &instances,
}
}
else {
- float mat[4][4];
-
- loc_eul_size_to_mat4(mat, translation, rotation, scale);
+ const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, scale);
for (float4x4 &transform : transforms) {
- mul_m4_m4_pre(transform.ptr(), mat);
+ transform = matrix * transform;
}
}
}
@@ -136,8 +133,7 @@ static void transform_volume(Volume *volume,
Main *bmain = DEG_get_bmain(params.depsgraph());
BKE_volume_load(volume, bmain);
- float matrix[4][4];
- loc_eul_size_to_mat4(matrix, translation, rotation, limited_scale);
+ const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, limited_scale);
openvdb::Mat4s vdb_matrix;
memcpy(vdb_matrix.asPointer(), matrix, sizeof(float[4][4]));
diff --git a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc
index 54dccb613a1..1c0e7106b19 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc
@@ -36,7 +36,7 @@
static bNodeSocketTemplate geo_node_volume_to_mesh_in[] = {
{SOCK_GEOMETRY, N_("Geometry")},
- {SOCK_STRING, N_("Grid")},
+ {SOCK_STRING, N_("Density")},
{SOCK_FLOAT, N_("Voxel Size"), 0.3f, 0.0f, 0.0f, 0.0f, 0.01f, FLT_MAX},
{SOCK_FLOAT, N_("Voxel Amount"), 64.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX},
{SOCK_FLOAT, N_("Threshold"), 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX},
@@ -64,7 +64,7 @@ static void geo_node_volume_to_mesh_init(bNodeTree *UNUSED(ntree), bNode *node)
sizeof(NodeGeometryVolumeToMesh), __func__);
data->resolution_mode = VOLUME_TO_MESH_RESOLUTION_MODE_GRID;
- bNodeSocket *grid_socket = nodeFindSocket(node, SOCK_IN, "Grid");
+ bNodeSocket *grid_socket = nodeFindSocket(node, SOCK_IN, "Density");
bNodeSocketValueString *grid_socket_value = (bNodeSocketValueString *)grid_socket->default_value;
STRNCPY(grid_socket_value->value, "density");
@@ -120,7 +120,7 @@ static void create_mesh_from_volume(GeometrySet &geometry_set_in,
Main *bmain = DEG_get_bmain(params.depsgraph());
BKE_volume_load(const_cast<Volume *>(volume), bmain);
- const std::string grid_name = params.get_input<std::string>("Grid");
+ const std::string grid_name = params.get_input<std::string>("Density");
VolumeGrid *volume_grid = BKE_volume_grid_find(volume, grid_name.c_str());
if (volume_grid == nullptr) {
return;
diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc
index 26df3f77738..b583523da98 100644
--- a/source/blender/nodes/intern/node_socket.cc
+++ b/source/blender/nodes/intern/node_socket.cc
@@ -52,7 +52,7 @@
struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree,
struct bNode *node,
struct bNodeSocketTemplate *stemp,
- int in_out)
+ eNodeSocketInOut in_out)
{
bNodeSocket *sock = nodeAddStaticSocket(
ntree, node, in_out, stemp->type, stemp->subtype, stemp->identifier, stemp->name);
@@ -102,8 +102,11 @@ struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree,
return sock;
}
-static bNodeSocket *verify_socket_template(
- bNodeTree *ntree, bNode *node, int in_out, ListBase *socklist, bNodeSocketTemplate *stemp)
+static bNodeSocket *verify_socket_template(bNodeTree *ntree,
+ bNode *node,
+ eNodeSocketInOut in_out,
+ ListBase *socklist,
+ bNodeSocketTemplate *stemp)
{
bNodeSocket *sock;
@@ -132,7 +135,7 @@ static bNodeSocket *verify_socket_template(
static void verify_socket_template_list(bNodeTree *ntree,
bNode *node,
- int in_out,
+ eNodeSocketInOut in_out,
ListBase *socklist,
bNodeSocketTemplate *stemp_first)
{
diff --git a/source/blender/nodes/intern/node_tree_multi_function.cc b/source/blender/nodes/intern/node_tree_multi_function.cc
index b973350becd..c77a6b42f97 100644
--- a/source/blender/nodes/intern/node_tree_multi_function.cc
+++ b/source/blender/nodes/intern/node_tree_multi_function.cc
@@ -164,7 +164,8 @@ static DataTypeConversions create_implicit_conversions()
add_implicit_conversion<float, float2>(conversions);
add_implicit_conversion<float, float3>(conversions);
add_implicit_conversion<float, int32_t>(conversions);
- add_implicit_conversion<float, bool>(conversions);
+ add_implicit_conversion<float, bool>(
+ conversions, "float to boolean", [](float a) { return a > 0.0f; });
add_implicit_conversion<float, Color4f>(
conversions, "float to Color4f", [](float a) { return Color4f(a, a, a, 1.0f); });
@@ -189,7 +190,8 @@ static DataTypeConversions create_implicit_conversions()
add_implicit_conversion<float3, Color4f>(
conversions, "float3 to Color4f", [](float3 a) { return Color4f(a.x, a.y, a.z, 1.0f); });
- add_implicit_conversion<int32_t, bool>(conversions);
+ add_implicit_conversion<int32_t, bool>(
+ conversions, "int32 to boolean", [](int32_t a) { return a > 0; });
add_implicit_conversion<int32_t, float>(conversions);
add_implicit_conversion<int32_t, float2>(
conversions, "int32 to float2", [](int32_t a) { return float2((float)a); });
@@ -209,9 +211,8 @@ static DataTypeConversions create_implicit_conversions()
return (a) ? Color4f(1.0f, 1.0f, 1.0f, 1.0f) : Color4f(0.0f, 0.0f, 0.0f, 1.0f);
});
- add_implicit_conversion<Color4f, bool>(conversions, "Color4f to boolean", [](Color4f a) {
- return a.r != 0.0f && a.g != 0.0f && a.b != 0.0f;
- });
+ add_implicit_conversion<Color4f, bool>(
+ conversions, "Color4f to boolean", [](Color4f a) { return rgb_to_grayscale(a) > 0.0f; });
add_implicit_conversion<Color4f, float>(
conversions, "Color4f to float", [](Color4f a) { return rgb_to_grayscale(a); });
add_implicit_conversion<Color4f, float2>(
diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc
index 3a9822fbc8e..472f903e1a5 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc
@@ -23,6 +23,8 @@
#include "node_shader_util.h"
+#include "NOD_math_functions.hh"
+
/* **************** VECTOR MATH ******************** */
static bNodeSocketTemplate sh_node_vector_math_in[] = {
{SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
@@ -177,117 +179,79 @@ static const blender::fn::MultiFunction &get_multi_function(
{
using blender::float3;
- const int mode = builder.bnode().custom1;
- switch (mode) {
- case NODE_VECTOR_MATH_ADD: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
- "Add", [](float3 a, float3 b) { return a + b; }};
- return fn;
- }
- case NODE_VECTOR_MATH_SUBTRACT: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
- "Subtract", [](float3 a, float3 b) { return a - b; }};
- return fn;
- }
- case NODE_VECTOR_MATH_MULTIPLY: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
- "Multiply", [](float3 a, float3 b) { return a * b; }};
- return fn;
- }
- case NODE_VECTOR_MATH_DIVIDE: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
- "Divide", [](float3 a, float3 b) { return float3::safe_divide(a, b); }};
- return fn;
- }
- case NODE_VECTOR_MATH_CROSS_PRODUCT: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
- "Cross Product", float3::cross_high_precision};
- return fn;
- }
- case NODE_VECTOR_MATH_PROJECT: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{"Project", float3::project};
- return fn;
- }
- case NODE_VECTOR_MATH_REFLECT: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
- "Reflect", [](float3 a, float3 b) { return a.reflected(b); }};
- return fn;
- }
- case NODE_VECTOR_MATH_DOT_PRODUCT: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{"Dot Product", float3::dot};
- return fn;
- }
- case NODE_VECTOR_MATH_DISTANCE: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{"Distance",
- float3::distance};
- return fn;
- }
- case NODE_VECTOR_MATH_LENGTH: {
- static blender::fn::CustomMF_SI_SO<float3, float> fn{"Length",
- [](float3 a) { return a.length(); }};
- return fn;
- }
- case NODE_VECTOR_MATH_SCALE: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float, float3> fn{
- "Scale", [](float3 a, float factor) { return a * factor; }};
- return fn;
- }
- case NODE_VECTOR_MATH_NORMALIZE: {
- static blender::fn::CustomMF_SI_SO<float3, float3> fn{
- "Normalize", [](float3 a) { return a.normalized(); }};
- return fn;
- }
- case NODE_VECTOR_MATH_REFRACT: {
- static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{
- "Refract",
- [](float3 a, float3 b, float c) { return float3::refract(a, b.normalized(), c); }};
- return fn;
- }
- case NODE_VECTOR_MATH_FACEFORWARD: {
- static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{
- "Faceforward", float3::faceforward};
- return fn;
- }
- case NODE_VECTOR_MATH_SNAP: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_FLOOR: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_CEIL: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_MODULO: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_FRACTION: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_ABSOLUTE: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_MINIMUM: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_MAXIMUM: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_WRAP: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_SINE: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_COSINE: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_TANGENT: {
- return builder.get_not_implemented_fn();
- }
- default:
- BLI_assert_unreachable();
- return builder.get_not_implemented_fn();
- };
+ NodeVectorMathOperation operation = NodeVectorMathOperation(builder.bnode().custom1);
+
+ const blender::fn::MultiFunction *multi_fn = nullptr;
+
+ blender::nodes::try_dispatch_float_math_fl3_fl3_to_fl3(
+ operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
+ static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{info.title_case_name,
+ function};
+ multi_fn = &fn;
+ });
+ if (multi_fn != nullptr) {
+ return *multi_fn;
+ }
+
+ blender::nodes::try_dispatch_float_math_fl3_fl3_fl3_to_fl3(
+ operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
+ static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{
+ info.title_case_name, function};
+ multi_fn = &fn;
+ });
+ if (multi_fn != nullptr) {
+ return *multi_fn;
+ }
+
+ blender::nodes::try_dispatch_float_math_fl3_fl3_fl_to_fl3(
+ operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
+ static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{
+ info.title_case_name, function};
+ multi_fn = &fn;
+ });
+ if (multi_fn != nullptr) {
+ return *multi_fn;
+ }
+
+ blender::nodes::try_dispatch_float_math_fl3_fl3_to_fl(
+ operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
+ static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{info.title_case_name,
+ function};
+ multi_fn = &fn;
+ });
+ if (multi_fn != nullptr) {
+ return *multi_fn;
+ }
+
+ blender::nodes::try_dispatch_float_math_fl3_fl_to_fl3(
+ operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
+ static blender::fn::CustomMF_SI_SI_SO<float3, float, float3> fn{info.title_case_name,
+ function};
+ multi_fn = &fn;
+ });
+ if (multi_fn != nullptr) {
+ return *multi_fn;
+ }
+
+ blender::nodes::try_dispatch_float_math_fl3_to_fl3(
+ operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
+ static blender::fn::CustomMF_SI_SO<float3, float3> fn{info.title_case_name, function};
+ multi_fn = &fn;
+ });
+ if (multi_fn != nullptr) {
+ return *multi_fn;
+ }
+
+ blender::nodes::try_dispatch_float_math_fl3_to_fl(
+ operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
+ static blender::fn::CustomMF_SI_SO<float3, float> fn{info.title_case_name, function};
+ multi_fn = &fn;
+ });
+ if (multi_fn != nullptr) {
+ return *multi_fn;
+ }
+
+ return builder.get_not_implemented_fn();
}
static void sh_node_vector_math_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder)
diff --git a/source/blender/python/gpu/gpu_py_state.c b/source/blender/python/gpu/gpu_py_state.c
index 110f5a6ff55..6b0fade8d1c 100644
--- a/source/blender/python/gpu/gpu_py_state.c
+++ b/source/blender/python/gpu/gpu_py_state.c
@@ -85,19 +85,20 @@ PyDoc_STRVAR(
" Defines the fixed pipeline blending equation.\n"
"\n"
" :param mode: The type of blend mode.\n"
- " * ``NONE`` No blending.\n"
- " * ``ALPHA`` The original color channels are interpolated according to the alpha value.\n"
- " * ``ALPHA_PREMULT`` The original color channels are interpolated according to the alpha "
- "value with the new colors pre-multiplied by this value.\n"
- " * ``ADDITIVE`` The original color channels are added by the corresponding ones.\n"
- " * ``ADDITIVE_PREMULT`` The original color channels are added by the corresponding ones "
+ " * ``NONE`` No blending.\n"
+ " * ``ALPHA`` The original color channels are interpolated according to the alpha "
+ "value.\n"
+ " * ``ALPHA_PREMULT`` The original color channels are interpolated according to the "
+ "alpha value with the new colors pre-multiplied by this value.\n"
+ " * ``ADDITIVE`` The original color channels are added by the corresponding ones.\n"
+ " * ``ADDITIVE_PREMULT`` The original color channels are added by the corresponding ones "
"that are pre-multiplied by the alpha value.\n"
- " * ``MULTIPLY`` The original color channels are multiplied by the corresponding ones.\n"
- " * ``SUBTRACT`` The original color channels are subtracted by the corresponding ones.\n"
- " * ``INVERT`` The original color channels are replaced by its complementary color.\n"
- //" * ``OIT``.\n"
- //" * ``BACKGROUND`` .\n"
- //" * ``CUSTOM`` .\n"
+ " * ``MULTIPLY`` The original color channels are multiplied by the corresponding ones.\n"
+ " * ``SUBTRACT`` The original color channels are subtracted by the corresponding ones.\n"
+ " * ``INVERT`` The original color channels are replaced by its complementary color.\n"
+ //" * ``OIT``.\n"
+ //" * ``BACKGROUND`` .\n"
+ //" * ``CUSTOM`` .\n"
" :type mode: str\n");
static PyObject *pygpu_state_blend_set(PyObject *UNUSED(self), PyObject *value)
{
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index c7816aed3c1..9ac8d4d9f47 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -363,4 +363,12 @@ if(WITH_POTRACE)
add_definitions(-DWITH_POTRACE)
endif()
+if(WITH_PUGIXML)
+ add_definitions(-DWITH_PUGIXML)
+endif()
+
+if(WITH_HARU)
+ add_definitions(-DWITH_HARU)
+endif()
+
blender_add_lib(bf_python "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c
index 9f12c9f80f1..676d1b8045f 100644
--- a/source/blender/python/intern/bpy_app_build_options.c
+++ b/source/blender/python/intern/bpy_app_build_options.c
@@ -65,6 +65,8 @@ static PyStructSequence_Field app_builtopts_info_fields[] = {
{"fluid", NULL},
{"xr_openxr", NULL},
{"potrace", NULL},
+ {"pugixml", NULL},
+ {"haru", NULL},
/* Sentinel (this line prevents `clang-format` wrapping into columns). */
{NULL},
};
@@ -311,6 +313,18 @@ static PyObject *make_builtopts_info(void)
SetObjIncref(Py_False);
#endif
+#ifdef WITH_PUGIXML
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_HARU
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
#undef SetObjIncref
return builtopts_info;
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 49ac2662a31..b9ab0ce4c29 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -2546,7 +2546,7 @@ static int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *sel
if (lib == NULL) {
if (err_not_found) {
PyErr_Format(PyExc_KeyError,
- "%s: lib name '%.240s' "
+ "%s: lib filepath '%.1024s' "
"does not reference a valid library",
err_prefix,
keylib_str);
diff --git a/source/blender/sequencer/CMakeLists.txt b/source/blender/sequencer/CMakeLists.txt
index 9d9553ed858..2b402b4750f 100644
--- a/source/blender/sequencer/CMakeLists.txt
+++ b/source/blender/sequencer/CMakeLists.txt
@@ -72,9 +72,9 @@ set(SRC
intern/multiview.h
intern/prefetch.c
intern/prefetch.h
- intern/proxy_job.c
intern/proxy.c
intern/proxy.h
+ intern/proxy_job.c
intern/render.c
intern/render.h
intern/sequencer.c
diff --git a/source/blender/sequencer/SEQ_iterator.h b/source/blender/sequencer/SEQ_iterator.h
index 44908dca85a..669c55e1f4c 100644
--- a/source/blender/sequencer/SEQ_iterator.h
+++ b/source/blender/sequencer/SEQ_iterator.h
@@ -51,15 +51,6 @@ typedef struct SeqIterator {
} \
((void)0)
-#define SEQ_CURRENT_BEGIN(_ed, _seq) \
- { \
- SeqIterator iter_macro; \
- for (SEQ_iterator_begin(_ed, &iter_macro, true); iter_macro.valid; \
- SEQ_iterator_next(&iter_macro)) { \
- _seq = iter_macro.seq;
-
-#define SEQ_CURRENT_END SEQ_ALL_END
-
void SEQ_iterator_begin(struct Editing *ed, SeqIterator *iter, const bool use_current_sequences);
void SEQ_iterator_next(SeqIterator *iter);
void SEQ_iterator_end(SeqIterator *iter);
diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c
index 33dd74cb527..55d92c1eb10 100644
--- a/source/blender/sequencer/intern/strip_add.c
+++ b/source/blender/sequencer/intern/strip_add.c
@@ -324,7 +324,7 @@ Sequence *SEQ_add_image_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL
/* Set initial scale based on load_data->fit_method. */
char file_path[FILE_MAX];
- BLI_join_dirfile(file_path, sizeof(file_path), load_data->path, load_data->name);
+ BLI_strncpy(file_path, load_data->path, sizeof(file_path));
BLI_path_abs(file_path, BKE_main_blendfile_path(bmain));
ImBuf *ibuf = IMB_loadiffname(file_path, IB_rect, seq->strip->colorspace_settings.name);
if (ibuf != NULL) {
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index e0c4ab8eaf3..0922aaaee53 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -218,13 +218,6 @@ static bool wm_draw_region_stereo_set(Main *bmain,
return false;
}
-static void wm_area_mark_invalid_backbuf(ScrArea *area)
-{
- if (area->spacetype == SPACE_VIEW3D) {
- ((View3D *)area->spacedata.first)->flag |= V3D_INVALID_BACKBUF;
- }
-}
-
static void wm_region_test_gizmo_do_draw(bContext *C,
ScrArea *area,
ARegion *region,
@@ -739,7 +732,6 @@ static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo)
}
}
- wm_area_mark_invalid_backbuf(area);
CTX_wm_area_set(C, NULL);
GPU_debug_group_end();
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index c7b940d0012..90840aa8358 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -326,7 +326,14 @@ elseif(WIN32)
elseif(APPLE)
if(WITH_PYTHON_MODULE)
- set(TARGETDIR_VER ${BLENDER_VERSION})
+ if(WITH_INSTALL_PORTABLE)
+ set(TARGETDIR_VER $<TARGET_FILE_DIR:blender>/../Resources/${BLENDER_VERSION})
+ # Keep the `BLENDER_VERSION` folder and bpy.so in the build folder.
+ set(INSTALL_BPY_TO_SITE_PACKAGES OFF)
+ else()
+ set(TARGETDIR_VER "${PYTHON_LIBPATH}/Resources/${BLENDER_VERSION}")
+ set(INSTALL_BPY_TO_SITE_PACKAGES ON)
+ endif()
else()
set(TARGETDIR_VER Blender.app/Contents/Resources/${BLENDER_VERSION})
endif()
@@ -686,6 +693,26 @@ elseif(WIN32)
DESTINATION "."
)
endif()
+ if(MSVC_ASAN)
+ # The asan dll's can be found in the same folder as the compiler, this is the easiest way to find these.
+ string(REPLACE "cl.exe" "clang_rt.asan_dynamic-x86_64.dll" ASAN_DLL ${CMAKE_C_COMPILER})
+ string(REPLACE "cl.exe" "clang_rt.asan_dbg_dynamic-x86_64.dll" ASAN_DEBUG_DLL ${CMAKE_C_COMPILER})
+ if(NOT EXISTS "${ASAN_DLL}")
+ message(FATAL_ERROR "Asan is enabled, but the ASAN runtime is not detected, this is an optional component during the MSVC install, please install it")
+ endif()
+ install(
+ FILES ${ASAN_DLL}
+ DESTINATION "."
+ CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel
+ )
+ install(
+ FILES ${ASAN_DEBUG_DLL}
+ DESTINATION "."
+ CONFIGURATIONS Debug
+ )
+ unset(ASAN_DLL)
+ unset(ASAN_DEBUG_DLL)
+ endif()
if(WITH_GMP)
install(
@@ -1005,6 +1032,20 @@ elseif(APPLE)
FILES ${LIBDIR}/openmp/lib/libomp.dylib
DESTINATION Blender.app/Contents/Resources/lib
)
+ if(WITH_PYTHON_MODULE)
+ # Move the dylib in a Blender version folder to keep the corresponding OpenMP version.
+ install(
+ DIRECTORY ${CMAKE_BINARY_DIR}/Resources/lib
+ DESTINATION ${TARGETDIR_VER}
+ )
+ add_custom_command(TARGET blender POST_BUILD
+ # The old `LC_LOAD_DYLIB` is the `LC_ID_DYLIB` of the LIBDIR OpenMP dylib.
+ # Change it to support multiple rpaths.
+ COMMAND xcrun install_name_tool -change "@executable_path/../Resources/lib/libomp.dylib" "@rpath/libomp.dylib" "$<TARGET_FILE:blender>"
+ # For installation into site-packages.
+ COMMAND xcrun install_name_tool -add_rpath "@loader_path/../Resources/${BLENDER_VERSION}/lib" "$<TARGET_FILE:blender>"
+ )
+ endif()
endif()
if(WITH_LLVM AND NOT LLVM_STATIC)
@@ -1036,6 +1077,14 @@ elseif(APPLE)
)
unset(_py_inc_suffix)
endif()
+ if(WITH_PYTHON_MODULE)
+ if(INSTALL_BPY_TO_SITE_PACKAGES)
+ install(
+ TARGETS blender
+ LIBRARY DESTINATION ${PYTHON_LIBPATH}/site-packages
+ )
+ endif()
+ endif()
if(WITH_DRACO)
install(
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 8941cc671dd..3d9201bec04 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -47,9 +47,14 @@ unset(_default_test_python_exe)
set(TEST_BLENDER_EXE_PARAMS --background -noaudio --factory-startup --debug-memory --debug-exit-on-error --python-exit-code 1)
# Python CTests
-if(WITH_BLENDER AND WITH_PYTHON)
+if(WITH_BLENDER AND WITH_PYTHON AND NOT WITH_PYTHON_MODULE)
add_subdirectory(python)
endif()
+# Blender as python module tests.
+if(WITH_PYTHON_MODULE)
+ add_subdirectory(blender_as_python_module)
+endif()
+
# GTest
add_subdirectory(gtests)
diff --git a/tests/blender_as_python_module/CMakeLists.txt b/tests/blender_as_python_module/CMakeLists.txt
new file mode 100644
index 00000000000..98e081672e9
--- /dev/null
+++ b/tests/blender_as_python_module/CMakeLists.txt
@@ -0,0 +1,33 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2021, Blender Foundation
+# All rights reserved.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+function(add_blender_as_python_module_test testname testscript)
+ if(NOT TEST_PYTHON_EXE)
+ message(FATAL_ERROR "No Python configured for running tests, set TEST_PYTHON_EXE.")
+ endif()
+
+ add_test(
+ NAME ${testname}
+ COMMAND ${TEST_PYTHON_EXE} ${testscript} ${ARGN}
+ )
+endfunction()
+
+add_blender_as_python_module_test(import_bpy ${CMAKE_CURRENT_LIST_DIR}/import_bpy.py)
diff --git a/tests/blender_as_python_module/import_bpy.py b/tests/blender_as_python_module/import_bpy.py
new file mode 100644
index 00000000000..bdc0277cfec
--- /dev/null
+++ b/tests/blender_as_python_module/import_bpy.py
@@ -0,0 +1,19 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+# ***** END GPL LICENSE BLOCK *****
+
+# Just import bpy and see if there are any dynamic loader errors.
+import bpy
diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt
index 969b748e973..92cebb7d274 100644
--- a/tests/python/CMakeLists.txt
+++ b/tests/python/CMakeLists.txt
@@ -713,6 +713,33 @@ if(WITH_CYCLES OR WITH_OPENGL_RENDER_TESTS)
endif()
endif()
+if(WITH_COMPOSITOR)
+ set(compositor_tests
+ color
+ converter
+ distort
+ filter
+ input
+ matte
+ output
+ vector
+
+ multiple_node_setups
+ )
+
+ foreach(comp_test ${compositor_tests})
+ add_python_test(
+ compositor_${comp_test}_test
+ ${CMAKE_CURRENT_LIST_DIR}/compositor_render_tests.py
+ -blender "${TEST_BLENDER_EXE}"
+ -testdir "${TEST_SRC_DIR}/compositor/${comp_test}"
+ -idiff "${OPENIMAGEIO_IDIFF}"
+ -outdir "${TEST_OUT_DIR}/compositor"
+ )
+ endforeach()
+
+endif()
+
if(WITH_OPENGL_DRAW_TESTS)
if(NOT OPENIMAGEIO_IDIFF)
MESSAGE(STATUS "Disabling OpenGL draw tests because OIIO idiff does not exist")
diff --git a/tests/python/bl_blendfile_library_overrides.py b/tests/python/bl_blendfile_library_overrides.py
index ab75a410590..e2c6432b380 100644
--- a/tests/python/bl_blendfile_library_overrides.py
+++ b/tests/python/bl_blendfile_library_overrides.py
@@ -1,6 +1,6 @@
# Apache License, Version 2.0
-# ./blender.bin --background -noaudio --python tests/python/bl_blendfile_library_overrides.py
+# ./blender.bin --background -noaudio --python tests/python/bl_blendfile_library_overrides.py -- --output-dir=/tmp/
import pathlib
import bpy
import sys
@@ -16,6 +16,8 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase):
OBJECT_LIBRARY_PARENT = "LibMeshParent"
MESH_LIBRARY_CHILD = "LibMeshChild"
OBJECT_LIBRARY_CHILD = "LibMeshChild"
+ MESH_LIBRARY_PERMISSIVE = "LibMeshPermissive"
+ OBJECT_LIBRARY_PERMISSIVE = "LibMeshPermissive"
def __init__(self, args):
self.args = args
@@ -33,6 +35,14 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase):
obj_child = bpy.data.objects.new(TestLibraryOverrides.OBJECT_LIBRARY_CHILD, object_data=mesh_child)
obj_child.parent = obj
bpy.context.collection.objects.link(obj_child)
+
+ mesh = bpy.data.meshes.new(TestLibraryOverrides.MESH_LIBRARY_PERMISSIVE)
+ obj = bpy.data.objects.new(TestLibraryOverrides.OBJECT_LIBRARY_PERMISSIVE, object_data=mesh)
+ bpy.context.collection.objects.link(obj)
+ obj.override_template_create()
+ prop = obj.override_library.properties.add(rna_path='scale')
+ prop.operations.add(operation='NOOP')
+
bpy.ops.wm.save_as_mainfile(filepath=str(self.output_path), check_existing=False, compress=False)
def __ensure_override_library_updated(self):
@@ -47,29 +57,109 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase):
bpy.ops.wm.link(directory=str(link_dir), filename=TestLibraryOverrides.OBJECT_LIBRARY_PARENT)
obj = bpy.data.objects[TestLibraryOverrides.OBJECT_LIBRARY_PARENT]
- assert(obj.override_library is None)
+ self.assertIsNone(obj.override_library)
local_id = obj.override_create()
- assert(local_id.override_library)
- assert(local_id.data.override_library is None)
+ self.assertIsNotNone(local_id.override_library)
+ self.assertIsNone(local_id.data.override_library)
assert(len(local_id.override_library.properties) == 0)
local_id.location.y = 1.0
self.__ensure_override_library_updated()
- assert (len(local_id.override_library.properties) == 1)
assert(len(local_id.override_library.properties) == 1)
override_prop = local_id.override_library.properties[0]
assert(override_prop.rna_path == "location");
assert(len(override_prop.operations) == 1)
override_operation = override_prop.operations[0]
- assert (override_operation.operation == 'REPLACE')
+ assert(override_operation.operation == 'REPLACE')
# Setting location.y overridded all elements in the location array. -1 is a wildcard.
assert(override_operation.subitem_local_index == -1)
+ def test_link_permissive(self):
+ """
+ Linked assets with a permissive template.
+
+ - Checks if the NOOP is properly handled.
+ - Checks if the correct properties and operations are created/updated.
+ """
+ bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True)
+ bpy.data.orphans_purge()
+
+ link_dir = self.output_path / "Object"
+ bpy.ops.wm.link(directory=str(link_dir), filename=TestLibraryOverrides.OBJECT_LIBRARY_PERMISSIVE)
+
+ obj = bpy.data.objects[TestLibraryOverrides.OBJECT_LIBRARY_PERMISSIVE]
+ self.assertIsNotNone(obj.override_library)
+ local_id = obj.override_create()
+ self.assertIsNotNone(local_id.override_library)
+ self.assertIsNone(local_id.data.override_library)
+ assert(len(local_id.override_library.properties) == 1)
+ override_prop = local_id.override_library.properties[0]
+ assert(override_prop.rna_path == "scale");
+ assert(len(override_prop.operations) == 1)
+ override_operation = override_prop.operations[0]
+ assert(override_operation.operation == 'NOOP')
+ assert(override_operation.subitem_local_index == -1)
+
+ local_id.location.y = 1.0
+ local_id.scale.x = 0.5
+ # `scale.x` will apply, but will be reverted when the library overrides
+ # are updated. This is by design so python scripts can still alter the
+ # properties locally what is a typical usecase in productions.
+ assert(local_id.scale.x == 0.5)
+ assert(local_id.location.y == 1.0)
+
+ self.__ensure_override_library_updated()
+ assert(local_id.scale.x == 1.0)
+ assert(local_id.location.y == 1.0)
+
+ assert(len(local_id.override_library.properties) == 2)
+ override_prop = local_id.override_library.properties[0]
+ assert(override_prop.rna_path == "scale");
+ assert(len(override_prop.operations) == 1)
+ override_operation = override_prop.operations[0]
+ assert(override_operation.operation == 'NOOP')
+ assert(override_operation.subitem_local_index == -1)
+
+ override_prop = local_id.override_library.properties[1]
+ assert(override_prop.rna_path == "location");
+ assert(len(override_prop.operations) == 1)
+ override_operation = override_prop.operations[0]
+ assert(override_operation.operation == 'REPLACE')
+ assert (override_operation.subitem_local_index == -1)
+
+
+class TestLibraryTemplate(TestHelper, unittest.TestCase):
+ MESH_LIBRARY_PERMISSIVE = "LibMeshPermissive"
+ OBJECT_LIBRARY_PERMISSIVE = "LibMeshPermissive"
+
+ def __init__(self, args):
+ pass
+
+ def test_permissive_template(self):
+ """
+ Test setting up a permissive template.
+ """
+ bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True)
+ mesh = bpy.data.meshes.new(TestLibraryTemplate.MESH_LIBRARY_PERMISSIVE)
+ obj = bpy.data.objects.new(TestLibraryTemplate.OBJECT_LIBRARY_PERMISSIVE, object_data=mesh)
+ bpy.context.collection.objects.link(obj)
+ assert(obj.override_library is None)
+ obj.override_template_create()
+ assert(obj.override_library is not None)
+ assert(len(obj.override_library.properties) == 0)
+ prop = obj.override_library.properties.add(rna_path='scale')
+ assert(len(obj.override_library.properties) == 1)
+ assert(len(prop.operations) == 0)
+ operation = prop.operations.add(operation='NOOP')
+ assert(len(prop.operations) == 1)
+ assert(operation.operation == 'NOOP')
+
TESTS = (
TestLibraryOverrides,
+ TestLibraryTemplate,
)
@@ -95,6 +185,7 @@ def main():
# Don't write thumbnails into the home directory.
bpy.context.preferences.filepaths.use_save_preview_images = False
+ bpy.context.preferences.experimental.use_override_templates = True
for Test in TESTS:
Test(args).run_all_tests()
diff --git a/tests/python/compositor_render_tests.py b/tests/python/compositor_render_tests.py
new file mode 100644
index 00000000000..6a026ae88d2
--- /dev/null
+++ b/tests/python/compositor_render_tests.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python3
+# Apache License, Version 2.0
+
+import argparse
+import os
+import shlex
+import shutil
+import subprocess
+import sys
+
+
+# When run from inside Blender, render and exit.
+try:
+ import bpy
+ inside_blender = True
+except ImportError:
+ inside_blender = False
+
+def get_arguments(filepath, output_filepath):
+ return [
+ "--background",
+ "-noaudio",
+ "--factory-startup",
+ "--enable-autoexec",
+ "--debug-memory",
+ "--debug-exit-on-error",
+ filepath,
+ "-P",
+ os.path.realpath(__file__),
+ "-o", output_filepath,
+ "-F", "PNG",
+ "-f", "1"]
+
+
+def create_argparse():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-blender", nargs="+")
+ parser.add_argument("-testdir", nargs=1)
+ parser.add_argument("-outdir", nargs=1)
+ parser.add_argument("-idiff", nargs=1)
+ return parser
+
+
+def main():
+ parser = create_argparse()
+ args = parser.parse_args()
+
+ blender = args.blender[0]
+ test_dir = args.testdir[0]
+ idiff = args.idiff[0]
+ output_dir = args.outdir[0]
+
+ from modules import render_report
+ report = render_report.Report("Compositor", output_dir, idiff)
+ report.set_pixelated(True)
+ report.set_reference_dir("compositor_renders")
+ ok = report.run(test_dir, blender, get_arguments, batch=True)
+
+ sys.exit(not ok)
+
+
+if not inside_blender and __name__ == "__main__":
+ main()
+
diff --git a/tests/python/operators.py b/tests/python/operators.py
index 461880ec214..309a872ac67 100644
--- a/tests/python/operators.py
+++ b/tests/python/operators.py
@@ -137,7 +137,6 @@ def main():
MeshTest("CubeEdgeSplit", "testCubeEdgeSplit", "expectedCubeEdgeSplit",
[OperatorSpecEditMode("edge_split", {}, "EDGE", {2, 5, 8, 11, 14, 17, 20, 23})]),
- ### 25
# edge ring select - Cannot be tested. Need user input.
# MeshTest("CubeEdgeRingSelect", "testCubeEdgeRingSelect", "expectedCubeEdgeRingSelect",
# [OperatorSpecEditMode("edgering_select", {}, "EDGE", {5, 20, 25, 26})]),
@@ -146,6 +145,16 @@ def main():
# MeshTest("EmptyMeshEdgeRingSelect", "testEmptyMeshdgeRingSelect", "expectedEmptyMeshEdgeRingSelect",
# [OperatorSpecEditMode("edgering_select", {}, "VERT", {})]),
+ # edges select sharp
+ MeshTest("CubeEdgesSelectSharp", "testCubeEdgeSelectSharp", "expectedCubeEdgeSelectSharp",
+ [OperatorSpecEditMode("edges_select_sharp", {}, "EDGE", {20})]),
+ MeshTest("SphereEdgesSelectSharp", "testSphereEdgesSelectSharp", "expectedSphereEdgeSelectSharp",
+ [OperatorSpecEditMode("edges_select_sharp", {"sharpness": 0.25}, "EDGE", {288})]),
+ MeshTest("HoledSphereEdgesSelectSharp", "testHoledSphereEdgesSelectSharp", "expectedHoledSphereEdgeSelectSharp",
+ [OperatorSpecEditMode("edges_select_sharp", {"sharpness": 0.18}, "VERT", {})]),
+ MeshTest("EmptyMeshEdgesSelectSharp", "testEmptyMeshEdgeSelectSharp", "expectedEmptyMeshEdgeSelectSharp",
+ [OperatorSpecEditMode("edges_select_sharp", {}, "VERT", {})]),
+
# face make planar
MeshTest("MonkeyFaceMakePlanar", "testMonkeyFaceMakePlanar",
"expectedMonkeyFaceMakePlanar",
@@ -208,6 +217,85 @@ def main():
[OperatorSpecEditMode("inset", {"thickness": 0.4,
"use_relative_offset": True}, "FACE",
{35, 36, 37, 45, 46, 47, 55, 56, 57})]),
+
+ # loop multi select
+ MeshTest("MokeyLoopMultiSelect", "testMonkeyLoopMultiSelect", "expectedMonkeyLoopMultiSelect",
+ [OperatorSpecEditMode("loop_multi_select", {}, "VERT", {355, 359, 73, 301, 302})]),
+ MeshTest("HoledGridLoopMultiSelect", "testGridLoopMultiSelect", "expectedGridLoopMultiSelect",
+ [OperatorSpecEditMode("loop_multi_select", {}, "VERT", {257, 169, 202, 207, 274, 278, 63})]),
+ MeshTest("EmptyMeshLoopMultiSelect", "testEmptyMeshLoopMultiSelect", "expectedEmptyMeshLoopMultiSelect",
+ [OperatorSpecEditMode("loop_multi_select", {}, "VERT", {})]),
+
+ # select all
+ MeshTest("CircleSelectAll", "testCircleSelectAll", "expectedCircleSelectAll",
+ [OperatorSpecEditMode("select_all", {}, "VERT", {1})]),
+ MeshTest("IsolatedVertsSelectAll", "testIsolatedVertsSelectAll", "expectedIsolatedVertsSelectAll",
+ [OperatorSpecEditMode("select_all", {}, "VERT", {})]),
+ MeshTest("EmptyMeshSelectAll", "testEmptyMeshSelectAll", "expectedEmptyMeshSelectAll",
+ [OperatorSpecEditMode("select_all", {}, "VERT", {})]),
+
+ # select axis - Cannot be tested. Needs active vert selection
+ # MeshTest("MonkeySelectAxisX", "testMonkeySelectAxisX", "expectedMonkeySelectAxisX",
+ # [OperatorSpecEditMode("select_axis", {"axis": "X"}, "VERT", {13})]),
+ # MeshTest("MonkeySelectAxisY", "testMonkeySelectAxisY", "expectedMonkeySelectAxisY",
+ # [OperatorSpecEditMode("select_axis", {"axis": "Y", "sign": "NEG"}, "FACE", {317})]),
+ # MeshTest("MonkeySelectAxisXYZ", "testMonkeySelectAxisXYZ", "expectedMonkeySelectAxisXYZ",
+ # [OperatorSpecEditMode("select_axis", {"axis": "X", "sign": "NEG"}, "FACE", {317}),
+ # OperatorSpecEditMode("select_axis", {"axis": "Y", "sign": "POS"}, "FACE", {}),
+ # OperatorSpecEditMode("select_axis", {"axis": "Z", "sign": "NEG"}, "FACE", {})]),
+
+ # select faces by sides
+ MeshTest("CubeSelectFacesBySide", "testCubeSelectFacesBySide", "expectedCubeSelectFacesBySide",
+ [OperatorSpecEditMode("select_face_by_sides", {"number": 4}, "FACE", {})]),
+ MeshTest("CubeSelectFacesBySideGreater", "testCubeSelectFacesBySideGreater", "expectedCubeSelectFacesBySideGreater",
+ [OperatorSpecEditMode("select_face_by_sides", {"number": 4, "type": "GREATER", "extend": True}, "FACE", {})]),
+ MeshTest("CubeSelectFacesBySideLess", "testCubeSelectFacesBySideLess", "expectedCubeSelectFacesBySideLess",
+ [OperatorSpecEditMode("select_face_by_sides", {"number": 4, "type": "GREATER", "extend": True}, "FACE", {})]),
+
+ # select interior faces
+ MeshTest("CubeSelectInteriorFaces", "testCubeSelectInteriorFaces", "expectedCubeSelectInteriorFaces",
+ [OperatorSpecEditMode("select_face_by_sides", {"number": 4}, "FACE", {})]),
+ MeshTest("HoledCubeSelectInteriorFaces", "testHoledCubeSelectInteriorFaces", "expectedHoledCubeSelectInteriorFaces",
+ [OperatorSpecEditMode("select_face_by_sides", {"number": 4}, "FACE", {})]),
+ MeshTest("EmptyMeshSelectInteriorFaces", "testEmptyMeshSelectInteriorFaces", "expectedEmptyMeshSelectInteriorFaces",
+ [OperatorSpecEditMode("select_face_by_sides", {"number": 4}, "FACE", {})]),
+
+ # select less
+ MeshTest("MonkeySelectLess", "testMonkeySelectLess", "expectedMonkeySelectLess",
+ [OperatorSpecEditMode("select_less", {}, "VERT", {2, 8, 24, 34, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 68,
+ 69, 70, 71, 74, 75, 78, 80, 81, 82, 83, 90, 91, 93, 95, 97, 99,
+ 101, 109, 111, 115, 117, 119, 121, 123, 125, 127, 129, 130, 131,
+ 132, 133, 134, 135, 136, 138, 141, 143, 145, 147, 149, 151, 153,
+ 155, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
+ 175, 176, 177, 178, 181, 182, 184, 185, 186, 187, 188, 189, 190,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
+ 206, 207, 208, 210, 216, 217, 218, 219, 220, 221, 222, 229, 230,
+ 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255,
+ 257, 259, 263, 267, 269, 271, 275, 277, 289, 291, 293, 295, 309,
+ 310, 311, 312, 316, 317, 318, 319, 320, 323, 325, 327, 329, 331,
+ 341, 347, 349, 350, 351, 354, 356, 359, 361, 363, 365, 367, 369,
+ 375, 379, 381, 382, 385, 386, 387, 388, 389, 390, 391, 392, 393,
+ 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406,
+ 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419,
+ 420, 421, 423, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434,
+ 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447,
+ 448, 449, 450, 451, 452, 454, 455, 456, 457, 458, 459, 460, 461,
+ 462, 463, 464, 471, 473, 474, 475, 476, 477, 478, 479, 480, 481,
+ 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 495,
+ 496, 497, 498, 499, 502, 505})]),
+ MeshTest("HoledCubeSelectLess", "testHoledCubeSelectLess", "expectedHoledCubeSelectLess",
+ [OperatorSpecEditMode("select_face_by_sides", {}, "FACE", {})]),
+ MeshTest("EmptyMeshSelectLess", "testEmptyMeshSelectLess", "expectedEmptyMeshSelectLess",
+ [OperatorSpecEditMode("select_face_by_sides", {}, "VERT", {})]),
+
+ # select linked
+ MeshTest("PlanesSelectLinked", "testPlanesSelectLinked", "expectedPlanesSelectedLinked",
+ [OperatorSpecEditMode("select_linked", {}, "VERT", {7})]),
+ MeshTest("CubesSelectLinked", "testCubesSelectLinked", "expectedCubesSelectLinked",
+ [OperatorSpecEditMode("select_linked", {}, "VERT", {11})]),
+ MeshTest("EmptyMeshSelectLinked", "testEmptyMeshSelectLinked", "expectedEmptyMeshSelectLinked",
+ [OperatorSpecEditMode("select_linked", {}, "VERT", {})]),
+
]
operators_test = RunTest(tests)