Compare commits

..

513 Commits

Author SHA1 Message Date
38b12c763f Merge branch 'master' into soc-2021-porting-modifiers-to-nodes_all 2021-08-22 08:51:26 +02:00
49a16a1ca8 Fix: Default selection in dissolve node. 2021-08-21 23:27:55 +02:00
7ac9f9a97f Fix: Inset socket nameing was wrong 2021-08-20 00:05:24 +02:00
cb66eb8da2 Fix: changed BMiter to BMOIter in BM_tag_<Elem_Type>_from_operator_slot 2021-08-19 23:25:38 +02:00
bfaf97dec9 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes_all 2021-08-19 22:40:00 +02:00
8137c1be09 SOC2021 Porting Modifiers To nodes all
This branch merges all branches from soc2021 porting modifiers to nodes
into one. The branche is mainly used to make a testbuild.
2021-08-19 22:07:01 +02:00
c674adb6f4 SOC2021 Porting Modifiers To nodes all
This branch merges all branches from soc2021 porting modifiers to nodes
into one. The branche is mainly used to make a testbuild.
2021-08-19 07:30:47 +02:00
2fb714443c Merge branch 'soc-2021-porting-modifiers-to-nodes-solidify' into soc-2021-porting-modifiers-to-nodes
# Conflicts:
#	release/scripts/startup/nodeitems_builtins.py
#	source/blender/blenkernel/BKE_node.h
#	source/blender/geometry/CMakeLists.txt
#	source/blender/makesrna/RNA_enum_types.h
#	source/blender/modifiers/CMakeLists.txt
#	source/blender/nodes/NOD_static_types.h
2021-08-17 22:46:29 +02:00
529a132cc9 Merge branch 'soc-2021-porting-modifiers-to-nodes-remesh-voxel' into soc-2021-porting-modifiers-to-nodes
# Conflicts:
#	release/scripts/startup/nodeitems_builtins.py
#	source/blender/blenkernel/BKE_node.h
#	source/blender/blenkernel/intern/node.cc
#	source/blender/nodes/CMakeLists.txt
#	source/blender/nodes/NOD_geometry.h
#	source/blender/nodes/NOD_static_types.h
#	source/blender/nodes/geometry/nodes/node_geo_remesh_voxel.cc
2021-08-17 22:42:40 +02:00
6e58f6b304 Merge branch 'soc-2021-porting-modifiers-to-nodes-remesh-blocks' into soc-2021-porting-modifiers-to-nodes
# Conflicts:
#	release/scripts/startup/nodeitems_builtins.py
#	source/blender/blenkernel/BKE_node.h
#	source/blender/geometry/CMakeLists.txt
#	source/blender/makesrna/intern/rna_nodetree.c
2021-08-17 22:39:49 +02:00
9e4e3b5f5f Merge branch 'soc-2021-porting-modifiers-to-nodes-merge-by-distance' into soc-2021-porting-modifiers-to-nodes
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
#	source/blender/makesrna/RNA_enum_types.h
2021-08-17 22:36:26 +02:00
844d975972 Merge branch 'soc-2021-porting-modifiers-to-nodes-extrude-and-move' into soc-2021-porting-modifiers-to-nodes
# Conflicts:
#	release/scripts/startup/nodeitems_builtins.py
#	source/blender/blenkernel/BKE_node.h
2021-08-17 22:35:07 +02:00
f5f2e685f5 Merge branch 'soc-2021-porting-modifiers-to-nodes-extrude' into soc-2021-porting-modifiers-to-nodes
# Conflicts:
#	release/scripts/startup/nodeitems_builtins.py
#	source/blender/blenkernel/BKE_node.h
#	source/blender/bmesh/intern/bmesh_mesh.c
#	source/blender/bmesh/intern/bmesh_mesh.h
2021-08-17 22:33:55 +02:00
7649b84462 Merge branch 'soc-2021-porting-modifiers-to-nodes-decimate' into soc-2021-porting-modifiers-to-nodes 2021-08-17 22:32:46 +02:00
6dda3a7f2e Cleanup 2021-08-16 07:56:36 +02:00
4a5d913d1d Merge remote-tracking branch 'origin/soc-2021-porting-modifiers-to-nodes-extrude-and-move' into soc-2021-porting-modifiers-to-nodes-extrude-and-move 2021-08-16 07:53:46 +02:00
038b87b8b2 Cleanup 2021-08-16 07:53:30 +02:00
9887dac2fb Geometry Nodes: Mesh Extrude
Node that extrudes vertices, edges and Faces. Uses the
corresponding bmesh operator.

I renamed D12108, which was previously named Mesh Extrude to Mesh Inset,
 because that uses the bmesh inset operators.

 NOTE: This requires an update of the attribute interpolation to work,
 that is not yet in master.

 Part of the GSOC 2021

Differential Revision: https://developer.blender.org/D12224
2021-08-16 07:50:52 +02:00
33c35c9340 Geometry Nodes: Mesh Extrude
Node that extrudes vertices, edges and Faces. Uses the
corresponding bmesh operator.

I renamed D12108, which was previously named Mesh Extrude to Mesh Inset,
 because that uses the bmesh inset operators.

 NOTE: This requires an update of the attribute interpolation to work,
 that is not yet in master.

 Part of the GSOC 2021
2021-08-16 07:48:04 +02:00
fad55ce70b Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-extrude-and-move
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
2021-08-15 09:13:45 +02:00
ce4420e803 Changes based on review by Jacques Lucke
(JacquesLucke)
2021-08-15 09:05:00 +02:00
4bab2cca5d Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-remesh-blocks
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
#	source/blender/modifiers/CMakeLists.txt
2021-08-15 02:10:46 +02:00
fb8c049232 Changes based on review by Hans Goudey (HooglyBoogly) and Jacques Lucke
(JacquesLucke)
2021-08-15 02:07:29 +02:00
45904e2dd1 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-remesh-voxel
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
2021-08-14 21:05:42 +02:00
ec0ebcdcc4 Changes based on review by Hans Goudey (HooglyBoogly) and Jacques Lucke
(JacquesLucke)
2021-08-14 20:52:49 +02:00
ee7b2e2678 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-decimate
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
2021-08-14 15:03:34 +02:00
bcb7f4c172 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-solidify 2021-08-14 00:08:23 +02:00
c54bdc7fb6 fixed typo in rna 2021-08-14 00:01:13 +02:00
a28e518917 Changes based on review by Hans Goudey (HooglyBoogly) 2021-08-13 23:57:13 +02:00
b60fa77678 Added missing line breaks at end of files. 2021-08-13 08:26:39 +02:00
4de8acc88d Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-merge-by-distance 2021-08-13 08:19:37 +02:00
7df84749ad Changes based on review bv Hans Goudey (HooglyBoogly) 2021-08-13 08:18:58 +02:00
20d2c92119 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-merge-by-distance
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
#	source/blender/editors/asset/ED_asset_temp_id_consumer.h
2021-08-12 21:49:52 +02:00
745ff852f5 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-solidify
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
#	source/blender/geometry/intern/solidify_nonmanifold.c
#	source/blender/nodes/NOD_static_types.h
2021-08-06 07:58:14 +02:00
a7dc3d1e90 Merge remote-tracking branch 'origin/soc-2021-porting-modifiers-to-nodes-extrude' into soc-2021-porting-modifiers-to-nodes-extrude 2021-08-06 07:53:56 +02:00
6fd836f53b Merged Master 2021-08-06 07:48:40 +02:00
991f6b15f3 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-extrude
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
2021-08-05 23:50:08 +02:00
aef45a4ef2 Merge remote-tracking branch 'origin/soc-2021-porting-modifiers-to-nodes-extrude' into soc-2021-porting-modifiers-to-nodes-extrude
# Conflicts:
#	source/blender/bmesh/intern/bmesh_mesh.c
#	source/blender/bmesh/intern/bmesh_mesh.h
#	source/blender/nodes/NOD_static_types.h
#	source/blender/nodes/geometry/nodes/node_geo_extrude.cc
2021-08-05 23:48:58 +02:00
504e3c563f added side selection. 2021-08-05 23:47:44 +02:00
b5573bfbf4 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-extrude 2021-08-03 21:02:56 +02:00
ba9561ab0d Geometry Nodes: Extrude
Differential Revision: https://developer.blender.org/D12108
2021-08-02 19:04:04 +02:00
c659af0c13 Geometry Nodes: Extrude 2021-08-02 19:02:38 +02:00
41f75384e7 Merge remote-tracking branch 'origin/soc-2021-porting-modifiers-to-nodes-remesh-voxel' into soc-2021-porting-modifiers-to-nodes-remesh-voxel
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
2021-07-31 00:21:24 +02:00
383a8e519b - changes based on review by Jacques Lucke (JacquesLucke) 2021-07-31 00:20:43 +02:00
6d2cc371b5 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-remesh-voxel
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
2021-07-31 00:15:29 +02:00
7a2994a741 - reverted unneeded change 2021-07-31 00:11:17 +02:00
326d86f23f Merge remote-tracking branch 'origin/soc-2021-porting-modifiers-to-nodes-remesh-blocks' into soc-2021-porting-modifiers-to-nodes-remesh-blocks
# Conflicts:
#	source/blender/nodes/geometry/nodes/node_geo_remesh_blocks.cc
2021-07-31 00:07:32 +02:00
17b7cbe975 - changes based on Review by Jacques Lucke (JacquesLucke) 2021-07-31 00:06:43 +02:00
94210c3186 - changes based on Review by Jacques Lucke (JacquesLucke) 2021-07-30 23:51:31 +02:00
9d2342fd28 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-remesh-blocks 2021-07-30 21:11:26 +02:00
86e359b03b - reverted unrelated changes 2021-07-30 21:07:29 +02:00
4c8def9895 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-decimate
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
#	source/blender/blenloader/intern/versioning_defaults.c
#	source/blender/editors/asset/intern/asset_filter.cc
#	source/blender/editors/interface/interface.c
#	source/blender/editors/interface/view2d_draw.c
#	source/blender/freestyle/intern/winged_edge/Curvature.cpp
#	source/blender/makesdna/DNA_fluid_types.h
#	source/blender/python/intern/bpy_props.c
#	source/blender/windowmanager/WM_types.h
#	source/blender/windowmanager/intern/wm_dragdrop.c
2021-07-30 21:02:50 +02:00
5e198321c2 - changes based on Review by Jacques Lucke (JacquesLucke) and feedback by Miro Horváth (dreamak). 2021-07-30 20:50:44 +02:00
c24be2dd44 GPencil: Fix unreported problems painting after import SVG
After doing an import, the bounding box of the stroke was not calculated and any operation related to brushes (Sculpt, Weight Paint and Vertex Paint) was not working as expected because the bounding box of the stroke was wrong.

This problem was solved automatically after any edit operation, but must be solved in the import process.
2021-07-30 16:56:30 +02:00
3f29b8ec64 Fix T89213: Some modifier properties have wrong subtype
This commit resolves these RNA warnings:
```
offset: "", WARN (bpy.rna): ...\source\blender\python\intern\bpy_rna.c:1505 pyrna_enum_to_py: current value '65536' matches no enum in 'FloatProperty', 'offset', 'subtype'
project_limit: "", WARN (bpy.rna): ...\source\blender\python\intern\bpy_rna.c:1505 pyrna_enum_to_py: current value '65536' matches no enum in 'FloatProperty', 'project_limit', 'subtype'
falloff_radius: "", WARN (bpy.rna): ...\source\blender\python\intern\bpy_rna.c:1505 pyrna_enum_to_py: current value '65567' matches no enum in 'FloatProperty', 'falloff_radius', 'subtype'
```
2021-07-30 16:56:30 +02:00
0b060a585d GHOST/X11: enable EGL
This will replace GLX with EGL for X11. GLEW does not support GLX and EGL
at the same time. Most distributions build GLEW with GLX support, so we
have to use the externally provided GLEW and build with EGL support.
This effectively sets WITH_SYSTEM_GLEW to OFF for all Linux configurations.

Differential Revision: https://developer.blender.org/D12034
2021-07-30 16:56:30 +02:00
e5c7f12f8b Fix T89976: Mirror Keys By Value performs wrong scale conversion
In the graph editor, Mirror Keys by Value would convert the value to mirror
over, to account for different units for linear & rotational properties.
The conversion was done in the different direction, though, resulting in
values that were too large by a factor of (180/pi)^2.
2021-07-30 16:56:30 +02:00
5466552a42 deps/win: Remove media foundation dep for ffmpeg
This caused a blender load error on windows N,
given we do not use these codecs they can safely
be disabled.

This will fix T90200 once the new libraries are
in SVN
2021-07-30 16:56:30 +02:00
ba06899b2a Fix T90295: inconsistent render pass order between Cycles and Eevee 2021-07-30 16:56:30 +02:00
b23cdd5737 Render: remove unused Blender Internal view layer settings
These should have been removed earlier but were forgotten.
2021-07-30 16:56:30 +02:00
df5551fb15 Render: disable Z pass by default, leave only Combined
It was somewhat arbitrary to have this one pass enabled that adds a bit of
additional memory and render time overhead, even though it's not necessarily
more important than others.
2021-07-30 16:56:30 +02:00
11012a8fc1 Assets/UI: Resolve major asset view UI template limitation
Before this, all asset view templates showing the same asset library
would show the same assets, even if they should show different ID types.
That was a major limitation since the design did forsee that this
template can be put anywhere in the UI to display various sub-sets of
assets.

Initially I did the ID type filtering close to the asset-list reading,
because I wanted to optimize reading so that we would only actually read
asset information from disk of the ID type to be shown. But this will be
quite complex and I'm not sure if I'll get to work on this anytime soon.
So this commit moves the filtering to the template display level solving
this limitation.

Note: This also adds the code to filter by tags, together with the ID
type. But it's not actually used anywhere yet.
2021-07-30 16:56:30 +02:00
300632742c Cleanup: Remove unnecessary code for asset view UI template
From what I can tell there is no reason anymore to do this. The design
has changed since this was added.
2021-07-30 16:56:30 +02:00
17fba21226 Assets/UI: Sanity check argument for UILayout.template_asset_view()
Was already doing some sanity checks, but wasn't checking if the passed
property actually is a collection property, which is important.
2021-07-30 16:56:30 +02:00
4b0255238d Cleanup: Pass asset handle to asset iterator, rather than wrapped file
This iterator was introduced before `AssetHandle` existed, so it was
dealing with the file data directly. Now we want as little code as
possible to deal with the file data, all access should happen via the
`AssetHandle`.
2021-07-30 16:56:30 +02:00
83d537c950 Cleanup: Consistent indent style for asset CMakeLists file
Was mixing 4 and 2 space indent in a single file.
2021-07-30 16:56:30 +02:00
ab66f1d792 install_deps: update OIDN to 1.4.1, and ISPC to 1.16.0.
Ref. T88438.
2021-07-30 16:56:30 +02:00
4c97a026e7 install_deps: Update OSL to 1.11.14.1.
This has been a huge pain to get working, for several reasons (new flags
needed, patching is now mandatory, etc.).

Further more, discovered that debian OIIO package is now silently
relying on OpenCV, without even proper handling of this dependency (at
least in the `-dev` package), so had to revert to force-build own OIIO
again on that distro for the time being.

Ref. T88438.
2021-07-30 16:56:30 +02:00
6d296ff00b Cleanup: OSL buildlib patch: Remove .rej part.
This patch contained changes for an `.rej` rejection file generated by
failed patch apply... Definitly nothing to do here.
2021-07-30 16:56:30 +02:00
db796922c8 install_deps: Update OIIO to 1.1.15.1.
Ref. T88438.
2021-07-30 16:56:30 +02:00
350d32f6d5 install_deps: Update llvm to 12.0 (with minimal now being 11.0).
Ref T88438.
2021-07-30 16:56:30 +02:00
d917311776 Install_deps: add flex dependency.
Was already installed on Debian-like and Fedore/Suse actually, now also
explicitely required on Arch and listed in docs.

Ref. T88438.
2021-07-30 16:56:29 +02:00
3a5fd9713e Install_deps: Add zstd dependency.
Ref T88438.
2021-07-30 16:56:29 +02:00
Germano Cavalcante
efee24c34e Fix 'BLI_task_parallel_mempool' keeping 'user_chunk' unchanged
When `BLI_task_parallel_mempool` does not use threading, the
`userdata_chunk` is allocated locally simulating a TLS.

However `func_reduce` is not called so the original chunk is ignored.

`task_parallel_iterator_no_threads` is another function that doesn't call
`func_reduce`. It also ignores `userdata_chunk_local` in the main iterator.

The solution in these cases is not to create a `userdata_chunk_local`.

This fixes T90131

Differential Revision: https://developer.blender.org/D12067
2021-07-30 16:56:29 +02:00
f68e8e4f23 deps: Reduce llvm/clang footprint for windows
We shipped the whole bin folder for llvm/clang
while we only needed clang-format, by shipping
just the bits we need we save about 700 megabytes
off our svn lib download.
2021-07-30 16:56:29 +02:00
35a4cef6b5 Data-block Preview: Create preview using current frame
The preview was always using frame 1, but maybe the object has changed and it's better create preview using the current frame.

Reviewed By: Severin

Differential Revision: https://developer.blender.org/D12018
2021-07-30 16:56:29 +02:00
695dd31e34 Cleanup: Remove debug-only code 2021-07-30 16:56:29 +02:00
5b0dfca417 Fix building without Cycles logging
Ideally can use assert() checks instead of suppressing the check entirely,
but for now just fix compilation error quickly.
2021-07-30 16:56:29 +02:00
9a9c533631 Cleanup: Fix build warning
Introduced in 3964785a14
2021-07-30 16:56:29 +02:00
jim man
f49bf8d05c cleanup: editor_image : Remove unused draw functions
These functions are unused currently..

Reviewed By: deadpin, jbakker

Differential Revision: https://developer.blender.org/D11968
2021-07-30 16:56:29 +02:00
48b6ccecb0 Fix Cycles crash with fluid object motion blur disabled
Motion attributes expects mesh to have non-zero number of motion steps,
which was violated in the case when fluid mesh had motion blur disabled.

This is a bit of annoying fix, because of the order of updates. More
ideal solution would be to handle cached and fluid velocities in the
sync_mesh_motion() which ensures all the dependencies between settings.
2021-07-30 16:56:29 +02:00
ce1e226b7c VSE: Change grid line drawing
Add overlay option to disable grid drawing.
Reuse drawing code from other editors (timeline editor)
Add argument `display_minor_lines` to function
`UI_view2d_draw_lines_x__discrete_frames_or_seconds`
This way minor line drawing can be disabled and so it doesn't cause
too much visual noise. Also spacing seems to be too fine, so VSE uses 3x
what is defined in preferences.

Reviewed By: fsiddi, Severin

Differential Revision: https://developer.blender.org/D11790
2021-07-30 16:56:29 +02:00
a4db9318fb VSE: don't snap by default
Snapping by default goes against convention, so this setting was
re-evaluated. Also snapping by default can conflict with new image
transform system, see T90156

There wasn't consensus, so disable snapping by default to follow
established convention.

ref T89665

Reviewed By: campbellbarton

Differential Revision: https://developer.blender.org/D12054
2021-07-30 16:56:29 +02:00
03368c5344 UI: Fix time labels drawing
Calculate frequency of time/frame label drawing, such that labels have
at least 10px margin and don't overlap.

Change timecode format:
- Use at least `mm:ss` format
- Don't display frames if all labels would end with +00

Reviewed By: Severin

Differential Revision: https://developer.blender.org/D11792
2021-07-30 16:56:29 +02:00
9f8e938900 Fix T89952: GPencil channel box selection offset
The channel box selection was offset for grease pencil layers.

This is a proposed fix by @yann-lty

Before:
{F10227973}

After:
{F10227974}

Reviewed By: #grease_pencil, antoniov

Maniphest Tasks: T89952

Differential Revision: https://developer.blender.org/D11962
2021-07-30 16:56:29 +02:00
490b36b289 Fix memory leaks in Python gizmo get/set handlers 2021-07-30 16:56:29 +02:00
f36b7c0c8c Fix gpu.types.GPUTexture crash when the size argument was too big
Missing length check on the size argument before copying it
into a fixed size buffer.
2021-07-30 16:56:29 +02:00
660bcfc32d Cleanup: use PyC_AsArray_FAST function where possible
Oversight in 2453dc1b0e.
2021-07-30 16:56:29 +02:00
b4ee5b7934 PyAPI: support multi-dimensional arrays for bpy.props vector types
- Multi-dimensional boolean, int and float vector types are supported.
- A sequence of int's for the "size" is used to declare dimensions.
- Nested sequences are required for default arguments.

Now it's possible to define matrix properties, for e.g:

  bpy.props.FloatVectorProperty(size=(4, 4), subtype='MATRIX')
2021-07-30 16:56:29 +02:00
a645d990d9 PyAPI: add multi-dimensional array conversion utility functions
Add array conversion functions that take dimension arguments.

- PyC_AsArray_Multi (version of PyC_AsArray).
- PyC_Tuple_PackArray_Multi_* (version of PyC_Tuple_Pack_*).
2021-07-30 16:56:29 +02:00
d13c3ac5d9 Cleanup: spelling 2021-07-30 16:56:29 +02:00
ae4affa280 Fix T75028: Improved Font Names in File Manager
When viewing font files in the File Manager, this patch uses the font's
family and style names to show the same type of string shown to users
in operating system lists. For example "Book Antiqua Regular" instead
of "BKANT.ttf"

see D12020 for details and examples.

Differential Revision: https://developer.blender.org/D12020

Reviewed by Campbell Barton and Julian Eisel
2021-07-30 16:56:29 +02:00
49240bcd25 Cycles: remove WITH_CYCLES_DEBUG, add WITH_CYCLES_DEBUG_NAN
WITH_CYCLES_DEBUG was used for rendering BVH debugging passes. But since we
mainly use Embree an OptiX now, this information is no longer important.

WITH_CYCLES_DEBUG_NAN will enable additional checks for NaNs and invalid values
in the kernel, for Cycles developers. Previously these asserts where enabled in
all debug builds, but this is too likely to crash Blender in scenes that render
fine regardless of the NaNs. So this is behind a CMake option now.

Fixes T90240
2021-07-30 16:56:29 +02:00
9ce2fc8a17 Cleanup: Remove unnecesary undefs
Macros `SEQ_ALL_END` and `SEQ_ALL_BEGIN` no longer use `seq->tmp`.
Therefore they are safe to use regardless from where they are called.
2021-07-30 16:56:29 +02:00
db5110e9d3 Assets: Improve error message when "Clear Asset" fails
When using "Clear Asset" from the Asset Browser but with an asset
selected that is not stored in the current file, we can show a more
informative error message.
2021-07-30 16:56:29 +02:00
a8eb36b7ef VSE: Fix audio not recalculated
Changing strip offsets with RNA properties didn't tag depsgraph to
update for new strip start/end points.
2021-07-30 16:56:29 +02:00
b0e3e55036 Cleanup: VSE cache invalidated twice
Multiple RNA update function invalidated cache twice.
2021-07-30 16:56:29 +02:00
Wannes Malfait
2bcdb4a19e Fix T90221: geometry viewer node links to other socket types
The viewer node in geometry node trees only supports geometry nodes.
This patch ensures that when ctrl shift clicking on a node, it will only
link to geometry sockets.

Differential Revision: https://developer.blender.org/D12055
2021-07-30 16:56:29 +02:00
641dade2be Remove the code in BKE_collection_move to preserve LayerCollection flags.
This code was actually buggy (forcefully re-enabling excluded layers in some
cases).

Further more, it should not be needed now that layerCollection resync code
reuses as much as possible existing layers instead of deleting and
re-creating them all the time.

Differential Revision: https://developer.blender.org/D12016
2021-07-30 16:56:29 +02:00
0f7254199b LayerCollection: Refactor of resync-with-Collection-hierarchy process.
The goal of this refactor is to improve resync of LayerCollections
hierarchy to match again Collection one.

Current code would destroy and re-create valid layers whenever a parent
collection would be removed, which leads to losing way too often
layer-related settings when editing collection hierarchies.

While this could be partially addressed from operators side, there was
no way to fix those issues from lower level, more generic ID management
code like ID remapping or library override resync processes.

The new code builds a shallow wrapper around existing (aka old) layers
hierarchy, does a set of checks to define the status of all existing
layers, and try to find the closest matching unused layer in cases where
layers and collections hierarchies do not match anymore.

The intent is to both re-use as much as possible existing layers, and
to pick the 'best' possible layer to re-use, following those heuristics:
 * Prefer layers children of current one first (in old hierarchy), and only
   use those from other higher-level hierarchies if no (grand-)child is found.
 * Prefer to use closest layers available in the old hierarchy.

NOTE: The new code is about 12%-15% slower than the previous one, which is
expected given the increased complexity. Note that this would not be an
issue in practice if this code was not called way too often (needs to
be converted to lazy update instead, which is a long known TODO).

NOTE: The LayerCollectionResync code uses its own built-in version of
FIFO queue, as performances in this code is currently a critical point
(it can get called tens of thousands of times during a single (heavy)
ID management operation currently, in a production file e.g.).

Differential Revision: https://developer.blender.org/D12016
2021-07-30 16:56:29 +02:00
Wannes Malfait
7fa2e087f5 Fix T89415: update multi input indices after deleting a node
When deleting a node, links attached to that node are deleted, but if one
of those links was connected to a multi input socket, the indices of the
other links connected to it were not updated. This adds updates both in
the case of a normal delete as well as after a delete with reconnect.

Differential Revision: https://developer.blender.org/D11716
2021-07-30 16:56:29 +02:00
d19528020f Fix particle system duplication duplicates all systems
Followup to rB3834dc2f7b38 (where getting the proper particle system was
fixed for the Adjust Last Operation panel in the Properties Editor). But
since this operator can also be called from the 3DView, get a current
particle system there as well.

Without this, _all_ particle systems would be copied when executing from
the 3DView (which was never really intended [operator description uses
singular] -- it just happens to use `copy_particle_systems_to_object`
internally as well -- same as the `Copy Active/All to Selected Objects`
operators)).

ref. T83317

Maniphest Tasks: T83317

Differential Revision: https://developer.blender.org/D12033
2021-07-30 16:56:29 +02:00
c67137ab0d Fix T90154, T90213: curve issues since recent cleanup commit
Caused by {rB8cbff7093d65}.

Since above commit only one modifier would get calculated and the
displaylist boundingbox was calculated wrong.

Maniphest Tasks: T90154

Differential Revision: https://developer.blender.org/D12037
2021-07-30 16:56:29 +02:00
43f0494929 Fix menu poll function being ignored for UILayout.menu
Using `UILayout.menu()` [1] or `UILayout.menu_contents() [2], the menu
would just always be added, the `poll()` check not being executed. As
API user I would expect the `poll()` to deterimine visiblity of the
menu.

[1] https://docs.blender.org/api/current/bpy.types.UILayout.html#bpy.types.UILayout.menu
[2] https://docs.blender.org/api/current/bpy.types.UILayout.html#bpy.types.UILayout.menu_contents

Differential Revision: https://developer.blender.org/D12053

Reviewed by: Campbell Barton
2021-07-30 16:56:29 +02:00
2c9e8a2f29 LineArt: Camera Overscan
Expand camera effective region to a portion beyond image frame so strokes won't end right at the border.

Reviewed By: Antonio Vazquez (antoniov)

Differential Revision: https://developer.blender.org/D12049
2021-07-30 16:56:29 +02:00
ffdf9fa1bf Fix (studio-reported) liboverride resync crash after recent changes.
Recent own rBabf3ce811f6e prevented any LayerCollection update during
the whole liboverride resync process, for both performances and feature
reasons.

However that means that the various runtime caches like the Base GHash
are not cleared anymore during ID remapping process, so we need to call
`BKE_main_collection_sync_remap` instead of `BKE_main_collection_sync`
when we finally are ready for this update.

Reported by @eyecandy (Andy Goralczyk) from Blender studio, thanks!
2021-07-30 16:56:29 +02:00
d360c5d8da VSE: Add tooltips for add_effect_strips operator
This patch adds propper tooltips to the effect strips in the "Add" menu.
Note that not all effect strips are actually in the "Effect Strips"
submenu like color strips, text strips or transitions. For these types
of effect strips, a dediacted tooltip is especially useful.

Reviewed By: ISS

Differential Revision: https://developer.blender.org/D11714
2021-07-30 16:56:29 +02:00
3e6fd42290 Cleanup: reduce indentation in bpy.props
Remove unnecessary NULL checks.
2021-07-30 16:56:29 +02:00
c2087da3d3 VSE: Draw strips transparent during transform overlap
While transforming a strip, draw the background semi-transparent
if it overlaps with another strip. It's convenient to see what's
underneath, especially with the upcoming Overwrite feature.

Thanks to @iss for the help and review.
2021-07-30 16:56:29 +02:00
31d0434344 Deps: ensure osl/bin/oslc is using static libpng
Pass `-DLINKSTATIC=ON` to the OSL CMake, to ensure it statically links to
our libpng. Previously this was only applied on Windows, it's now on all
platforms.
2021-07-30 16:56:29 +02:00
b1602da72f Add StringRef::trim() functions
Add three functions that trim characters from the front & end of a
`StringRef`. All functions return a new `StringRef` that references a
sub-string of the original `StringRef`.

- `trim(chars_to_remove)`: strips all characters from the start and end
  that occur in `chars_to_remove`.
- `trim(char_to_remove)`: same, but with a single character to remove.
- `trim()`: remove leading & trailing whitespace, so same as
  `trim(" \r\n\t")`

Reviewed By: JacquesLucke

Differential Revision: https://developer.blender.org/D12031
2021-07-30 16:56:29 +02:00
8105cc6692 Fix LLVM 12 symbol conflict with Mesa drivers, after recent Linux libs update 2021-07-30 16:56:29 +02:00
12298a5251 Fix LibOverride crashing in some cases where reference linked data gets MIA.
When the root of an override hierarchy disapears, there is no way to do
a proper resync, just abort.

Reported by studio, thx.
2021-07-30 16:56:29 +02:00
Himanshi Kalra
5b6ced1346 Regression Testing: Running tests based on blend files
Runs tests based on blend files with minimum python interaction.
Developed as part of GSoC 2021 - Regression Testing of Geometry Nodes.
Earlier, tests were built from scratch by adding a modifier/operation
from the Python API.
Now, tests can also be created inside blender and are compared using
Python script.

Features: Automatically adding expected object if it doesn't exist.
This patch adds tests for the following Geometry Nodes category:
* Curves
* Geometry
* Mesh
* Points

The implemented UML diagram for refactoring of mesh test framework.
{F10225906}

Technical Changes:
SpecMeshTest: It adds the modifier/operation based on the Spec provided.
BlendFileTest: It applies already existing modifier/operation from the blend file.

Test folders hierarchy with tests. This folder should be extracted to `lib\tests\modeling`
{F10240651}
Note: The `geometry_nodes` folder might lie under another `geometry_nodes` folder while extracting, please double check. Use the inner-most one.
The hierarchy should be:
-`lib\tests\modeling\geometry_nodes\mesh`
-`lib\tests\modeling\geometry_nodes\points`
and so on.

* From `ctest` the tests should be run as `ctest -R geo_node -C [Configuration]` on Windows.
* Each single test can be run with its entire name e..g `ctest -R geo_node_geometry_join_geometry`.(just an example). Run `ctest -N -R geo_node` to see all tests.
* From blender, the tests can be run `blender -b path\to\blend\file --python path\to\geo_node_test.py`

Reviewed By: zazizizou, JacquesLucke

Differential Revision: https://developer.blender.org/D11611
2021-07-30 16:56:29 +02:00
6a5df54477 Fix memory leak with Python RNA property get callback errors
Failure to return a list of the expected size & type wasn't
decrementing the value, leaking a reference.

Caused by 127b5423d6 a workaround for the
real error that was fixed f5e020a7a6.
2021-07-30 16:56:29 +02:00
Charlie Jolly
d7f228a394 Geometry Nodes: Add node labels to Attribute maths nodes
This adds the operator name to the node label which is consistent with the shading nodes.
The vector node has `Vector` as a prefix.

The Attribute nodes already have a different coloured header.

The same label is used when collapsing nodes, this helps readability.

Reviewed By: pablovazquez

Differential Revision: https://developer.blender.org/D10749
2021-07-30 16:56:29 +02:00
8c06fb2267 Added YAML builtbot config file.
Builtbot is switching over from json to yaml. Both
configuration files should be kept in sync for now.

The json file will be removed when everything works as expected.
2021-07-30 16:56:29 +02:00
53ed446f1f BlenRead: Add GHash-based search for already read linked IDs.
Ths commit adds a new `IDNameLibMap` to `Main`, used during file reading
to quickly find already read linked IDs.

Without that, search would use string-based search over list of linked
data, which becomes extremely slow and inneficient in cases where a lot
of IDs are linked from a same library. See also {T89194}.

Extrem-usecase reported in T89194 is now about 4 times faster in linked
data reading (about 2 times faster for the whole .blend file loading).

More normal cases (like Sprites studio production files) have barely
measurable speed improvements, a few percents at best.

NOTE: `main_idmap` API was extended to support insertion and removal of
IDs from the mapping, avoids having to re-create the whole thing several
time during libraries expansion in readcode.

Differential Revision: https://developer.blender.org/D11757
2021-07-30 16:56:29 +02:00
8311cc98db PyAPI: support different int sizes for PyC_AsArray 2021-07-30 16:56:29 +02:00
cac41070c0 Cleanup: pass sizeof array element to PyC_AsArray
Replace the is_double argument which was only used for single/double
precision floats.

This allows supporting different sized int types more easily.
2021-07-30 16:56:29 +02:00
c4c2f117ff Fix missing passes update on Use Denoising change
Makes it so Render Layers node in the compositor is updated as soon
as Use Denoising is changed for the final render.

Differential Revision: https://developer.blender.org/D12010
2021-07-30 16:56:29 +02:00
b9658d548c Deps builder: OIIO/OSL/ISPC/OIDN/LLVM/Flex updates
This diff somewhat snowballed out of updating OIDN to 1.4.1 it had some
changes that allowed us to remove the arm hacks we had in place and
revert to using identical versions for a whole bunch of deps. But that
required an update to ISPC which needed a newer LLVM and if we're
updating LLVM we may as well update OSL, and when we update OSL, OIIO
may as well be dragged in soo......anyhow...

This diff updates:

LLVM 9.0.0 (11.0.1 for mac/arm) -> 12.0.0
OIIO 2.1.15.0 -> 2.2.15.1
OSL 1.11.10.0 -> 1.11.14.1
winflex_bison 2.5.5-> 2.5.24 (ispc needed newer bison, windows only dep)
OIDN 1.4.0 -> 1.4.1
ISPC v1.14.1(random hash for mac/arm) -> v1.16.0
Flex 2.6.4 (ISPC needed newer Flex than available on CentOS 7)

and removes most of the "special arm/mac" versions. I think just ssl and
embree are left with special versions.

notable changes:
@LazyDodo included some clang headers in the linux/mac harvest which are
needed to start writing custom clang based tooling like D9465 these were
already shipping on windows, but not the other platforms.

[macOS] Change the `LC_ID_DYLIB` of OpenMP  for {D11997}. This changes
where the executables look for dylibs.

Reviewed By: sebbas, LazyDodo

Differential Revision: https://developer.blender.org/D11748
2021-07-30 16:56:29 +02:00
6bae63d69d Cleanup: add note from T85517 fix 2021-07-30 16:56:29 +02:00
7eb08a7ab0 Cleanup: comment spelling & punctuation 2021-07-30 16:56:29 +02:00
122bad7f7a LineArt: Occlusion accuracy fix.
This patch fixes occlusion function to handle one specific case (when an edge shares a point with triangle) better,especially when there's overlapping edges in this case.
2021-07-30 16:56:29 +02:00
Aaron Carlisle
a7ac6c014e Anotations: Fix a several issues with stroke placement
Previously, this option was not exposed in the UI, only for the clip editor.
There were also multiple rna properties that did the same thing for each of the 2D editors.

There was also an issue where the property enum items were the same as the 3d view which didnt make much sense.

Reviewed By: antoniov

Differential Revision: https://developer.blender.org/D12027
2021-07-30 16:56:29 +02:00
1e35b59443 Fix compile error on macos introduced in last commit
std::optional::value() is not available on macos.
2021-07-30 16:56:28 +02:00
Christoph Lendenfeld
3f55b127e7 Fix: Instantly hide bones after hitting H key in pose sliding
When using a pose slider it is possible to hide bones with the 'H' key.
Before this patch the screen didn't update, so you had to move the mouse 1 pixel to update.
This patch makes it so it updates right away

Reviewed by: Sybren A. Stüvel
Differential Revision: https://developer.blender.org/D12024
Ref: D12024
2021-07-30 16:56:28 +02:00
4822a11bdd Compositor: Full frame Box Mask node
Adds full frame implementation to this node operation.
No functional changes.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D11627
2021-07-30 16:56:28 +02:00
f79ac72208 Compositor: Full frame Levels node
Adds full frame implementation to this node operations.
No functional changes.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D11749
2021-07-30 16:56:28 +02:00
f464c18540 Compositor: Fix memory leak when exporting operations on debug 2021-07-30 16:56:28 +02:00
7482a56554 Compositor: Full frame Scale node
Adds full frame implementation to this node operations.
No functional changes.

Includes a new operation method `init_data` used to initialize any data
needed after operations are linked and resolutions determined.
Once tiled implementation is removed `initExecution` may be renamed
to `init_rendering` and `init_data` to `init_execution`.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D11944
2021-07-30 16:56:28 +02:00
035cf075e2 Cycles: upgrade CUDA to 11.4
This fixes a performance regression on Ampere cards, on specific scenes like
classroom. For cycles-x there is little difference, but this is still helpful
for LTS releases, and we need to upgrade at some point anyway.
2021-07-30 16:56:28 +02:00
Nikhil Shringarpurey
26f3c8717d Cleanup: fix compiler warnings due to implicit cast
Differential Revision: https://developer.blender.org/D11950
2021-07-30 16:56:28 +02:00
a2b0f4bc32 Fix Python error in benchmark executable detection after recent changes 2021-07-30 16:56:28 +02:00
43111cdfdf LayerCollections: Add a way to prevent their resync with Collection hierarchy.
This is an easy & safe, yet not-so-nice way to address the
LayerCollections vs. Collections hierarchy resync problem.

Currently this resync is enforced everytime something changes in the
Collections hierarchy, which is extremely inneficient, and can even
produce 'loss' of LayerCollection data during complex Collection
processes.

Current example is during Library Overrides resync process. New code:
 * Makes resync significantly faster (between 10 and 15%).
 * Fixes 'disappearing' layer collections settings on sub-collections'
   layers.

NOTE: This is not a proper fix for the underlying issue. However,
implementing and testing the 'lazy update' solution as proposed by
{T73411} requires a significant amount of time (especially in testing
and tracking all places where code would need to ensure LayerCollections
are up-to-date), which is not possible currently.

Differential Revision: https://developer.blender.org/D11889
2021-07-30 16:56:28 +02:00
e7694f68a1 Cleanup: Fix compiler warning in previous commit 2021-07-30 16:56:28 +02:00
9b13a5759b Fix T90127: Merge Down layer doesn't take the transform location into account
Now the layer transformation is applied before the merge.
2021-07-30 16:56:28 +02:00
7ec4a83a6c Mantaflow: Remove Noise Type Option
Mantflow only supports wavelet noise, thus the parameter with only one option is no longer useful.

Differential Revision: https://developer.blender.org/D6770
2021-07-30 16:56:28 +02:00
Germano Cavalcante
57c04b3165 Cleanup: Rearrange mesh extraction files
In the draw module, it's not easy to identify what its header is, and
where the shared functions are.

So move `draw_cache_extract_mesh_extractors.c` and
`draw_cache_extract_mesh_private.h` to the same folder as the extractors
and rename these files to make them more identifiable.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D11991
2021-07-30 16:56:28 +02:00
59a9c07d09 macOS Cleanup: Remove old version specific code
Reviewed By: #platform_macos, brecht
Differential Revision: https://developer.blender.org/D12021
2021-07-30 16:56:28 +02:00
f488c7ee69 VSE: Fix snapping bugs
Fix hold offset check causing missing snapping point when strip have
only still frames.

Fix effect strips of transformed strips causing snapping to prevoius
strip positions.

Reviewed By: mano-wii

Differential Revision: https://developer.blender.org/D11948
2021-07-30 16:56:28 +02:00
9d1ce7d5a9 Cleanup: missed comment in D12029
No functional change.
2021-07-30 16:56:28 +02:00
55fe618254 Geometry Nodes: Fix vector math project bug
Implementation is incorrect compared to Cycles/Eevee.

Reported by @DrDubosc in comments of T88922.

Differential Revision: https://developer.blender.org/D12029
2021-07-30 16:56:28 +02:00
d7aa608ab7 VSE: Fix truncated label
Label for snapping current frame to strips was cut off and not very readable.

Reviewed By: HooglyBoogly

Differential Revision: https://developer.blender.org/D11951
2021-07-30 16:56:28 +02:00
04001b2b02 Revert "cmake: enable Wayland by default"
This reverts commit a2ccd0e495.

This change was part of the still-under-review patch D11489, which
hasn't been accepted yet.
2021-07-30 16:56:28 +02:00
ba98a976cb Revert "GHOST/wayland: use Wayland only when 'BLENDER_WAYLAND' is set"
This reverts commit c971c851d3.

This change was part of the still-under-review patch D11489, which
hasn't been accepted yet.
2021-07-30 16:56:28 +02:00
Stefan Werner
a2877c0caf Cycles: Fixed memory leak in ColorSpaceManager
Cached OCIO processors were not freed, instead the color spaces were freed twice.

Reviewed By: brecht, sergey

Differential Revision: https://developer.blender.org/D12011
2021-07-30 16:56:28 +02:00
947c098519 Cleanup: clang tidy 2021-07-30 16:56:28 +02:00
Himanshi Kalra
95b6beb8d8 Fix T85517: Cannot type Space while holding Shift key in text-field like spaces.
Fix for T85517
Bug: Couldn't type space while holding down the shift key in text spaces (e.g. when saving a file, changing the name of object).

Changes: Removing the key combination of Shift + space in `WM_event_is_ime_switch` method.

Reviewed By: harley, mont29

Maniphest Tasks: T85517

Differential Revision: https://developer.blender.org/D10452
2021-07-30 16:56:28 +02:00
b85e249875 Cleanup: clang-format 2021-07-30 16:56:28 +02:00
6c0f7276dc Cleanup: spelling in comments 2021-07-30 16:56:28 +02:00
6333be56d9 Cleanup: use doxy comments 2021-07-30 16:56:28 +02:00
0888a0af14 UI: Line Art: Rename "Baking" panel to "Bake"
Avoid using verbs for panel names, and be consistent with the
"Bake" panel in Cycles, Ocean Modifier, etc.
2021-07-30 16:56:28 +02:00
511f6ff09a UI: Line Art: Always use Material icon on picker
The Material picker shouldn't change icon based on it's state,
it should always display the Material icon.
2021-07-30 16:56:28 +02:00
b829b0b555 UI: Fix button alignment on Grease Pencil modifiers 2021-07-30 16:56:28 +02:00
27b5d234ae UI: Line Art Modifier: Tweaks to labels and tooltips
- Clearer tooltips for Source Object/Collection.
- Remove redundant Source/Target on labels.
- Always write Grease Pencil with title case.
2021-07-30 16:56:28 +02:00
62a84f0995 Fix T86768, bevel doesn't loop slide sometimes.
Six years ago, Bug T44961 about unwanted spikes had me not do a loop
slide if the angle was too extreme, to avoid unwanted spikes.
The current bug showed that that angle was much too big, and limited
desired behavior in many cases. Changing the angle from 0.25 radians
to 0.0001 radians (about 0.006 degrees) still fixes the original bug
and seems very unlikely to be limiting desired behavior now.
2021-07-30 16:56:28 +02:00
8bdbfee9d7 Fix T89391, etc. Boolean bugs when objects have negative scale.
The old modifier code, now just used for Fast, has code in it to
flip faces of arguments when their tranform's negativity differs
from the main object's transform's negativity.
I had neglected to put that logic in when I made the change that
skipped the round trip through BMesh.
Fixing this means that the results are more what the user expects
when some or all operands have negative scales.
2021-07-30 16:56:28 +02:00
Christoph Lendenfeld
9e56b50e9f Fix: Remove automatic hiding of bones when using the pose slider
This patch addresses the issue raised in T88340.
When entering a pose sliding operator bones would automatically get hidden.
While technically not a bug it was decided that it is too confusing.
Hiding with 'H' is still possible though, just won't happen automatically

Reviewed by: Sybren A. Stüvel
Differential Revision: https://developer.blender.org/D11883
Ref: D11883
2021-07-30 16:56:28 +02:00
77feb1dcac GHOST/wayland: use Wayland only when 'BLENDER_WAYLAND' is set 2021-07-30 16:56:28 +02:00
5c729d4c26 cmake: enable Wayland by default 2021-07-30 16:56:28 +02:00
6e4f6f94e4 GHOST/wayland: explicitly delete 'GHOST_SystemWayland' when fallback to X11 2021-07-30 16:56:28 +02:00
121e854ee2 Cleanup: fix warning -Wparentheses 2021-07-30 16:56:28 +02:00
f90cd854ec UI: Do not abbreviate/shorten wording
Abbreviations are harder to read and understand thus it is best to be direct.
For example without understanding and context it is hard to know exactly what "Len" means.
2021-07-30 16:56:28 +02:00
70b2d56e8d GTest: Use INC/INC_SYS for Libmv/OSD tests
This change transitions libmv/osd tests to our
blender_add_test_executable macro that explicitly
takes the include directories as a parameter.

This is in preparation for future clean-up of
global include directories.

Differential Revision: https://developer.blender.org/D12012
Reviewed By: sergey
2021-07-30 16:56:28 +02:00
21d8d5279c Revert "VSE UX: Make Speed Effect strips more user friendly."
This reverts commit 3123f33380 and
a092baa7f9.
2021-07-30 16:56:28 +02:00
Fredrik Hansson
b6f5841d23 Weld Modifier: add "loose_edges" option
This improve the cloth modeling workflow by allowing you to weld only the
edges that are used for the sewing forces.

Reviewed By: mano-wii, weasel

Differential Revision: https://developer.blender.org/D10710
2021-07-30 16:56:28 +02:00
253d0ffe97 Many tweaks to f-curve drawing code 2021-07-30 16:56:28 +02:00
Germano Cavalcante
370a3cf599 VSE UX: Make Speed Effect strips more user friendly.
**Drawing Changes:**
- F-curve drawing for Stretch, Multiply, Length and Frame Number.
- Value drawing when no keyframes for Stretch, Length and Frame Numbers.

General view of the new drawing for each speed effect mode:
{F9796642, size=full}

Detail of the horizontal zero (blue) line in the new `Multiply` mode:
{F9798520, size=full}

Nice to have (but I don't know how):
- Auto adjusting of endframe when using Multiply or Boost.

Differential Revision: https://developer.blender.org/D6110
2021-07-30 16:56:28 +02:00
462c91debd PyDocs: Fix syntax errors resulting in warnings 2021-07-30 16:56:28 +02:00
0bc2620854 XR: Fix for Viewport Denoising Artifacts
Addresses T76003. When using VR with Eevee and viewport denoising,
scene geometry could sometimes be occluded for one eye. Solution is
to use a separate GPUViewport/GPUOffscreen for each VR view instead
of reusing a single one for rendering.

Reviewed By: Julian Eisel, Clément Foucault

Differential Revision: http://developer.blender.org/D11858
2021-07-30 16:56:28 +02:00
b18d421924 Fix T89393: crash when selecting edges when geometry nodes has "on cage" turned on
The core problem is that the geometry nodes modifier sometimes support
"mapping" (i.e. it remembers which new vertices correspond to edit mode
vertices) and sometimes it does not, depending on what the nodes are doing.
Also see rB07ce9910f7cc.

The solution here is that the fallback case in `BKE_mesh_foreach_mapped_edge`
does not call the callback with "invalid" indices.

Differential Revision: https://developer.blender.org/D12007
2021-07-30 16:56:28 +02:00
24011d3e9e Fix T90065: disable attribute search in places where there is too little context
Differential Revision: https://developer.blender.org/D12008
2021-07-30 16:56:28 +02:00
ce1a4929c3 Fix: avoid creating improper rotation matrix
This might change the rotation of some instances after a Curve to Points.
Unfortunately, there is not much we can do about that, the math before
was just wrong. The forward and up axis stayed the same though.

Differential Revision: https://developer.blender.org/D12006
2021-07-30 16:56:28 +02:00
ee07416685 Fix T89829: wrong active context path check in spreadsheet
The problem was that the modifier was reevaluated all the time, even
between showing the attribute search and clicking on the attribute
name. This freed the data referenced by attribute search. The real bug
here was that the dependency graph was tagged for update even
though nothing changed. This was because the spreadsheet thought
its active context has changed and it wanted to compute the new
value to be shown in the spreadsheet.

The reason for the bug was that I confused how the tree-path of a
node editor works. The second element in the tree path contains
the name of the group node in the root tree that we're in (instead
of the first element).

Differential Revision: https://developer.blender.org/D12009
2021-07-30 16:56:27 +02:00
fc91ec92a3 Another slight increase in speed for Delaunay CDT.
When the new "need_ids" flag is false and the output type is not
one of the valid BMesh kinds, there is no need to propagate even
a dummy id to all of the faces.
2021-07-30 16:56:27 +02:00
5efb0d1d2e Cleanup: double spaces in strings 2021-07-30 16:56:27 +02:00
7ce8fce0fe Cleanup: code comments punctuation / spacing 2021-07-30 16:56:27 +02:00
ee10b21c55 Cleanup: de-duplicate code for edge-split tagging
Share functionality for single and multi-threaded edge-split tagging.

Remove logic that ensured vert & loop indices in bm_mesh_edges_sharp_tag
(missing from fd9fc809b7).
2021-07-30 16:56:27 +02:00
e68767640e XR: Reference Space Improvements
Improves control over the XR reference space by using the stage ref
space (user-defined tracking bounds) instead of local ref space
(position at application launch), if available. Also adds an
"absolute tracking" session option to skip applying eye offsets that
are normally added for placing users exactly at landmarks.

By enabling absolute tracking, users can define the tracking origin
in a way that is not linked to the headset position. Instead, the
tracking values given by the XR runtime are left unadjusted and a
user can manually calibrate an "origin" landmark object to adjust to
their real world space.

Can be useful for applications that use external tracking systems
and those that primarily only need to use controllers and not the
headset (e.g. motion capture).

The absolute tracking option requires an update to the VR
Scene Inspection addon to be accessible by regular users.

Reviewed By: Julian Eisel

Differential Revision: http://developer.blender.org/D10946
2021-07-30 16:56:27 +02:00
c19eea1d93 Cleanup: "position tracking" typo in enum member 2021-07-30 16:56:27 +02:00
3d4454e641 Cleanup: remove unused BM_mesh_loop_normals_update function
The only difference with BM_loops_calc_normal_vcos was passing in
custom coordinates which may be NULL.
2021-07-30 16:56:27 +02:00
dd3e69ea7a Fix error setting sharp edges in recent normal calculation changes
bm_mesh_edges_sharp_tag was called with setting sharp edges enabled.
Error in 39b2a7bb7e.
2021-07-30 16:56:27 +02:00
2933a0ec9b Cleanup: remove normal assignment from bm_mesh_edges_sharp_tag
This was added in 0b7f581397
but seems not to be needed as the assignment was never correct
since only one corner on either side of the smooth edge had the
vertex normal written to it.
2021-07-30 16:56:27 +02:00
da860d5d1b Edit Mesh: multi-thread auto-smooth sharp-edge calculation
Merge the sharp edge tagging into bm_mesh_loops_calc_normals,
this has the advantage that edge tagging can be performed as part of
walking over each vertices edges - instead of tagging in a separate loop.

Even though this will tag edges twice (once for each vertex),
the computation isn't heavy as it's only calculating a dot-product
between the two face users to compare the angle.

This change combined with 4ba06ad0a8
makes BM_loops_calc_normal_vcos around 5.68x faster,
with an overall speedup over 2.6x when transforming a high poly mesh.
(tested on a system with 32 cores).

Reviewed By: mont29

Ref D11970
2021-07-30 16:56:27 +02:00
426ac092ec Edit Mesh: multi-thread auto-smooth & custom normal calculations
Supported multi-threading for bm_mesh_loops_calc_normals.

This is done by operating on vertex-loops instead of face-loops.

Single threaded operation still loops over faces since iterating
over vertices adds some overhead in the case of custom-normals
as the order used for accessing loops must be the same as iterating
of a faces loops.

From isolated timing tests of bm_mesh_loops_calc_normals on high
poly models, this gives between 3.5x to 10x speedup,
with larger gains for meshes with custom-normals.

NOTE: this is part one of two patches for multi-threaded auto-smooth,
tagging edges as sharp is still single threaded.

Reviewed By: mont29

Ref D11928
2021-07-30 16:56:27 +02:00
9162d9827e Man Page: Fix spelling 2021-07-30 16:56:27 +02:00
Christoph Lendenfeld
4fdfcde98d Animation: Generic Slider implementation
Extract the slider gui implemented for the pose slide tools.
Generalise it so it can be used by other tools as well.

Reviewed by: Sybren A. Stüvel
Differential Revision: https://developer.blender.org/D9314
Ref: D9314
2021-07-30 16:56:27 +02:00
b1f3d49296 Geometry Nodes: Display Node Warnings in Modifier
With this commit, node warnings added to nodes during evaluation
(not "Info" warnings) will also draw in the modifier. In the future
there could be a "search for this node" button as well.

Differential Revision: https://developer.blender.org/D11983
2021-07-30 16:56:27 +02:00
164e0ada87 Cleanup: Add function to check a curve's spline types
The need for this has come up a few times.
2021-07-30 16:56:27 +02:00
e089f41bcd Fix: "Bake" automatically calculated handles in set handle node
Because these handles are calculated lazily, we need to make sure they
are calculated before switching to a manually positioned mode.
I doubt it would ever be necessary, but theoretically this could happen
on a per-point level, to avoid calculating handles not in the selection.
2021-07-30 16:56:27 +02:00
Germano Cavalcante
8fb5731173 VSE: Speed Effect layout updates
**Changes:**
- New enums correspond to 4 modes: `Stretch`, `Multiply`, `Frame Number` and `Length`.
- "`Multiply Factor`" has been removed;
- Value corresponding to "`use as speed`" enabled is now the value appended to the `Multiply` enum;
- Value corresponding to "`use as speed`" disabled is now the value appended to the `Frame Number` enum;
- Value corresponding to "`Scale to Length`" enabled is now the value appended to the `Length` enum;
- Except `Stretch` each mode has now its respective control values.

Differential Revision: https://developer.blender.org/D11856
2021-07-30 16:56:27 +02:00
f137a3409b Fix name used when parsing arguments 2021-07-30 16:56:27 +02:00
4c251dd864 PyGPU: new method 'GPUFrameBuffer.read_depth'
Method requested by users in order to port addons to new API.
2021-07-30 16:56:27 +02:00
5ab90b1052 Compositor: Fix crash when using empty input sources
It's the case of Image or Movie Clip node when not selecting any
source or an empty one.
Render methods expect an output buffer with size, only render
operations with resolution.
2021-07-30 16:56:27 +02:00
63d957c645 Compositor: Full frame Texture node
Adds full frame implementation to this node operation.
No functional changes.
2021-07-30 16:56:27 +02:00
2aac74b657 Compositor: Full frame Movie Clip node
Adds full frame implementation to this node operation.
No functional changes.
2x faster than tiled fallback.
2021-07-30 16:56:27 +02:00
a109435043 Compositor: Fix buffer area iterating past the end 2021-07-30 16:56:27 +02:00
1bdc33cc2a Compositor: Add coordinates to BuffersIterator
Allows to cover many use cases where iterating both buffers and
coordinates is needed.
2021-07-30 16:56:27 +02:00
33569fc1f1 Fix T90026: attributes added in editmode are lost on modeswitch
When exiting editmode, customdata [and thus attributes] are copied from
**BMesh** to **Mesh** (in `BM_mesh_bm_to_me`).
When adding attributes, these were always added via
`CustomData_add_layer_named` only.
Instead (if we are in mesh editmode), we need to go through
`BM_data_layer_add_named` to properly update the **BMesh** (see
`update_data_blocks`) so we have stuff available to copy back to
**Mesh** when exiting editmode.
Same is done for removing (also going through BMesh).

This is now done, DomainInfo is updated to point to BMesh (instead of
Mesh) customdata when in editmode.

Maniphest Tasks: T90026

Differential Revision: https://developer.blender.org/D11998
2021-07-30 16:56:27 +02:00
Johnny Matthews
4d25d74a1a Geometry Nodes: Set Bezier Handle Type Node
This node takes a curve and a point selection and allows you to set the
specified (or all) points left/right or both handles to a given type.

Differential Revision: https://developer.blender.org/D11992
2021-07-30 16:56:27 +02:00
b652f01504 Tests: continue running benchmarks if some tests fail to build or run
Convenient when testing many revisions where some might be broken.
2021-07-30 16:56:01 +02:00
ee367eecf4 Tests: improve finding of Blender executables in benchmarking
* Allow specifying a folder and automatically setting the proper executable
  name depending on the operating system
* Use executables from configs for listing devices instead of a blender
  command being available
2021-07-30 16:56:01 +02:00
01aa9f34af Versioning: move "until next subveresion bump" code
Move "until next subveresion bump" code into the 300.13 version block.
This should have happened in rB8d5b9478a25.
2021-07-30 16:56:01 +02:00
cf243cd302 Cleanup: Silence warning - unused parameter 2021-07-30 16:56:01 +02:00
Yann Lanthony
41f6c7b298 Fix T89733: Py API: bpy.data.orphans_purge argument parsing
On Windows, using `bpy.data.orphans_purge` with some arguments (eg: `do_recursive=True`) does not produce the expected results. This is due to arguments not being parsed correctly on this platform with the current code.

The proposed fix is based on how other functions with boolean attributes are exposed to the Python API.

Reviewed By: #python_api, mont29

Maniphest Tasks: T89733

Differential Revision: https://developer.blender.org/D11963
2021-07-30 16:56:01 +02:00
Philipp Oeser
292724c389 Make polls for removing mesh data layers consistent
This was reported in T90026 for attributes, but was also true for:
- UVMaps
- Vertex Colors
- Sculpt Vertex Colors
- Face Maps

For Vertex groups and Shapekeys this was already done (in that their
remove poll would check if there is a vertex group or shapekey to begin
with), now make this consistent across all mentioned types.

Thx @vvv for the initial patch (where this was done for attributes only)

ref T90026

Reviewed By: HooglyBoogly

Maniphest Tasks: T90026

Differential Revision: https://developer.blender.org/D11990
2021-07-30 16:56:01 +02:00
e16982fe94 Bump subversion to avoid infinite enabling pose_library add-on
Bump Blender's sub-version to make sure the pose_library add-on isn't
auto-enabled on every run of Blender.
2021-07-30 16:56:01 +02:00
3115e957d6 Cleanup: Move reorganize asset files
I'm trying to move away from general files with lots of things in them,
and instead have many small & focused files. I find that easier to
work with since everything has clear responsibilities, even if there is
some minor overhead in managing all these files.
I also try to differentiate more clearly between public and internal
files. So source files and internal headers are in a `intern/`
sub-directory, public functions are in a number of headers one level
higher.
For convenience and to make this compatible with our existing general
headers in `editors/include`, I made the `ED_asset.h` there include all
these public headers.
This is of course a bit of an experiment, let's see how it works in
practice.

Also corrected the name of `ED_asset_can_make_single_from_context()`.
2021-07-30 16:56:01 +02:00
Germano Cavalcante
aa23609f14 Draw Cache: extract tris in parallel ranges
The `ibo.tris` extraction in multithread is currently only done if the
mesh has only 1 material.

Now we cache a map indicating the index of each polygon after sort and
thus allow the extraction of tris with materials in multithreaded.

As caching is a heavy operation and was already being performed in
multi-thread for triangle offsets, no significant improvements are
expected.

The benefit will be much greater when we can skip updating the cache
while transforming a geometry.

**Profiling:**
||master:|PATCH:
|---|---|---|
|large_mesh_editing_materials:|Average: 13.855380 FPS|Average: 15.525684 FPS
||rdata 9ms iter 36ms (frame 71ms)|rdata 9ms iter 29ms (frame 64ms)
|subdiv_mesh_final_only_materials:|Average: 28.113742 FPS|Average: 28.633599 FPS
||rdata 0ms iter 1ms (frame 36ms)|rdata 0ms iter 1ms (frame 35ms)

1.1x overall speedup

Differential Revision: https://developer.blender.org/D11445
2021-07-30 16:56:01 +02:00
49e72bf3b0 Fix T90017: Bone widget drawing inconsistent with editing
The `lines_loose` extractor did not trigger loose geometry caching.
2021-07-30 16:56:01 +02:00
ff7563fb57 Cleanup: Move loose geometry cache creation to render data task
This centralizes caching functions.
2021-07-30 16:56:01 +02:00
76dbc9a0e9 Cleanup: Centralize/unify asset library reference from/to enum code
This was an open TODO, I wanted to have code for translating asset
library references from and to enum values in a central place, and
access that in the same way from both the Asset Browser and the
Workspace RNA code.

* Adds own file for the related functions.
* Adds doxygen comments.
* Updates RNA callbacks to properly use these functions.
* Let these functions call each other, avoid duplicating logic.
2021-07-30 16:56:01 +02:00
e775f2239a Assets: Replace duplicated asset library reference type from DNA
Since recently it's possible to access assets from outside the
File/Asset Browser, via the asset view template. So we are slowly
moving away from file space specific code to dedicated asset system
code. I introduced `AssetLibraryReference` as a duplicate of
`FileSelectAssetLibraryUID`, with a plan to delete the latter in a
separate cleanup commit. That's exactly what this commit is.

This will cause Asset Browsers to open with the default "Current File"
Asset Library. We could avoid that, but it's a minor issue really.
2021-07-30 16:56:01 +02:00
46eeaa0544 Assets: Rename workspace active asset library DNA variable
This new variable was introduced with 7898089de3. We don't usually use
an `active` prefix variable. Plus, this makes the name match the one of
the Asset Browser active library variable, so we can use the
`rna_def_asset_library_reference_common()` helper for both.

This will cause Asset Views to open with the default "Current File"
Asset Library. We could avoid that, but it's a minor issue really.
2021-07-30 16:56:01 +02:00
b7ad67082b Cleanup: Add missing doxygen file/group comment in new asset file 2021-07-30 16:56:01 +02:00
9848426848 Fix incorrect use of BLI_assert with error strings
Some asserts were never raised because of invalid checks.
2021-07-30 16:56:01 +02:00
209a07e3b5 Cleanup: replace BLI_assert(test || !"text") with BLI_assert_msg(test, text) 2021-07-30 16:56:01 +02:00
Yuki Hashimoto
7a9822ace1 Cleanup: correct the comment in ghost
The same comments were written in clientToScreen and screenToClient in
GHOST. I corrected them.

Ref D11986
2021-07-30 16:56:00 +02:00
93e7fb464a Fix bug in assert in delaunay test.
Assert was trying to say x coords of arcs lined up, and didn't do that.
2021-07-30 16:56:00 +02:00
0220c85f47 Cleanup: Split set_preview_visibilty. 2021-07-30 16:56:00 +02:00
118f4dc93b Cleanup: replace BLI_assert(!"text") with BLI_assert_msg(0, "text") 2021-07-30 16:56:00 +02:00
5f35c9c3cd Cleanup: spelling 2021-07-30 16:56:00 +02:00
f4a30c2c20 Cleanup: replace BLI_assert(0 && "text") with BLI_assert_msg 2021-07-30 16:56:00 +02:00
7a129b0a6f Fix T89881: ignore unavailable sockets when searching for link cycles 2021-07-30 16:56:00 +02:00
5a0a69166b Fix compile issue. 2021-07-30 16:56:00 +02:00
55e603a5bb Fix i18n utils_cli mistake.
Reported by James Monthea (@jmonteath), thanks.
2021-07-30 16:56:00 +02:00
c127093820 Cleanup Preview rendering: Separate world preparation.
Small cleanup that moves world preparation out of scene preparation.
2021-07-30 16:56:00 +02:00
405c41e431 Cleanup: use named enum types.
Added ePreviewRenderMethod and ePreviewType.
2021-07-30 16:56:00 +02:00
e9b69bbd85 Cleanup: replace NB with NOTE in comments 2021-07-30 16:56:00 +02:00
Smitty van Bodegom
e18f76a0cb UI: Use more descriptive wording for particle modifier conversions
Currently the wording is a bit unclear: it doesn't specify //what// the particles will be converted into. This clarifies it by stating what the particles will be converted into: they will either be converted to a mesh or the instances will be made real.

Reviewed By: Blendify

Differential Revision: https://developer.blender.org/D11795
2021-07-30 16:56:00 +02:00
Romain Toumi
61aca25ee2 UI: Fix Cycles Materials menu Layout
Fix an incoherence between the Eevee Materials menu and the Cycles Materials menu :

Eevee :
{F10230448}

Cycles :
{F10230449}

Simply Fixed by replacing the Cycles UI code by the Eevee UI code.

Thanks to @Brainzman for helping me create this diff and translate

Reviewed By: Blendify

Differential Revision: https://developer.blender.org/D11979
2021-07-30 16:56:00 +02:00
7da330e57a Fix API doc generation after recent context additions 2021-07-30 16:56:00 +02:00
5355f00f41 Fix T89827: Attribute transfer node crash on mesh with no faces
Just add a check for whether the mesh has faces when retrieving an
attribute on the corner domain. In the future there could be an info
message in the node in this case, since maybe it's not intuitive.
2021-07-30 16:56:00 +02:00
5d91724656 Fix memory leak with asset view template operator properties 2021-07-30 16:56:00 +02:00
9eda619105 Cleanup: Store asset-handle in drag data
Would previously pass a few properties that are available via the
asset-handle now. This asset-handle is also required for some of the
asset API, e.g. the temporary ID loading. This will probably be needed
before too long.
2021-07-30 16:56:00 +02:00
2610e7480b Cleanup: Use asset utility function to get the asset .blend path
For this to work, the utility function needs to be callable without
context, which is only needed for a File Browser specific hack anyway
(doesn't apply to this usage of it).
2021-07-30 16:56:00 +02:00
b2bfadf511 Cleanup: Move asset-handle functions to own file
Keeps files minimal and focused. I much prefer that over having all
kinds of stuff in general files like `asset_edit.cc`.
2021-07-30 16:56:00 +02:00
9b0c917f8a Cleanup: Getters for asset-handle data
While the asset-handle design is supposed to be temporary (see
35affaa971), I prefer keeping the fact that it's nothing but a file
entry pointer an implementation detail that is abstracted away. So this
introduces getters for the file data we typically access for
asset-handles.
2021-07-30 16:56:00 +02:00
1dd6775ad7 Cleanup: Use const for internal file data of asset-handle
Note that the current asset-handle design is temporary, see
35affaa971. I still prefer this to be const, as code outside the
asset-list/file-list code should never mess with the file data of an
asset.
2021-07-30 16:56:00 +02:00
3ac14e4220 Asset: Clearly describe RNA property description as temporary
The asset handle design is only temporary (see 35affaa971) and this
RNA property is only needed for internal, technical reasons of the asset
view template. So although not nice, at least make it clear in the RNA
property description that this should not be used.
2021-07-30 16:56:00 +02:00
b18e973f54 Cleanup: Correct asset TODO comment, move setter next to getter 2021-07-30 16:56:00 +02:00
616816c694 Fix T89993: Failed assert drawing single point cyclic splines
The same check used for the curve to mesh node.
2021-07-30 16:56:00 +02:00
b1c09892ad Fix T89687: Curve to mesh node incorrect face orientation
The new faces should have a winding direction that points them outward,
the fix was swapping the order of each face's edge and vertex indices.
2021-07-30 16:56:00 +02:00
bcbc626a05 Cleanup: Use const arguments and less sequential iteration
Using const indexes and offsets helps to make the logic less sequential,
which is hopefully easier to understand and possibly easier to parallelize
in the future. Also order return arguments last.
2021-07-30 16:56:00 +02:00
16ec757b94 Armature test: properly initialize bone hierarchy
Fix segfault in `BKE_armature_find_selected_bones_test` by property
initializing the bone hierarchy listbases.

No functional changes to Blender.
2021-07-30 16:56:00 +02:00
Jagannadhan Ravi
9744ca099e Speedup rigid body "Copy from Active" operator
If there were lots of selected objects without an existing rigid body,
we would add rigid bodies to them one by one.

This would be slow in python, now we instead do this as a batch
operation in C.

On my (Intel) MacBook it used to take 60 seconds and with this change it
takes about 0.3 seconds.

Reviewed By: Sebastian Parborg

Differential Revision: http://developer.blender.org/D11957
2021-07-30 16:56:00 +02:00
2c75332d4f Cleanup: Fix missing braces warning on Clang 2021-07-30 16:56:00 +02:00
12a26c3381 Pose Library: remove assumption about Action group names
Remove the assumption of the pose library that Action groups are named
after the bones in the armature. Even though this assumption is correct
when the keys are created by Blender, action groups can be renamed. Keys
created by Python scripts can also use arbitrary group names.

Since there is more code in Blender making this assumption, and looping
over selected bones is also a common occurrence, this commit contains
some generic functionality to aid in this:

- `BKE_armature_find_selected_bones`: function that iterates over all
  bones in an armature and calls a callback for each selected one. It
  returns a struct with info about the selection states (all or no bones
  selected).
- `BKE_armature_find_selected_bone_names(armature)` uses the above
  function to return a set of selected bone names.
- `BKE_pose_find_fcurves_with_bones()` calls a callback for each FCurve
  in an Action that targets a bone, also passing it the bone name.
2021-07-30 16:56:00 +02:00
d2b00a5774 Cleanup: fix clang-tidy warning readability-qualified-auto
No functional changes.
2021-07-30 16:56:00 +02:00
5e5b471789 Cleanup: fix clang-tidy readability-else-after-return
No functional changes
2021-07-30 16:56:00 +02:00
3e179144a4 Cleanup: fix clang-tidy warning modernize-use-nullptr
No functional changes.
2021-07-30 16:56:00 +02:00
69c623ab16 Pose backup: convert from C to C++
Convert `pose_backup.c` (in C) to `pose_backup.cc` (in C++). This will
make future improvements easier. For now, it's the same code with just
some additional explicit casts (C++ doesn't allow implicitly casting
`void *`), `NULL` changed into `nullptr`, and some other simple changes.

No functional changes.
2021-07-30 16:56:00 +02:00
9b4afce6a2 Fix T89981: missing refresh on the compositors render layer node when adding/removing AOVs
Just refresh the node's outputs via ntreeCompositUpdateRLayers().

Maniphest Tasks: T89981

Differential Revision: https://developer.blender.org/D11973
2021-07-30 16:56:00 +02:00
024e169d0f Fix T89982: Geometry Nodes: 'New' Button tries to create node_tree on active modifier, rather than button context
When done from the Properties Editor, the context's modifier should be
used (this is where the button is located), when done from elsewhere,
the active modifier is still the way to go (since the context modifier is
not available then)

Maniphest Tasks: T89982

Differential Revision: https://developer.blender.org/D11972
2021-07-30 16:56:00 +02:00
Johnny Matthews
e2c52ea2e7 Fix: Bezier segment node adds handles incorrectly
This caused the "cyclic" attribute to appear dysfunctional.
2021-07-30 16:56:00 +02:00
a113eca4d4 Fix T89979: Assert in edit mode with curve to mesh node
The node tagged polys normals dirty,  but the function to calculate the
normals didn't clear the dirty flags for polys. Now clear the poly and
corner dirty normal flags.
2021-07-30 16:56:00 +02:00
26e15daa7a Cleanup: use single back-tick quoting in comments
While doxygen supports both, conform to our style guide.

Note that single back-tick's are already used in a majority of comments.
2021-07-30 16:56:00 +02:00
5b77e167ab Cleanup: use doxygen style parameters in noise.c
These used their own ad-hoc syntax.
2021-07-30 16:56:00 +02:00
9f0fad8b6d Cleanup: added const keyword to BLI_dlrbTree search functions. 2021-07-30 16:56:00 +02:00
0c211e94f2 Cleanup: Remove redundant forward declarations. 2021-07-30 16:56:00 +02:00
63acac2cf4 Fix crash in delaunay C interface test.
The test forgot to set the new need_ids field, which luckily
exposed a bug in the C api for delaunay when that field is false.
Fixed the bug and the test, and added a test for the need_ids false
case.
2021-07-30 16:56:00 +02:00
fb91ddeb9c Compositor: Fix crash when connecting multiple constant inputs
Operation receiving inputs was being folded more than once
when it was constant foldable.
2021-07-30 16:56:00 +02:00
8bfceff845 LineArt: UI cleanups.
Wording on the UI, slider consistency and material mask switches layout.

Reviewed By: Sebastian Parborg (zeddb)

Differential Revision: http://developer.blender.org/D11839
2021-07-30 16:56:00 +02:00
1af5e8cab1 Cleanup: reserve C++ comments for disabled code
Use C comments for plain text.
2021-07-30 16:56:00 +02:00
3852211d2c Cleanup: use '#if 0' for disabling multiple lines 2021-07-30 16:56:00 +02:00
49e4e4c08d Cleanup: Make function static, use const object argument
Also use `const Curve *` instead of `const Object *`, since the
function works at a lower level than objects anyway.

And also remove another unused function. Since this section of code
for converting curves to meshes will likely be replaced, it's nicer to
see which parts actually remain used at this point.
2021-07-30 16:56:00 +02:00
40d270248d Cleanup: spelling 2021-07-30 16:56:00 +02:00
4f27228b0c Cleanup: quiet GCC maybe-uninitialized warning
Function signatures for snap callbacks used `const` incorrectly
which was hidden by casting function types.

This made it seem as if the input arguments wouldn't be change and
wouldn't be initialized.

Name return arguments with an `r_` prefix, order them last,
remove function casts and correct `const` usage.
2021-07-30 16:56:00 +02:00
84f565ed4f Cleanup: Remove unused function 2021-07-30 16:56:00 +02:00
45f4c8ed78 Docs: Update RNA to user manual mappings 2021-07-30 16:56:00 +02:00
55898b107e Cleanup: Clang format 2021-07-30 16:55:59 +02:00
a7bf4ce629 Compositor: Export operation results as debug option
When fixing issues, seeing operation results can be helpful for
detecting which operation went wrong.

This commit adds an option for exporting all operations results to
image files.
Exceptions are:
- Output operations: They are already exported or can be seen in UI.
- Constant operations: There are too many and is rarely useful.

They are exported to "<temp session folder>/COM_operations/"
with filenames "<operation class name>_<operation id>.png".
Only works on full frame execution mode.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D11722
2021-07-30 16:55:59 +02:00
60af1ead0c Compositor: Full frame Brightness node
Adds full frame implementation to this node operation.
No functional changes.
2.4x faster than tiled fallback.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D11677
2021-07-30 16:55:59 +02:00
9f2a38db45 Compositor: Full frame Mix node
Adds full frame implementation to this node operations.
No functional changes.
2.3x faster than tiled fallback on average.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D11686
2021-07-30 16:55:59 +02:00
3e9f20ae90 Compositor: Full frame Viewer node
Adds full frame implementation to this node operation.
No functional changes.
No performance changes.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D11698
2021-07-30 16:55:59 +02:00
eba3086802 Compositor: Full frame Double Edge Mask node
Adds full frame implementation to this node operation.
No functional changes.
No performances changes.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D11750
2021-07-30 16:55:59 +02:00
7b03da863a Compositor: Full frame Ellipse Mask node
Adds full frame implementation to this node operation.
No functional changes.
3x times faster than tiled fallback.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D11635
2021-07-30 16:55:59 +02:00
41cc9fa930 Compositor: Buffer iterators
Currently we mostly iterate buffer areas using x/y loops or through
utility methods extending from base classes.

To simplify code in simple operations this commit adds wrappers for
specifying buffer areas and their iterators for raw buffers with any
element stride:
- BufferRange: Specifies a range of contiguous buffer elements from a
 given element index.
- BufferRangeIterator: Iterates elements in a BufferRange.
- BufferArea: Specifies a rectangle area of elements in a 2D buffer.
- BufferAreaIterator: Iterates elements in a BufferArea.
- BuffersIterator: Simultaneously iterates an area of elements in an
 output buffer and any number of input buffers.
- BuffersIteratorBuilder: Helper for building BuffersIterator adding
 buffers one by one.
For iterating areas coordinates it adds `XRange` and `YRange` methods
that return `IndexRange`.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D11882
2021-07-30 16:55:59 +02:00
8d88c7c811 Cleanup: Move asset library reference C++ wrapper to own files
Although currently only the asset list code uses the asset library
reference wrapper, it can stand on its own and may be used in more
places in the future. So I prefer to give it its own source & header
file.

Also removed unused includes, added proper namespaces as per our C++
style guidelines, and removed an unnecessary TODO comment.
2021-07-30 16:55:59 +02:00
c051cdc3df Cleanup: Remove unused function, unused declaration 2021-07-30 16:55:59 +02:00
9150ba6845 Fix some mesh edition macro operators incorrectly setting an empty description string.
No operator or macro should be missing description. But if they do, then
they should use NULL pointer, and not an empty string.

This behavior was already enforced (through an assert) for operators,
previous commit made it the same for macros.
2021-07-30 16:55:59 +02:00
879c922f2b Fix broken 'undocumented' case in registration of Macro opertators.
Code dealing with macro operators missing description field was slightly
different than the one from Operator registration.

This lead to invalid memory accesses in some python introspection cases
like the i18n messages extraction code in `bl_i18n_utils` module.
2021-07-30 16:55:59 +02:00
212aa101a1 Cleanup: Separate keyframes_draw and keyframes_keylist.
The keylist functions are used in other places for none drawing related
stuff. Fe pose_slide uses it.
2021-07-30 16:55:59 +02:00
2c731304c3 Revert "Depsgraph: Implement 'ID_RECALC_GEOMETRY_DEFORM'"
This reverts commits
 bfa3dc91b7,
 52b94049f2,
 ae379714e4,
 a770faa811,
 4ed029fc02,
 101a493ab5 and
 62a2faa7ef.

And fixes T89955.

Changing the dependency graph is a can of worms and the result is
a kind of unpredictable.

A different solution will be planned.
2021-07-30 16:55:59 +02:00
9ae685bc97 Object update: Remove fallback from batch_cache_deform_tag
Falback is not really necessary, and causes
`BKE_object_data_batch_cache_dirty_tag` to run multithreaded in an
unsafe way.

No functional changes.
2021-07-30 16:55:59 +02:00
2be5b2fcf0 Fix T89941: No path`s bevel update, when I change bevel profile curve
Update was skipping the batch cache.
2021-07-30 16:55:59 +02:00
745f6ac101 Cleanup: minor correction to delaunay_2d_cdt doc-string
Use more conventional syntax for default arguments.
2021-07-30 16:55:59 +02:00
243d8df588 Cleanup: remove unused pathlib import 2021-07-30 16:55:59 +02:00
da79efd820 Cleanup: remove unused MTex.pmapto, pmaptoneg & defines
These have not been in use since 2.57
fafbd9d71b.
2021-07-30 16:55:59 +02:00
ccbd93299d Fix: memcpy overlapping region ASAN warning in curve trim node 2021-07-30 16:55:59 +02:00
bd0af14c16 Cleanup: Make curve trim node code more semantically correct
The code used `Spline::LookupResult` in a way that referred to evaluated
points and control points interchangeably. That didn't affect the logic,
but the code became harder to read. Instead, introduce a local struct
to contain the data in a more obvious way.
2021-07-30 16:55:59 +02:00
4aa3f06f1f Update documentation string for mathutils.geometry.delaunay_2d_cdt. 2021-07-30 16:55:59 +02:00
57e639caa1 Make it optional to track input->output mapping in delaunay_2d_calc.
Some uses of delaunay_2d_calc don't need to know the original verts,
edges, and faces that correspond to output elements.
This change adds a "need_ids" value to the CDT input spec, default true,
which tracks the input ids only when true.
The python api mathutils.geometry.delaunay_2d_cdt gets an optional
final bool argument that is the value of need_ids. If the argument
is not supplied, it is true by default, so this won't break old uses
of the API.

On a sample text test, not tracking ids save about 30% of the runtime.
For most inputs the difference will not be so dramatic: it only really
kicks in if there are a lot of holes.
2021-07-30 16:55:59 +02:00
ceb42e4cc5 Fix T89929: Crash when hiding in the render a previously keyframed volume
Regression introduced in {rBbfa3dc91b754}.

`ID_RECALC_GEOMETRY` should tag all operations of the `GEOMETRY`
component and not just the operation of node `GEOMETRY_EVAL_INIT`.
2021-07-30 16:55:59 +02:00
Angus Stanton
54c69bf729 Geometry Nodes: Curve Trim Node
This node implements shortening each spline in the curve based on
either a length from the start of each spline, or a factor of the
total length of each spline, similar to the "Start & End Mapping"
panel of curve properties.

For Bezier curves, the first and last control points are adjusted
to maintain the shape of the curve, but NURB splines are currently
implicitly converted to poly splines.

The node is implemented to avoid copying where possible, so it outputs
a changed version of the input curve rather than a new one.

Differential Revision: https://developer.blender.org/D11901
2021-07-30 16:55:59 +02:00
8725fc5087 Speed up Delaunay raycast.
From Erik Abrahamsson, this uses parallel loops for raycasting.
It speeds up one example with many crossings of a bezier curve,
from 0.68s to 0.28s.
2021-07-30 16:51:35 +02:00
2b3f1fe2f2 Versioning: fix vertex group name loss in linked duplicates.
After rB3b6ee8cee708 by @HooglyBoogly vertex groups were moved
to mesh data, and versioning code was provided to upgrade old
files. However, it fails to consider the case of linked duplicates
having different name lists, and dependent on the object order
can cause some of the names to be lost. This can even be all of
them, if there is a duplicate without any names, which can be
easily created by lazy Python code.

To fix this, change the code to use the longest available name list.

Differential Revision: https://developer.blender.org/D11958
2021-07-30 16:51:35 +02:00
Angus Stanton
f0a98f14f0 Fix: Incorrect logic in spline lookup function
This section of code deals with evaluated points,
so that is the size it should use.
2021-07-30 16:51:35 +02:00
88f33af4ac Greatly improve speed of Delaunay when have a lot of holes.
Using part of a patch from Erik Abrahamsson, this replaces the
use of linked lists for original id tracking by Sets.
I had thought that the lists were unlikely to grow to more than
a few elements, but when the mesh has a lot of holes (whose
original ids go *outside* the hole, and therefore, most of the
mesh), this assumption can be very wrong.
On a Text regression test, the time went from 11.67s to 0.16s
with this fix. I also tested to make sure that Boolean didn't
slow down with this, and found it actually had a very slight speedup.

Using Sets exposed a dependency on the ordering of the items
in the id lists, luckily caught by a mesh intersect regression test,
so fixed that.
2021-07-30 16:51:35 +02:00
Jesse Yurkovich
41d4a7b55e Fix T89868: Crash showing thumbnail of wide-aspect image
Scaling down images could create images with a width or height of zero.

Clamp at 1 to prevent a crash, also add an assert to scaling functions.

Ref D11956
2021-07-30 16:51:35 +02:00
43a0d4eecb Cleanup: Simplify realizing of pointcloud instances
Just a small change to make the function slightly shorter.
2021-07-30 16:51:35 +02:00
8c8597a623 Fix T89624: Vertex painting causes mesh to flicker
The `ibo.lines_paint_mask` extractor doesn't have a callback to iterate
bmesh faces, this made `filter_into` ignore the extractor.
2021-07-30 16:51:35 +02:00
8ac3b212ef Cleanup: Simplify logic, use C++ types
Also remove an unecessary null check, and make inner loop simpler.
2021-07-30 16:51:35 +02:00
05b2831ff1 VSE: Fix multicam splitting all selected strips
`split_multicam` used split operator, where if more strips than
multicam were selected, all would be split, which is undesirable.

Add `Sequence.split()` RNA API function. to split individual strips.
Function accepts `frame` and `split_method arguments`. Returns right
strip after splitting.

In case when strip being split have effects, these will be split too, so
no invalid state should be created.

Selection is not handled, this is by design up to user.

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D11926
2021-07-30 16:51:35 +02:00
a6d9100505 Fix T89722: Duplicate macro can cause strips to overlap
Bug caused by 78693d524c accidentally removing overlap handling when
transform operator is canceled.

Reviewed By: campbellbarton

Differential Revision: https://developer.blender.org/D11899
2021-07-30 16:51:35 +02:00
956e41db7b Cleanup: Move gpencil_geom.c to C++
This will help enable development on optimizations to the perimeter
calculation here. Using C++ data structures like Array can make the
code easier to read as well.

Longer term, this can help improve integration with attributes
and possibly the new curve code (since strokes and curves are
quite similar in theory).

Differential Revision: https://developer.blender.org/D11941
2021-07-30 16:51:34 +02:00
0415578ce1 Fix T89899: Crashes when accessing vertex groups from objects
We need to be more strict about trying to retrieve a list of vertex group
names from objects now, as only three object types support them.
This commit adds a check for vertex group support in a few places, the
data transfer operator/modifier, copying vertex groups to selected
objects, and the vertex group remove and clear functions.

Differential Revision: https://developer.blender.org/D11947
2021-07-30 16:51:34 +02:00
c155315698 Cleanup: Get vertex group names directly from grease pencil data 2021-07-30 16:51:34 +02:00
8d79fe22ca Cleanup: Remove redundant logic
The object type was checked twice unnecessarily. Also use a function
for the check to be more explicit.
2021-07-30 16:51:34 +02:00
e2ffe9d630 Surface Deform: support sparse binding mode for improving performance.
When a vertex group is used to limit the influence of the modifier
to a subset of vertices, binding data for vertices with zero weight
is not needed. This wastes memory, disk space and CPU cycles.

If the vertex group contents is known to be final and constant,
it is reasonable to optimize by only storing data group vertices.
This has to be an option in case the group can change.

Supporting this requires adding a vertex index field and spliting
the vertex count into mesh and bind variants, but both happen to
fit in available padding. The old numverts field is renamed to the
new bound vertex count field to maintain the array length invariant.
Versioning is used to initialize the other new fields.

If a file with sparse binding is opened in an old blender version,
it is corrupted into a non-sparse bind with vertex count mismatch,
preventing the modifier from working until rebind.

Differential Revision: https://developer.blender.org/D11924
2021-07-30 16:51:34 +02:00
5c7968ab0d Fix T89875: False dependency cycle on particle systems
`POINT_CACHE_RESET` pointed to `GEOMETRY_EVAL_INIT` while
`GEOMETRY_EVAL_INIT` pointed to `POINT_CACHE_RESET`.

Now `POINT_CACHE_RESET` points to the same nodes pointed to by
`GEOMETRY_EVAL_INIT` thus avoiding the dependency cycle.
2021-07-30 16:51:34 +02:00
9a58acb71c Fix T89782: Segfault populating popup menu with dimensions above the opengl limit
The crash happens because `GPU_offscreen_create` is called with `err_out` `NULL`.

This patch proposes a solution within the `GPU_offscreen_create` itself
and raises an error report in the interface if a menu is called with
dimensions beyond what is supported.

Ref T89782

Maniphest Tasks: T89782

Differential Revision: https://developer.blender.org/D11927
2021-07-30 16:51:34 +02:00
233862ed04 Cleanup: preview rendering, update assumptions in comment
The `action_preview_render()` function used to just render, but now it
also temporarily applies the pose. Its comment is now updated for this.

No functional changes.
2021-07-30 16:51:34 +02:00
58e2f62483 Rename UI error message on attributes panel for name collisions
* Name Collisions > Name collisions
* Info icon > Error icon
2021-07-30 16:51:34 +02:00
30f431aeac Fix T89861: Checking face selection breaks UV stitch operator 2021-07-30 16:51:34 +02:00
7a29a37e7b Fix T70356: Scaling up 1x1 pixel image reads past buffer bounds
Also resolve a crash when when displaying thumbnails, see T89868.
2021-07-30 16:51:34 +02:00
105850b750 Cleanup: reduce variable scope in task_iterator.c
Would have prevented the error in
15cdcb4e90.
2021-07-30 16:51:34 +02:00
1caf30a6a9 Fix error using uninitialized state in BLI_task_parallel_mempool
Single threaded operation used the state before it had variables
written into it.

Error in 15cdcb4e90.
2021-07-30 16:51:34 +02:00
b3602acd22 Cleanup: sort struct declarations 2021-07-30 16:51:34 +02:00
38dd4ac4dd Cleanup: remove redundant parentheses 2021-07-30 16:51:34 +02:00
91b76b38be Cleanup: spelling in comments 2021-07-30 16:51:33 +02:00
8428aec80e Cleanup: compiler warnings 2021-07-30 16:51:33 +02:00
Aidan Haile
c1bd9ecd01 Fix T49944: Compositor ID Mask Anti-Aliasing not working
Replaces current ID Mask node Anti-Aliasing operation by SMAA
operations with default settings as proposed by Jeroen Bakker.
SMAA produces smoother edges.

Reviewed By: manzanilla

Differential Revision: https://developer.blender.org/D11881
2021-07-30 16:51:33 +02:00
Red Mser
54c46ca4c1 UI: Flip driver editor debug lines
In driver editor, vertically flip the value debug lines to align
them with the timeline header values. This makes it easier to read
the values. Also set the line width explicitly, which was incorrect
in some cases.

Differential Revision: https://developer.blender.org/D8877
2021-07-30 16:51:32 +02:00
ce382eec94 Cleanup: Clang tidy 2021-07-30 16:51:32 +02:00
ae8cf5ecfd Cleanup: Remove use of designated initializers in C++ code
Does not compile on Windows.
2021-07-30 16:51:32 +02:00
2e297933ca Cleanup: Move UI list template code to own file (C++)
This move was already prepared with 788d380460 and 26b098c04f. The
template is quite big already, better to give it its own file. Plus it
could use some C++ features like RAII and maybe some more object
oriented code. I plan further refactoring there.
2021-07-30 16:51:32 +02:00
a0a35f78f3 Fix failing tests from vertex group name parameter copy
It turns out `BKE_mesh_copy_parameters` can be called while other
tools are running calculations, which meant that it was called at the
same time as `armature_deform_coords_impl`. Beause of that, we
shouldn't do any freeing (of the old vertex group names) there.

Since the materials are copied in the "for_eval" version anyway,
it seems to make sense to copy the vertex group name list there also.

Fixes T89877, and also the failing `deform_modifiers` test.

Differential Revision: https://developer.blender.org/D11936
2021-07-30 16:51:32 +02:00
c58b00a6af Cleanup: unused variable capture 2021-07-30 16:51:32 +02:00
081638638c Animation/add-ons: Enable the poselib add-on by default
The new Asset Browser-based pose library is partially implemented in an
add-on. This commit enables the add-on by default, as the old pose
library was built-in and thus always enabled.

The ability to disable the add-on is there mostly for cases where
people/studios want to use their own custom pose library.
2021-07-30 16:51:32 +02:00
c0d5c13b46 Fix T88281: Pose Library 'flip pose' sometimes flips wrong
Correct cases where the X-axis of the bone (in pose space) aligns with
the pose-space Y or Z-axis. In these cases the decomposition of the
matrix fails, and a negative scale of the X-axis turns into a 180°
rotation around the Y-axis. An extra -1 scale to the X and Z axes of the
resulting matrix seems to fix things.
2021-07-30 16:51:32 +02:00
9987a2b11e Asset Browser: Python mixin utility for category-specific panels
Using this mixin for a panel definition, it's possible to set in which
categories the panel should appear. This is used by the Pose Library
add-on.
2021-07-30 16:51:32 +02:00
75feaceab8 UI/Assets: Initial Asset View UI template
The asset view UI template is a mini-version of the Asset Browser that
can be placed in regular layouts, regions or popups. At this point it's
made specifically for placement in vertical layouts, it can be made more
flexible in the future.
Generally the way this is implemented will likely change a lot still as
the asset system evolves.

The Pose Library add-on will use the asset view to display pose
libraries in the 3D View sidebar.

References:
* https://developer.blender.org/T86139
* https://code.blender.org/2021/06/asset-browser-project-update/#what-are-we-building
* https://code.blender.org/2021/05/pose-library-v2-0/#use-from-3d-viewport

Notes:
* Important limitation: Due to the early & WIP implementation of the
  asset list, all asset views showing the same library will show the
  same assets. That is despite the ID type filter option the template
  provides. The first asset view created will determine what's visible.
  Of course this should be made to work eventually.
* The template supports passing an activate and a drag operator name.
  The former is called when an asset is clicked on (e.g. to apply the
  asset) the latter when dragging (e.g. to .blend a pose asset). If no
  drag operator is set, regular asset drag & drop will be executed.
* The template returns the properties for both operators (see example
  below).
* The argument list for using the template is quite long, but we can't
  avoid that currently. The UI list design requires that we pass a
  number of RNA or custom properties to work with, that for the Pose
  Libraries should be registered at the Pose Library add-on level, not
  in core Blender.
* Idea is that Python scripts or add-ons that want to use the asset view
  can register custom properties, to hold data like the list of assets,
  and the active asset index. Maybe that will change in future and we
  can manage these internally.

As an example, the pose library add-on uses it like this:
```
activate_op_props, drag_op_props = layout.template_asset_view(
    "pose_assets",
    workspace,
    "active_asset_library",
    wm,
    "pose_assets",
    workspace,
    "active_pose_asset_index",
    filter_id_types={"filter_action"},
    activate_operator="poselib.apply_pose_asset",
    drag_operator="poselib.blend_pose_asset",
)
drag_op_props.release_confirm = True
drag_op_props.flipped = wm.poselib_flipped
activate_op_props.flipped = wm.poselib_flipped
```
2021-07-30 16:51:31 +02:00
e3b1fb44b4 Cleanup: Use const for UI icon getter function 2021-07-30 16:51:31 +02:00
612ac59fc9 UI: Support defining UI lists in C
So far all UI lists had to be defined in Python, this makes it possible
to define them in C as well. Note that there is a whole bunch of special
handling for the Python API that isn't there for C. I think most
importantly custom properties support, which currently can't be added
for C defined UI lists.

The upcoming asset view UI template will use this, which needs to be
defined in C.

Adds a new file `interface_template_list.cc`, which at this point is
mostly a dummy to have a place for the `ED_uilisttypes_ui()` definition.
I plan a separate cleanup to move the UI-list template to that file.
2021-07-30 16:51:31 +02:00
33d495399f UI: New button/widget type for Asset Browser like preview tiles
This button type shows a preview image above centered text, similar to
the File Browser files in Thumbnail Display Mode or the default Asset
Browser display. In fact we may want to port these over to use the new
button type at some point.

Will be used by the asset view UI template that will be added in a
following commit. That is basically a mini version of the Asset Browser
that can be displayed elsewhere in the UI.
2021-07-30 16:51:31 +02:00
0a35fee6bc UI: Auto-scroll to keep active text buttons in view
If a text button is activated that is not in view (i.e. scrolled away),
the scrolling will now be adjusted to have it in view (with some
small additional margin). While entering text, the view may also be
updated should the button move out of view, for whatever reason. For the
most part, this feature shouldn't be needed and won't kick in, except
when a clicked on text button is partially out of view or very close to
the region edge. It's however quite important for the previously
committed feature, that is, pressing Ctrl+F to start searching in a UI
list. The end of the list where the scroll button appears may not be in
view. Plus while filtering the number of visible items changes so the
scrolling has to be updated to keep the search button visible.

Note that I disabled the auto-scrolling for when the text button spawned
an additional popup, like for search-box buttons. That is because
current code assumes the button to have a fixed position while the popup
is open. There is no code to update the popup position together with the
button/scrolling.

I also think that the logic added here could be used in more places,
e.g. for the "ensure file in view" logic the File Browser does.
2021-07-30 16:51:31 +02:00
3c76c983aa UI: Support pressing Ctrl+F over UI lists to search
Adds an operator invoked by default with Ctrl+F that while hovering a UI
list, opens the search field of the list and enables text input for it.
With this commit the search button may actually be out of view after
Ctrl+F still. The following commit adds auto-scroll to solve that.

A downside is that in the Properties, there also is Ctrl+F to start
the editor-wide search. That's not unusual in Blender though (e.g.
scolling with the mouse over a UI list also scrolls the list, not the
region).
2021-07-30 16:51:31 +02:00
7083656da3 UI: Support UI list tooltips, defined via Python scripts
Makes it possible to create tooltips for UI list rows, which can be
filled in .py scripts, similar to how they can extend other menus. This
is used by the (to be committed) Pose Library add-on to display pose
operations (selecting bones of a pose, blending a pose, etc).

It's important that the Python scripts check if the UI list is the
correct one by checking the list ID.
For this to work, a new `bpy.context.ui_list` can be checked. For
example, the Pose Library add-on does the following check:
```
def is_pose_asset_view() -> bool:
  # Important: Must check context first, or the menu is added for every kind of list.
  list = getattr(context, "ui_list", None)
  if not list or list.bl_idname != "UI_UL_asset_view" or list.list_id != "pose_assets":
    return False
  if not context.asset_handle:
    return False
  return True
```
2021-07-30 16:51:31 +02:00
fb797b18d5 UI: Support left-right arrow key walk navigation in UI lists
Add improved arrow key walk navigation in grid layout UI List templates.
Pressing up or down walks the active item to the adjacent row in that
direction, while left and right walk through the items along the columns
wrapping at the rows.

Note from Julian:
In combination with the following commit, this has the important
limitation that the list's custom activate operator won't be called when
"walking over" an item that is scrolled out of the list. That is because
we don't actually create any buttons for those that could be used for
the handling logic. For our purposes of the pose libraries that should
be fine since the asset view list is always made big enough to display
all items. Solving this might be difficult, we don't properly support
nesting boxes with proper scrolling in regular layouts. It's all just
hacked a bit for UI-lists to work. Overlaps quite a bit with T86149.

Differential Revision: https://developer.blender.org/D11063
2021-07-30 16:51:31 +02:00
dd7c341c32 UI: Internal support for custom UI list item drag & activate operators
For pose libraries, we need to be able to apply a pose whenever
activating (clicking) an item in the Pose Library asset view and blend
it by dragging (press & move). And since we want to allow Python scripts
to define what happens at least when activating an asset (so they can
define for example a custom "Apply" operator for preset assets), it
makes sense to just let them pass an operator name to the asset view
template. The template will be introduced in a following commit.
2021-07-30 16:51:31 +02:00
58d1fe4790 UI: New UI list layout type for big preview tiles
This new layout type is meant for the upcoming asset view UI template.
With it it is possible to show big asset previews with their names in a
responsive grid layout.

Notes:
* The layout is only available for C defined UI lists. We could expose
  it to Python, but I think there are still some scrolling issues to be
  fixed first. (The asset view template doesn't use scrolling for the UI
  list.)
* I'd consider this a more usable version of the existing `GRID` layout
  type. We may remove that in favor of the new one in future.
2021-07-30 16:51:31 +02:00
caacb0f7bd UI: UI list refactor & preparations for asset view template
This is more of a first-pass refactor for the UI list template. More
improvements could be done, but that's better done separately. Main
purpose of this is to make the UI list code more manageable and ready
for the asset view template.

No functional changes for users.

* Split the huge template function into more manageable functions, with
  clear names and a few structs with high coherency.
* Move runtime data management to the template code, with a free
  callback called from BKE. This is UI data and should be managed at
  that level.
* Replace boolean arguments with bit-flags (easily extendable and more
  readable from the caller).
* Allow passing custom-data to the UI list for callbacks to access.
* Make list grip button for resizing optional.
* Put logic for generating the internal UI list identifier (stored in
  .blends) into function. This is a quite important bit and a later
  commit adds a related function. Good to have a clear API for this.
* Improve naming, comments, etc.

As part of further cleanups I'd like to move this to an own file.
2021-07-30 16:51:31 +02:00
135d1bd9ec Assets: temporarily apply pose when generating preview image
When generating a preview image for a pose, temporarily apply it to the
armature. Contrary to the usual pose application, this ignores the
selected bones and always applies the entire pose.
2021-07-30 16:51:31 +02:00
a4cf4273fd Animation: new pose library based on Asset Browser
Introduce new pose library, based on the Asset Browser. Contrary to the
old pose library (in `editors/armature/pose_lib.c`), which stored an
entire library of poses in an `Action`, in the new library each pose is
its own `Action` datablock. This is done for compatibility with the
asset browser, and also to make it easier to attach preview images,
share datablocks, etc. Furthermore, it opens the door to having
animation snippets in the pose library as well.

This commit contains the C code for the pose library; in order to fully
use it, an addon is required as well (which will be committed shortly).
2021-07-30 16:51:31 +02:00
4812ad4d26 Animation: add function to blend Action into pose
Add function `BKE_pose_apply_action_blend()`, which blends a given
Action into current pose. The Action is evaluated at a specified frame,
and the result is applied to the armature's pose.

A blend factor can be given to blend between the current pose and the
one in the Action. Quaternions are interpolated with SLERP; it is
assumed that their FCurves are consecutively stored in the Action.

This function will be used in the upcoming new Pose Library.
2021-07-30 16:51:31 +02:00
e8d00e507a Animation: apply pose to all or selected bones of armature
New function `BKE_pose_apply_action_all_bones()`, which will be
necessary for the upcoming pose library v2.0.

This renames the function `BKE_pose_apply_action` to
`BKE_pose_apply_action_selected_bones`, to reflect that it only works on
selected bones, to contrast it to the new function.
2021-07-30 16:51:31 +02:00
393fd9168f Assets: Open Blend File operator
Add operator 'Open Blend File' to the Asset Browser. This operator:
- starts a new Blender process,
- opens the blend file containing the asset,
- monitors the new Blender process, and when it stops,
- reloads the assets to show any changes made.
2021-07-30 16:51:31 +02:00
727d58dedd Assets: Abstraction for temporary loading of asset data-blocks
This is an editor-level abstraction for the `BLO_library_temp_xxx()`
API for temporary loading of data-blocks from another Blend file. It
abstracts away the asset specific code, like asset file-path handling
and local asset data-block handling.

Main use-case for this is applying assets as presets that are based on
data-blocks, like poses. Such preset assets are an important part of the
asset system design, so such an abstraction will likely find more usage
in the future.
2021-07-30 16:51:31 +02:00
d0a2763b04 File/Asset Browser: Extend file-entry and asset handle Python API
Adds the following to `bpy.types.FileSelectEntry`:
* `id_type`: The data-block type the file represenets, if any.
* `local_id`: The local data-block it represents, if any (assets only).

And the following to `bpy.types.AssetHandle`:
* `local_id`: The local data-block the asset represents, if any.

This kind of information and the references are important for asset related
operators and UIs. They will be used by upcoming Pose Library features.
2021-07-30 16:51:31 +02:00
ab7046ab1c Assets: Initial Asset List as part of the Asset System design
Implements a basic, WIP version of the asset list. This is needed to
give the asset view UI template asset reading and displaying
functionality.

See:
* Asset System: Data Storage, Reading & UI Access - https://developer.blender.org/T88184

Especially the asset list internals should change. It uses the
File/Asset Browser's `FileList` API, which isn't really meant for access
from outside the File Browser. But as explained in T88184, it does a lot
of the stuff we currently need, so we (Sybren Stüvel and I) decided to
go this route for now. Work on a file-list rewrite which integrates well
with the asset system started in the `asset-system-filelist` branch.

Further includes:
* Operator to reload the asset list.
* New `bpy.types.AssetHandle.get_full_library_path()` function, which
  gets the full path of the asset via the asset-list.
* Changes to preview loading to prevent the preview loading job to run
  eternally for asset views. File Browsers have this issue too, but
  should be fixed separately.
2021-07-30 16:51:31 +02:00
0d889f1f4c Assets: Show asset path in asset browser sidebar
It's useful to know where an asset is stored in, before this there was no way
to tell this. This could probably be displayed nicer in the UI but we're
currently unsure how. But at least the information is there now.
2021-07-30 16:51:31 +02:00
91b3814301 Assets: AssetHandle type as temporary design to reference assets
With temporary I mean that this is not intended to be part of the
eventual asset system design. For that we are planning to have an
`AssetRepresentation` instead, see T87235. Once the `AssetList` is
implemented (see T88184), that would be the owner of the asset
representations.

However for the upcoming asset system, asset browser, asset view and
pose library commits we need some kind of asset handle to pass around.
That is what this commit introduces.
Idea is a handle to wrap the `FileDirEntry` representing the asset, and
an API to access its data (currently very small, will be extended in
further commits). So the fact that an asset is currently a file
internally is abstracted away. However: We have to expose it as file in
the Python API, because we can't return the asset-handle directly there,
for reasons explained in the code. So the active asset file is exposed
as `bpy.context.asset_file_handle`.
2021-07-30 16:51:31 +02:00
fada98c621 Assets: Expose active asset library in context
For the Asset Browser, this returns the active asset library of the
Asset Browser, otherwise it returns the one active in the workspace.

This gives simple access to the active asset library from UI code and
Python scripts. For example the upcoming Pose Library add-on uses this,
as well as the upcoming asset view template.
2021-07-30 16:51:30 +02:00
675536fd4b Assets: Add an active asset library per workspace, for the UI to use
This per-workspace active asset library will be used by the asset views
later. Note that Asset Browsers have their own active asset library,
overriding the one from the workspace.

As part of this the `FileSelectAssetLibraryUID` type gets replaced by
`AssetLibraryReference` which is on the asset level now, not the
File/Asset Browser level. But some more work is needed to complete that,
which is better done in a separate commit.
This also moves the asset library from/to enum-value logic from RNA to
the editor asset level, which will later be used by the asset view.
2021-07-30 16:51:30 +02:00
Robert Sheldon
5f4edeb367 Fix T88188: Allow keyframing vertex mass in cloth sim
Update vertex weights between simulation steps if they have changed.
This allows for animated vertex weights in the cloth sim.

Reviewed By: Sebastian Parborg

Differential Revision: http://developer.blender.org/D11640
2021-07-30 16:51:30 +02:00
f993802456 Library loading: Fix access of out-of-scope memory in py context manager
The `__enter__` function of the `bpy.data.libraries.load` context manager
was storing a pointer to a stack-allocated variable, which was subsequently
used in the `__exit__` function, causing a crash. This is now fixed.

Thanks @Severin for the patch.
2021-07-30 16:51:30 +02:00
Paul Golter
8225cca4fb Fix: Subtitles: Order of channels in the .blend file will be kept in the .rst file.
If text strips have the same start frame but are stacked on top of each
other in different channels the order in which they are written in the
.rst file was random before.

Reviewed By: Richard Antalik

Differential Revision: https://developer.blender.org/D11903
2021-07-30 16:51:30 +02:00
Heinrich Schuchardt
5d7bb20b17 Add support for RISC-V architecture
* On RISC-V GCC 10.3 does not define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n.
* Avoid a build error
  "Please add support for your platform in build_config.h"
  Cf: https://github.com/sergeyvfx/libNumaAPI/pull/3

Differential Revision: https://developer.blender.org/D11910
2021-07-30 16:51:30 +02:00
2b49389786 Cleanup: LayerCollection resync: Proper r_ prefix for return function parameter. 2021-07-30 16:51:30 +02:00
12e8ecd09c Cleanup: improve comments, remove debug printf 2021-07-30 16:51:30 +02:00
27d0c21eeb Keymap: use Shift-Tab to toggle snap in the sequencer
Match the same shortcut for the 3D view & UV editor.
2021-07-30 16:51:30 +02:00
68e06b10d8 Cleanup: LayerCollection resync code.
Mainly naming (also droping the `layer_collection`  in favor of just
`layer` for internal code, this is clear enough and much shorter). Add
proper parent/child identifiers, `r_` prefix for parameters also used as
return values, etc.

Also made some parameters const.
2021-07-30 16:51:30 +02:00
da777ab2e5 Fix: crash when creating new node links
This was a regression in rBc27ef1e9e8e663e02173e518c1e669e9845b3d1f.
2021-07-30 16:51:30 +02:00
021eb28836 Fix T89870: Vertex groups lost when opening 3.0 files in 2.93
The original refactor for vertex groups (3b6ee8cee7)
forgot to bump the minimum file requirement.

I'm also bumping the subversion to 12 so everyone can switch to a
working subversion number.

Differential Revision: https://developer.blender.org/D11931
2021-07-30 16:51:30 +02:00
56ce9c8ff2 macOS/glog: Silence syscall deprecation warning
Upstream will release the fix in 0.6 which will take time.
Silence two warnings.

Differential Revision: https://developer.blender.org/D11246
2021-07-30 16:51:30 +02:00
34e273c2ed Keymap: use Alt-Q instead of D for transfer mode operator
This now works in all modes (not just sculpt) and activates on press
instead of release. See design task T89757.
2021-07-30 16:51:30 +02:00
eb525f8466 Revert "Keymap: use D-Key for view-pie menu"
This reverts commit f92f5d1ac6.

See: T89757 for rationale for reverting this change.
2021-07-30 16:51:30 +02:00
19e5a0783a Fix: missing null check
This was a regression in rB3b6ee8cee7080af200e25e944fe30d310240e138.
2021-07-30 16:51:30 +02:00
9c4b18dd96 Geometry Nodes: dim links whose start and end sockets are not visible
This makes node trees with long links that cross other nodes easier to work with.
Dimmed links will be ignored by various modal operators like cut and reroute insertion.

Differential Revision: https://developer.blender.org/D11813
2021-07-30 16:51:30 +02:00
04d5bac6e6 Cleanup: use raw strings, quiet clang-tidy warnings 2021-07-30 16:51:30 +02:00
1f30133770 Cleanup: replace BLI_assert(!"text") with BLI_assert_msg(0, "text")
This shows the text as part of the assertion message.
2021-07-30 16:51:30 +02:00
1a1955776b Cleanup: clang-format 2021-07-30 16:51:30 +02:00
d5d8f1f6cc Cleanup: ensure one newline at end of file, strip trailing space 2021-07-30 16:51:29 +02:00
0dbfb40d20 CMake: update config for checking utility 2021-07-30 16:51:29 +02:00
b7de6735c1 BLI_task: add a callback to initialize TLS
Useful when TLS requires it's own allocated structures.
2021-07-30 16:51:29 +02:00
98f92c807a BLI_memarena: support merging memory arenas
Useful when thread-local storage has it's own memory arena containing
data which is kept after the multi-threaded operation has finished.
2021-07-30 16:51:29 +02:00
4aa2187dce deps_builder: zstd 1.5.0
Having zstd available is a requirement for landing D5799

Reviewed By: sybren

Differential Revision: https://developer.blender.org/D11079
2021-07-30 16:51:29 +02:00
694249940a GHOST/wayland: create mmap-ed file manually if memfd_create is unavailable 2021-07-30 16:51:29 +02:00
e3d8f427d5 CMake: Have CMake Control the C++ version.
We were manually setting the compiler flags
for C++17 support for this previously. CMake
can do this for us in a uniform way without
having to worry about compiler specifics.

Setting these flags manually somehow brought
out some unwanted behaviour (CMake switching
back to C++14) in the nightly CMake builds.

Unsure if that's a CMake bug or planned
new behaviour for future version, but best
to play it safe.

These flags are supported since CMake 3.1
so should not break anything.

Reviewed by: Campbell Barton

Differential Revision: https://developer.blender.org/D11891
2021-07-30 16:51:29 +02:00
d948bd616d Bezier Spline: Add a more generalized insertion utility
This logic is from the curve sundivide node, used to add points with
proper handles in between two existing points. However, the same logic
is used for trimming of Bezier splines, and possibly interactive point
insertion in the future, so it's helpful as a general utility.

The logic is converted to depend on a bezier spline instead of being
static. A temporary segment spline can be used for the latter use case.
2021-07-30 16:51:29 +02:00
239bf16cc7 Merge remote-tracking branch 'origin/soc-2021-porting-modifiers-to-nodes-merge-by-distance' into soc-2021-porting-modifiers-to-nodes-merge-by-distance 2021-07-24 22:48:52 +02:00
529913b2df - copied point cloud support from D10888 to this patch
- added support for selection with point cloud mode
2021-07-24 22:48:42 +02:00
2c6aeb6240 - copied point cloud support from D10888 to this patch
- added support for selection with point cloud mode
2021-07-24 22:47:58 +02:00
9503e34e99 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-merge-by-distance
# Conflicts:
#	source/blender/modifiers/intern/MOD_weld.c
2021-07-24 11:41:37 +02:00
5c79a2953b changes based on review by Hans Goudey (HooglyBoogly) 2021-07-24 11:38:36 +02:00
7f33ff779f Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-remesh-blocks 2021-07-24 11:20:30 +02:00
80870aebd0 added mode selector 2021-07-23 23:23:49 +02:00
aaee6e13d4 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-remesh-blocks
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
2021-07-23 21:08:25 +02:00
096d6017cc Merge remote-tracking branch 'origin/soc-2021-porting-modifiers-to-nodes-merge-by-distance' into soc-2021-porting-modifiers-to-nodes-merge-by-distance 2021-07-23 21:07:07 +02:00
18f45f874c Geometry Nodes: Merge by Distance (Direct Modifier Port)
This patch is a direct port of the Weld modifier that moves the
common code to the geometry module.
I had made another version of a Merge by Distance Modifier (D10888), with an own implementation,
but I found that the original modifiers algorithm gives finer results.

Differential Revision: https://developer.blender.org/D12019
2021-07-23 21:00:07 +02:00
607119dd3f formatting 2021-07-23 12:03:45 +02:00
d777efbf5c Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-merge-by-distance
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
2021-07-23 08:15:08 +02:00
7425af128f initial commit 2021-07-23 08:14:34 +02:00
9823ac0767 initial commit 2021-07-19 23:48:50 +02:00
226ae2e69f moved remesh_blocks to geometry module 2021-07-19 00:10:22 +02:00
0b654b04cb Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-remesh-blocks 2021-07-16 23:13:48 +02:00
474828bf25 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-remesh-voxel 2021-07-16 21:51:01 +02:00
c21f9930bc removed makesrna from includes in CMakeLists.txt 2021-07-16 21:17:19 +02:00
906347042d - added geometry module
- moved solidify to geometry module
2021-07-15 22:33:26 +02:00
0d8bb5f898 more cleanup 2021-07-15 11:28:08 +02:00
bcd1a5af89 Cleanup 2021-07-15 11:19:56 +02:00
de9dda76ab Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-solidify
# Conflicts:
#	release/scripts/startup/nodeitems_builtins.py
#	source/blender/blenkernel/BKE_node.h
#	source/blender/blenkernel/intern/node.cc
#	source/blender/blenkernel/intern/solidify_nonmanifold.c
#	source/blender/nodes/CMakeLists.txt
#	source/blender/nodes/NOD_geometry.h
#	source/blender/nodes/NOD_static_types.h
2021-07-15 00:07:52 +02:00
6beb133315 Changes based on review by Jacques Lucke (JacquesLucke) 2021-07-14 23:56:29 +02:00
f9f3ece427 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-decimate
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
2021-07-14 19:42:12 +02:00
db07041c44 Geometry Nodes: Remesh Blocks
This patch adds a Remesh Voxel node (compared to Remesh Blocks)
The node uses the BKE function for voxel remeshing used in the modifier as well.

Part of the GSOC 2021

Differential Revision: https://developer.blender.org/D11907
2021-07-14 01:08:20 +02:00
62ecb33642 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-remesh-voxel
# Conflicts:
#	release/scripts/startup/nodeitems_builtins.py
#	source/blender/blenkernel/BKE_node.h
2021-07-14 00:28:50 +02:00
e1f9b7442b cleanup 2021-07-14 00:27:13 +02:00
7bad25040a - renamed WITH_MOD_REMESH to WITH_REMESH_DUALCON
since it is now shared between node and modifier no longer specific to
the modifier.
2021-07-14 00:23:50 +02:00
c7a1eeaf7b Merge remote-tracking branch 'origin/soc-2021-porting-modifiers-to-nodes-remesh-blocks' into soc-2021-porting-modifiers-to-nodes-remesh-blocks
# Conflicts:
#	source/blender/nodes/geometry/nodes/node_geo_remesh_blocks.cc
2021-07-13 23:43:22 +02:00
b191448bcb - fixed a bug with mesh renderin points. 2021-07-13 23:42:13 +02:00
0a75579e1f Geometry Nodes: Remesh Blocks
This patch adds a Remesh Blocks node (compared to Remesh Voxel)

It internaly  moves the remesh algorithm,
used in all modes of the Remesh modifier except the Voxel mode to blender kernel
and shares that code with the modifier.

Differential Revision: https://developer.blender.org/D11905
2021-07-13 22:15:37 +02:00
80f6798191 - cleanup 2021-07-13 22:00:23 +02:00
60c84d0a64 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-remesh-blocks
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
2021-07-13 20:39:12 +02:00
ef0e0af332 - Renamed Remesh to Remesh Block.
- Moved Dualcon Remesh to BKE
- Used new BKE_mesh_remesh_blocks in modifier and node.
2021-07-12 23:55:33 +02:00
344b59b66c Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-remesh
# Conflicts:
#	release/scripts/startup/nodeitems_builtins.py
#	source/blender/blenkernel/BKE_node.h
2021-07-09 23:29:44 +02:00
77116c1841 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-decimate
# Conflicts:
#	release/scripts/startup/nodeitems_builtins.py
#	source/blender/blenkernel/BKE_node.h
#	source/blender/blenkernel/intern/node.cc
2021-07-09 10:30:41 +02:00
950f1bf476 Renamed Limittypes from Face to Border and from Edge to Selection
because you can use them with different domains and the real difference
is how it uses this data.
2021-07-09 10:18:08 +02:00
d2b9cc41e7 Added attribute delimiter for dissolve node 2021-07-08 12:11:23 +02:00
1512c5c973 changes based on review by Hans Goudey (HooglyBoogly) 2021-07-07 09:17:15 +02:00
402422e8ab Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-decimate
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
#	source/blender/blenkernel/intern/node.cc
#	source/blender/nodes/CMakeLists.txt
#	source/blender/nodes/NOD_geometry.h
#	source/blender/nodes/NOD_static_types.h
2021-07-06 22:26:09 +02:00
126026c63c Merge remote-tracking branch 'origin/soc-2021-porting-modifiers-to-nodes-decimate' into soc-2021-porting-modifiers-to-nodes-decimate 2021-07-06 22:24:03 +02:00
79f8e7137d cleanup 2021-07-06 22:22:53 +02:00
54a45d1c1b Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-remesh
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
#	source/blender/nodes/NOD_geometry.h
2021-07-05 22:23:42 +02:00
bcc1b614d8 Geometry Nodes: Collapse Node, Dissolve Node, Unsubdivide Node
initially working node

added factor as slot

Merge branch 'master' into gsoc-2021-porting-modifiers-to-nodes-decimate

# Conflicts:
#	source/blender/blenkernel/BKE_node.h
#	source/blender/blenkernel/intern/node.cc
#	source/blender/nodes/CMakeLists.txt
#	source/blender/nodes/NOD_geometry.h
#	source/blender/nodes/NOD_static_types.h

Split decimate into three different nodes.

Set default values for dissolve node

removed decimate node and reformatting

Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-decimate

# Conflicts:
#	source/blender/blenkernel/BKE_node.h
#	source/blender/nodes/CMakeLists.txt

merged with master and cleanup

Differential Revision: https://developer.blender.org/D11791
2021-07-03 00:56:23 +02:00
7cacec80e5 merged with master and cleanup 2021-07-03 00:07:14 +02:00
d85d59afc9 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-decimate
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
#	source/blender/nodes/CMakeLists.txt
2021-07-02 21:57:53 +02:00
703bdbe492 removed decimate node and reformatting 2021-07-02 21:49:59 +02:00
328084acb6 Set default values for dissolve node 2021-07-02 21:36:21 +02:00
78322cbee6 Split decimate into three different nodes. 2021-07-02 20:49:28 +02:00
9722c8348d Merge branch 'master' into gsoc-2021-porting-modifiers-to-nodes-decimate
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
#	source/blender/blenkernel/intern/node.cc
#	source/blender/nodes/CMakeLists.txt
#	source/blender/nodes/NOD_geometry.h
#	source/blender/nodes/NOD_static_types.h
2021-06-27 10:28:21 +02:00
f0f26b3fcb - cleanup 2021-06-25 09:15:21 +02:00
28ee6ef31a - changes previously lost due to merge conflict.
- some more cleanup.
2021-06-25 09:06:18 +02:00
6afd66c2eb Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-solidify 2021-06-25 08:04:02 +02:00
5379633e59 - corrected two comments in corresponding test 2021-06-24 23:11:39 +02:00
051ce30390 Merge branch 'master' into gsoc-2021-porting-modifiers-to-nodes-solidify 2021-06-24 21:16:25 +02:00
1f70e8b748 - changes based on review by Hans Goudey. 2021-06-24 01:37:45 +02:00
ecc67c10e1 - changes based on review by Hans Goudey. 2021-06-24 00:40:57 +02:00
75df5d34d3 - some more cleanup 2021-06-22 11:31:34 +02:00
aedf0f3efa Merge remote-tracking branch 'origin/gsoc-2021-porting-modifiers-to-nodes-solidify' into gsoc-2021-porting-modifiers-to-nodes-solidify
# Conflicts:
#	source/blender/nodes/CMakeLists.txt
#	source/blender/nodes/geometry/nodes/node_geo_solidifiy.cc
2021-06-22 10:49:28 +02:00
97aab4245e - re-added the one important file that I deleted by accident. 2021-06-22 10:43:29 +02:00
897838a2cc - deleted unneeded files 2021-06-22 09:45:28 +02:00
0766941f8f rebaseing and cleanup 2021-06-22 09:41:49 +02:00
bfbeabeb39 - selection for simple 2021-06-22 09:40:18 +02:00
efcab1bc1b makeing node and modifier working with solidify kernel version. 2021-06-22 09:37:36 +02:00
4a4445124e moved solidify to Blender Kernel 2021-06-22 09:28:13 +02:00
a58a4cfc14 - working with data from node 2021-06-22 09:26:06 +02:00
c71b4ee3f6 solidify_extrude_generaly working. 2021-06-22 09:25:49 +02:00
496e3b2b1a - rebased to master
- removed solidify extrude mode from node and reverted solidify extrude
back to internal version in modifier
- fixed vertex-groups for
2021-06-22 09:22:19 +02:00
fa06eb9b97 - added output groups for rim and fill 2021-06-22 09:20:46 +02:00
7d2b039942 Initial setup for solidify node
solidify_extrude_generaly working.

- working with data from node

- added basic support for input data

moved solidify to Blender Kernel

makeing node and modifier working with solidify kernel version.

- added offset and boundary data enums for nonmanifold mode.

- selection for simple

make selection work for complex mode

rebaseing and cleanup

Differential Revision: https://developer.blender.org/D11575
2021-06-22 09:18:10 +02:00
a13e9edfbb - selection for simple 2021-06-22 09:16:06 +02:00
00a3241095 makeing node and modifier working with solidify kernel version. 2021-06-22 09:12:54 +02:00
171a1feeb3 moved solidify to Blender Kernel 2021-06-22 09:04:35 +02:00
c17b1601b7 - added basic support for input data 2021-06-22 09:00:02 +02:00
931b1ed7c7 - working with data from node 2021-06-22 09:00:02 +02:00
b51602996e solidify_extrude_generaly working. 2021-06-22 09:00:02 +02:00
1cc5ab539b Initial setup for solidify node 2021-06-22 09:00:02 +02:00
f12f0f0cd9 generalized material offset for solidify_modifier 2021-06-22 08:59:34 +02:00
2869ee328c added back vertex-group reverse option. 2021-06-22 08:59:34 +02:00
84ecc6c3e1 rebaseing and cleanup 2021-06-22 08:59:34 +02:00
0176d404f1 - selection for simple 2021-06-22 08:59:34 +02:00
821b17be25 makeing node and modifier working with solidify kernel version. 2021-06-22 08:59:34 +02:00
751679edc2 moved solidify to Blender Kernel 2021-06-22 08:59:34 +02:00
fd9932d380 - working with data from node 2021-06-22 08:59:34 +02:00
da94c057fd solidify_extrude_generaly working. 2021-06-22 08:59:34 +02:00
a44785c4dc - formatting 2021-06-22 08:59:34 +02:00
ef51c65775 - rebased to master
- removed solidify extrude mode from node and reverted solidify extrude
back to internal version in modifier
- fixed vertex-groups for
2021-06-22 08:59:34 +02:00
b4ff2ce85d - added output groups for rim and fill 2021-06-22 08:59:34 +02:00
1640c3536f Initial setup for solidify node
solidify_extrude_generaly working.

- working with data from node

- added basic support for input data

moved solidify to Blender Kernel

makeing node and modifier working with solidify kernel version.

- added offset and boundary data enums for nonmanifold mode.

- selection for simple

make selection work for complex mode

rebaseing and cleanup

Differential Revision: https://developer.blender.org/D11575
2021-06-22 08:59:34 +02:00
08fc5f1d8e make selection work for complex mode 2021-06-22 08:59:34 +02:00
339b7a7b03 - selection for simple 2021-06-22 08:59:34 +02:00
5af6c35dd1 - added offset and boundary data enums for nonmanifold mode. 2021-06-22 08:59:34 +02:00
a33076f769 makeing node and modifier working with solidify kernel version. 2021-06-22 08:59:33 +02:00
7026eca6e3 moved solidify to Blender Kernel 2021-06-22 08:59:33 +02:00
0291553d70 - added basic support for input data 2021-06-22 08:59:33 +02:00
48fc1bde95 - working with data from node 2021-06-22 08:59:33 +02:00
48dc0c6fd6 solidify_extrude_generaly working. 2021-06-22 08:59:33 +02:00
95bd8e494c Initial setup for solidify node 2021-06-22 08:59:33 +02:00
328406cf60 generalized material offset for solidify_modifier 2021-06-18 21:14:59 +02:00
3ecf0753e8 added back vertex-group reverse option. 2021-06-18 17:22:24 +02:00
dbeb2a7724 Merge remote-tracking branch 'origin/gsoc-2021-porting-modifiers-to-nodes-solidify' into gsoc-2021-porting-modifiers-to-nodes-solidify
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
#	source/blender/blenkernel/BKE_solidifiy.h
#	source/blender/blenkernel/CMakeLists.txt
#	source/blender/blenkernel/intern/node.cc
#	source/blender/blenkernel/intern/solidify_nonmanifold.c
#	source/blender/makesrna/intern/rna_nodetree.c
#	source/blender/modifiers/intern/MOD_solidify.c
#	source/blender/nodes/CMakeLists.txt
#	source/blender/nodes/NOD_geometry.h
#	source/blender/nodes/NOD_static_types.h
2021-06-18 16:24:12 +02:00
f07aa393bf - formatting 2021-06-18 16:07:51 +02:00
68a28e1982 - rebased to master
- removed solidify extrude mode from node and reverted solidify extrude
back to internal version in modifier
- fixed vertex-groups for
2021-06-18 16:07:51 +02:00
f23bb03cbb - added output groups for rim and fill 2021-06-18 16:07:51 +02:00
1fcbade10c Initial setup for solidify node
solidify_extrude_generaly working.

- working with data from node

- added basic support for input data

moved solidify to Blender Kernel

makeing node and modifier working with solidify kernel version.

- added offset and boundary data enums for nonmanifold mode.

- selection for simple

make selection work for complex mode

rebaseing and cleanup

Differential Revision: https://developer.blender.org/D11575
2021-06-18 16:07:51 +02:00
cbe359bbf2 make selection work for complex mode 2021-06-18 16:07:51 +02:00
3493fefb74 - selection for simple 2021-06-18 16:07:51 +02:00
8f600e8256 - added offset and boundary data enums for nonmanifold mode. 2021-06-18 16:07:51 +02:00
607eef0ae7 makeing node and modifier working with solidify kernel version. 2021-06-18 16:07:51 +02:00
035ee22a50 moved solidify to Blender Kernel 2021-06-18 16:07:51 +02:00
e39543a64d - added basic support for input data 2021-06-18 16:07:51 +02:00
a97bfc4e31 - working with data from node 2021-06-18 16:07:51 +02:00
30ea058694 solidify_extrude_generaly working. 2021-06-18 16:07:51 +02:00
6fad4ce981 Initial setup for solidify node 2021-06-18 16:07:51 +02:00
c718d169a9 rebaseing and cleanup 2021-06-10 21:01:34 +02:00
0a96b035cf make selection work for complex mode 2021-06-10 20:11:24 +02:00
39f1908ba9 - selection for simple 2021-06-10 20:11:24 +02:00
1f38c1f3b2 - added offset and boundary data enums for nonmanifold mode. 2021-06-10 20:11:24 +02:00
5444335e44 makeing node and modifier working with solidify kernel version. 2021-06-10 20:11:24 +02:00
531c65fd93 moved solidify to Blender Kernel 2021-06-10 20:11:09 +02:00
1e07e070fc - added basic support for input data 2021-06-10 20:10:23 +02:00
29c0528eb6 - working with data from node 2021-06-10 20:10:23 +02:00
174052e1de solidify_extrude_generaly working. 2021-06-10 20:10:23 +02:00
caac062b55 Initial setup for solidify node 2021-06-10 20:10:23 +02:00
2f65eed0e7 - make initial setup work. 2021-05-27 21:05:39 +02:00
ff8ad9b24b - first impression 2021-05-27 20:32:20 +02:00
641d268d59 added factor as slot 2021-05-26 00:55:37 +02:00
d82bda7b44 initially working node 2021-05-26 00:45:40 +02:00
ded679d866 Initial setup for decimate node 2021-05-20 20:21:06 +02:00
0ddfdb0dbf Initial setup for remesh node 2021-05-20 11:01:08 +02:00
303 changed files with 6285 additions and 11624 deletions

View File

@@ -269,10 +269,11 @@ if(UNIX AND NOT APPLE)
option(WITH_SYSTEM_EIGEN3 "Use the systems Eigen3 library" OFF)
endif()
# Geometry
option(WITH_REMESH_DUALCON "Enable Remesh Algorithm using Dualcon" ON)
# Modifiers
option(WITH_MOD_FLUID "Enable Mantaflow Fluid Simulation Framework" ON)
option(WITH_MOD_REMESH "Enable Remesh Modifier" ON)
option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" ON)
# Image format support
@@ -1598,7 +1599,8 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNUSED_PARAMETER -Wunused-parameter)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ALL -Wall)
# Using C++20 features while having C++17 as the project language isn't allowed by MSVC.
# Designated initializer is a C++20 feature & breaks MSVC build. Dropping MSVC 2019 or
# updating to C++20 allows removing this.
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_CXX20_DESIGNATOR -Wc++20-designator)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_AUTOLOGICAL_COMPARE -Wno-tautological-compare)
@@ -1994,7 +1996,7 @@ if(FIRST_RUN)
info_cfg_text("Modifiers:")
info_cfg_option(WITH_MOD_FLUID)
info_cfg_option(WITH_MOD_OCEANSIM)
info_cfg_option(WITH_MOD_REMESH)
info_cfg_option(WITH_REMESH_DUALCON)
info_cfg_text("OpenGL:")
if(WIN32)

View File

@@ -37,7 +37,7 @@ set(WITH_LZMA ON CACHE BOOL "" FORCE)
set(WITH_LZO ON CACHE BOOL "" FORCE)
set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE)
set(WITH_MOD_OCEANSIM ON CACHE BOOL "" FORCE)
set(WITH_MOD_REMESH ON CACHE BOOL "" FORCE)
set(WITH_REMESH_DUALCON ON CACHE BOOL "" FORCE)
set(WITH_NANOVDB ON CACHE BOOL "" FORCE)
set(WITH_OPENAL ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)

View File

@@ -43,7 +43,7 @@ set(WITH_LZMA OFF CACHE BOOL "" FORCE)
set(WITH_LZO OFF CACHE BOOL "" FORCE)
set(WITH_MOD_FLUID OFF CACHE BOOL "" FORCE)
set(WITH_MOD_OCEANSIM OFF CACHE BOOL "" FORCE)
set(WITH_MOD_REMESH OFF CACHE BOOL "" FORCE)
set(WITH_REMESH_DUALCON OFF CACHE BOOL "" FORCE)
set(WITH_NANOVDB OFF CACHE BOOL "" FORCE)
set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)

View File

@@ -38,7 +38,7 @@ set(WITH_LZMA ON CACHE BOOL "" FORCE)
set(WITH_LZO ON CACHE BOOL "" FORCE)
set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE)
set(WITH_MOD_OCEANSIM ON CACHE BOOL "" FORCE)
set(WITH_MOD_REMESH ON CACHE BOOL "" FORCE)
set(WITH_REMESH_DUALCON ON CACHE BOOL "" FORCE)
set(WITH_NANOVDB ON CACHE BOOL "" FORCE)
set(WITH_OPENAL ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)

View File

@@ -51,9 +51,9 @@ buildbot:
gcc:
version: '9.0.0'
cuda10:
version: '10.1.243'
version: '10.1.0'
cuda11:
version: '11.4.1'
version: '11.4.0'
optix:
version: '7.1.0'
cmake:

View File

@@ -37,7 +37,7 @@ if(WITH_AUDASPACE)
add_subdirectory(audaspace)
endif()
if(WITH_MOD_REMESH)
if(WITH_REMESH_DUALCON)
add_subdirectory(dualcon)
endif()

View File

@@ -424,7 +424,7 @@ static inline void set_enum(PointerRNA &ptr, const char *name, const string &ide
static inline string get_string(PointerRNA &ptr, const char *name)
{
char cstrbuf[1024];
char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf), NULL);
char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf));
string str(cstr);
if (cstr != cstrbuf)
MEM_freeN(cstr);

View File

@@ -36,10 +36,10 @@ static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledDiffuseBsdf),
ccl_device float3 calculate_principled_diffuse_brdf(
const PrincipledDiffuseBsdf *bsdf, float3 N, float3 V, float3 L, float3 H, float *pdf)
{
float NdotL = dot(N, L);
float NdotV = dot(N, V);
float NdotL = max(dot(N, L), 0.0f);
float NdotV = max(dot(N, V), 0.0f);
if (NdotL <= 0 || NdotV <= 0) {
if (NdotL < 0 || NdotV < 0) {
*pdf = 0.0f;
return make_float3(0.0f, 0.0f, 0.0f);
}

View File

@@ -997,6 +997,7 @@ class USERPREF_PT_theme_text_style(ThemePanel, CenterAlignMixIn, Panel):
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
col = flow.column()
col.row().prop(font_style, "font_kerning_style", expand=True)
col.prop(font_style, "points")
col = flow.column(align=True)

View File

@@ -532,6 +532,7 @@ geometry_node_categories = [
NodeItem("GeometryNodeJoinGeometry"),
NodeItem("GeometryNodeSeparateComponents"),
NodeItem("GeometryNodeRaycast"),
NodeItem("GeometryNodeMergeByDistance"),
]),
GeometryNodeCategory("GEO_INPUT", "Input", items=[
NodeItem("GeometryNodeObjectInfo"),
@@ -554,6 +555,14 @@ geometry_node_categories = [
NodeItem("GeometryNodeEdgeSplit"),
NodeItem("GeometryNodeSubdivisionSurface"),
NodeItem("GeometryNodeMeshSubdivide"),
NodeItem("GeometryNodeSolidify"),
NodeItem("GeometryNodeRemeshVoxel"),
NodeItem("GeometryNodeRemeshBlocks"),
NodeItem("GeometryNodeMeshExtrude"),
NodeItem("GeometryNodeMeshInset"),
NodeItem("GeometryNodeCollapse"),
NodeItem("GeometryNodeUnsubdivide"),
NodeItem("GeometryNodeDissolve"),
]),
GeometryNodeCategory("GEO_PRIMITIVES_MESH", "Mesh Primitives", items=[
NodeItem("GeometryNodeMeshCircle"),

View File

@@ -118,6 +118,7 @@ add_subdirectory(blenloader)
add_subdirectory(depsgraph)
add_subdirectory(ikplugin)
add_subdirectory(simulation)
add_subdirectory(geometry)
add_subdirectory(gpu)
add_subdirectory(imbuf)
add_subdirectory(nodes)

View File

@@ -98,13 +98,13 @@ void BLF_batch_draw_flush(void);
void BLF_batch_draw_end(void);
/* Draw the string using the current font. */
void BLF_draw_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info)
void BLF_draw_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
ATTR_NONNULL(2);
void BLF_draw(int fontid, const char *str, size_t str_len) ATTR_NONNULL(2);
void BLF_draw_ascii_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info)
void BLF_draw(int fontid, const char *str, size_t len) ATTR_NONNULL(2);
void BLF_draw_ascii_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
ATTR_NONNULL(2);
void BLF_draw_ascii(int fontid, const char *str, size_t str_len) ATTR_NONNULL(2);
int BLF_draw_mono(int fontid, const char *str, size_t str_len, int cwidth) ATTR_NONNULL(2);
void BLF_draw_ascii(int fontid, const char *str, size_t len) ATTR_NONNULL(2);
int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth) ATTR_NONNULL(2);
typedef bool (*BLF_GlyphBoundsFn)(const char *str,
const size_t str_step_ofs,
@@ -116,45 +116,43 @@ typedef bool (*BLF_GlyphBoundsFn)(const char *str,
void BLF_boundbox_foreach_glyph_ex(int fontid,
const char *str,
size_t str_len,
size_t len,
BLF_GlyphBoundsFn user_fn,
void *user_data,
struct ResultBLF *r_info) ATTR_NONNULL(2);
void BLF_boundbox_foreach_glyph(int fontid,
const char *str,
size_t str_len,
size_t len,
BLF_GlyphBoundsFn user_fn,
void *user_data) ATTR_NONNULL(2);
/* Get the string byte offset that fits within a given width */
size_t BLF_width_to_strlen(
int fontid, const char *str, size_t str_len, float width, float *r_width) ATTR_NONNULL(2);
size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width)
ATTR_NONNULL(2);
/* Same as BLF_width_to_strlen but search from the string end */
size_t BLF_width_to_rstrlen(
int fontid, const char *str, size_t str_len, float width, float *r_width) ATTR_NONNULL(2);
size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width, float *r_width)
ATTR_NONNULL(2);
/* This function return the bounding box of the string
* and are not multiplied by the aspect.
*/
void BLF_boundbox_ex(int fontid,
const char *str,
size_t str_len,
size_t len,
struct rctf *box,
struct ResultBLF *r_info) ATTR_NONNULL(2);
void BLF_boundbox(int fontid, const char *str, size_t str_len, struct rctf *box) ATTR_NONNULL();
void BLF_boundbox(int fontid, const char *str, size_t len, struct rctf *box) ATTR_NONNULL();
/* The next both function return the width and height
* of the string, using the current font and both value
* are multiplied by the aspect of the font.
*/
float BLF_width_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info)
float BLF_width_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
float BLF_width(int fontid, const char *str, size_t str_len) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
float BLF_height_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info)
float BLF_width(int fontid, const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
float BLF_height_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
float BLF_height(int fontid, const char *str, size_t str_len) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
float BLF_height(int fontid, const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* Return dimensions of the font without any sample text. */
int BLF_height_max(int fontid) ATTR_WARN_UNUSED_RESULT;
@@ -165,8 +163,8 @@ float BLF_ascender(int fontid) ATTR_WARN_UNUSED_RESULT;
/* The following function return the width and height of the string, but
* just in one call, so avoid extra freetype2 stuff.
*/
void BLF_width_and_height(
int fontid, const char *str, size_t str_len, float *r_width, float *r_height) ATTR_NONNULL();
void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height)
ATTR_NONNULL();
/* For fixed width fonts only, returns the width of a
* character.
@@ -223,9 +221,9 @@ void BLF_buffer_col(int fontid, const float rgba[4]) ATTR_NONNULL(2);
/* Draw the string into the buffer, this function draw in both buffer,
* float and unsigned char _BUT_ it's not necessary set both buffer, NULL is valid here.
*/
void BLF_draw_buffer_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info)
void BLF_draw_buffer_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
ATTR_NONNULL(2);
void BLF_draw_buffer(int fontid, const char *str, size_t str_len) ATTR_NONNULL(2);
void BLF_draw_buffer(int fontid, const char *str, size_t len) ATTR_NONNULL(2);
/* Add a path to the font dir paths. */
void BLF_dir_add(const char *path) ATTR_NONNULL();
@@ -256,9 +254,8 @@ void BLF_default_dpi(int dpi);
void BLF_default_set(int fontid);
int BLF_default(void); /* get default font ID so we can pass it to other functions */
/* Draw the string using the default font, size and dpi. */
void BLF_draw_default(float x, float y, float z, const char *str, size_t str_len) ATTR_NONNULL();
void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t str_len)
ATTR_NONNULL();
void BLF_draw_default(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL();
void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL();
/* Set size and DPI, and return default font ID. */
int BLF_set_default(void);

View File

@@ -521,7 +521,7 @@ static void blf_draw_gl__end(FontBLF *font)
}
}
void BLF_draw_ex(int fontid, const char *str, const size_t str_len, struct ResultBLF *r_info)
void BLF_draw_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
@@ -530,27 +530,27 @@ void BLF_draw_ex(int fontid, const char *str, const size_t str_len, struct Resul
if (font) {
blf_draw_gl__start(font);
if (font->flags & BLF_WORD_WRAP) {
blf_font_draw__wrap(font, str, str_len, r_info);
blf_font_draw__wrap(font, str, len, r_info);
}
else {
blf_font_draw(font, str, str_len, r_info);
blf_font_draw(font, str, len, r_info);
}
blf_draw_gl__end(font);
}
}
void BLF_draw(int fontid, const char *str, const size_t str_len)
void BLF_draw(int fontid, const char *str, size_t len)
{
if (str_len == 0 || str[0] == '\0') {
if (len == 0 || str[0] == '\0') {
return;
}
/* Avoid bgl usage to corrupt BLF drawing. */
GPU_bgl_end();
BLF_draw_ex(fontid, str, str_len, NULL);
BLF_draw_ex(fontid, str, len, NULL);
}
void BLF_draw_ascii_ex(int fontid, const char *str, const size_t str_len, struct ResultBLF *r_info)
void BLF_draw_ascii_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
@@ -560,27 +560,27 @@ void BLF_draw_ascii_ex(int fontid, const char *str, const size_t str_len, struct
blf_draw_gl__start(font);
if (font->flags & BLF_WORD_WRAP) {
/* Use non-ASCII draw function for word-wrap. */
blf_font_draw__wrap(font, str, str_len, r_info);
blf_font_draw__wrap(font, str, len, r_info);
}
else {
blf_font_draw_ascii(font, str, str_len, r_info);
blf_font_draw_ascii(font, str, len, r_info);
}
blf_draw_gl__end(font);
}
}
void BLF_draw_ascii(int fontid, const char *str, const size_t str_len)
void BLF_draw_ascii(int fontid, const char *str, size_t len)
{
if (str_len == 0 || str[0] == '\0') {
if (len == 0 || str[0] == '\0') {
return;
}
BLF_draw_ascii_ex(fontid, str, str_len, NULL);
BLF_draw_ascii_ex(fontid, str, len, NULL);
}
int BLF_draw_mono(int fontid, const char *str, const size_t str_len, int cwidth)
int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
{
if (str_len == 0 || str[0] == '\0') {
if (len == 0 || str[0] == '\0') {
return 0;
}
@@ -589,7 +589,7 @@ int BLF_draw_mono(int fontid, const char *str, const size_t str_len, int cwidth)
if (font) {
blf_draw_gl__start(font);
columns = blf_font_draw_mono(font, str, str_len, cwidth);
columns = blf_font_draw_mono(font, str, len, cwidth);
blf_draw_gl__end(font);
}
@@ -606,7 +606,7 @@ int BLF_draw_mono(int fontid, const char *str, const size_t str_len, int cwidth)
*/
void BLF_boundbox_foreach_glyph_ex(int fontid,
const char *str,
size_t str_len,
size_t len,
BLF_GlyphBoundsFn user_fn,
void *user_data,
struct ResultBLF *r_info)
@@ -621,26 +621,25 @@ void BLF_boundbox_foreach_glyph_ex(int fontid,
BLI_assert(0);
}
else {
blf_font_boundbox_foreach_glyph(font, str, str_len, user_fn, user_data, r_info);
blf_font_boundbox_foreach_glyph(font, str, len, user_fn, user_data, r_info);
}
}
}
void BLF_boundbox_foreach_glyph(
int fontid, const char *str, const size_t str_len, BLF_GlyphBoundsFn user_fn, void *user_data)
int fontid, const char *str, size_t len, BLF_GlyphBoundsFn user_fn, void *user_data)
{
BLF_boundbox_foreach_glyph_ex(fontid, str, str_len, user_fn, user_data, NULL);
BLF_boundbox_foreach_glyph_ex(fontid, str, len, user_fn, user_data, NULL);
}
size_t BLF_width_to_strlen(
int fontid, const char *str, const size_t str_len, float width, float *r_width)
size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width)
{
FontBLF *font = blf_get(fontid);
if (font) {
const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
size_t ret;
ret = blf_font_width_to_strlen(font, str, str_len, width / xa, r_width);
ret = blf_font_width_to_strlen(font, str, len, width / xa, r_width);
if (r_width) {
*r_width *= xa;
}
@@ -653,15 +652,14 @@ size_t BLF_width_to_strlen(
return 0;
}
size_t BLF_width_to_rstrlen(
int fontid, const char *str, const size_t str_len, float width, float *r_width)
size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width, float *r_width)
{
FontBLF *font = blf_get(fontid);
if (font) {
const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
size_t ret;
ret = blf_font_width_to_rstrlen(font, str, str_len, width / xa, r_width);
ret = blf_font_width_to_rstrlen(font, str, len, width / xa, r_width);
if (r_width) {
*r_width *= xa;
}
@@ -675,7 +673,7 @@ size_t BLF_width_to_rstrlen(
}
void BLF_boundbox_ex(
int fontid, const char *str, const size_t str_len, rctf *r_box, struct ResultBLF *r_info)
int fontid, const char *str, size_t len, rctf *r_box, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
@@ -683,48 +681,47 @@ void BLF_boundbox_ex(
if (font) {
if (font->flags & BLF_WORD_WRAP) {
blf_font_boundbox__wrap(font, str, str_len, r_box, r_info);
blf_font_boundbox__wrap(font, str, len, r_box, r_info);
}
else {
blf_font_boundbox(font, str, str_len, r_box, r_info);
blf_font_boundbox(font, str, len, r_box, r_info);
}
}
}
void BLF_boundbox(int fontid, const char *str, const size_t str_len, rctf *r_box)
void BLF_boundbox(int fontid, const char *str, size_t len, rctf *r_box)
{
BLF_boundbox_ex(fontid, str, str_len, r_box, NULL);
BLF_boundbox_ex(fontid, str, len, r_box, NULL);
}
void BLF_width_and_height(
int fontid, const char *str, const size_t str_len, float *r_width, float *r_height)
void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height)
{
FontBLF *font = blf_get(fontid);
if (font) {
blf_font_width_and_height(font, str, str_len, r_width, r_height, NULL);
blf_font_width_and_height(font, str, len, r_width, r_height, NULL);
}
else {
*r_width = *r_height = 0.0f;
}
}
float BLF_width_ex(int fontid, const char *str, const size_t str_len, struct ResultBLF *r_info)
float BLF_width_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
BLF_RESULT_CHECK_INIT(r_info);
if (font) {
return blf_font_width(font, str, str_len, r_info);
return blf_font_width(font, str, len, r_info);
}
return 0.0f;
}
float BLF_width(int fontid, const char *str, const size_t str_len)
float BLF_width(int fontid, const char *str, size_t len)
{
return BLF_width_ex(fontid, str, str_len, NULL);
return BLF_width_ex(fontid, str, len, NULL);
}
float BLF_fixed_width(int fontid)
@@ -738,22 +735,22 @@ float BLF_fixed_width(int fontid)
return 0.0f;
}
float BLF_height_ex(int fontid, const char *str, const size_t str_len, struct ResultBLF *r_info)
float BLF_height_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
BLF_RESULT_CHECK_INIT(r_info);
if (font) {
return blf_font_height(font, str, str_len, r_info);
return blf_font_height(font, str, len, r_info);
}
return 0.0f;
}
float BLF_height(int fontid, const char *str, const size_t str_len)
float BLF_height(int fontid, const char *str, size_t len)
{
return BLF_height_ex(fontid, str, str_len, NULL);
return BLF_height_ex(fontid, str, len, NULL);
}
int BLF_height_max(int fontid)
@@ -897,27 +894,24 @@ void blf_draw_buffer__end(void)
{
}
void BLF_draw_buffer_ex(int fontid,
const char *str,
const size_t str_len,
struct ResultBLF *r_info)
void BLF_draw_buffer_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
if (font && (font->buf_info.fbuf || font->buf_info.cbuf)) {
blf_draw_buffer__start(font);
if (font->flags & BLF_WORD_WRAP) {
blf_font_draw_buffer__wrap(font, str, str_len, r_info);
blf_font_draw_buffer__wrap(font, str, len, r_info);
}
else {
blf_font_draw_buffer(font, str, str_len, r_info);
blf_font_draw_buffer(font, str, len, r_info);
}
blf_draw_buffer__end();
}
}
void BLF_draw_buffer(int fontid, const char *str, const size_t str_len)
void BLF_draw_buffer(int fontid, const char *str, size_t len)
{
BLF_draw_buffer_ex(fontid, str, str_len, NULL);
BLF_draw_buffer_ex(fontid, str, len, NULL);
}
char *BLF_display_name_from_file(const char *filename)

View File

@@ -68,23 +68,23 @@ int BLF_set_default(void)
return global_font_default;
}
void BLF_draw_default(float x, float y, float z, const char *str, const size_t str_len)
void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
{
ASSERT_DEFAULT_SET;
const uiStyle *style = UI_style_get();
BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi);
BLF_position(global_font_default, x, y, z);
BLF_draw(global_font_default, str, str_len);
BLF_draw(global_font_default, str, len);
}
/* same as above but call 'BLF_draw_ascii' */
void BLF_draw_default_ascii(float x, float y, float z, const char *str, const size_t str_len)
void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len)
{
ASSERT_DEFAULT_SET;
const uiStyle *style = UI_style_get();
BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi);
BLF_position(global_font_default, x, y, z);
BLF_draw_ascii(global_font_default, str, str_len); /* XXX, use real length */
BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */
}

View File

@@ -365,7 +365,7 @@ BLI_INLINE void blf_kerning_step_fast(FontBLF *font,
static void blf_font_draw_ex(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
const size_t str_len,
size_t len,
struct ResultBLF *r_info,
int pen_y)
{
@@ -374,14 +374,14 @@ static void blf_font_draw_ex(FontBLF *font,
int pen_x = 0;
size_t i = 0;
if (str_len == 0) {
if (len == 0) {
/* early output, don't do any IMM OpenGL. */
return;
}
blf_batch_draw_begin(font);
while ((i < str_len) && str[i]) {
while ((i < len) && str[i]) {
g = blf_utf8_next_fast(font, gc, str, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
@@ -407,16 +407,16 @@ static void blf_font_draw_ex(FontBLF *font,
r_info->width = pen_x;
}
}
void blf_font_draw(FontBLF *font, const char *str, const size_t str_len, struct ResultBLF *r_info)
void blf_font_draw(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
blf_font_draw_ex(font, gc, str, str_len, r_info, 0);
blf_font_draw_ex(font, gc, str, len, r_info, 0);
blf_glyph_cache_release(font);
}
/* faster version of blf_font_draw, ascii only for view dimensions */
static void blf_font_draw_ascii_ex(
FontBLF *font, const char *str, size_t str_len, struct ResultBLF *r_info, int pen_y)
FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info, int pen_y)
{
unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev = NULL;
@@ -426,7 +426,7 @@ static void blf_font_draw_ascii_ex(
blf_batch_draw_begin(font);
while ((c = *(str++)) && str_len--) {
while ((c = *(str++)) && len--) {
BLI_assert(c < GLYPH_ASCII_TABLE_SIZE);
g = gc->glyph_ascii_table[c];
if (UNLIKELY(g == NULL)) {
@@ -456,16 +456,13 @@ static void blf_font_draw_ascii_ex(
blf_glyph_cache_release(font);
}
void blf_font_draw_ascii(FontBLF *font,
const char *str,
const size_t str_len,
struct ResultBLF *r_info)
void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
blf_font_draw_ascii_ex(font, str, str_len, r_info, 0);
blf_font_draw_ascii_ex(font, str, len, r_info, 0);
}
/* use fixed column width, but an utf8 character may occupy multiple columns */
int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int cwidth)
int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
{
unsigned int c;
GlyphBLF *g;
@@ -477,7 +474,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int
blf_batch_draw_begin(font);
while ((i < str_len) && str[i]) {
while ((i < len) && str[i]) {
g = blf_utf8_next_fast(font, gc, str, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
@@ -515,7 +512,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int
static void blf_font_draw_buffer_ex(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
const size_t str_len,
size_t len,
struct ResultBLF *r_info,
int pen_y)
{
@@ -534,7 +531,7 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
/* another buffer specific call for color conversion */
while ((i < str_len) && str[i]) {
while ((i < len) && str[i]) {
g = blf_utf8_next_fast(font, gc, str, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
@@ -649,13 +646,10 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
}
}
void blf_font_draw_buffer(FontBLF *font,
const char *str,
const size_t str_len,
struct ResultBLF *r_info)
void blf_font_draw_buffer(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
blf_font_draw_buffer_ex(font, gc, str, str_len, r_info, 0);
blf_font_draw_buffer_ex(font, gc, str, len, r_info, 0);
blf_glyph_cache_release(font);
}
@@ -691,7 +685,7 @@ static bool blf_font_width_to_strlen_glyph_process(FontBLF *font,
}
size_t blf_font_width_to_strlen(
FontBLF *font, const char *str, const size_t str_len, float width, float *r_width)
FontBLF *font, const char *str, size_t len, float width, float *r_width)
{
unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev;
@@ -701,7 +695,7 @@ size_t blf_font_width_to_strlen(
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
const int width_i = (int)width;
for (i_prev = i = 0, width_new = pen_x = 0, g_prev = NULL, c_prev = 0; (i < str_len) && str[i];
for (i_prev = i = 0, width_new = pen_x = 0, g_prev = NULL, c_prev = 0; (i < len) && str[i];
i_prev = i, width_new = pen_x, c_prev = c, g_prev = g) {
g = blf_utf8_next_fast(font, gc, str, &i, &c);
@@ -719,7 +713,7 @@ size_t blf_font_width_to_strlen(
}
size_t blf_font_width_to_rstrlen(
FontBLF *font, const char *str, const size_t str_len, float width, float *r_width)
FontBLF *font, const char *str, size_t len, float width, float *r_width)
{
unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev;
@@ -730,7 +724,7 @@ size_t blf_font_width_to_rstrlen(
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
const int width_i = (int)width;
i = BLI_strnlen(str, str_len);
i = BLI_strnlen(str, len);
s = BLI_str_find_prev_char_utf8(str, &str[i]);
i = (size_t)((s != NULL) ? s - str : 0);
s_prev = BLI_str_find_prev_char_utf8(str, s);
@@ -771,7 +765,7 @@ size_t blf_font_width_to_rstrlen(
static void blf_font_boundbox_ex(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
const size_t str_len,
size_t len,
rctf *box,
struct ResultBLF *r_info,
int pen_y)
@@ -787,7 +781,7 @@ static void blf_font_boundbox_ex(FontBLF *font,
box->ymin = 32000.0f;
box->ymax = -32000.0f;
while ((i < str_len) && str[i]) {
while ((i < len) && str[i]) {
g = blf_utf8_next_fast(font, gc, str, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
@@ -835,16 +829,16 @@ static void blf_font_boundbox_ex(FontBLF *font,
}
}
void blf_font_boundbox(
FontBLF *font, const char *str, const size_t str_len, rctf *r_box, struct ResultBLF *r_info)
FontBLF *font, const char *str, size_t len, rctf *r_box, struct ResultBLF *r_info)
{
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
blf_font_boundbox_ex(font, gc, str, str_len, r_box, r_info, 0);
blf_font_boundbox_ex(font, gc, str, len, r_box, r_info, 0);
blf_glyph_cache_release(font);
}
void blf_font_width_and_height(FontBLF *font,
const char *str,
const size_t str_len,
size_t len,
float *r_width,
float *r_height,
struct ResultBLF *r_info)
@@ -862,19 +856,16 @@ void blf_font_width_and_height(FontBLF *font,
}
if (font->flags & BLF_WORD_WRAP) {
blf_font_boundbox__wrap(font, str, str_len, &box, r_info);
blf_font_boundbox__wrap(font, str, len, &box, r_info);
}
else {
blf_font_boundbox(font, str, str_len, &box, r_info);
blf_font_boundbox(font, str, len, &box, r_info);
}
*r_width = (BLI_rctf_size_x(&box) * xa);
*r_height = (BLI_rctf_size_y(&box) * ya);
}
float blf_font_width(FontBLF *font,
const char *str,
const size_t str_len,
struct ResultBLF *r_info)
float blf_font_width(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
float xa;
rctf box;
@@ -887,18 +878,15 @@ float blf_font_width(FontBLF *font,
}
if (font->flags & BLF_WORD_WRAP) {
blf_font_boundbox__wrap(font, str, str_len, &box, r_info);
blf_font_boundbox__wrap(font, str, len, &box, r_info);
}
else {
blf_font_boundbox(font, str, str_len, &box, r_info);
blf_font_boundbox(font, str, len, &box, r_info);
}
return BLI_rctf_size_x(&box) * xa;
}
float blf_font_height(FontBLF *font,
const char *str,
const size_t str_len,
struct ResultBLF *r_info)
float blf_font_height(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
float ya;
rctf box;
@@ -911,10 +899,10 @@ float blf_font_height(FontBLF *font,
}
if (font->flags & BLF_WORD_WRAP) {
blf_font_boundbox__wrap(font, str, str_len, &box, r_info);
blf_font_boundbox__wrap(font, str, len, &box, r_info);
}
else {
blf_font_boundbox(font, str, str_len, &box, r_info);
blf_font_boundbox(font, str, len, &box, r_info);
}
return BLI_rctf_size_y(&box) * ya;
}
@@ -942,7 +930,7 @@ float blf_font_fixed_width(FontBLF *font)
static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
const size_t str_len,
size_t len,
BLF_GlyphBoundsFn user_fn,
void *user_data,
struct ResultBLF *r_info,
@@ -954,12 +942,12 @@ static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
size_t i = 0, i_curr;
rcti gbox;
if (str_len == 0) {
if (len == 0) {
/* early output. */
return;
}
while ((i < str_len) && str[i]) {
while ((i < len) && str[i]) {
i_curr = i;
g = blf_utf8_next_fast(font, gc, str, &i, &c);
@@ -993,13 +981,13 @@ static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
}
void blf_font_boundbox_foreach_glyph(FontBLF *font,
const char *str,
const size_t str_len,
size_t len,
BLF_GlyphBoundsFn user_fn,
void *user_data,
struct ResultBLF *r_info)
{
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
blf_font_boundbox_foreach_glyph_ex(font, gc, str, str_len, user_fn, user_data, r_info, 0);
blf_font_boundbox_foreach_glyph_ex(font, gc, str, len, user_fn, user_data, r_info, 0);
blf_glyph_cache_release(font);
}
@@ -1020,12 +1008,12 @@ void blf_font_boundbox_foreach_glyph(FontBLF *font,
*/
static void blf_font_wrap_apply(FontBLF *font,
const char *str,
const size_t str_len,
size_t len,
struct ResultBLF *r_info,
void (*callback)(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
const size_t str_len,
size_t len,
int pen_y,
void *userdata),
void *userdata)
@@ -1044,8 +1032,8 @@ static void blf_font_wrap_apply(FontBLF *font,
size_t start, last[2];
} wrap = {font->wrap_width != -1 ? font->wrap_width : INT_MAX, 0, {0, 0}};
// printf("%s wrapping (%d, %d) `%s`:\n", __func__, str_len, strlen(str), str);
while ((i < str_len) && str[i]) {
// printf("%s wrapping (%d, %d) `%s`:\n", __func__, len, strlen(str), str);
while ((i < len) && str[i]) {
/* wrap vars */
size_t i_curr = i;
@@ -1073,7 +1061,7 @@ static void blf_font_wrap_apply(FontBLF *font,
if (UNLIKELY((pen_x_next >= wrap.wrap_width) && (wrap.start != wrap.last[0]))) {
do_draw = true;
}
else if (UNLIKELY(((i < str_len) && str[i]) == 0)) {
else if (UNLIKELY(((i < len) && str[i]) == 0)) {
/* need check here for trailing newline, else we draw it */
wrap.last[0] = i + ((g->c != '\n') ? 1 : 0);
wrap.last[1] = i;
@@ -1124,61 +1112,54 @@ static void blf_font_wrap_apply(FontBLF *font,
static void blf_font_draw__wrap_cb(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
const size_t str_len,
size_t len,
int pen_y,
void *UNUSED(userdata))
{
blf_font_draw_ex(font, gc, str, str_len, NULL, pen_y);
blf_font_draw_ex(font, gc, str, len, NULL, pen_y);
}
void blf_font_draw__wrap(FontBLF *font,
const char *str,
const size_t str_len,
struct ResultBLF *r_info)
void blf_font_draw__wrap(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
blf_font_wrap_apply(font, str, str_len, r_info, blf_font_draw__wrap_cb, NULL);
blf_font_wrap_apply(font, str, len, r_info, blf_font_draw__wrap_cb, NULL);
}
/* blf_font_boundbox__wrap */
static void blf_font_boundbox_wrap_cb(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
const size_t str_len,
int pen_y,
void *userdata)
static void blf_font_boundbox_wrap_cb(
FontBLF *font, GlyphCacheBLF *gc, const char *str, size_t len, int pen_y, void *userdata)
{
rctf *box = userdata;
rctf box_single;
blf_font_boundbox_ex(font, gc, str, str_len, &box_single, NULL, pen_y);
blf_font_boundbox_ex(font, gc, str, len, &box_single, NULL, pen_y);
BLI_rctf_union(box, &box_single);
}
void blf_font_boundbox__wrap(
FontBLF *font, const char *str, const size_t str_len, rctf *box, struct ResultBLF *r_info)
FontBLF *font, const char *str, size_t len, rctf *box, struct ResultBLF *r_info)
{
box->xmin = 32000.0f;
box->xmax = -32000.0f;
box->ymin = 32000.0f;
box->ymax = -32000.0f;
blf_font_wrap_apply(font, str, str_len, r_info, blf_font_boundbox_wrap_cb, box);
blf_font_wrap_apply(font, str, len, r_info, blf_font_boundbox_wrap_cb, box);
}
/* blf_font_draw_buffer__wrap */
static void blf_font_draw_buffer__wrap_cb(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
const size_t str_len,
size_t len,
int pen_y,
void *UNUSED(userdata))
{
blf_font_draw_buffer_ex(font, gc, str, str_len, NULL, pen_y);
blf_font_draw_buffer_ex(font, gc, str, len, NULL, pen_y);
}
void blf_font_draw_buffer__wrap(FontBLF *font,
const char *str,
const size_t str_len,
size_t len,
struct ResultBLF *r_info)
{
blf_font_wrap_apply(font, str, str_len, r_info, blf_font_draw_buffer__wrap_cb, NULL);
blf_font_wrap_apply(font, str, len, r_info, blf_font_draw_buffer__wrap_cb, NULL);
}
/** \} */
@@ -1189,14 +1170,14 @@ void blf_font_draw_buffer__wrap(FontBLF *font,
int blf_font_count_missing_chars(FontBLF *font,
const char *str,
const size_t str_len,
const size_t len,
int *r_tot_chars)
{
int missing = 0;
size_t i = 0;
*r_tot_chars = 0;
while (i < str_len) {
while (i < len) {
unsigned int c;
if ((c = str[i]) < GLYPH_ASCII_TABLE_SIZE) {

View File

@@ -53,55 +53,46 @@ struct FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem
void blf_font_attach_from_mem(struct FontBLF *font, const unsigned char *mem, int mem_size);
void blf_font_size(struct FontBLF *font, unsigned int size, unsigned int dpi);
void blf_font_draw(struct FontBLF *font,
const char *str,
size_t str_len,
struct ResultBLF *r_info);
void blf_font_draw(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
void blf_font_draw__wrap(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
struct ResultBLF *r_info);
void blf_font_draw_ascii(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
struct ResultBLF *r_info);
int blf_font_draw_mono(struct FontBLF *font, const char *str, size_t str_len, int cwidth);
int blf_font_draw_mono(struct FontBLF *font, const char *str, size_t len, int cwidth);
void blf_font_draw_buffer(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
struct ResultBLF *r_info);
void blf_font_draw_buffer__wrap(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
struct ResultBLF *r_info);
size_t blf_font_width_to_strlen(
struct FontBLF *font, const char *str, size_t str_len, float width, float *r_width);
struct FontBLF *font, const char *str, size_t len, float width, float *r_width);
size_t blf_font_width_to_rstrlen(
struct FontBLF *font, const char *str, size_t str_len, float width, float *r_width);
struct FontBLF *font, const char *str, size_t len, float width, float *r_width);
void blf_font_boundbox(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
struct rctf *r_box,
struct ResultBLF *r_info);
void blf_font_boundbox__wrap(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
struct rctf *r_box,
struct ResultBLF *r_info);
void blf_font_width_and_height(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
float *r_width,
float *r_height,
struct ResultBLF *r_info);
float blf_font_width(struct FontBLF *font,
const char *str,
size_t str_len,
struct ResultBLF *r_info);
float blf_font_height(struct FontBLF *font,
const char *str,
size_t str_len,
struct ResultBLF *r_info);
float blf_font_width(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
float blf_font_height(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
float blf_font_fixed_width(struct FontBLF *font);
int blf_font_height_max(struct FontBLF *font);
int blf_font_width_max(struct FontBLF *font);
@@ -112,7 +103,7 @@ char *blf_display_name(struct FontBLF *font);
void blf_font_boundbox_foreach_glyph(struct FontBLF *font,
const char *str,
size_t str_len,
size_t len,
bool (*user_fn)(const char *str,
const size_t str_step_ofs,
const struct rcti *glyph_step_bounds,
@@ -125,7 +116,7 @@ void blf_font_boundbox_foreach_glyph(struct FontBLF *font,
int blf_font_count_missing_chars(struct FontBLF *font,
const char *str,
const size_t str_len,
const size_t len,
int *r_tot_chars);
void blf_font_free(struct FontBLF *font);

View File

@@ -1,37 +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.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef struct AnonymousAttributeID AnonymousAttributeID;
AnonymousAttributeID *BKE_anonymous_attribute_id_new_weak(const char *debug_name);
AnonymousAttributeID *BKE_anonymous_attribute_id_new_strong(const char *debug_name);
bool BKE_anonymous_attribute_id_has_strong_references(const AnonymousAttributeID *anonymous_id);
void BKE_anonymous_attribute_id_increment_weak(const AnonymousAttributeID *anonymous_id);
void BKE_anonymous_attribute_id_increment_strong(const AnonymousAttributeID *anonymous_id);
void BKE_anonymous_attribute_id_decrement_weak(const AnonymousAttributeID *anonymous_id);
void BKE_anonymous_attribute_id_decrement_strong(const AnonymousAttributeID *anonymous_id);
const char *BKE_anonymous_attribute_id_debug_name(const AnonymousAttributeID *anonymous_id);
const char *BKE_anonymous_attribute_id_internal_name(const AnonymousAttributeID *anonymous_id);
#ifdef __cplusplus
}
#endif

View File

@@ -1,223 +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.
*/
#pragma once
#include <atomic>
#include <string>
#include "BLI_hash.hh"
#include "BLI_string_ref.hh"
#include "BKE_anonymous_attribute.h"
namespace blender::bke {
template<bool IsStrongReference> class OwnedAnonymousAttributeID {
private:
const AnonymousAttributeID *data_ = nullptr;
public:
OwnedAnonymousAttributeID() = default;
explicit OwnedAnonymousAttributeID(StringRefNull debug_name)
{
if constexpr (IsStrongReference) {
data_ = BKE_anonymous_attribute_id_new_strong(debug_name.c_str());
}
else {
data_ = BKE_anonymous_attribute_id_new_weak(debug_name.c_str());
}
}
/* This transfers ownership, so no incref is necessary. */
explicit OwnedAnonymousAttributeID(const AnonymousAttributeID *anonymous_id)
: data_(anonymous_id)
{
}
template<bool OtherIsStrong>
OwnedAnonymousAttributeID(const OwnedAnonymousAttributeID<OtherIsStrong> &other)
{
data_ = other.data_;
this->incref();
}
template<bool OtherIsStrong>
OwnedAnonymousAttributeID(OwnedAnonymousAttributeID<OtherIsStrong> &&other)
{
data_ = other.data_;
this->incref();
other.decref();
other.data_ = nullptr;
}
~OwnedAnonymousAttributeID()
{
this->decref();
}
template<bool OtherIsStrong>
OwnedAnonymousAttributeID &operator=(const OwnedAnonymousAttributeID<OtherIsStrong> &other)
{
if (this == &other) {
return *this;
}
this->~OwnedAnonymousAttributeID();
new (this) OwnedAnonymousAttributeID(other);
return *this;
}
template<bool OtherIsStrong>
OwnedAnonymousAttributeID &operator=(OwnedAnonymousAttributeID<OtherIsStrong> &&other)
{
if (this == &other) {
return *this;
}
this->~OwnedAnonymousAttributeID();
new (this) OwnedAnonymousAttributeID(std::move(other));
return *this;
}
operator bool() const
{
return data_ != nullptr;
}
StringRefNull debug_name() const
{
BLI_assert(data_ != nullptr);
return BKE_anonymous_attribute_id_debug_name(data_);
}
bool has_strong_references() const
{
BLI_assert(data_ != nullptr);
return BKE_anonymous_attribute_id_has_strong_references(data_);
}
const AnonymousAttributeID *extract()
{
const AnonymousAttributeID *extracted_data = data_;
/* Don't decref because the caller becomes the new owner. */
data_ = nullptr;
return extracted_data;
}
const AnonymousAttributeID *get()
{
return data_;
}
private:
void incref()
{
if (data_ == nullptr) {
return;
}
if constexpr (IsStrongReference) {
BKE_anonymous_attribute_id_increment_strong(data_);
}
else {
BKE_anonymous_attribute_id_increment_weak(data_);
}
}
void decref()
{
if (data_ == nullptr) {
return;
}
if constexpr (IsStrongReference) {
BKE_anonymous_attribute_id_decrement_strong(data_);
}
else {
BKE_anonymous_attribute_id_decrement_weak(data_);
}
}
};
using StrongAnonymousAttributeID = OwnedAnonymousAttributeID<true>;
using WeakAnonymousAttributeID = OwnedAnonymousAttributeID<false>;
class AttributeIDRef {
private:
StringRef name_;
const AnonymousAttributeID *anonymous_id_ = nullptr;
public:
AttributeIDRef() = default;
AttributeIDRef(StringRef name) : name_(name)
{
}
AttributeIDRef(StringRefNull name) : name_(name)
{
}
AttributeIDRef(const char *name) : name_(name)
{
}
AttributeIDRef(const std::string &name) : name_(name)
{
}
/* The anonymous id is only borrowed, the caller has to keep a reference to it. */
AttributeIDRef(const AnonymousAttributeID *anonymous_id) : anonymous_id_(anonymous_id)
{
}
operator bool() const
{
return this->is_named() || this->is_anonymous();
}
friend bool operator==(const AttributeIDRef &a, const AttributeIDRef &b)
{
return a.anonymous_id_ == b.anonymous_id_ && a.name_ == b.name_;
}
uint64_t hash() const
{
return get_default_hash_2(name_, anonymous_id_);
}
bool is_named() const
{
return !name_.is_empty();
}
bool is_anonymous() const
{
return anonymous_id_ != nullptr;
}
StringRef name() const
{
BLI_assert(this->is_named());
return name_;
}
const AnonymousAttributeID &anonymous_id() const
{
BLI_assert(this->is_anonymous());
return *anonymous_id_;
}
};
} // namespace blender::bke

View File

@@ -22,7 +22,6 @@
#include "FN_generic_span.hh"
#include "FN_generic_virtual_array.hh"
#include "BKE_anonymous_attribute.hh"
#include "BKE_attribute.h"
#include "BLI_color.hh"
@@ -105,8 +104,8 @@ struct AttributeInitMove : public AttributeInit {
};
/* Returns false when the iteration should be stopped. */
using AttributeForeachCallback = blender::FunctionRef<bool(
const blender::bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data)>;
using AttributeForeachCallback = blender::FunctionRef<bool(blender::StringRefNull attribute_name,
const AttributeMetaData &meta_data)>;
namespace blender::bke {
@@ -334,30 +333,26 @@ class CustomDataAttributes {
void reallocate(const int size);
std::optional<blender::fn::GSpan> get_for_read(
const blender::bke::AttributeIDRef &attribute_id) const;
std::optional<blender::fn::GSpan> get_for_read(const blender::StringRef name) const;
blender::fn::GVArrayPtr get_for_read(const AttributeIDRef &attribute_id,
blender::fn::GVArrayPtr get_for_read(const StringRef name,
const CustomDataType data_type,
const void *default_value) const;
template<typename T>
blender::fn::GVArray_Typed<T> get_for_read(const blender::bke::AttributeIDRef &attribute_id,
blender::fn::GVArray_Typed<T> get_for_read(const blender::StringRef name,
const T &default_value) const
{
const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
const CustomDataType type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
GVArrayPtr varray = this->get_for_read(attribute_id, type, &default_value);
GVArrayPtr varray = this->get_for_read(name, type, &default_value);
return blender::fn::GVArray_Typed<T>(std::move(varray));
}
std::optional<blender::fn::GMutableSpan> get_for_write(
const blender::bke::AttributeIDRef &attribute_id);
bool create(const blender::bke::AttributeIDRef &attribute_id, const CustomDataType data_type);
bool create_by_move(const blender::bke::AttributeIDRef &attribute_id,
const CustomDataType data_type,
void *buffer);
bool remove(const blender::bke::AttributeIDRef &attribute_id);
std::optional<blender::fn::GMutableSpan> get_for_write(const blender::StringRef name);
bool create(const blender::StringRef name, const CustomDataType data_type);
bool create_by_move(const blender::StringRef name, const CustomDataType data_type, void *buffer);
bool remove(const blender::StringRef name);
bool foreach_attribute(const AttributeForeachCallback callback,
const AttributeDomain domain) const;

View File

@@ -33,7 +33,6 @@
extern "C" {
#endif
struct AnonymousAttributeID;
struct BMesh;
struct BlendDataReader;
struct BlendWriter;
@@ -194,12 +193,6 @@ void *CustomData_add_layer_named(struct CustomData *data,
void *layer,
int totelem,
const char *name);
void *CustomData_add_layer_anonymous(struct CustomData *data,
int type,
eCDAllocType alloctype,
void *layer,
int totelem,
const struct AnonymousAttributeID *anonymous_id);
/* frees the active or first data layer with the give type.
* returns 1 on success, 0 if no layer with the given type is found
@@ -238,11 +231,6 @@ void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
const int type,
const char *name,
const int totelem);
void *CustomData_duplicate_referenced_layer_anonymous(
CustomData *data,
const int type,
const struct AnonymousAttributeID *anonymous_id,
const int totelem);
bool CustomData_is_referenced_layer(struct CustomData *data, int type);
/* Duplicate all the layers with flag NOFREE, and remove the flag from duplicated layers. */

View File

@@ -31,7 +31,6 @@
#include "BLI_user_counter.hh"
#include "BLI_vector_set.hh"
#include "BKE_anonymous_attribute.hh"
#include "BKE_attribute_access.hh"
#include "BKE_geometry_set.h"
@@ -89,11 +88,11 @@ class GeometryComponent {
GeometryComponentType type() const;
/* Return true when any attribute with this name exists, including built in attributes. */
bool attribute_exists(const blender::bke::AttributeIDRef &attribute_id) const;
bool attribute_exists(const blender::StringRef attribute_name) const;
/* Return the data type and domain of an attribute with the given name if it exists. */
std::optional<AttributeMetaData> attribute_get_meta_data(
const blender::bke::AttributeIDRef &attribute_id) const;
const blender::StringRef attribute_name) const;
/* Returns true when the geometry component supports this attribute domain. */
bool attribute_domain_supported(const AttributeDomain domain) const;
@@ -105,12 +104,12 @@ class GeometryComponent {
/* Get read-only access to the highest priority attribute with the given name.
* Returns null if the attribute does not exist. */
blender::bke::ReadAttributeLookup attribute_try_get_for_read(
const blender::bke::AttributeIDRef &attribute_id) const;
const blender::StringRef attribute_name) const;
/* Get read and write access to the highest priority attribute with the given name.
* Returns null if the attribute does not exist. */
blender::bke::WriteAttributeLookup attribute_try_get_for_write(
const blender::bke::AttributeIDRef &attribute_id);
const blender::StringRef attribute_name);
/* Get a read-only attribute for the domain based on the given attribute. This can be used to
* interpolate from one domain to another.
@@ -121,10 +120,10 @@ class GeometryComponent {
const AttributeDomain to_domain) const;
/* Returns true when the attribute has been deleted. */
bool attribute_try_delete(const blender::bke::AttributeIDRef &attribute_id);
bool attribute_try_delete(const blender::StringRef attribute_name);
/* Returns true when the attribute has been created. */
bool attribute_try_create(const blender::bke::AttributeIDRef &attribute_id,
bool attribute_try_create(const blender::StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type,
const AttributeInit &initializer);
@@ -134,7 +133,7 @@ class GeometryComponent {
bool attribute_try_create_builtin(const blender::StringRef attribute_name,
const AttributeInit &initializer);
blender::Set<blender::bke::AttributeIDRef> attribute_ids() const;
blender::Set<std::string> attribute_names() const;
bool attribute_foreach(const AttributeForeachCallback callback) const;
virtual bool is_empty() const;
@@ -143,7 +142,7 @@ class GeometryComponent {
* Returns null when the attribute does not exist or cannot be converted to the requested domain
* and data type. */
std::unique_ptr<blender::fn::GVArray> attribute_try_get_for_read(
const blender::bke::AttributeIDRef &attribute_id,
const blender::StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type) const;
@@ -151,18 +150,18 @@ class GeometryComponent {
* left unchanged. Returns null when the attribute does not exist or cannot be adapted to the
* requested domain. */
std::unique_ptr<blender::fn::GVArray> attribute_try_get_for_read(
const blender::bke::AttributeIDRef &attribute_id, const AttributeDomain domain) const;
const blender::StringRef attribute_name, const AttributeDomain domain) const;
/* Get a virtual array to read data of an attribute with the given data type. The domain is
* left unchanged. Returns null when the attribute does not exist or cannot be converted to the
* requested data type. */
blender::bke::ReadAttributeLookup attribute_try_get_for_read(
const blender::bke::AttributeIDRef &attribute_id, const CustomDataType data_type) const;
const blender::StringRef attribute_name, const CustomDataType data_type) const;
/* Get a virtual array to read the data of an attribute. If that is not possible, the returned
* virtual array will contain a default value. This never returns null. */
std::unique_ptr<blender::fn::GVArray> attribute_get_for_read(
const blender::bke::AttributeIDRef &attribute_id,
const blender::StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type,
const void *default_value = nullptr) const;
@@ -170,15 +169,14 @@ class GeometryComponent {
/* Should be used instead of the method above when the requested data type is known at compile
* time for better type safety. */
template<typename T>
blender::fn::GVArray_Typed<T> attribute_get_for_read(
const blender::bke::AttributeIDRef &attribute_id,
const AttributeDomain domain,
const T &default_value) const
blender::fn::GVArray_Typed<T> attribute_get_for_read(const blender::StringRef attribute_name,
const AttributeDomain domain,
const T &default_value) const
{
const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
const CustomDataType type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
std::unique_ptr varray = this->attribute_get_for_read(
attribute_id, domain, type, &default_value);
attribute_name, domain, type, &default_value);
return blender::fn::GVArray_Typed<T>(std::move(varray));
}
@@ -193,7 +191,7 @@ class GeometryComponent {
* is created that will overwrite the existing attribute in the end.
*/
blender::bke::OutputAttribute attribute_try_get_for_output(
const blender::bke::AttributeIDRef &attribute_id,
const blender::StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type,
const void *default_value = nullptr);
@@ -202,30 +200,28 @@ class GeometryComponent {
* attributes are not read, i.e. the attribute is used only for output. Since values are not read
* from this attribute, no default value is necessary. */
blender::bke::OutputAttribute attribute_try_get_for_output_only(
const blender::bke::AttributeIDRef &attribute_id,
const blender::StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type);
/* Statically typed method corresponding to the equally named generic one. */
template<typename T>
blender::bke::OutputAttribute_Typed<T> attribute_try_get_for_output(
const blender::bke::AttributeIDRef &attribute_id,
const AttributeDomain domain,
const T default_value)
const blender::StringRef attribute_name, const AttributeDomain domain, const T default_value)
{
const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
const CustomDataType data_type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
return this->attribute_try_get_for_output(attribute_id, domain, data_type, &default_value);
return this->attribute_try_get_for_output(attribute_name, domain, data_type, &default_value);
}
/* Statically typed method corresponding to the equally named generic one. */
template<typename T>
blender::bke::OutputAttribute_Typed<T> attribute_try_get_for_output_only(
const blender::bke::AttributeIDRef &attribute_id, const AttributeDomain domain)
const blender::StringRef attribute_name, const AttributeDomain domain)
{
const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
const CustomDataType data_type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
return this->attribute_try_get_for_output_only(attribute_id, domain, data_type);
return this->attribute_try_get_for_output_only(attribute_name, domain, data_type);
}
private:

View File

@@ -59,10 +59,9 @@ struct AttributeKind {
* will contain the highest complexity data type and the highest priority domain among every
* attribute with the given name on all of the input components.
*/
void geometry_set_gather_instances_attribute_info(
Span<GeometryInstanceGroup> set_groups,
Span<GeometryComponentType> component_types,
const Set<std::string> &ignored_attributes,
Map<AttributeIDRef, AttributeKind> &r_attributes);
void geometry_set_gather_instances_attribute_info(Span<GeometryInstanceGroup> set_groups,
Span<GeometryComponentType> component_types,
const Set<std::string> &ignored_attributes,
Map<std::string, AttributeKind> &r_attributes);
} // namespace blender::bke

View File

@@ -346,7 +346,7 @@ typedef struct bNodeType {
#define NODE_CLASS_OP_FILTER 5
#define NODE_CLASS_GROUP 6
// #define NODE_CLASS_FILE 7
#define NODE_CLASS_CONVERTER 8
#define NODE_CLASS_CONVERTOR 8
#define NODE_CLASS_MATTE 9
#define NODE_CLASS_DISTORT 10
// #define NODE_CLASS_OP_DYNAMIC 11 /* deprecated */
@@ -1472,7 +1472,15 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_CURVE_SET_HANDLES 1072
#define GEO_NODE_CURVE_SPLINE_TYPE 1073
#define GEO_NODE_CURVE_SELECT_HANDLES 1074
#define GEO_NODE_SOLIDIFY 1075
#define GEO_NODE_REMESH_VOXEL 1076
#define GEO_NODE_REMESH_BLOCKS 1077
#define GEO_NODE_MERGE_BY_DISTANCE 1078
#define GEO_NODE_MESH_EXTRUDE 1079
#define GEO_NODE_MESH_INSET 1080
#define GEO_NODE_COLLAPSE 1081
#define GEO_NODE_UNSUBDIVIDE 1082
#define GEO_NODE_DISSOLVE 1083
/** \} */
/* -------------------------------------------------------------------- */

View File

@@ -76,7 +76,6 @@ set(SRC
intern/anim_path.c
intern/anim_sys.c
intern/anim_visualization.c
intern/anonymous_attribute.cc
intern/appdir.c
intern/armature.c
intern/armature_selection.cc
@@ -296,8 +295,6 @@ set(SRC
BKE_anim_path.h
BKE_anim_visualization.h
BKE_animsys.h
BKE_anonymous_attribute.h
BKE_anonymous_attribute.hh
BKE_appdir.h
BKE_armature.h
BKE_armature.hh

View File

@@ -1,92 +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.
*/
#include "BKE_anonymous_attribute.hh"
using namespace blender::bke;
struct AnonymousAttributeID {
mutable std::atomic<int> refcount_weak = 0;
mutable std::atomic<int> refcount_strong = 0;
std::string debug_name;
std::string internal_name;
};
static std::string get_new_internal_name()
{
static std::atomic<int> index = 0;
const int next_index = index.fetch_add(1);
return "anonymous_attribute_" + std::to_string(next_index);
}
AnonymousAttributeID *BKE_anonymous_attribute_id_new_weak(const char *debug_name)
{
AnonymousAttributeID *anonymous_id = new AnonymousAttributeID();
anonymous_id->debug_name = debug_name;
anonymous_id->internal_name = get_new_internal_name();
anonymous_id->refcount_weak.store(1);
return anonymous_id;
}
AnonymousAttributeID *BKE_anonymous_attribute_id_new_strong(const char *debug_name)
{
AnonymousAttributeID *anonymous_id = new AnonymousAttributeID();
anonymous_id->debug_name = debug_name;
anonymous_id->internal_name = get_new_internal_name();
anonymous_id->refcount_weak.store(1);
anonymous_id->refcount_strong.store(1);
return anonymous_id;
}
bool BKE_anonymous_attribute_id_has_strong_references(const AnonymousAttributeID *anonymous_id)
{
return anonymous_id->refcount_strong.load() >= 1;
}
void BKE_anonymous_attribute_id_increment_weak(const AnonymousAttributeID *anonymous_id)
{
anonymous_id->refcount_weak.fetch_add(1);
}
void BKE_anonymous_attribute_id_increment_strong(const AnonymousAttributeID *anonymous_id)
{
anonymous_id->refcount_weak.fetch_add(1);
anonymous_id->refcount_strong.fetch_add(1);
}
void BKE_anonymous_attribute_id_decrement_weak(const AnonymousAttributeID *anonymous_id)
{
const int new_refcount = anonymous_id->refcount_weak.fetch_sub(1) - 1;
if (new_refcount == 0) {
delete anonymous_id;
}
}
void BKE_anonymous_attribute_id_decrement_strong(const AnonymousAttributeID *anonymous_id)
{
anonymous_id->refcount_strong.fetch_sub(1);
BKE_anonymous_attribute_id_decrement_weak(anonymous_id);
}
const char *BKE_anonymous_attribute_id_debug_name(const AnonymousAttributeID *anonymous_id)
{
return anonymous_id->debug_name.c_str();
}
const char *BKE_anonymous_attribute_id_internal_name(const AnonymousAttributeID *anonymous_id)
{
return anonymous_id->internal_name.c_str();
}

View File

@@ -334,20 +334,8 @@ bool BuiltinCustomDataLayerProvider::exists(const GeometryComponent &component)
return data != nullptr;
}
static bool custom_data_layer_matches_attribute_id(const CustomDataLayer &layer,
const AttributeIDRef &attribute_id)
{
if (!attribute_id) {
return false;
}
if (attribute_id.is_anonymous()) {
return layer.anonymous_id == &attribute_id.anonymous_id();
}
return layer.name == attribute_id.name();
}
ReadAttributeLookup CustomDataAttributeProvider::try_get_for_read(
const GeometryComponent &component, const AttributeIDRef &attribute_id) const
const GeometryComponent &component, const StringRef attribute_name) const
{
const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
if (custom_data == nullptr) {
@@ -355,7 +343,7 @@ ReadAttributeLookup CustomDataAttributeProvider::try_get_for_read(
}
const int domain_size = component.attribute_domain_size(domain_);
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
if (!custom_data_layer_matches_attribute_id(layer, attribute_id)) {
if (layer.name != attribute_name) {
continue;
}
const CustomDataType data_type = (CustomDataType)layer.type;
@@ -380,7 +368,7 @@ ReadAttributeLookup CustomDataAttributeProvider::try_get_for_read(
}
WriteAttributeLookup CustomDataAttributeProvider::try_get_for_write(
GeometryComponent &component, const AttributeIDRef &attribute_id) const
GeometryComponent &component, const StringRef attribute_name) const
{
CustomData *custom_data = custom_data_access_.get_custom_data(component);
if (custom_data == nullptr) {
@@ -388,17 +376,10 @@ WriteAttributeLookup CustomDataAttributeProvider::try_get_for_write(
}
const int domain_size = component.attribute_domain_size(domain_);
for (CustomDataLayer &layer : MutableSpan(custom_data->layers, custom_data->totlayer)) {
if (!custom_data_layer_matches_attribute_id(layer, attribute_id)) {
if (layer.name != attribute_name) {
continue;
}
if (attribute_id.is_named()) {
CustomData_duplicate_referenced_layer_named(
custom_data, layer.type, layer.name, domain_size);
}
else {
CustomData_duplicate_referenced_layer_anonymous(
custom_data, layer.type, &attribute_id.anonymous_id(), domain_size);
}
CustomData_duplicate_referenced_layer_named(custom_data, layer.type, layer.name, domain_size);
const CustomDataType data_type = (CustomDataType)layer.type;
switch (data_type) {
case CD_PROP_FLOAT:
@@ -421,7 +402,7 @@ WriteAttributeLookup CustomDataAttributeProvider::try_get_for_write(
}
bool CustomDataAttributeProvider::try_delete(GeometryComponent &component,
const AttributeIDRef &attribute_id) const
const StringRef attribute_name) const
{
CustomData *custom_data = custom_data_access_.get_custom_data(component);
if (custom_data == nullptr) {
@@ -430,8 +411,7 @@ bool CustomDataAttributeProvider::try_delete(GeometryComponent &component,
const int domain_size = component.attribute_domain_size(domain_);
for (const int i : IndexRange(custom_data->totlayer)) {
const CustomDataLayer &layer = custom_data->layers[i];
if (this->type_is_supported((CustomDataType)layer.type) &&
custom_data_layer_matches_attribute_id(layer, attribute_id)) {
if (this->type_is_supported((CustomDataType)layer.type) && layer.name == attribute_name) {
CustomData_free_layer(custom_data, layer.type, domain_size, i);
return true;
}
@@ -439,39 +419,24 @@ bool CustomDataAttributeProvider::try_delete(GeometryComponent &component,
return false;
}
static void *add_generic_custom_data_layer(CustomData &custom_data,
const CustomDataType data_type,
const eCDAllocType alloctype,
void *layer_data,
const int domain_size,
const AttributeIDRef &attribute_id)
static bool add_named_custom_data_layer_from_attribute_init(const StringRef attribute_name,
CustomData &custom_data,
const CustomDataType data_type,
const int domain_size,
const AttributeInit &initializer)
{
if (attribute_id.is_named()) {
char attribute_name_c[MAX_NAME];
attribute_id.name().copy(attribute_name_c);
return CustomData_add_layer_named(
&custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_name_c);
}
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
return CustomData_add_layer_anonymous(
&custom_data, data_type, alloctype, layer_data, domain_size, &anonymous_id);
}
char attribute_name_c[MAX_NAME];
attribute_name.copy(attribute_name_c);
static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attribute_id,
CustomData &custom_data,
const CustomDataType data_type,
const int domain_size,
const AttributeInit &initializer)
{
switch (initializer.type) {
case AttributeInit::Type::Default: {
void *data = add_generic_custom_data_layer(
custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_id);
void *data = CustomData_add_layer_named(
&custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_name_c);
return data != nullptr;
}
case AttributeInit::Type::VArray: {
void *data = add_generic_custom_data_layer(
custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_id);
void *data = CustomData_add_layer_named(
&custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_name_c);
if (data == nullptr) {
return false;
}
@@ -481,8 +446,8 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
}
case AttributeInit::Type::MoveArray: {
void *source_data = static_cast<const AttributeInitMove &>(initializer).data;
void *data = add_generic_custom_data_layer(
custom_data, data_type, CD_ASSIGN, source_data, domain_size, attribute_id);
void *data = CustomData_add_layer_named(
&custom_data, data_type, CD_ASSIGN, source_data, domain_size, attribute_name_c);
if (data == nullptr) {
MEM_freeN(source_data);
return false;
@@ -496,7 +461,7 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
}
bool CustomDataAttributeProvider::try_create(GeometryComponent &component,
const AttributeIDRef &attribute_id,
const StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type,
const AttributeInit &initializer) const
@@ -512,13 +477,13 @@ bool CustomDataAttributeProvider::try_create(GeometryComponent &component,
return false;
}
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
if (layer.name == attribute_name) {
return false;
}
}
const int domain_size = component.attribute_domain_size(domain_);
add_custom_data_layer_from_attribute_init(
attribute_id, *custom_data, data_type, domain_size, initializer);
add_named_custom_data_layer_from_attribute_init(
attribute_name, *custom_data, data_type, domain_size, initializer);
return true;
}
@@ -533,14 +498,7 @@ bool CustomDataAttributeProvider::foreach_attribute(const GeometryComponent &com
const CustomDataType data_type = (CustomDataType)layer.type;
if (this->type_is_supported(data_type)) {
AttributeMetaData meta_data{domain_, data_type};
AttributeIDRef attribute_id;
if (layer.anonymous_id != nullptr) {
attribute_id = layer.anonymous_id;
}
else {
attribute_id = layer.name;
}
if (!callback(attribute_id, meta_data)) {
if (!callback(layer.name, meta_data)) {
return false;
}
}
@@ -549,7 +507,7 @@ bool CustomDataAttributeProvider::foreach_attribute(const GeometryComponent &com
}
ReadAttributeLookup NamedLegacyCustomDataProvider::try_get_for_read(
const GeometryComponent &component, const AttributeIDRef &attribute_id) const
const GeometryComponent &component, const StringRef attribute_name) const
{
const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
if (custom_data == nullptr) {
@@ -557,7 +515,7 @@ ReadAttributeLookup NamedLegacyCustomDataProvider::try_get_for_read(
}
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
if (layer.type == stored_type_) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
if (layer.name == attribute_name) {
const int domain_size = component.attribute_domain_size(domain_);
return {as_read_attribute_(layer.data, domain_size), domain_};
}
@@ -567,7 +525,7 @@ ReadAttributeLookup NamedLegacyCustomDataProvider::try_get_for_read(
}
WriteAttributeLookup NamedLegacyCustomDataProvider::try_get_for_write(
GeometryComponent &component, const AttributeIDRef &attribute_id) const
GeometryComponent &component, const StringRef attribute_name) const
{
CustomData *custom_data = custom_data_access_.get_custom_data(component);
if (custom_data == nullptr) {
@@ -575,7 +533,7 @@ WriteAttributeLookup NamedLegacyCustomDataProvider::try_get_for_write(
}
for (CustomDataLayer &layer : MutableSpan(custom_data->layers, custom_data->totlayer)) {
if (layer.type == stored_type_) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
if (layer.name == attribute_name) {
const int domain_size = component.attribute_domain_size(domain_);
void *data_old = layer.data;
void *data_new = CustomData_duplicate_referenced_layer_named(
@@ -591,7 +549,7 @@ WriteAttributeLookup NamedLegacyCustomDataProvider::try_get_for_write(
}
bool NamedLegacyCustomDataProvider::try_delete(GeometryComponent &component,
const AttributeIDRef &attribute_id) const
const StringRef attribute_name) const
{
CustomData *custom_data = custom_data_access_.get_custom_data(component);
if (custom_data == nullptr) {
@@ -600,7 +558,7 @@ bool NamedLegacyCustomDataProvider::try_delete(GeometryComponent &component,
for (const int i : IndexRange(custom_data->totlayer)) {
const CustomDataLayer &layer = custom_data->layers[i];
if (layer.type == stored_type_) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
if (layer.name == attribute_name) {
const int domain_size = component.attribute_domain_size(domain_);
CustomData_free_layer(custom_data, stored_type_, domain_size, i);
custom_data_access_.update_custom_data_pointers(component);
@@ -669,11 +627,11 @@ CustomDataAttributes &CustomDataAttributes::operator=(const CustomDataAttributes
return *this;
}
std::optional<GSpan> CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id) const
std::optional<GSpan> CustomDataAttributes::get_for_read(const StringRef name) const
{
BLI_assert(size_ != 0);
for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
if (layer.name == name) {
const CPPType *cpp_type = custom_data_type_to_cpp_type((CustomDataType)layer.type);
BLI_assert(cpp_type != nullptr);
return GSpan(*cpp_type, layer.data, size_);
@@ -687,13 +645,13 @@ std::optional<GSpan> CustomDataAttributes::get_for_read(const AttributeIDRef &at
* value if the attribute doesn't exist. If no default value is provided, the default value for the
* type will be used.
*/
GVArrayPtr CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id,
GVArrayPtr CustomDataAttributes::get_for_read(const StringRef name,
const CustomDataType data_type,
const void *default_value) const
{
const CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
std::optional<GSpan> attribute = this->get_for_read(attribute_id);
std::optional<GSpan> attribute = this->get_for_read(name);
if (!attribute) {
const int domain_size = this->size_;
return std::make_unique<GVArray_For_SingleValue>(
@@ -708,12 +666,12 @@ GVArrayPtr CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id
return conversions.try_convert(std::make_unique<GVArray_For_GSpan>(*attribute), *type);
}
std::optional<GMutableSpan> CustomDataAttributes::get_for_write(const AttributeIDRef &attribute_id)
std::optional<GMutableSpan> CustomDataAttributes::get_for_write(const StringRef name)
{
/* If this assert hits, it most likely means that #reallocate was not called at some point. */
BLI_assert(size_ != 0);
for (CustomDataLayer &layer : MutableSpan(data.layers, data.totlayer)) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
if (layer.name == name) {
const CPPType *cpp_type = custom_data_type_to_cpp_type((CustomDataType)layer.type);
BLI_assert(cpp_type != nullptr);
return GMutableSpan(*cpp_type, layer.data, size_);
@@ -722,29 +680,30 @@ std::optional<GMutableSpan> CustomDataAttributes::get_for_write(const AttributeI
return {};
}
bool CustomDataAttributes::create(const AttributeIDRef &attribute_id,
const CustomDataType data_type)
bool CustomDataAttributes::create(const StringRef name, const CustomDataType data_type)
{
void *result = add_generic_custom_data_layer(
data, data_type, CD_DEFAULT, nullptr, size_, attribute_id);
char name_c[MAX_NAME];
name.copy(name_c);
void *result = CustomData_add_layer_named(&data, data_type, CD_DEFAULT, nullptr, size_, name_c);
return result != nullptr;
}
bool CustomDataAttributes::create_by_move(const blender::bke::AttributeIDRef &attribute_id,
bool CustomDataAttributes::create_by_move(const blender::StringRef name,
const CustomDataType data_type,
void *buffer)
{
void *result = add_generic_custom_data_layer(
data, data_type, CD_ASSIGN, buffer, size_, attribute_id);
char name_c[MAX_NAME];
name.copy(name_c);
void *result = CustomData_add_layer_named(&data, data_type, CD_ASSIGN, buffer, size_, name_c);
return result != nullptr;
}
bool CustomDataAttributes::remove(const blender::bke::AttributeIDRef &attribute_id)
bool CustomDataAttributes::remove(const blender::StringRef name)
{
bool result = false;
for (const int i : IndexRange(data.totlayer)) {
const CustomDataLayer &layer = data.layers[i];
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
if (layer.name == name) {
CustomData_free_layer(&data, layer.type, size_, i);
result = true;
}
@@ -763,14 +722,7 @@ bool CustomDataAttributes::foreach_attribute(const AttributeForeachCallback call
{
for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
AttributeMetaData meta_data{domain, (CustomDataType)layer.type};
AttributeIDRef attribute_id;
if (layer.anonymous_id != nullptr) {
attribute_id = layer.anonymous_id;
}
else {
attribute_id = layer.name;
}
if (!callback(attribute_id, meta_data)) {
if (!callback(layer.name, meta_data)) {
return false;
}
}
@@ -814,23 +766,21 @@ bool GeometryComponent::attribute_is_builtin(const blender::StringRef attribute_
}
blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
const blender::bke::AttributeIDRef &attribute_id) const
const StringRef attribute_name) const
{
using namespace blender::bke;
const ComponentAttributeProviders *providers = this->get_attribute_providers();
if (providers == nullptr) {
return {};
}
if (attribute_id.is_named()) {
const BuiltinAttributeProvider *builtin_provider =
providers->builtin_attribute_providers().lookup_default_as(attribute_id.name(), nullptr);
if (builtin_provider != nullptr) {
return {builtin_provider->try_get_for_read(*this), builtin_provider->domain()};
}
const BuiltinAttributeProvider *builtin_provider =
providers->builtin_attribute_providers().lookup_default_as(attribute_name, nullptr);
if (builtin_provider != nullptr) {
return {builtin_provider->try_get_for_read(*this), builtin_provider->domain()};
}
for (const DynamicAttributesProvider *dynamic_provider :
providers->dynamic_attribute_providers()) {
ReadAttributeLookup attribute = dynamic_provider->try_get_for_read(*this, attribute_id);
ReadAttributeLookup attribute = dynamic_provider->try_get_for_read(*this, attribute_name);
if (attribute) {
return attribute;
}
@@ -850,23 +800,21 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_adapt_dom
}
blender::bke::WriteAttributeLookup GeometryComponent::attribute_try_get_for_write(
const blender::bke::AttributeIDRef &attribute_id)
const StringRef attribute_name)
{
using namespace blender::bke;
const ComponentAttributeProviders *providers = this->get_attribute_providers();
if (providers == nullptr) {
return {};
}
if (attribute_id.is_named()) {
const BuiltinAttributeProvider *builtin_provider =
providers->builtin_attribute_providers().lookup_default_as(attribute_id.name(), nullptr);
if (builtin_provider != nullptr) {
return {builtin_provider->try_get_for_write(*this), builtin_provider->domain()};
}
const BuiltinAttributeProvider *builtin_provider =
providers->builtin_attribute_providers().lookup_default_as(attribute_name, nullptr);
if (builtin_provider != nullptr) {
return {builtin_provider->try_get_for_write(*this), builtin_provider->domain()};
}
for (const DynamicAttributesProvider *dynamic_provider :
providers->dynamic_attribute_providers()) {
WriteAttributeLookup attribute = dynamic_provider->try_get_for_write(*this, attribute_id);
WriteAttributeLookup attribute = dynamic_provider->try_get_for_write(*this, attribute_name);
if (attribute) {
return attribute;
}
@@ -874,57 +822,53 @@ blender::bke::WriteAttributeLookup GeometryComponent::attribute_try_get_for_writ
return {};
}
bool GeometryComponent::attribute_try_delete(const blender::bke::AttributeIDRef &attribute_id)
bool GeometryComponent::attribute_try_delete(const StringRef attribute_name)
{
using namespace blender::bke;
const ComponentAttributeProviders *providers = this->get_attribute_providers();
if (providers == nullptr) {
return {};
}
if (attribute_id.is_named()) {
const BuiltinAttributeProvider *builtin_provider =
providers->builtin_attribute_providers().lookup_default_as(attribute_id.name(), nullptr);
if (builtin_provider != nullptr) {
return builtin_provider->try_delete(*this);
}
const BuiltinAttributeProvider *builtin_provider =
providers->builtin_attribute_providers().lookup_default_as(attribute_name, nullptr);
if (builtin_provider != nullptr) {
return builtin_provider->try_delete(*this);
}
bool success = false;
for (const DynamicAttributesProvider *dynamic_provider :
providers->dynamic_attribute_providers()) {
success = dynamic_provider->try_delete(*this, attribute_id) || success;
success = dynamic_provider->try_delete(*this, attribute_name) || success;
}
return success;
}
bool GeometryComponent::attribute_try_create(const blender::bke::AttributeIDRef &attribute_id,
bool GeometryComponent::attribute_try_create(const StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type,
const AttributeInit &initializer)
{
using namespace blender::bke;
if (!attribute_id) {
if (attribute_name.is_empty()) {
return false;
}
const ComponentAttributeProviders *providers = this->get_attribute_providers();
if (providers == nullptr) {
return false;
}
if (attribute_id.is_named()) {
const BuiltinAttributeProvider *builtin_provider =
providers->builtin_attribute_providers().lookup_default_as(attribute_id.name(), nullptr);
if (builtin_provider != nullptr) {
if (builtin_provider->domain() != domain) {
return false;
}
if (builtin_provider->data_type() != data_type) {
return false;
}
return builtin_provider->try_create(*this, initializer);
const BuiltinAttributeProvider *builtin_provider =
providers->builtin_attribute_providers().lookup_default_as(attribute_name, nullptr);
if (builtin_provider != nullptr) {
if (builtin_provider->domain() != domain) {
return false;
}
if (builtin_provider->data_type() != data_type) {
return false;
}
return builtin_provider->try_create(*this, initializer);
}
for (const DynamicAttributesProvider *dynamic_provider :
providers->dynamic_attribute_providers()) {
if (dynamic_provider->try_create(*this, attribute_id, domain, data_type, initializer)) {
if (dynamic_provider->try_create(*this, attribute_name, domain, data_type, initializer)) {
return true;
}
}
@@ -950,12 +894,11 @@ bool GeometryComponent::attribute_try_create_builtin(const blender::StringRef at
return builtin_provider->try_create(*this, initializer);
}
Set<blender::bke::AttributeIDRef> GeometryComponent::attribute_ids() const
Set<std::string> GeometryComponent::attribute_names() const
{
Set<blender::bke::AttributeIDRef> attributes;
this->attribute_foreach([&](const blender::bke::AttributeIDRef &attribute_id,
const AttributeMetaData &UNUSED(meta_data)) {
attributes.add(attribute_id);
Set<std::string> attributes;
this->attribute_foreach([&](StringRefNull name, const AttributeMetaData &UNUSED(meta_data)) {
attributes.add(name);
return true;
});
return attributes;
@@ -988,9 +931,9 @@ bool GeometryComponent::attribute_foreach(const AttributeForeachCallback callbac
}
for (const DynamicAttributesProvider *provider : providers->dynamic_attribute_providers()) {
const bool continue_loop = provider->foreach_attribute(
*this, [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
if (attribute_id.is_anonymous() || handled_attribute_names.add(attribute_id.name())) {
return callback(attribute_id, meta_data);
*this, [&](StringRefNull name, const AttributeMetaData &meta_data) {
if (handled_attribute_names.add(name)) {
return callback(name, meta_data);
}
return true;
});
@@ -1002,9 +945,9 @@ bool GeometryComponent::attribute_foreach(const AttributeForeachCallback callbac
return true;
}
bool GeometryComponent::attribute_exists(const blender::bke::AttributeIDRef &attribute_id) const
bool GeometryComponent::attribute_exists(const blender::StringRef attribute_name) const
{
blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_id);
blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_name);
if (attribute) {
return true;
}
@@ -1012,12 +955,11 @@ bool GeometryComponent::attribute_exists(const blender::bke::AttributeIDRef &att
}
std::optional<AttributeMetaData> GeometryComponent::attribute_get_meta_data(
const blender::bke::AttributeIDRef &attribute_id) const
const StringRef attribute_name) const
{
std::optional<AttributeMetaData> result{std::nullopt};
this->attribute_foreach([&](const blender::bke::AttributeIDRef &current_attribute_id,
const AttributeMetaData &meta_data) {
if (attribute_id == current_attribute_id) {
this->attribute_foreach([&](StringRefNull name, const AttributeMetaData &meta_data) {
if (attribute_name == name) {
result = meta_data;
return false;
}
@@ -1035,11 +977,11 @@ static std::unique_ptr<blender::fn::GVArray> try_adapt_data_type(
}
std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_read(
const blender::bke::AttributeIDRef &attribute_id,
const StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type) const
{
blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_id);
blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_name);
if (!attribute) {
return {};
}
@@ -1065,13 +1007,13 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r
}
std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_try_get_for_read(
const blender::bke::AttributeIDRef &attribute_id, const AttributeDomain domain) const
const StringRef attribute_name, const AttributeDomain domain) const
{
if (!this->attribute_domain_supported(domain)) {
return {};
}
blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_id);
blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_name);
if (!attribute) {
return {};
}
@@ -1084,9 +1026,9 @@ std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_try_get_for_
}
blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
const blender::bke::AttributeIDRef &attribute_id, const CustomDataType data_type) const
const blender::StringRef attribute_name, const CustomDataType data_type) const
{
blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_id);
blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_name);
if (!attribute) {
return {};
}
@@ -1101,13 +1043,13 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
}
std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_get_for_read(
const blender::bke::AttributeIDRef &attribute_id,
const StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type,
const void *default_value) const
{
std::unique_ptr<blender::bke::GVArray> varray = this->attribute_try_get_for_read(
attribute_id, domain, data_type);
attribute_name, domain, data_type);
if (varray) {
return varray;
}
@@ -1123,22 +1065,15 @@ class GVMutableAttribute_For_OutputAttribute
: public blender::fn::GVMutableArray_For_GMutableSpan {
public:
GeometryComponent *component;
std::string attribute_name;
blender::bke::WeakAnonymousAttributeID anonymous_attribute_id;
std::string final_name;
GVMutableAttribute_For_OutputAttribute(GMutableSpan data,
GeometryComponent &component,
const blender::bke::AttributeIDRef &attribute_id)
: blender::fn::GVMutableArray_For_GMutableSpan(data), component(&component)
std::string final_name)
: blender::fn::GVMutableArray_For_GMutableSpan(data),
component(&component),
final_name(std::move(final_name))
{
if (attribute_id.is_named()) {
this->attribute_name = attribute_id.name();
}
else {
const AnonymousAttributeID *anonymous_id = &attribute_id.anonymous_id();
BKE_anonymous_attribute_id_increment_weak(anonymous_id);
this->anonymous_attribute_id = blender::bke::WeakAnonymousAttributeID{anonymous_id};
}
}
~GVMutableAttribute_For_OutputAttribute() override
@@ -1158,28 +1093,21 @@ static void save_output_attribute(blender::bke::OutputAttribute &output_attribut
dynamic_cast<GVMutableAttribute_For_OutputAttribute &>(output_attribute.varray());
GeometryComponent &component = *varray.component;
AttributeIDRef attribute_id;
if (!varray.attribute_name.empty()) {
attribute_id = varray.attribute_name;
}
else {
attribute_id = varray.anonymous_attribute_id.extract();
}
const StringRefNull name = varray.final_name;
const AttributeDomain domain = output_attribute.domain();
const CustomDataType data_type = output_attribute.custom_data_type();
const CPPType &cpp_type = output_attribute.cpp_type();
component.attribute_try_delete(attribute_id);
if (!component.attribute_try_create(attribute_id, domain, data_type, AttributeInitDefault())) {
if (!varray.attribute_name.empty()) {
CLOG_WARN(&LOG,
"Could not create the '%s' attribute with type '%s'.",
varray.attribute_name.c_str(),
cpp_type.name().c_str());
}
component.attribute_try_delete(name);
if (!component.attribute_try_create(
varray.final_name, domain, data_type, AttributeInitDefault())) {
CLOG_WARN(&LOG,
"Could not create the '%s' attribute with type '%s'.",
name.c_str(),
cpp_type.name().c_str());
return;
}
WriteAttributeLookup write_attribute = component.attribute_try_get_for_write(attribute_id);
WriteAttributeLookup write_attribute = component.attribute_try_get_for_write(name);
BUFFER_FOR_CPP_TYPE_VALUE(varray.type(), buffer);
for (const int i : IndexRange(varray.size())) {
varray.get(i, buffer);
@@ -1189,7 +1117,7 @@ static void save_output_attribute(blender::bke::OutputAttribute &output_attribut
static blender::bke::OutputAttribute create_output_attribute(
GeometryComponent &component,
const blender::bke::AttributeIDRef &attribute_id,
const blender::StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type,
const bool ignore_old_values,
@@ -1199,7 +1127,7 @@ static blender::bke::OutputAttribute create_output_attribute(
using namespace blender::fn;
using namespace blender::bke;
if (!attribute_id) {
if (attribute_name.is_empty()) {
return {};
}
@@ -1207,8 +1135,7 @@ static blender::bke::OutputAttribute create_output_attribute(
BLI_assert(cpp_type != nullptr);
const nodes::DataTypeConversions &conversions = nodes::get_implicit_type_conversions();
if (attribute_id.is_named() && component.attribute_is_builtin(attribute_id.name())) {
const StringRef attribute_name = attribute_id.name();
if (component.attribute_is_builtin(attribute_name)) {
WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_name);
if (!attribute) {
if (default_value) {
@@ -1242,18 +1169,18 @@ static blender::bke::OutputAttribute create_output_attribute(
const int domain_size = component.attribute_domain_size(domain);
WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_id);
WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_name);
if (!attribute) {
if (default_value) {
const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value};
component.attribute_try_create(
attribute_id, domain, data_type, AttributeInitVArray(&default_varray));
attribute_name, domain, data_type, AttributeInitVArray(&default_varray));
}
else {
component.attribute_try_create(attribute_id, domain, data_type, AttributeInitDefault());
component.attribute_try_create(attribute_name, domain, data_type, AttributeInitDefault());
}
attribute = component.attribute_try_get_for_write(attribute_id);
attribute = component.attribute_try_get_for_write(attribute_name);
if (!attribute) {
/* Can't create the attribute. */
return {};
@@ -1275,28 +1202,28 @@ static blender::bke::OutputAttribute create_output_attribute(
else {
/* Fill the temporary array with values from the existing attribute. */
GVArrayPtr old_varray = component.attribute_get_for_read(
attribute_id, domain, data_type, default_value);
attribute_name, domain, data_type, default_value);
old_varray->materialize_to_uninitialized(IndexRange(domain_size), data);
}
GVMutableArrayPtr varray = std::make_unique<GVMutableAttribute_For_OutputAttribute>(
GMutableSpan{*cpp_type, data, domain_size}, component, attribute_id);
GMutableSpan{*cpp_type, data, domain_size}, component, attribute_name);
return OutputAttribute(std::move(varray), domain, save_output_attribute, true);
}
blender::bke::OutputAttribute GeometryComponent::attribute_try_get_for_output(
const blender::bke::AttributeIDRef &attribute_id,
const StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type,
const void *default_value)
{
return create_output_attribute(*this, attribute_id, domain, data_type, false, default_value);
return create_output_attribute(*this, attribute_name, domain, data_type, false, default_value);
}
blender::bke::OutputAttribute GeometryComponent::attribute_try_get_for_output_only(
const blender::bke::AttributeIDRef &attribute_id,
const blender::StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type)
{
return create_output_attribute(*this, attribute_id, domain, data_type, true, nullptr);
return create_output_attribute(*this, attribute_name, domain, data_type, true, nullptr);
}

View File

@@ -116,13 +116,12 @@ class BuiltinAttributeProvider {
class DynamicAttributesProvider {
public:
virtual ReadAttributeLookup try_get_for_read(const GeometryComponent &component,
const AttributeIDRef &attribute_id) const = 0;
const StringRef attribute_name) const = 0;
virtual WriteAttributeLookup try_get_for_write(GeometryComponent &component,
const AttributeIDRef &attribute_id) const = 0;
virtual bool try_delete(GeometryComponent &component,
const AttributeIDRef &attribute_id) const = 0;
const StringRef attribute_name) const = 0;
virtual bool try_delete(GeometryComponent &component, const StringRef attribute_name) const = 0;
virtual bool try_create(GeometryComponent &UNUSED(component),
const AttributeIDRef &UNUSED(attribute_id),
const StringRef UNUSED(attribute_name),
const AttributeDomain UNUSED(domain),
const CustomDataType UNUSED(data_type),
const AttributeInit &UNUSED(initializer)) const
@@ -155,15 +154,15 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
}
ReadAttributeLookup try_get_for_read(const GeometryComponent &component,
const AttributeIDRef &attribute_id) const final;
const StringRef attribute_name) const final;
WriteAttributeLookup try_get_for_write(GeometryComponent &component,
const AttributeIDRef &attribute_id) const final;
const StringRef attribute_name) const final;
bool try_delete(GeometryComponent &component, const AttributeIDRef &attribute_id) const final;
bool try_delete(GeometryComponent &component, const StringRef attribute_name) const final;
bool try_create(GeometryComponent &component,
const AttributeIDRef &attribute_id,
const StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type,
const AttributeInit &initializer) const final;
@@ -232,10 +231,10 @@ class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider {
}
ReadAttributeLookup try_get_for_read(const GeometryComponent &component,
const AttributeIDRef &attribute_id) const final;
const StringRef attribute_name) const final;
WriteAttributeLookup try_get_for_write(GeometryComponent &component,
const AttributeIDRef &attribute_id) const final;
bool try_delete(GeometryComponent &component, const AttributeIDRef &attribute_id) const final;
const StringRef attribute_name) const final;
bool try_delete(GeometryComponent &component, const StringRef attribute_name) const final;
bool foreach_attribute(const GeometryComponent &component,
const AttributeForeachCallback callback) const final;
void foreach_domain(const FunctionRef<void(AttributeDomain)> callback) const final;

View File

@@ -1254,10 +1254,11 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
bool in_cache = bvhcache_find(
bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
BVHCache *bvh_cache = *bvh_cache_p;
bvhtree_balance(tree, true);
if (in_cache == false) {
tree = bvhtree_from_editmesh_looptri_create_tree(
epsilon, tree_type, axis, em, looptri_mask, looptri_num_active);
bvhtree_balance(tree, true);
/* Save on cache for later use */
// printf("BVHTree built and saved on cache\n");

View File

@@ -25,7 +25,6 @@
#include "DNA_curve_types.h"
#include "BKE_anonymous_attribute.hh"
#include "BKE_curve.h"
#include "BKE_spline.hh"
@@ -331,13 +330,13 @@ void CurveEval::assert_valid_point_attributes() const
return;
}
const int layer_len = splines_.first()->attributes.data.totlayer;
Map<blender::bke::AttributeIDRef, AttributeMetaData> map;
Map<StringRefNull, AttributeMetaData> map;
for (const SplinePtr &spline : splines_) {
BLI_assert(spline->attributes.data.totlayer == layer_len);
spline->attributes.foreach_attribute(
[&](const blender::bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
[&](StringRefNull name, const AttributeMetaData &meta_data) {
map.add_or_modify(
attribute_id,
name,
[&](AttributeMetaData *map_data) {
/* All unique attribute names should be added on the first spline. */
BLI_assert(spline == splines_.first());

View File

@@ -46,7 +46,6 @@
#include "BLT_translation.h"
#include "BKE_anonymous_attribute.h"
#include "BKE_customdata.h"
#include "BKE_customdata_file.h"
#include "BKE_deform.h"
@@ -2128,10 +2127,6 @@ bool CustomData_merge(const struct CustomData *source,
if (flag & CD_FLAG_NOCOPY) {
continue;
}
if (layer->anonymous_id &&
!BKE_anonymous_attribute_id_has_strong_references(layer->anonymous_id)) {
continue;
}
if (!(mask & CD_TYPE_AS_MASK(type))) {
continue;
}
@@ -2171,11 +2166,6 @@ bool CustomData_merge(const struct CustomData *source,
newlayer->active_mask = lastmask;
newlayer->flag |= flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY);
changed = true;
if (layer->anonymous_id != NULL) {
BKE_anonymous_attribute_id_increment_weak(layer->anonymous_id);
newlayer->anonymous_id = layer->anonymous_id;
}
}
}
@@ -2216,10 +2206,6 @@ static void customData_free_layer__internal(CustomDataLayer *layer, int totelem)
{
const LayerTypeInfo *typeInfo;
if (layer->anonymous_id != NULL) {
BKE_anonymous_attribute_id_decrement_weak(layer->anonymous_id);
layer->anonymous_id = NULL;
}
if (!(layer->flag & CD_FLAG_NOFREE) && layer->data) {
typeInfo = layerType_getInfo(layer->type);
@@ -2663,27 +2649,6 @@ void *CustomData_add_layer_named(CustomData *data,
return NULL;
}
void *CustomData_add_layer_anonymous(struct CustomData *data,
int type,
eCDAllocType alloctype,
void *layerdata,
int totelem,
const AnonymousAttributeID *anonymous_id)
{
const char *name = BKE_anonymous_attribute_id_internal_name(anonymous_id);
CustomDataLayer *layer = customData_add_layer__internal(
data, type, alloctype, layerdata, totelem, name);
CustomData_update_typemap(data);
if (layer == NULL) {
return NULL;
}
BKE_anonymous_attribute_id_increment_weak(anonymous_id);
layer->anonymous_id = anonymous_id;
return layer->data;
}
bool CustomData_free_layer(CustomData *data, int type, int totelem, int index)
{
const int index_first = CustomData_get_layer_index(data, type);
@@ -2847,20 +2812,6 @@ void *CustomData_duplicate_referenced_layer_named(CustomData *data,
return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
}
void *CustomData_duplicate_referenced_layer_anonymous(CustomData *data,
const int type,
const AnonymousAttributeID *anonymous_id,
const int totelem)
{
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].anonymous_id == anonymous_id) {
return customData_duplicate_referenced_layer_index(data, i, totelem);
}
}
BLI_assert_unreachable();
return NULL;
}
void CustomData_duplicate_referenced_layers(CustomData *data, int totelem)
{
for (int i = 0; i < data->totlayer; i++) {
@@ -4293,8 +4244,7 @@ void CustomData_blend_write_prepare(CustomData *data,
for (i = 0, j = 0; i < totlayer; i++) {
CustomDataLayer *layer = &data->layers[i];
/* Layers with this flag set are not written to file. */
if ((layer->flag & CD_FLAG_NOCOPY) || layer->anonymous_id != NULL) {
if (layer->flag & CD_FLAG_NOCOPY) { /* Layers with this flag set are not written to file. */
data->totlayer--;
// CLOG_WARN(&LOG, "skipping layer %p (%s)", layer, layer->name);
}

View File

@@ -892,7 +892,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
public:
ReadAttributeLookup try_get_for_read(const GeometryComponent &component,
const AttributeIDRef &attribute_id) const final
const StringRef attribute_name) const final
{
const CurveEval *curve = get_curve_from_component_for_read(component);
if (curve == nullptr || curve->splines().size() == 0) {
@@ -902,13 +902,13 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
Span<SplinePtr> splines = curve->splines();
Vector<GSpan> spans; /* GSpan has no default constructor. */
spans.reserve(splines.size());
std::optional<GSpan> first_span = splines[0]->attributes.get_for_read(attribute_id);
std::optional<GSpan> first_span = splines[0]->attributes.get_for_read(attribute_name);
if (!first_span) {
return {};
}
spans.append(*first_span);
for (const int i : IndexRange(1, splines.size() - 1)) {
std::optional<GSpan> span = splines[i]->attributes.get_for_read(attribute_id);
std::optional<GSpan> span = splines[i]->attributes.get_for_read(attribute_name);
if (!span) {
/* All splines should have the same set of data layers. It would be possible to recover
* here and return partial data instead, but that would add a lot of complexity for a
@@ -945,7 +945,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
/* This function is almost the same as #try_get_for_read, but without const. */
WriteAttributeLookup try_get_for_write(GeometryComponent &component,
const AttributeIDRef &attribute_id) const final
const StringRef attribute_name) const final
{
CurveEval *curve = get_curve_from_component_for_write(component);
if (curve == nullptr || curve->splines().size() == 0) {
@@ -955,13 +955,13 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
MutableSpan<SplinePtr> splines = curve->splines();
Vector<GMutableSpan> spans; /* GMutableSpan has no default constructor. */
spans.reserve(splines.size());
std::optional<GMutableSpan> first_span = splines[0]->attributes.get_for_write(attribute_id);
std::optional<GMutableSpan> first_span = splines[0]->attributes.get_for_write(attribute_name);
if (!first_span) {
return {};
}
spans.append(*first_span);
for (const int i : IndexRange(1, splines.size() - 1)) {
std::optional<GMutableSpan> span = splines[i]->attributes.get_for_write(attribute_id);
std::optional<GMutableSpan> span = splines[i]->attributes.get_for_write(attribute_name);
if (!span) {
/* All splines should have the same set of data layers. It would be possible to recover
* here and return partial data instead, but that would add a lot of complexity for a
@@ -996,7 +996,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
return attribute;
}
bool try_delete(GeometryComponent &component, const AttributeIDRef &attribute_id) const final
bool try_delete(GeometryComponent &component, const StringRef attribute_name) const final
{
CurveEval *curve = get_curve_from_component_for_write(component);
if (curve == nullptr) {
@@ -1006,7 +1006,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
/* Reuse the boolean for all splines; we expect all splines to have the same attributes. */
bool layer_freed = false;
for (SplinePtr &spline : curve->splines()) {
layer_freed = spline->attributes.remove(attribute_id);
layer_freed = spline->attributes.remove(attribute_name);
}
return layer_freed;
}
@@ -1034,7 +1034,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
}
bool try_create(GeometryComponent &component,
const AttributeIDRef &attribute_id,
const StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type,
const AttributeInit &initializer) const final
@@ -1053,7 +1053,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
/* First check the one case that allows us to avoid copying the input data. */
if (splines.size() == 1 && initializer.type == AttributeInit::Type::MoveArray) {
void *source_data = static_cast<const AttributeInitMove &>(initializer).data;
if (!splines[0]->attributes.create_by_move(attribute_id, data_type, source_data)) {
if (!splines[0]->attributes.create_by_move(attribute_name, data_type, source_data)) {
MEM_freeN(source_data);
return false;
}
@@ -1062,7 +1062,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
/* Otherwise just create a custom data layer on each of the splines. */
for (const int i : splines.index_range()) {
if (!splines[i]->attributes.create(attribute_id, data_type)) {
if (!splines[i]->attributes.create(attribute_name, data_type)) {
/* If attribute creation fails on one of the splines, we cannot leave the custom data
* layers in the previous splines around, so delete them before returning. However,
* this is not an expected case. */
@@ -1076,7 +1076,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
return true;
}
WriteAttributeLookup write_attribute = this->try_get_for_write(component, attribute_id);
WriteAttributeLookup write_attribute = this->try_get_for_write(component, attribute_name);
/* We just created the attribute, it should exist. */
BLI_assert(write_attribute);

View File

@@ -818,20 +818,16 @@ class VArray_For_VertexWeights final : public VArray<float> {
class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
public:
ReadAttributeLookup try_get_for_read(const GeometryComponent &component,
const AttributeIDRef &attribute_id) const final
const StringRef attribute_name) const final
{
BLI_assert(component.type() == GEO_COMPONENT_TYPE_MESH);
if (!attribute_id.is_named()) {
return {};
}
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const Mesh *mesh = mesh_component.get_for_read();
if (mesh == nullptr) {
return {};
}
std::string name = attribute_id.name();
const int vertex_group_index = BLI_findstringindex(
&mesh->vertex_group_names, name.c_str(), offsetof(bDeformGroup, name));
&mesh->vertex_group_names, attribute_name.data(), offsetof(bDeformGroup, name));
if (vertex_group_index < 0) {
return {};
}
@@ -847,21 +843,17 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
}
WriteAttributeLookup try_get_for_write(GeometryComponent &component,
const AttributeIDRef &attribute_id) const final
const StringRef attribute_name) const final
{
BLI_assert(component.type() == GEO_COMPONENT_TYPE_MESH);
if (!attribute_id.is_named()) {
return {};
}
MeshComponent &mesh_component = static_cast<MeshComponent &>(component);
Mesh *mesh = mesh_component.get_for_write();
if (mesh == nullptr) {
return {};
}
const std::string name = attribute_id.name();
const int vertex_group_index = BLI_findstringindex(
&mesh->vertex_group_names, name.c_str(), offsetof(bDeformGroup, name));
&mesh->vertex_group_names, attribute_name.data(), offsetof(bDeformGroup, name));
if (vertex_group_index < 0) {
return {};
}
@@ -880,21 +872,17 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
ATTR_DOMAIN_POINT};
}
bool try_delete(GeometryComponent &component, const AttributeIDRef &attribute_id) const final
bool try_delete(GeometryComponent &component, const StringRef attribute_name) const final
{
BLI_assert(component.type() == GEO_COMPONENT_TYPE_MESH);
if (!attribute_id.is_named()) {
return false;
}
MeshComponent &mesh_component = static_cast<MeshComponent &>(component);
Mesh *mesh = mesh_component.get_for_write();
if (mesh == nullptr) {
return true;
}
const std::string name = attribute_id.name();
const int vertex_group_index = BLI_findstringindex(
&mesh->vertex_group_names, name.c_str(), offsetof(bDeformGroup, name));
&mesh->vertex_group_names, attribute_name.data(), offsetof(bDeformGroup, name));
if (vertex_group_index < 0) {
return false;
}

View File

@@ -319,7 +319,7 @@ void geometry_set_instances_attribute_foreach(const GeometrySet &geometry_set,
void geometry_set_gather_instances_attribute_info(Span<GeometryInstanceGroup> set_groups,
Span<GeometryComponentType> component_types,
const Set<std::string> &ignored_attributes,
Map<AttributeIDRef, AttributeKind> &r_attributes)
Map<std::string, AttributeKind> &r_attributes)
{
for (const GeometryInstanceGroup &set_group : set_groups) {
const GeometrySet &set = set_group.geometry_set;
@@ -329,24 +329,23 @@ void geometry_set_gather_instances_attribute_info(Span<GeometryInstanceGroup> se
}
const GeometryComponent &component = *set.get_component_for_read(component_type);
component.attribute_foreach(
[&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
if (attribute_id.is_named() && ignored_attributes.contains(attribute_id.name())) {
return true;
}
auto add_info = [&](AttributeKind *attribute_kind) {
attribute_kind->domain = meta_data.domain;
attribute_kind->data_type = meta_data.data_type;
};
auto modify_info = [&](AttributeKind *attribute_kind) {
attribute_kind->domain = meta_data.domain; /* TODO: Use highest priority domain. */
attribute_kind->data_type = bke::attribute_data_type_highest_complexity(
{attribute_kind->data_type, meta_data.data_type});
};
component.attribute_foreach([&](StringRefNull name, const AttributeMetaData &meta_data) {
if (ignored_attributes.contains(name)) {
return true;
}
auto add_info = [&](AttributeKind *attribute_kind) {
attribute_kind->domain = meta_data.domain;
attribute_kind->data_type = meta_data.data_type;
};
auto modify_info = [&](AttributeKind *attribute_kind) {
attribute_kind->domain = meta_data.domain; /* TODO: Use highest priority domain. */
attribute_kind->data_type = bke::attribute_data_type_highest_complexity(
{attribute_kind->data_type, meta_data.data_type});
};
r_attributes.add_or_modify(attribute_id, add_info, modify_info);
return true;
});
r_attributes.add_or_modify(name, add_info, modify_info);
return true;
});
}
}
}
@@ -501,11 +500,11 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGrou
static void join_attributes(Span<GeometryInstanceGroup> set_groups,
Span<GeometryComponentType> component_types,
const Map<AttributeIDRef, AttributeKind> &attribute_info,
const Map<std::string, AttributeKind> &attribute_info,
GeometryComponent &result)
{
for (Map<AttributeIDRef, AttributeKind>::Item entry : attribute_info.items()) {
const AttributeIDRef attribute_id = entry.key;
for (Map<std::string, AttributeKind>::Item entry : attribute_info.items()) {
StringRef name = entry.key;
const AttributeDomain domain_output = entry.value.domain;
const CustomDataType data_type_output = entry.value.data_type;
const CPPType *cpp_type = bke::custom_data_type_to_cpp_type(data_type_output);
@@ -513,7 +512,7 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups,
result.attribute_try_create(
entry.key, domain_output, data_type_output, AttributeInitDefault());
WriteAttributeLookup write_attribute = result.attribute_try_get_for_write(attribute_id);
WriteAttributeLookup write_attribute = result.attribute_try_get_for_write(name);
if (!write_attribute || &write_attribute.varray->type() != cpp_type ||
write_attribute.domain != domain_output) {
continue;
@@ -532,7 +531,7 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups,
continue; /* Domain size is 0, so no need to increment the offset. */
}
GVArrayPtr source_attribute = component.attribute_try_get_for_read(
attribute_id, domain_output, data_type_output);
name, domain_output, data_type_output);
if (source_attribute) {
fn::GVArray_GSpan src_span{*source_attribute};
@@ -642,7 +641,7 @@ static void join_instance_groups_mesh(Span<GeometryInstanceGroup> set_groups,
}
/* Don't copy attributes that are stored directly in the mesh data structs. */
Map<AttributeIDRef, AttributeKind> attributes;
Map<std::string, AttributeKind> attributes;
geometry_set_gather_instances_attribute_info(
set_groups,
component_types,
@@ -663,7 +662,7 @@ static void join_instance_groups_pointcloud(Span<GeometryInstanceGroup> set_grou
PointCloudComponent &dst_component = result.get_component_for_write<PointCloudComponent>();
dst_component.replace(new_pointcloud);
Map<AttributeIDRef, AttributeKind> attributes;
Map<std::string, AttributeKind> attributes;
geometry_set_gather_instances_attribute_info(
set_groups, {GEO_COMPONENT_TYPE_POINT_CLOUD}, {"position"}, attributes);
join_attributes(set_groups,
@@ -697,7 +696,7 @@ static void join_instance_groups_curve(Span<GeometryInstanceGroup> set_groups, G
CurveComponent &dst_component = result.get_component_for_write<CurveComponent>();
dst_component.replace(curve);
Map<AttributeIDRef, AttributeKind> attributes;
Map<std::string, AttributeKind> attributes;
geometry_set_gather_instances_attribute_info(
set_groups,
{GEO_COMPONENT_TYPE_CURVE},

View File

@@ -620,10 +620,7 @@ bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const
}
if (new_count == 1) {
if (gps->dvert) {
BKE_gpencil_free_stroke_weights(gps);
MEM_freeN(gps->dvert);
}
BKE_gpencil_free_stroke_weights(gps);
MEM_freeN(gps->points);
gps->points = nullptr;
gps->dvert = nullptr;
@@ -631,24 +628,27 @@ bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const
return false;
}
new_pt = (bGPDspoint *)MEM_mallocN(sizeof(bGPDspoint) * new_count, "gp_stroke_points_trimmed");
memcpy(new_pt, &pt[index_from], sizeof(bGPDspoint) * new_count);
new_pt = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * new_count, "gp_stroke_points_trimmed");
for (int i = 0; i < new_count; i++) {
memcpy(&new_pt[i], &pt[i + index_from], sizeof(bGPDspoint));
}
if (gps->dvert) {
new_dv = (MDeformVert *)MEM_mallocN(sizeof(MDeformVert) * new_count,
new_dv = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * new_count,
"gp_stroke_dverts_trimmed");
for (int i = 0; i < new_count; i++) {
dv = &gps->dvert[i + index_from];
new_dv[i].flag = dv->flag;
new_dv[i].totweight = dv->totweight;
new_dv[i].dw = (MDeformWeight *)MEM_mallocN(sizeof(MDeformWeight) * dv->totweight,
new_dv[i].dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
"gp_stroke_dverts_dw_trimmed");
for (int j = 0; j < dv->totweight; j++) {
new_dv[i].dw[j].weight = dv->dw[j].weight;
new_dv[i].dw[j].def_nr = dv->dw[j].def_nr;
}
BKE_defvert_clear(dv);
}
BKE_gpencil_free_stroke_weights(gps);
MEM_freeN(gps->dvert);
gps->dvert = new_dv;
}
@@ -692,21 +692,25 @@ bool BKE_gpencil_stroke_split(bGPdata *gpd,
gpf, gps, gps->mat_nr, new_count, gps->thickness);
new_pt = new_gps->points; /* Allocated from above. */
memcpy(new_pt, &pt[before_index], sizeof(bGPDspoint) * new_count);
for (int i = 0; i < new_count; i++) {
memcpy(&new_pt[i], &pt[i + before_index], sizeof(bGPDspoint));
}
if (gps->dvert) {
new_dv = (MDeformVert *)MEM_mallocN(sizeof(MDeformVert) * new_count,
new_dv = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * new_count,
"gp_stroke_dverts_remaining(MDeformVert)");
for (int i = 0; i < new_count; i++) {
dv = &gps->dvert[i + before_index];
new_dv[i].flag = dv->flag;
new_dv[i].totweight = dv->totweight;
new_dv[i].dw = (MDeformWeight *)MEM_mallocN(sizeof(MDeformWeight) * dv->totweight,
new_dv[i].dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
"gp_stroke_dverts_dw_remaining(MDeformWeight)");
for (int j = 0; j < dv->totweight; j++) {
new_dv[i].dw[j].weight = dv->dw[j].weight;
new_dv[i].dw[j].def_nr = dv->dw[j].def_nr;
}
BKE_defvert_clear(dv);
}
new_gps->dvert = new_dv;
}

View File

@@ -1481,7 +1481,7 @@ static bool id_name_final_build(char *name, char *base_name, size_t base_name_le
/* Code above may have generated invalid utf-8 string, due to raw truncation.
* Ensure we get a valid one now. */
base_name_len -= (size_t)BLI_str_utf8_invalid_strip(base_name, base_name_len);
base_name_len -= (size_t)BLI_utf8_invalid_strip(base_name, base_name_len);
/* Also truncate orig name, and start the whole check again. */
name[base_name_len] = '\0';
@@ -1731,7 +1731,7 @@ bool BKE_id_new_name_validate(ListBase *lb, ID *id, const char *tname, const boo
else {
/* disallow non utf8 chars,
* the interface checks for this but new ID's based on file names don't */
BLI_str_utf8_invalid_strip(name, strlen(name));
BLI_utf8_invalid_strip(name, strlen(name));
}
ID *id_sorting_hint = NULL;

View File

@@ -5135,6 +5135,7 @@ static void registerGeometryNodes()
register_node_type_geo_attribute_vector_rotate();
register_node_type_geo_boolean();
register_node_type_geo_bounding_box();
register_node_type_geo_collapse();
register_node_type_geo_collection_info();
register_node_type_geo_convex_hull();
register_node_type_geo_curve_endpoints();
@@ -5155,12 +5156,15 @@ static void registerGeometryNodes()
register_node_type_geo_curve_to_points();
register_node_type_geo_curve_trim();
register_node_type_geo_delete_geometry();
register_node_type_geo_dissolve();
register_node_type_geo_edge_split();
register_node_type_geo_input_material();
register_node_type_geo_is_viewport();
register_node_type_geo_join_geometry();
register_node_type_geo_material_assign();
register_node_type_geo_material_replace();
register_node_type_geo_mesh_extrude();
register_node_type_geo_mesh_inset();
register_node_type_geo_mesh_primitive_circle();
register_node_type_geo_mesh_primitive_cone();
register_node_type_geo_mesh_primitive_cube();
@@ -5180,14 +5184,19 @@ static void registerGeometryNodes()
register_node_type_geo_point_translate();
register_node_type_geo_points_to_volume();
register_node_type_geo_raycast();
register_node_type_geo_merge_by_distance();
register_node_type_geo_sample_texture();
register_node_type_geo_select_by_handle_type();
register_node_type_geo_select_by_material();
register_node_type_geo_separate_components();
register_node_type_geo_solidify();
register_node_type_geo_subdivision_surface();
register_node_type_geo_switch();
register_node_type_geo_remesh_voxel();
register_node_type_geo_remesh_blocks();
register_node_type_geo_transform();
register_node_type_geo_triangulate();
register_node_type_geo_unsubdivide();
register_node_type_geo_viewer();
register_node_type_geo_volume_to_mesh();
}

View File

@@ -308,7 +308,7 @@ int txt_extended_ascii_as_utf8(char **str)
int added = 0;
while ((*str)[i]) {
if ((bad_char = BLI_str_utf8_invalid_byte(*str + i, length - i)) == -1) {
if ((bad_char = BLI_utf8_invalid_byte(*str + i, length - i)) == -1) {
break;
}
@@ -322,7 +322,7 @@ int txt_extended_ascii_as_utf8(char **str)
i = 0;
while ((*str)[i]) {
if ((bad_char = BLI_str_utf8_invalid_byte((*str) + i, length - i)) == -1) {
if ((bad_char = BLI_utf8_invalid_byte((*str) + i, length - i)) == -1) {
memcpy(newstr + mi, (*str) + i, length - i + 1);
break;
}

View File

@@ -196,8 +196,6 @@ MINLINE unsigned int log2_ceil_u(unsigned int x);
MINLINE int divide_round_i(int a, int b);
MINLINE int mod_i(int i, int n);
MINLINE float round_to_even(float f);
MINLINE signed char round_fl_to_char(float a);
MINLINE unsigned char round_fl_to_uchar(float a);
MINLINE short round_fl_to_short(float a);

View File

@@ -31,8 +31,8 @@ char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t
ATTR_NONNULL();
size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, size_t maxncpy)
ATTR_NONNULL();
ptrdiff_t BLI_str_utf8_invalid_byte(const char *str, size_t length) ATTR_NONNULL();
int BLI_str_utf8_invalid_strip(char *str, size_t length) ATTR_NONNULL();
ptrdiff_t BLI_utf8_invalid_byte(const char *str, size_t length) ATTR_NONNULL();
int BLI_utf8_invalid_strip(char *str, size_t length) ATTR_NONNULL();
/* warning, can return -1 on bad chars */
int BLI_str_utf8_size(const char *p) ATTR_NONNULL();

View File

@@ -302,7 +302,7 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile *pf)
/* Get the name. */
if (face->family_name) {
BLI_snprintf(vfd->name, sizeof(vfd->name), "%s %s", face->family_name, face->style_name);
BLI_str_utf8_invalid_strip(vfd->name, strlen(vfd->name));
BLI_utf8_invalid_strip(vfd->name, strlen(vfd->name));
}
/* Select a character map. */

View File

@@ -363,14 +363,6 @@ MINLINE signed char round_db_to_char_clamp(double a){
#undef _round_clamp_fl_impl
#undef _round_clamp_db_impl
/**
* Round to closest even number, halfway cases are rounded away from zero.
*/
MINLINE float round_to_even(float f)
{
return roundf(f * 0.5f) * 2.0f;
}
/* integer division that rounds 0.5 up, particularly useful for color blending
* with integers, to avoid gradual darkening when rounding down */
MINLINE int divide_round_i(int a, int b)

View File

@@ -70,7 +70,7 @@ static const size_t utf8_skip_data[256] = {
*
* \return the offset of the first invalid byte.
*/
ptrdiff_t BLI_str_utf8_invalid_byte(const char *str, size_t length)
ptrdiff_t BLI_utf8_invalid_byte(const char *str, size_t length)
{
const unsigned char *p, *perr, *pend = (const unsigned char *)str + length;
unsigned char c;
@@ -200,14 +200,14 @@ utf8_error:
*
* \return number of stripped bytes.
*/
int BLI_str_utf8_invalid_strip(char *str, size_t length)
int BLI_utf8_invalid_strip(char *str, size_t length)
{
ptrdiff_t bad_char;
int tot = 0;
BLI_assert(str[length] == '\0');
while ((bad_char = BLI_str_utf8_invalid_byte(str, length)) != -1) {
while ((bad_char = BLI_utf8_invalid_byte(str, length)) != -1) {
str += bad_char;
length -= (size_t)(bad_char + 1);

View File

@@ -266,7 +266,7 @@ static const char *utf8_invalid_tests[][3] = {
};
/* clang-format on */
/* BLI_str_utf8_invalid_strip (and indirectly, BLI_str_utf8_invalid_byte). */
/* BLI_utf8_invalid_strip (and indirectly, BLI_utf8_invalid_byte). */
TEST(string, Utf8InvalidBytes)
{
for (int i = 0; utf8_invalid_tests[i][0] != nullptr; i++) {
@@ -277,7 +277,7 @@ TEST(string, Utf8InvalidBytes)
char buff[80];
memcpy(buff, tst, sizeof(buff));
const int num_errors_found = BLI_str_utf8_invalid_strip(buff, sizeof(buff) - 1);
const int num_errors_found = BLI_utf8_invalid_strip(buff, sizeof(buff) - 1);
printf("[%02d] -> [%02d] \"%s\" -> \"%s\"\n", num_errors, num_errors_found, tst, buff);
EXPECT_EQ(num_errors_found, num_errors);

View File

@@ -1446,4 +1446,242 @@ void BM_mesh_vert_coords_apply_with_mat4(BMesh *bm,
}
}
/** \} */
/**
* Use to select bmesh vertex data based on an array of bool.
*/
void BM_select_vertices(BMesh *bm, const bool *mask)
{
BMIter iter;
BMVert *v;
int i;
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
BM_elem_flag_set(v, BM_ELEM_SELECT, mask[i]);
}
}
/**
* Use to select bmesh edge data based on an array of bool.
*/
void BM_select_edges(BMesh *bm, const bool *mask)
{
BMIter iter;
BMEdge *e;
int i;
BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
BM_elem_flag_set(e, BM_ELEM_SELECT, mask[i]);
}
}
/**
* Use to select bmesh face data based on an array of bool.
*/
void BM_select_faces(BMesh *bm, const bool *mask)
{
BMIter iter;
BMFace *f;
int i = 0;
BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
BM_elem_flag_set(f, BM_ELEM_SELECT, mask[i]);
}
}
/**
* Use to temporary tag bmesh edge data based on an array of bool.
*/
void BM_tag_vertices(BMesh *bm, const bool *mask)
{
BMIter iter;
BMVert *v;
int i;
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
BM_elem_flag_set(v, BM_ELEM_TAG, mask[i]);
}
}
/**
* Use to temporary tag bmesh edge data based on an array of bool.
*/
void BM_tag_edges(BMesh *bm, const bool *mask)
{
BMIter iter;
BMEdge *e;
int i;
BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
BM_elem_flag_set(e, BM_ELEM_TAG, mask[i]);
}
}
/**
* Use to temporary tag bmesh face data based on an array of bool.
*/
void BM_tag_faces(BMesh *bm, const bool *mask)
{
BMIter iter;
BMFace *f;
int i;
BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
BM_elem_flag_set(f, BM_ELEM_TAG, mask[i]);
}
}
/**
* Write selected bmesh vertex to array of bool with length of totvert.
*/
void BM_get_selected_vertices(BMesh *bm, bool *selection)
{
BMIter iter;
BMVert *v;
int i;
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
selection[i] = BM_elem_flag_test(v, BM_ELEM_SELECT);
}
}
/**
* Write selected bmesh edge to array of bool with length of totedge.
*/
void BM_get_selected_edges(BMesh *bm, bool *selection)
{
BMIter iter;
BMEdge *e;
int i;
BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
selection[i] = BM_elem_flag_test(e, BM_ELEM_SELECT);
}
}
/**
* Write selected bmesh face to array of bool with length of totpoly.
*/
void BM_get_selected_faces(BMesh *bm, bool *selection)
{
BMIter iter;
BMFace *f;
int i;
BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
selection[i] = BM_elem_flag_test(f, BM_ELEM_SELECT);
}
}
/**
* Write tagged bmesh vertex to array of bool with length of totvert.
*/
void BM_get_tagged_vertices(BMesh *bm, bool *selection)
{
BMIter iter;
BMVert *v;
int i;
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
selection[i] = BM_elem_flag_test(v, BM_ELEM_TAG);
}
}
/**
* Write tagged bmesh edge to array of bool with length of totedge.
*/
void BM_get_tagged_edges(BMesh *bm, bool *selection)
{
BMIter iter;
BMEdge *e;
int i;
BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
selection[i] = BM_elem_flag_test(e, BM_ELEM_TAG);
}
}
/**
* Write tagged bmesh faces to array of bool with length of totpoly.
*/
void BM_get_tagged_faces(BMesh *bm, bool *selection)
{
BMIter iter;
BMFace *f;
int i;
BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
selection[i] = BM_elem_flag_test(f, BM_ELEM_TAG);
}
}
/**
* Use to remove tag from all bmesh verts that are tagged with another tag.
*/
void BM_untag_vertices_by_tag(BMesh *bm, int tag)
{
BMIter iter;
BMVert *v;
int i;
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
if (BM_elem_flag_test(v, tag)) {
BM_elem_flag_disable(v, BM_ELEM_TAG);
}
}
}
/**
* Use to remove tag from all bmesh edges that are tagged with another tag.
*/
void BM_untag_edges_by_tag(BMesh *bm, int tag)
{
BMIter iter;
BMEdge *e;
int i;
BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
if (BM_elem_flag_test(e, tag)) {
BM_elem_flag_disable(e, BM_ELEM_TAG);
}
}
}
/**
* Use to remove tag from all bmesh faces that are tagged with another tag.
*/
void BM_untag_faces_by_tag(BMesh *bm, int tag)
{
BMIter iter;
BMFace *f;
int i;
BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
if (BM_elem_flag_test(f, tag)) {
BM_elem_flag_disable(f, BM_ELEM_TAG);
}
}
}
void BM_tag_vertices_from_operator_slot(BMesh *bm,
BMOperator *b_mesh_operator,
const char *slot,
const int tag)
{
BMOIter iter;
BMVert *v;
BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
BMO_ITER (v, &iter, b_mesh_operator->slots_out, slot, tag) {
BM_elem_flag_enable(v, BM_ELEM_TAG);
}
}
void BM_tag_edges_from_operator_slot(BMesh *bm,
BMOperator *b_mesh_operator,
const char *slot,
const int tag)
{
BMOIter iter;
BMEdge *e;
BM_mesh_elem_hflag_disable_all(bm, BM_EDGE, BM_ELEM_TAG, false);
BMO_ITER (e, &iter, b_mesh_operator->slots_out, slot, tag) {
BM_elem_flag_enable(e, BM_ELEM_TAG);
}
}
void BM_tag_faces_from_operator_slot(BMesh *bm,
BMOperator *b_mesh_operator,
const char *slot,
const int tag)
{
BMOIter iter;
BMFace *f;
BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
BMO_ITER (f, &iter, b_mesh_operator->slots_out, slot, tag) {
BM_elem_flag_enable(f, BM_ELEM_TAG);
}
}

View File

@@ -134,3 +134,36 @@ void BM_mesh_vert_coords_apply(BMesh *bm, const float (*vert_coords)[3]);
void BM_mesh_vert_coords_apply_with_mat4(BMesh *bm,
const float (*vert_coords)[3],
const float mat[4][4]);
void BM_select_vertices(BMesh *bm, const bool *mask);
void BM_select_edges(BMesh *bm, const bool *mask);
void BM_select_faces(BMesh *bm, const bool *mask);
void BM_tag_vertices(BMesh *bm, const bool *mask);
void BM_tag_edges(BMesh *bm, const bool *mask);
void BM_tag_faces(BMesh *bm, const bool *mask);
void BM_get_selected_vertices(BMesh *bm, bool *selection);
void BM_get_selected_edges(BMesh *bm, bool *selection);
void BM_get_selected_faces(BMesh *bm, bool *selection);
void BM_get_tagged_vertices(BMesh *bm, bool *selection);
void BM_get_tagged_edges(BMesh *bm, bool *selection);
void BM_get_tagged_faces(BMesh *bm, bool *selection);
void BM_untag_vertices_by_tag(BMesh *bm, int tag);
void BM_untag_edges_by_tag(BMesh *bm, int tag);
void BM_untag_faces_by_tag(BMesh *bm, int tag);
void BM_tag_vertices_from_operator_slot(BMesh *bm,
BMOperator *b_mesh_operator,
const char *slot,
const int tag);
void BM_tag_edges_from_operator_slot(BMesh *bm,
BMOperator *b_mesh_operator,
const char *slot,
const int tag);
void BM_tag_faces_from_operator_slot(BMesh *bm,
BMOperator *b_mesh_operator,
const char *slot,
const int tag);

View File

@@ -1898,6 +1898,9 @@ static BMOpDefine bmo_inset_individual_def = {
{{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
{"thickness", BMO_OP_SLOT_FLT}, /* thickness */
{"depth", BMO_OP_SLOT_FLT}, /* depth */
{"thickness_array", BMO_OP_SLOT_PTR}, /* thickness */
{"depth_array", BMO_OP_SLOT_PTR}, /* depth */
{"use_attributes", BMO_OP_SLOT_BOOL}, /* Use spans for thickness and depth */
{"use_even_offset", BMO_OP_SLOT_BOOL}, /* scale the offset to give more even thickness */
{"use_interpolate", BMO_OP_SLOT_BOOL}, /* blend face data across the inset */
{"use_relative_offset", BMO_OP_SLOT_BOOL}, /* scale the offset by surrounding geometry */
@@ -1929,6 +1932,9 @@ static BMOpDefine bmo_inset_region_def = {
{"use_edge_rail", BMO_OP_SLOT_BOOL}, /* inset the region along existing edges */
{"thickness", BMO_OP_SLOT_FLT}, /* thickness */
{"depth", BMO_OP_SLOT_FLT}, /* depth */
{"thickness_array", BMO_OP_SLOT_PTR}, /* thickness */
{"depth_array", BMO_OP_SLOT_PTR}, /* depth */
{"use_attributes", BMO_OP_SLOT_BOOL}, /* Use spans for thickness and depth */
{"use_outset", BMO_OP_SLOT_BOOL}, /* outset rather than inset */
{{'\0'}},
},

View File

@@ -428,6 +428,9 @@ typedef enum {
BMO_DELIM_SEAM = 1 << 2,
BMO_DELIM_SHARP = 1 << 3,
BMO_DELIM_UV = 1 << 4,
BMO_DELIM_EDGE_SELECTION_INVSE = 1 << 5,
BMO_DELIM_EDGE_SELECTION = 1 << 6,
BMO_DELIM_FACE_SELECTION = 1 << 7,
} BMO_Delimit;
void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag);

View File

@@ -419,6 +419,9 @@ void bmo_inset_individual_exec(BMesh *bm, BMOperator *op)
BMOIter oiter;
MemArena *interp_arena = NULL;
const bool use_attributes = BMO_slot_bool_get(op->slots_in, "use_attributes");
const float *thickness_array = BMO_slot_ptr_get(op->slots_in, "thickness_array");
const float *depth_array = BMO_slot_ptr_get(op->slots_in, "depth_array");
const float thickness = BMO_slot_float_get(op->slots_in, "thickness");
const float depth = BMO_slot_float_get(op->slots_in, "depth");
const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
@@ -433,19 +436,37 @@ void bmo_inset_individual_exec(BMesh *bm, BMOperator *op)
if (use_interpolate) {
interp_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
}
int i = 0;
if (use_attributes) {
BMO_ITER_INDEX (f, &oiter, op->slots_in, "faces", BM_FACE, i) {
bmo_face_inset_individual(bm,
f,
interp_arena,
thickness_array[i],
depth_array[i],
use_even_offset,
use_relative_offset,
use_interpolate);
BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
bmo_face_inset_individual(bm,
f,
interp_arena,
thickness,
depth,
use_even_offset,
use_relative_offset,
use_interpolate);
if (use_interpolate) {
BLI_memarena_clear(interp_arena);
}
}
}
else {
BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
bmo_face_inset_individual(bm,
f,
interp_arena,
thickness,
depth,
use_even_offset,
use_relative_offset,
use_interpolate);
if (use_interpolate) {
BLI_memarena_clear(interp_arena);
if (use_interpolate) {
BLI_memarena_clear(interp_arena);
}
}
}
@@ -683,6 +704,9 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
const bool use_edge_rail = BMO_slot_bool_get(op->slots_in, "use_edge_rail");
const bool use_interpolate = BMO_slot_bool_get(op->slots_in, "use_interpolate");
const float thickness = BMO_slot_float_get(op->slots_in, "thickness");
const bool use_attributes = BMO_slot_bool_get(op->slots_in, "use_attributes");
const float *thickness_array = BMO_slot_ptr_get(op->slots_in, "thickness_array");
const float *depth_array = BMO_slot_ptr_get(op->slots_in, "depth_array");
const float depth = BMO_slot_float_get(op->slots_in, "depth");
#ifdef USE_LOOP_CUSTOMDATA_MERGE
const bool has_math_ldata = (use_interpolate && CustomData_has_math(&bm->ldata));
@@ -1096,7 +1120,12 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
}
/* apply the offset */
madd_v3_v3fl(v_split->co, tvec, thickness);
if (use_attributes) {
madd_v3_v3fl(v_split->co, tvec, thickness_array[v_split->head.index]);
}
else {
madd_v3_v3fl(v_split->co, tvec, thickness);
}
}
/* this saves expensive/slow glue check for common cases */

View File

@@ -104,6 +104,22 @@ static bool bm_edge_is_delimiter(const BMEdge *e,
BLI_assert(BM_edge_is_manifold(e));
if (delimit != 0) {
if (delimit & BMO_DELIM_EDGE_SELECTION_INVSE) {
if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
return true;
}
}
if (delimit & BMO_DELIM_EDGE_SELECTION) {
if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
return true;
}
}
if (delimit & BMO_DELIM_FACE_SELECTION) {
if (BM_elem_flag_test(e->l->f, BM_ELEM_TAG) !=
BM_elem_flag_test(e->l->radial_next->f, BM_ELEM_TAG)) {
return true;
}
}
if (delimit & BMO_DELIM_SEAM) {
if (BM_elem_flag_test(e, BM_ELEM_SEAM)) {
return true;

View File

@@ -328,14 +328,10 @@ set(SRC
operations/COM_FastGaussianBlurOperation.h
operations/COM_GammaCorrectOperation.cc
operations/COM_GammaCorrectOperation.h
operations/COM_GaussianAlphaBlurBaseOperation.cc
operations/COM_GaussianAlphaBlurBaseOperation.h
operations/COM_GaussianAlphaXBlurOperation.cc
operations/COM_GaussianAlphaXBlurOperation.h
operations/COM_GaussianAlphaYBlurOperation.cc
operations/COM_GaussianAlphaYBlurOperation.h
operations/COM_GaussianBlurBaseOperation.cc
operations/COM_GaussianBlurBaseOperation.h
operations/COM_GaussianBokehBlurOperation.cc
operations/COM_GaussianBokehBlurOperation.h
operations/COM_GaussianXBlurOperation.cc
@@ -519,8 +515,6 @@ set(SRC
operations/COM_ScaleOperation.h
operations/COM_ScreenLensDistortionOperation.cc
operations/COM_ScreenLensDistortionOperation.h
operations/COM_TransformOperation.cc
operations/COM_TransformOperation.h
operations/COM_TranslateOperation.cc
operations/COM_TranslateOperation.h
operations/COM_WrapOperation.cc

View File

@@ -33,8 +33,6 @@ enum class eExecutionModel {
FullFrame
};
enum class eDimension { X, Y };
/**
* \brief possible data types for sockets
* \ingroup Model
@@ -121,8 +119,6 @@ constexpr float COM_PREVIEW_SIZE = 140.f;
constexpr float COM_RULE_OF_THIRDS_DIVIDER = 100.0f;
constexpr float COM_BLUR_BOKEH_PIXELS = 512;
constexpr rcti COM_SINGLE_ELEM_AREA = {0, 1, 0, 1};
constexpr IndexRange XRange(const rcti &area)
{
return IndexRange(area.xmin, area.xmax - area.xmin);

View File

@@ -239,12 +239,6 @@ class CompositorContext {
this->m_hasActiveOpenCLDevices = hasAvtiveOpenCLDevices;
}
/** Whether it has a view with a specific name and not the default one. */
bool has_explicit_view() const
{
return m_viewName && m_viewName[0] != '\0';
}
/**
* \brief get the active rendering view
*/

View File

@@ -245,9 +245,7 @@ void MemoryBuffer::copy_from(const MemoryBuffer *src,
void MemoryBuffer::copy_from(const uchar *src, const rcti &area)
{
const int elem_stride = this->get_num_channels();
const int row_stride = elem_stride * getWidth();
copy_from(src, area, 0, this->get_num_channels(), elem_stride, row_stride, 0);
copy_from(src, area, 0, this->get_num_channels(), this->get_num_channels(), 0);
}
void MemoryBuffer::copy_from(const uchar *src,
@@ -255,18 +253,10 @@ void MemoryBuffer::copy_from(const uchar *src,
const int channel_offset,
const int elem_size,
const int elem_stride,
const int row_stride,
const int to_channel_offset)
{
copy_from(src,
area,
channel_offset,
elem_size,
elem_stride,
row_stride,
area.xmin,
area.ymin,
to_channel_offset);
copy_from(
src, area, channel_offset, elem_size, elem_stride, area.xmin, area.ymin, to_channel_offset);
}
void MemoryBuffer::copy_from(const uchar *src,
@@ -274,7 +264,6 @@ void MemoryBuffer::copy_from(const uchar *src,
const int channel_offset,
const int elem_size,
const int elem_stride,
const int row_stride,
const int to_x,
const int to_y,
const int to_channel_offset)
@@ -284,9 +273,10 @@ void MemoryBuffer::copy_from(const uchar *src,
const int width = BLI_rcti_size_x(&area);
const int height = BLI_rcti_size_y(&area);
const uchar *const src_start = src + area.ymin * row_stride + channel_offset;
const int src_row_stride = width * elem_stride;
const uchar *const src_start = src + area.ymin * src_row_stride + channel_offset;
for (int y = 0; y < height; y++) {
const uchar *from_elem = src_start + y * row_stride + area.xmin * elem_stride;
const uchar *from_elem = src_start + y * src_row_stride;
float *to_elem = &this->get_value(to_x, to_y + y, to_channel_offset);
const float *row_end = to_elem + width * this->elem_stride;
while (to_elem < row_end) {
@@ -356,16 +346,7 @@ void MemoryBuffer::copy_from(const ImBuf *src,
else if (src->rect) {
const uchar *uc_buf = (uchar *)src->rect;
const int elem_stride = src->channels;
const int row_stride = elem_stride * src->x;
copy_from(uc_buf,
area,
channel_offset,
elem_size,
elem_stride,
row_stride,
to_x,
to_y,
to_channel_offset);
copy_from(uc_buf, area, channel_offset, elem_size, elem_stride, to_x, to_y, to_channel_offset);
if (ensure_linear_space) {
colorspace_to_scene_linear(this, area, src->rect_colorspace);
}
@@ -424,48 +405,12 @@ void MemoryBuffer::addPixel(int x, int y, const float color[4])
}
}
static void read_ewa_elem(void *userdata, int x, int y, float result[4])
{
const MemoryBuffer *buffer = static_cast<const MemoryBuffer *>(userdata);
buffer->read_elem_checked(x, y, result);
}
void MemoryBuffer::read_elem_filtered(
const float x, const float y, float dx[2], float dy[2], float *out) const
{
BLI_assert(this->m_datatype == DataType::Color);
const float deriv[2][2] = {{dx[0], dx[1]}, {dy[0], dy[1]}};
float inv_width = 1.0f / (float)this->getWidth(), inv_height = 1.0f / (float)this->getHeight();
/* TODO(sergey): Render pipeline uses normalized coordinates and derivatives,
* but compositor uses pixel space. For now let's just divide the values and
* switch compositor to normalized space for EWA later.
*/
float uv_normal[2] = {get_relative_x(x) * inv_width, get_relative_y(y) * inv_height};
float du_normal[2] = {deriv[0][0] * inv_width, deriv[0][1] * inv_height};
float dv_normal[2] = {deriv[1][0] * inv_width, deriv[1][1] * inv_height};
BLI_ewa_filter(this->getWidth(),
this->getHeight(),
false,
true,
uv_normal,
du_normal,
dv_normal,
read_ewa_elem,
const_cast<MemoryBuffer *>(this),
out);
}
/* TODO(manzanilla): to be removed with tiled implementation. */
static void read_ewa_pixel_sampled(void *userdata, int x, int y, float result[4])
{
MemoryBuffer *buffer = (MemoryBuffer *)userdata;
buffer->read(result, x, y);
}
/* TODO(manzanilla): to be removed with tiled implementation. */
void MemoryBuffer::readEWA(float *result, const float uv[2], const float derivatives[2][2])
{
if (m_is_a_single_elem) {

View File

@@ -191,96 +191,23 @@ class MemoryBuffer {
void read_elem(int x, int y, float *out) const
{
memcpy(out, get_elem(x, y), get_elem_bytes_len());
}
void read_elem_checked(int x, int y, float *out) const
{
if (x < m_rect.xmin || x >= m_rect.xmax || y < m_rect.ymin || y >= m_rect.ymax) {
clear_elem(out);
}
else {
read_elem(x, y, out);
}
}
void read_elem_checked(float x, float y, float *out) const
{
if (x < m_rect.xmin || x >= m_rect.xmax || y < m_rect.ymin || y >= m_rect.ymax) {
clear_elem(out);
}
else {
read_elem(x, y, out);
}
}
void read_elem_bilinear(float x, float y, float *out) const
{
/* Only clear past +/-1 borders to be able to smooth edges. */
if (x <= m_rect.xmin - 1.0f || x >= m_rect.xmax || y <= m_rect.ymin - 1.0f ||
y >= m_rect.ymax) {
clear_elem(out);
return;
}
if (m_is_a_single_elem) {
if (x >= m_rect.xmin && x < m_rect.xmax - 1.0f && y >= m_rect.ymin &&
y < m_rect.ymax - 1.0f) {
memcpy(out, m_buffer, get_elem_bytes_len());
return;
}
/* Do sampling at borders to smooth edges. */
const float last_x = getWidth() - 1.0f;
const float rel_x = get_relative_x(x);
float single_x = 0.0f;
if (rel_x < 0.0f) {
single_x = rel_x;
}
else if (rel_x > last_x) {
single_x = rel_x - last_x;
}
const float last_y = getHeight() - 1.0f;
const float rel_y = get_relative_y(y);
float single_y = 0.0f;
if (rel_y < 0.0f) {
single_y = rel_y;
}
else if (rel_y > last_y) {
single_y = rel_y - last_y;
}
BLI_bilinear_interpolation_fl(m_buffer, out, 1, 1, m_num_channels, single_x, single_y);
return;
}
BLI_bilinear_interpolation_fl(m_buffer,
out,
getWidth(),
getHeight(),
m_num_channels,
get_relative_x(x),
get_relative_y(y));
memcpy(out, get_elem(x, y), m_num_channels * sizeof(float));
}
void read_elem_sampled(float x, float y, PixelSampler sampler, float *out) const
{
switch (sampler) {
case PixelSampler::Nearest:
read_elem_checked(x, y, out);
this->read_elem(x, y, out);
break;
case PixelSampler::Bilinear:
case PixelSampler::Bicubic:
/* No bicubic. Current implementation produces fuzzy results. */
read_elem_bilinear(x, y, out);
this->readBilinear(out, x, y);
break;
}
}
void read_elem_filtered(
const float x, const float y, float dx[2], float dy[2], float *out) const;
/**
* Get channel value at given coordinates.
*/
@@ -476,8 +403,6 @@ class MemoryBuffer {
y = y + m_rect.ymin;
}
/* TODO(manzanilla): to be removed with tiled implementation. For applying #MemoryBufferExtend
* use #wrap_pixel. */
inline void read(float *result,
int x,
int y,
@@ -500,7 +425,6 @@ class MemoryBuffer {
}
}
/* TODO(manzanilla): to be removed with tiled implementation. */
inline void readNoCheck(float *result,
int x,
int y,
@@ -583,14 +507,12 @@ class MemoryBuffer {
int channel_offset,
int elem_size,
int elem_stride,
int row_stride,
int to_channel_offset);
void copy_from(const uchar *src,
const rcti &area,
int channel_offset,
int elem_size,
int elem_stride,
int row_stride,
int to_x,
int to_y,
int to_channel_offset);
@@ -660,21 +582,6 @@ class MemoryBuffer {
return get_memory_width() * get_memory_height();
}
void clear_elem(float *out) const
{
memset(out, 0, this->m_num_channels * sizeof(float));
}
template<typename T> T get_relative_x(T x) const
{
return x - m_rect.xmin;
}
template<typename T> T get_relative_y(T y) const
{
return y - m_rect.ymin;
}
void copy_single_elem_from(const MemoryBuffer *src,
int channel_offset,
int elem_size,

View File

@@ -248,9 +248,7 @@ void NodeGraph::add_proxies_group_inputs(bNode *b_node, bNode *b_node_io)
}
}
void NodeGraph::add_proxies_group_outputs(const CompositorContext &context,
bNode *b_node,
bNode *b_node_io)
void NodeGraph::add_proxies_group_outputs(bNode *b_node, bNode *b_node_io, bool use_buffer)
{
bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
BLI_assert(b_group_tree); /* should have been checked in advance */
@@ -263,8 +261,7 @@ void NodeGraph::add_proxies_group_outputs(const CompositorContext &context,
b_sock_io = b_sock_io->next) {
bNodeSocket *b_sock_group = find_b_node_output(b_node, b_sock_io->identifier);
if (b_sock_group) {
if (context.isGroupnodeBufferEnabled() &&
context.get_execution_model() == eExecutionModel::Tiled) {
if (use_buffer) {
SocketBufferNode *buffer = new SocketBufferNode(b_node_io, b_sock_io, b_sock_group);
add_node(buffer, b_group_tree, key, is_active_group);
}
@@ -300,7 +297,7 @@ void NodeGraph::add_proxies_group(const CompositorContext &context,
}
if (b_node_io->type == NODE_GROUP_OUTPUT && (b_node_io->flag & NODE_DO_OUTPUT)) {
add_proxies_group_outputs(context, b_node, b_node_io);
add_proxies_group_outputs(b_node, b_node_io, context.isGroupnodeBufferEnabled());
}
}

View File

@@ -107,9 +107,7 @@ class NodeGraph {
bool is_active_group);
void add_proxies_group_inputs(bNode *b_node, bNode *b_node_io);
void add_proxies_group_outputs(const CompositorContext &context,
bNode *b_node,
bNode *b_node_io);
void add_proxies_group_outputs(bNode *b_node, bNode *b_node_io, bool use_buffer);
void add_proxies_group(const CompositorContext &context, bNode *b_node, bNodeInstanceKey key);
void add_proxies_reroute(bNodeTree *b_ntree,

View File

@@ -82,12 +82,8 @@ void NodeOperation::determineResolution(unsigned int resolution[2],
input.determineResolution(resolution, preferredResolution);
used_resolution_index = m_resolutionInputSocketIndex;
}
if (modify_determined_resolution_fn_) {
modify_determined_resolution_fn_(resolution);
}
unsigned int temp2[2] = {resolution[0], resolution[1]};
unsigned int temp[2];
for (unsigned int index = 0; index < m_inputs.size(); index++) {
if (index == used_resolution_index) {

View File

@@ -287,8 +287,6 @@ class NodeOperation {
*/
unsigned int m_resolutionInputSocketIndex;
std::function<void(unsigned int resolution[2])> modify_determined_resolution_fn_;
/**
* \brief mutex reference for very special node initializations
* \note only use when you really know what you are doing.
@@ -519,15 +517,6 @@ class NodeOperation {
*/
void setResolutionInputSocketIndex(unsigned int index);
/**
* Set a custom function to modify determined resolution from main input just before setting it
* as preferred resolution for the other inputs.
*/
void set_determined_resolution_modifier(std::function<void(unsigned int resolution[2])> fn)
{
modify_determined_resolution_fn_ = fn;
}
/**
* \brief get the render priority of this node.
* \note only applicable for output operations like ViewerOperation

View File

@@ -124,10 +124,6 @@ void CryptomatteNode::input_operations_from_render_source(
RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name);
if (render_layer) {
LISTBASE_FOREACH (RenderPass *, render_pass, &render_layer->passes) {
if (context.has_explicit_view() && !STREQ(render_pass->view, context.getViewName())) {
continue;
}
const std::string combined_name = combined_layer_pass_name(render_layer, render_pass);
if (blender::StringRef(combined_name).startswith(prefix)) {
RenderLayersProg *op = new RenderLayersProg(

View File

@@ -30,31 +30,20 @@ RotateNode::RotateNode(bNode *editorNode) : Node(editorNode)
}
void RotateNode::convertToOperations(NodeConverter &converter,
const CompositorContext &context) const
const CompositorContext & /*context*/) const
{
NodeInput *inputSocket = this->getInputSocket(0);
NodeInput *inputDegreeSocket = this->getInputSocket(1);
NodeOutput *outputSocket = this->getOutputSocket(0);
RotateOperation *operation = new RotateOperation();
SetSamplerOperation *sampler = new SetSamplerOperation();
sampler->setSampler((PixelSampler)this->getbNode()->custom1);
converter.addOperation(sampler);
converter.addOperation(operation);
PixelSampler sampler = (PixelSampler)this->getbNode()->custom1;
switch (context.get_execution_model()) {
case eExecutionModel::Tiled: {
SetSamplerOperation *sampler_op = new SetSamplerOperation();
sampler_op->setSampler(sampler);
converter.addOperation(sampler_op);
converter.addLink(sampler_op->getOutputSocket(), operation->getInputSocket(0));
converter.mapInputSocket(inputSocket, sampler_op->getInputSocket(0));
break;
}
case eExecutionModel::FullFrame: {
operation->set_sampler(sampler);
converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
break;
}
}
converter.addLink(sampler->getOutputSocket(), operation->getInputSocket(0));
converter.mapInputSocket(inputSocket, sampler->getInputSocket(0));
converter.mapInputSocket(inputDegreeSocket, operation->getInputSocket(1));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
}

View File

@@ -22,7 +22,6 @@
#include "COM_RotateOperation.h"
#include "COM_ScaleOperation.h"
#include "COM_SetSamplerOperation.h"
#include "COM_TransformOperation.h"
#include "COM_TranslateOperation.h"
#include "BKE_tracking.h"
@@ -43,12 +42,18 @@ void Stabilize2dNode::convertToOperations(NodeConverter &converter,
NodeInput *imageInput = this->getInputSocket(0);
MovieClip *clip = (MovieClip *)editorNode->id;
bool invert = (editorNode->custom2 & CMP_NODEFLAG_STABILIZE_INVERSE) != 0;
const PixelSampler sampler = (PixelSampler)editorNode->custom1;
ScaleRelativeOperation *scaleOperation = new ScaleRelativeOperation();
scaleOperation->setSampler((PixelSampler)editorNode->custom1);
RotateOperation *rotateOperation = new RotateOperation();
rotateOperation->setDoDegree2RadConversion(false);
TranslateOperation *translateOperation = new TranslateOperation();
MovieClipAttributeOperation *scaleAttribute = new MovieClipAttributeOperation();
MovieClipAttributeOperation *angleAttribute = new MovieClipAttributeOperation();
MovieClipAttributeOperation *xAttribute = new MovieClipAttributeOperation();
MovieClipAttributeOperation *yAttribute = new MovieClipAttributeOperation();
SetSamplerOperation *psoperation = new SetSamplerOperation();
psoperation->setSampler((PixelSampler)editorNode->custom1);
scaleAttribute->setAttribute(MCA_SCALE);
scaleAttribute->setFramenumber(context.getFramenumber());
@@ -74,67 +79,38 @@ void Stabilize2dNode::convertToOperations(NodeConverter &converter,
converter.addOperation(angleAttribute);
converter.addOperation(xAttribute);
converter.addOperation(yAttribute);
converter.addOperation(scaleOperation);
converter.addOperation(translateOperation);
converter.addOperation(rotateOperation);
converter.addOperation(psoperation);
switch (context.get_execution_model()) {
case eExecutionModel::Tiled: {
ScaleRelativeOperation *scaleOperation = new ScaleRelativeOperation();
scaleOperation->setSampler(sampler);
RotateOperation *rotateOperation = new RotateOperation();
rotateOperation->setDoDegree2RadConversion(false);
TranslateOperation *translateOperation = new TranslateOperation();
SetSamplerOperation *psoperation = new SetSamplerOperation();
psoperation->setSampler(sampler);
converter.addLink(scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(1));
converter.addLink(scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(2));
converter.addOperation(scaleOperation);
converter.addOperation(translateOperation);
converter.addOperation(rotateOperation);
converter.addOperation(psoperation);
converter.addLink(angleAttribute->getOutputSocket(), rotateOperation->getInputSocket(1));
converter.addLink(scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(1));
converter.addLink(scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(2));
converter.addLink(xAttribute->getOutputSocket(), translateOperation->getInputSocket(1));
converter.addLink(yAttribute->getOutputSocket(), translateOperation->getInputSocket(2));
converter.addLink(angleAttribute->getOutputSocket(), rotateOperation->getInputSocket(1));
converter.mapOutputSocket(getOutputSocket(), psoperation->getOutputSocket());
converter.addLink(xAttribute->getOutputSocket(), translateOperation->getInputSocket(1));
converter.addLink(yAttribute->getOutputSocket(), translateOperation->getInputSocket(2));
if (invert) {
// Translate -> Rotate -> Scale.
converter.mapInputSocket(imageInput, translateOperation->getInputSocket(0));
converter.mapOutputSocket(getOutputSocket(), psoperation->getOutputSocket());
converter.addLink(translateOperation->getOutputSocket(), rotateOperation->getInputSocket(0));
converter.addLink(rotateOperation->getOutputSocket(), scaleOperation->getInputSocket(0));
if (invert) {
// Translate -> Rotate -> Scale.
converter.mapInputSocket(imageInput, translateOperation->getInputSocket(0));
converter.addLink(scaleOperation->getOutputSocket(), psoperation->getInputSocket(0));
}
else {
// Scale -> Rotate -> Translate.
converter.mapInputSocket(imageInput, scaleOperation->getInputSocket(0));
converter.addLink(translateOperation->getOutputSocket(),
rotateOperation->getInputSocket(0));
converter.addLink(rotateOperation->getOutputSocket(), scaleOperation->getInputSocket(0));
converter.addLink(scaleOperation->getOutputSocket(), rotateOperation->getInputSocket(0));
converter.addLink(rotateOperation->getOutputSocket(), translateOperation->getInputSocket(0));
converter.addLink(scaleOperation->getOutputSocket(), psoperation->getInputSocket(0));
}
else {
// Scale -> Rotate -> Translate.
converter.mapInputSocket(imageInput, scaleOperation->getInputSocket(0));
converter.addLink(scaleOperation->getOutputSocket(), rotateOperation->getInputSocket(0));
converter.addLink(rotateOperation->getOutputSocket(),
translateOperation->getInputSocket(0));
converter.addLink(translateOperation->getOutputSocket(), psoperation->getInputSocket(0));
}
break;
}
case eExecutionModel::FullFrame: {
TransformOperation *transform_op = new TransformOperation();
transform_op->set_sampler(sampler);
transform_op->set_convert_rotate_degree_to_rad(false);
transform_op->set_invert(invert);
converter.addOperation(transform_op);
converter.mapInputSocket(imageInput, transform_op->getInputSocket(0));
converter.addLink(xAttribute->getOutputSocket(), transform_op->getInputSocket(1));
converter.addLink(yAttribute->getOutputSocket(), transform_op->getInputSocket(2));
converter.addLink(angleAttribute->getOutputSocket(), transform_op->getInputSocket(3));
converter.addLink(scaleAttribute->getOutputSocket(), transform_op->getInputSocket(4));
converter.mapOutputSocket(getOutputSocket(), transform_op->getOutputSocket());
}
converter.addLink(translateOperation->getOutputSocket(), psoperation->getInputSocket(0));
}
}

View File

@@ -22,7 +22,6 @@
#include "COM_ScaleOperation.h"
#include "COM_SetSamplerOperation.h"
#include "COM_SetValueOperation.h"
#include "COM_TransformOperation.h"
#include "COM_TranslateOperation.h"
namespace blender::compositor {
@@ -33,7 +32,7 @@ TransformNode::TransformNode(bNode *editorNode) : Node(editorNode)
}
void TransformNode::convertToOperations(NodeConverter &converter,
const CompositorContext &context) const
const CompositorContext & /*context*/) const
{
NodeInput *imageInput = this->getInputSocket(0);
NodeInput *xInput = this->getInputSocket(1);
@@ -41,51 +40,33 @@ void TransformNode::convertToOperations(NodeConverter &converter,
NodeInput *angleInput = this->getInputSocket(3);
NodeInput *scaleInput = this->getInputSocket(4);
switch (context.get_execution_model()) {
case eExecutionModel::Tiled: {
ScaleRelativeOperation *scaleOperation = new ScaleRelativeOperation();
converter.addOperation(scaleOperation);
ScaleRelativeOperation *scaleOperation = new ScaleRelativeOperation();
converter.addOperation(scaleOperation);
RotateOperation *rotateOperation = new RotateOperation();
rotateOperation->setDoDegree2RadConversion(false);
converter.addOperation(rotateOperation);
RotateOperation *rotateOperation = new RotateOperation();
rotateOperation->setDoDegree2RadConversion(false);
converter.addOperation(rotateOperation);
TranslateOperation *translateOperation = new TranslateOperation();
converter.addOperation(translateOperation);
TranslateOperation *translateOperation = new TranslateOperation();
converter.addOperation(translateOperation);
SetSamplerOperation *sampler = new SetSamplerOperation();
sampler->setSampler((PixelSampler)this->getbNode()->custom1);
converter.addOperation(sampler);
SetSamplerOperation *sampler = new SetSamplerOperation();
sampler->setSampler((PixelSampler)this->getbNode()->custom1);
converter.addOperation(sampler);
converter.mapInputSocket(imageInput, sampler->getInputSocket(0));
converter.addLink(sampler->getOutputSocket(), scaleOperation->getInputSocket(0));
converter.mapInputSocket(scaleInput, scaleOperation->getInputSocket(1));
converter.mapInputSocket(scaleInput, scaleOperation->getInputSocket(2)); // xscale = yscale
converter.mapInputSocket(imageInput, sampler->getInputSocket(0));
converter.addLink(sampler->getOutputSocket(), scaleOperation->getInputSocket(0));
converter.mapInputSocket(scaleInput, scaleOperation->getInputSocket(1));
converter.mapInputSocket(scaleInput, scaleOperation->getInputSocket(2)); // xscale = yscale
converter.addLink(scaleOperation->getOutputSocket(), rotateOperation->getInputSocket(0));
converter.mapInputSocket(angleInput, rotateOperation->getInputSocket(1));
converter.addLink(scaleOperation->getOutputSocket(), rotateOperation->getInputSocket(0));
converter.mapInputSocket(angleInput, rotateOperation->getInputSocket(1));
converter.addLink(rotateOperation->getOutputSocket(), translateOperation->getInputSocket(0));
converter.mapInputSocket(xInput, translateOperation->getInputSocket(1));
converter.mapInputSocket(yInput, translateOperation->getInputSocket(2));
converter.addLink(rotateOperation->getOutputSocket(), translateOperation->getInputSocket(0));
converter.mapInputSocket(xInput, translateOperation->getInputSocket(1));
converter.mapInputSocket(yInput, translateOperation->getInputSocket(2));
converter.mapOutputSocket(getOutputSocket(), translateOperation->getOutputSocket());
break;
}
case eExecutionModel::FullFrame: {
TransformOperation *op = new TransformOperation();
op->set_sampler((PixelSampler)this->getbNode()->custom1);
converter.addOperation(op);
converter.mapInputSocket(imageInput, op->getInputSocket(0));
converter.mapInputSocket(xInput, op->getInputSocket(1));
converter.mapInputSocket(yInput, op->getInputSocket(2));
converter.mapInputSocket(angleInput, op->getInputSocket(3));
converter.mapInputSocket(scaleInput, op->getInputSocket(4));
converter.mapOutputSocket(getOutputSocket(), op->getOutputSocket());
break;
}
}
converter.mapOutputSocket(getOutputSocket(), translateOperation->getOutputSocket());
}
} // namespace blender::compositor

View File

@@ -17,8 +17,6 @@
*/
#include "COM_BlurBaseOperation.h"
#include "COM_ConstantOperation.h"
#include "BLI_math.h"
#include "MEM_guardedalloc.h"
@@ -38,15 +36,11 @@ BlurBaseOperation::BlurBaseOperation(DataType data_type)
this->m_size = 1.0f;
this->m_sizeavailable = false;
this->m_extend_bounds = false;
use_variable_size_ = false;
}
void BlurBaseOperation::init_data()
void BlurBaseOperation::initExecution()
{
if (execution_model_ == eExecutionModel::FullFrame) {
updateSize();
}
this->m_inputProgram = this->getInputSocketReader(0);
this->m_inputSize = this->getInputSocketReader(1);
this->m_data.image_in_width = this->getWidth();
this->m_data.image_in_height = this->getHeight();
if (this->m_data.relative) {
@@ -67,12 +61,6 @@ void BlurBaseOperation::init_data()
this->m_data.sizex = round_fl_to_int(this->m_data.percentx * 0.01f * sizex);
this->m_data.sizey = round_fl_to_int(this->m_data.percenty * 0.01f * sizey);
}
}
void BlurBaseOperation::initExecution()
{
this->m_inputProgram = this->getInputSocketReader(0);
this->m_inputSize = this->getInputSocketReader(1);
QualityStepHelper::initExecution(COM_QH_MULTIPLY);
}
@@ -177,82 +165,23 @@ void BlurBaseOperation::setData(const NodeBlurData *data)
memcpy(&m_data, data, sizeof(NodeBlurData));
}
int BlurBaseOperation::get_blur_size(eDimension dim) const
{
switch (dim) {
case eDimension::X:
return m_data.sizex;
case eDimension::Y:
return m_data.sizey;
}
return -1;
}
void BlurBaseOperation::updateSize()
{
if (this->m_sizeavailable || use_variable_size_) {
return;
if (!this->m_sizeavailable) {
float result[4];
this->getInputSocketReader(1)->readSampled(result, 0, 0, PixelSampler::Nearest);
this->m_size = result[0];
this->m_sizeavailable = true;
}
switch (execution_model_) {
case eExecutionModel::Tiled: {
float result[4];
this->getInputSocketReader(1)->readSampled(result, 0, 0, PixelSampler::Nearest);
this->m_size = result[0];
break;
}
case eExecutionModel::FullFrame: {
NodeOperation *size_input = get_input_operation(SIZE_INPUT_INDEX);
if (size_input->get_flags().is_constant_operation) {
m_size = *static_cast<ConstantOperation *>(size_input)->get_constant_elem();
} /* Else use default. */
break;
}
}
this->m_sizeavailable = true;
}
void BlurBaseOperation::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
{
if (!m_extend_bounds) {
NodeOperation::determineResolution(resolution, preferredResolution);
return;
}
switch (execution_model_) {
case eExecutionModel::Tiled: {
NodeOperation::determineResolution(resolution, preferredResolution);
resolution[0] += 2 * m_size * m_data.sizex;
resolution[1] += 2 * m_size * m_data.sizey;
break;
}
case eExecutionModel::FullFrame: {
/* Setting a modifier ensures all non main inputs have extended bounds as preferred
* resolution, avoiding unnecessary resolution convertions that would hide constant
* operations. */
set_determined_resolution_modifier([=](unsigned int res[2]) {
/* Rounding to even prevents jiggling in backdrop while switching size values. */
res[0] += round_to_even(2 * m_size * m_data.sizex);
res[1] += round_to_even(2 * m_size * m_data.sizey);
});
NodeOperation::determineResolution(resolution, preferredResolution);
break;
}
}
}
void BlurBaseOperation::get_area_of_interest(const int input_idx,
const rcti &output_area,
rcti &r_input_area)
{
switch (input_idx) {
case 0:
r_input_area = output_area;
break;
case 1:
r_input_area = use_variable_size_ ? output_area : COM_SINGLE_ELEM_AREA;
break;
NodeOperation::determineResolution(resolution, preferredResolution);
if (this->m_extend_bounds) {
resolution[0] += 2 * this->m_size * m_data.sizex;
resolution[1] += 2 * this->m_size * m_data.sizey;
}
}

View File

@@ -18,7 +18,7 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
#include "COM_QualityStepHelper.h"
#define MAX_GAUSSTAB_RADIUS 30000
@@ -27,16 +27,10 @@
namespace blender::compositor {
class BlurBaseOperation : public MultiThreadedOperation, public QualityStepHelper {
class BlurBaseOperation : public NodeOperation, public QualityStepHelper {
private:
bool m_extend_bounds;
protected:
static constexpr int IMAGE_INPUT_INDEX = 0;
static constexpr int SIZE_INPUT_INDEX = 1;
protected:
BlurBaseOperation(DataType data_type8);
BlurBaseOperation(DataType data_type);
float *make_gausstab(float rad, int size);
#ifdef BLI_HAVE_SSE2
__m128 *convert_gausstab_sse(const float *gausstab, int size);
@@ -55,11 +49,9 @@ class BlurBaseOperation : public MultiThreadedOperation, public QualityStepHelpe
float m_size;
bool m_sizeavailable;
/* Flags for inheriting classes. */
bool use_variable_size_;
bool m_extend_bounds;
public:
virtual void init_data() override;
/**
* Initialize the execution
*/
@@ -83,14 +75,8 @@ class BlurBaseOperation : public MultiThreadedOperation, public QualityStepHelpe
this->m_extend_bounds = extend_bounds;
}
int get_blur_size(eDimension dim) const;
void determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2]) override;
virtual void get_area_of_interest(int input_idx,
const rcti &output_area,
rcti &r_input_area) override;
};
} // namespace blender::compositor

View File

@@ -17,8 +17,6 @@
*/
#include "COM_BokehBlurOperation.h"
#include "COM_ConstantOperation.h"
#include "BLI_math.h"
#include "COM_OpenCLDevice.h"
@@ -26,11 +24,6 @@
namespace blender::compositor {
constexpr int IMAGE_INPUT_INDEX = 0;
constexpr int BOKEH_INPUT_INDEX = 1;
constexpr int BOUNDING_BOX_INPUT_INDEX = 2;
constexpr int SIZE_INPUT_INDEX = 3;
BokehBlurOperation::BokehBlurOperation()
{
this->addInputSocket(DataType::Color);
@@ -51,23 +44,6 @@ BokehBlurOperation::BokehBlurOperation()
this->m_extend_bounds = false;
}
void BokehBlurOperation::init_data()
{
if (execution_model_ == eExecutionModel::FullFrame) {
updateSize();
}
NodeOperation *bokeh = get_input_operation(BOKEH_INPUT_INDEX);
const int width = bokeh->getWidth();
const int height = bokeh->getHeight();
const float dimension = MIN2(width, height);
m_bokehMidX = width / 2.0f;
m_bokehMidY = height / 2.0f;
m_bokehDimension = dimension / 2.0f;
}
void *BokehBlurOperation::initializeTileData(rcti * /*rect*/)
{
lockMutex();
@@ -82,11 +58,18 @@ void *BokehBlurOperation::initializeTileData(rcti * /*rect*/)
void BokehBlurOperation::initExecution()
{
initMutex();
this->m_inputProgram = getInputSocketReader(0);
this->m_inputBokehProgram = getInputSocketReader(1);
this->m_inputBoundingBoxReader = getInputSocketReader(2);
int width = this->m_inputBokehProgram->getWidth();
int height = this->m_inputBokehProgram->getHeight();
float dimension = MIN2(width, height);
this->m_bokehMidX = width / 2.0f;
this->m_bokehMidY = height / 2.0f;
this->m_bokehDimension = dimension / 2.0f;
QualityStepHelper::initExecution(COM_QH_INCREASE);
}
@@ -242,146 +225,23 @@ void BokehBlurOperation::executeOpenCL(OpenCLDevice *device,
void BokehBlurOperation::updateSize()
{
if (this->m_sizeavailable) {
return;
if (!this->m_sizeavailable) {
float result[4];
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;
}
switch (execution_model_) {
case eExecutionModel::Tiled: {
float result[4];
this->getInputSocketReader(3)->readSampled(result, 0, 0, PixelSampler::Nearest);
this->m_size = result[0];
CLAMP(this->m_size, 0.0f, 10.0f);
break;
}
case eExecutionModel::FullFrame: {
NodeOperation *size_input = get_input_operation(SIZE_INPUT_INDEX);
if (size_input->get_flags().is_constant_operation) {
m_size = *static_cast<ConstantOperation *>(size_input)->get_constant_elem();
CLAMP(m_size, 0.0f, 10.0f);
} /* Else use default. */
break;
}
}
this->m_sizeavailable = true;
}
void BokehBlurOperation::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
{
if (!m_extend_bounds) {
NodeOperation::determineResolution(resolution, preferredResolution);
return;
}
switch (execution_model_) {
case eExecutionModel::Tiled: {
NodeOperation::determineResolution(resolution, preferredResolution);
const float max_dim = MAX2(resolution[0], resolution[1]);
resolution[0] += 2 * this->m_size * max_dim / 100.0f;
resolution[1] += 2 * this->m_size * max_dim / 100.0f;
break;
}
case eExecutionModel::FullFrame: {
set_determined_resolution_modifier([=](unsigned int res[2]) {
const float max_dim = MAX2(res[0], res[1]);
/* Rounding to even prevents image jiggling in backdrop while switching size values. */
float add_size = round_to_even(2 * this->m_size * max_dim / 100.0f);
res[0] += add_size;
res[1] += add_size;
});
NodeOperation::determineResolution(resolution, preferredResolution);
break;
}
}
}
void BokehBlurOperation::get_area_of_interest(const int input_idx,
const rcti &output_area,
rcti &r_input_area)
{
switch (input_idx) {
case IMAGE_INPUT_INDEX: {
const float max_dim = MAX2(this->getWidth(), this->getHeight());
const float add_size = m_size * max_dim / 100.0f;
r_input_area.xmin = output_area.xmin - add_size;
r_input_area.xmax = output_area.xmax + add_size;
r_input_area.ymin = output_area.ymin - add_size;
r_input_area.ymax = output_area.ymax + add_size;
break;
}
case BOKEH_INPUT_INDEX: {
NodeOperation *bokeh_input = getInputOperation(BOKEH_INPUT_INDEX);
r_input_area.xmin = 0;
r_input_area.xmax = bokeh_input->getWidth();
r_input_area.ymin = 0;
r_input_area.ymax = bokeh_input->getHeight();
break;
}
case BOUNDING_BOX_INPUT_INDEX:
r_input_area = output_area;
break;
case SIZE_INPUT_INDEX: {
r_input_area = COM_SINGLE_ELEM_AREA;
break;
}
}
}
void BokehBlurOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
const float max_dim = MAX2(this->getWidth(), this->getHeight());
const int pixel_size = m_size * max_dim / 100.0f;
const float m = m_bokehDimension / pixel_size;
const MemoryBuffer *image_input = inputs[IMAGE_INPUT_INDEX];
const MemoryBuffer *bokeh_input = inputs[BOKEH_INPUT_INDEX];
MemoryBuffer *bounding_input = inputs[BOUNDING_BOX_INPUT_INDEX];
BuffersIterator<float> it = output->iterate_with({bounding_input}, area);
const rcti &image_rect = image_input->get_rect();
for (; !it.is_end(); ++it) {
const int x = it.x;
const int y = it.y;
const float bounding_box = *it.in(0);
if (bounding_box <= 0.0f) {
image_input->read_elem(x, y, it.out);
continue;
}
float color_accum[4] = {0};
float multiplier_accum[4] = {0};
if (pixel_size < 2) {
image_input->read_elem(x, y, color_accum);
multiplier_accum[0] = 1.0f;
multiplier_accum[1] = 1.0f;
multiplier_accum[2] = 1.0f;
multiplier_accum[3] = 1.0f;
}
const int miny = MAX2(y - pixel_size, image_rect.ymin);
const int maxy = MIN2(y + pixel_size, image_rect.ymax);
const int minx = MAX2(x - pixel_size, image_rect.xmin);
const int maxx = MIN2(x + pixel_size, image_rect.xmax);
const int step = getStep();
const int elem_stride = image_input->elem_stride * step;
const int row_stride = image_input->row_stride * step;
const float *row_color = image_input->get_elem(minx, miny);
for (int ny = miny; ny < maxy; ny += step, row_color += row_stride) {
const float *color = row_color;
const float v = m_bokehMidY - (ny - y) * m;
for (int nx = minx; nx < maxx; nx += step, color += elem_stride) {
const float u = m_bokehMidX - (nx - x) * m;
float bokeh[4];
bokeh_input->read_elem_checked(u, v, bokeh);
madd_v4_v4v4(color_accum, bokeh, color);
add_v4_v4(multiplier_accum, bokeh);
}
}
it.out[0] = color_accum[0] * (1.0f / multiplier_accum[0]);
it.out[1] = color_accum[1] * (1.0f / multiplier_accum[1]);
it.out[2] = color_accum[2] * (1.0f / multiplier_accum[2]);
it.out[3] = color_accum[3] * (1.0f / multiplier_accum[3]);
NodeOperation::determineResolution(resolution, preferredResolution);
if (this->m_extend_bounds) {
const float max_dim = MAX2(resolution[0], resolution[1]);
resolution[0] += 2 * this->m_size * max_dim / 100.0f;
resolution[1] += 2 * this->m_size * max_dim / 100.0f;
}
}

View File

@@ -18,12 +18,12 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
#include "COM_QualityStepHelper.h"
namespace blender::compositor {
class BokehBlurOperation : public MultiThreadedOperation, public QualityStepHelper {
class BokehBlurOperation : public NodeOperation, public QualityStepHelper {
private:
SocketReader *m_inputProgram;
SocketReader *m_inputBokehProgram;
@@ -31,7 +31,6 @@ class BokehBlurOperation : public MultiThreadedOperation, public QualityStepHelp
void updateSize();
float m_size;
bool m_sizeavailable;
float m_bokehMidX;
float m_bokehMidY;
float m_bokehDimension;
@@ -40,8 +39,6 @@ class BokehBlurOperation : public MultiThreadedOperation, public QualityStepHelp
public:
BokehBlurOperation();
void init_data() override;
void *initializeTileData(rcti *rect) override;
/**
* The inner loop of this operation.
@@ -82,11 +79,6 @@ class BokehBlurOperation : public MultiThreadedOperation, public QualityStepHelp
void determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2]) override;
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -27,7 +27,6 @@ ChannelMatteOperation::ChannelMatteOperation()
addOutputSocket(DataType::Value);
this->m_inputImageProgram = nullptr;
flags.can_be_constant = true;
}
void ChannelMatteOperation::initExecution()
@@ -122,37 +121,4 @@ void ChannelMatteOperation::executePixelSampled(float output[4],
output[0] = MIN2(alpha, inColor[3]);
}
void ChannelMatteOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
const float *color = it.in(0);
/* Matte operation. */
float alpha = color[this->m_ids[0]] - MAX2(color[this->m_ids[1]], color[this->m_ids[2]]);
/* Flip because 0.0 is transparent, not 1.0. */
alpha = 1.0f - alpha;
/* Test range. */
if (alpha > m_limit_max) {
alpha = color[3]; /* Whatever it was prior. */
}
else if (alpha < m_limit_min) {
alpha = 0.0f;
}
else { /* Blend. */
alpha = (alpha - m_limit_min) / m_limit_range;
}
/* Store matte(alpha) value in [0] to go with
* COM_SetAlphaMultiplyOperation and the Value output.
*/
/* Don't make something that was more transparent less transparent. */
*it.out = MIN2(alpha, color[3]);
}
}
} // namespace blender::compositor

View File

@@ -18,7 +18,7 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_MixOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
class ChannelMatteOperation : public MultiThreadedOperation {
class ChannelMatteOperation : public NodeOperation {
private:
SocketReader *m_inputImageProgram;
@@ -71,10 +71,6 @@ class ChannelMatteOperation : public MultiThreadedOperation {
this->m_limit_channel = nodeChroma->channel;
this->m_matte_channel = custom2;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -29,7 +29,6 @@ ChromaMatteOperation::ChromaMatteOperation()
this->m_inputImageProgram = nullptr;
this->m_inputKeyProgram = nullptr;
flags.can_be_constant = true;
}
void ChromaMatteOperation::initExecution()
@@ -111,58 +110,4 @@ void ChromaMatteOperation::executePixelSampled(float output[4],
}
}
void ChromaMatteOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
const float acceptance = this->m_settings->t1; /* In radians. */
const float cutoff = this->m_settings->t2; /* In radians. */
const float gain = this->m_settings->fstrength;
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
const float *in_image = it.in(0);
const float *in_key = it.in(1);
/* Store matte(alpha) value in [0] to go with
* #COM_SetAlphaMultiplyOperation and the Value output. */
/* Algorithm from book "Video Demystified", does not include the spill reduction part. */
/* Find theta, the angle that the color space should be rotated based on key. */
/* Rescale to `-1.0..1.0`. */
// const float image_Y = (in_image[0] * 2.0f) - 1.0f; // UNUSED
const float image_cb = (in_image[1] * 2.0f) - 1.0f;
const float image_cr = (in_image[2] * 2.0f) - 1.0f;
// const float key_Y = (in_key[0] * 2.0f) - 1.0f; // UNUSED
const float key_cb = (in_key[1] * 2.0f) - 1.0f;
const float key_cr = (in_key[2] * 2.0f) - 1.0f;
const float theta = atan2(key_cr, key_cb);
/* Rotate the cb and cr into x/z space. */
const float x_angle = image_cb * cosf(theta) + image_cr * sinf(theta);
const float z_angle = image_cr * cosf(theta) - image_cb * sinf(theta);
/* If within the acceptance angle. */
/* If kfg is <0 then the pixel is outside of the key color. */
const float kfg = x_angle - (fabsf(z_angle) / tanf(acceptance / 2.0f));
if (kfg > 0.0f) { /* Found a pixel that is within key color. */
const float beta = atan2(z_angle, x_angle);
float alpha = 1.0f - (kfg / gain);
/* Ff beta is within the cutoff angle. */
if (fabsf(beta) < (cutoff / 2.0f)) {
alpha = 0.0f;
}
/* Don't make something that was more transparent less transparent. */
it.out[0] = alpha < in_image[3] ? alpha : in_image[3];
}
else { /* Pixel is outside key color. */
it.out[0] = in_image[3]; /* Make pixel just as transparent as it was before. */
}
}
}
} // namespace blender::compositor

View File

@@ -18,7 +18,7 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_MixOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
class ChromaMatteOperation : public MultiThreadedOperation {
class ChromaMatteOperation : public NodeOperation {
private:
NodeChroma *m_settings;
SocketReader *m_inputImageProgram;
@@ -50,10 +50,6 @@ class ChromaMatteOperation : public MultiThreadedOperation {
{
this->m_settings = nodeChroma;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -29,7 +29,6 @@ ColorMatteOperation::ColorMatteOperation()
this->m_inputImageProgram = nullptr;
this->m_inputKeyProgram = nullptr;
flags.can_be_constant = true;
}
void ColorMatteOperation::initExecution()
@@ -83,40 +82,4 @@ void ColorMatteOperation::executePixelSampled(float output[4],
}
}
void ColorMatteOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
const float hue = m_settings->t1;
const float sat = m_settings->t2;
const float val = m_settings->t3;
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
const float *in_color = it.in(0);
const float *in_key = it.in(1);
/* Store matte(alpha) value in [0] to go with
* COM_SetAlphaMultiplyOperation and the Value output.
*/
float h_wrap;
if (
/* Do hue last because it needs to wrap, and does some more checks. */
/* #sat */ (fabsf(in_color[1] - in_key[1]) < sat) &&
/* #val */ (fabsf(in_color[2] - in_key[2]) < val) &&
/* Multiply by 2 because it wraps on both sides of the hue,
* otherwise 0.5 would key all hue's. */
/* #hue */
((h_wrap = 2.0f * fabsf(in_color[0] - in_key[0])) < hue || (2.0f - h_wrap) < hue)) {
it.out[0] = 0.0f; /* Make transparent. */
}
else { /* Pixel is outside key color. */
it.out[0] = in_color[3]; /* Make pixel just as transparent as it was before. */
}
}
}
} // namespace blender::compositor

View File

@@ -18,7 +18,7 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_MixOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
class ColorMatteOperation : public MultiThreadedOperation {
class ColorMatteOperation : public NodeOperation {
private:
NodeChroma *m_settings;
SocketReader *m_inputImageProgram;
@@ -50,10 +50,6 @@ class ColorMatteOperation : public MultiThreadedOperation {
{
this->m_settings = nodeChroma;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -29,7 +29,6 @@ ColorRampOperation::ColorRampOperation()
this->m_inputProgram = nullptr;
this->m_colorBand = nullptr;
this->flags.can_be_constant = true;
}
void ColorRampOperation::initExecution()
{
@@ -52,13 +51,4 @@ void ColorRampOperation::deinitExecution()
this->m_inputProgram = nullptr;
}
void ColorRampOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
BKE_colorband_evaluate(m_colorBand, *it.in(0), it.out);
}
}
} // namespace blender::compositor

View File

@@ -18,12 +18,12 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
#include "DNA_texture_types.h"
namespace blender::compositor {
class ColorRampOperation : public MultiThreadedOperation {
class ColorRampOperation : public NodeOperation {
private:
/**
* Cached reference to the inputProgram
@@ -53,10 +53,6 @@ class ColorRampOperation : public MultiThreadedOperation {
{
this->m_colorBand = colorBand;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -32,7 +32,6 @@ ColorSpillOperation::ColorSpillOperation()
this->m_inputFacReader = nullptr;
this->m_spillChannel = 1; // GREEN
this->m_spillMethod = 0;
flags.can_be_constant = true;
}
void ColorSpillOperation::initExecution()
@@ -119,36 +118,4 @@ void ColorSpillOperation::executePixelSampled(float output[4],
}
}
void ColorSpillOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
const float *color = it.in(0);
const float factor = MIN2(1.0f, *it.in(1));
float map;
switch (m_spillMethod) {
case 0: /* simple */
map = factor *
(color[m_spillChannel] - (m_settings->limscale * color[m_settings->limchan]));
break;
default: /* average */
map = factor * (color[m_spillChannel] -
(m_settings->limscale * AVG(color[m_channel2], color[m_channel3])));
break;
}
if (map > 0.0f) {
it.out[0] = color[0] + m_rmut * (m_settings->uspillr * map);
it.out[1] = color[1] + m_gmut * (m_settings->uspillg * map);
it.out[2] = color[2] + m_bmut * (m_settings->uspillb * map);
it.out[3] = color[3];
}
else {
copy_v4_v4(it.out, color);
}
}
}
} // namespace blender::compositor

View File

@@ -18,7 +18,7 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
class ColorSpillOperation : public MultiThreadedOperation {
class ColorSpillOperation : public NodeOperation {
protected:
NodeColorspill *m_settings;
SocketReader *m_inputImageReader;
@@ -65,10 +65,6 @@ class ColorSpillOperation : public MultiThreadedOperation {
}
float calculateMapValue(float fac, float *input);
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -27,7 +27,6 @@ namespace blender::compositor {
ConvertBaseOperation::ConvertBaseOperation()
{
this->m_inputOperation = nullptr;
this->flags.can_be_constant = true;
}
void ConvertBaseOperation::initExecution()
@@ -40,14 +39,6 @@ void ConvertBaseOperation::deinitExecution()
this->m_inputOperation = nullptr;
}
void ConvertBaseOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
BuffersIterator<float> it = output->iterate_with(inputs, area);
update_memory_buffer_partial(it);
}
/* ******** Value to Color ******** */
ConvertValueToColorOperation::ConvertValueToColorOperation() : ConvertBaseOperation()
@@ -67,14 +58,6 @@ void ConvertValueToColorOperation::executePixelSampled(float output[4],
output[3] = 1.0f;
}
void ConvertValueToColorOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
{
for (; !it.is_end(); ++it) {
it.out[0] = it.out[1] = it.out[2] = *it.in(0);
it.out[3] = 1.0f;
}
}
/* ******** Color to Value ******** */
ConvertColorToValueOperation::ConvertColorToValueOperation() : ConvertBaseOperation()
@@ -93,14 +76,6 @@ void ConvertColorToValueOperation::executePixelSampled(float output[4],
output[0] = (inputColor[0] + inputColor[1] + inputColor[2]) / 3.0f;
}
void ConvertColorToValueOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
{
for (; !it.is_end(); ++it) {
const float *in = it.in(0);
it.out[0] = (in[0] + in[1] + in[2]) / 3.0f;
}
}
/* ******** Color to BW ******** */
ConvertColorToBWOperation::ConvertColorToBWOperation() : ConvertBaseOperation()
@@ -119,13 +94,6 @@ void ConvertColorToBWOperation::executePixelSampled(float output[4],
output[0] = IMB_colormanagement_get_luminance(inputColor);
}
void ConvertColorToBWOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
{
for (; !it.is_end(); ++it) {
it.out[0] = IMB_colormanagement_get_luminance(it.in(0));
}
}
/* ******** Color to Vector ******** */
ConvertColorToVectorOperation::ConvertColorToVectorOperation() : ConvertBaseOperation()
@@ -144,13 +112,6 @@ void ConvertColorToVectorOperation::executePixelSampled(float output[4],
copy_v3_v3(output, color);
}
void ConvertColorToVectorOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
{
for (; !it.is_end(); ++it) {
copy_v3_v3(it.out, it.in(0));
}
}
/* ******** Value to Vector ******** */
ConvertValueToVectorOperation::ConvertValueToVectorOperation() : ConvertBaseOperation()
@@ -169,13 +130,6 @@ void ConvertValueToVectorOperation::executePixelSampled(float output[4],
output[0] = output[1] = output[2] = value;
}
void ConvertValueToVectorOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
{
for (; !it.is_end(); ++it) {
it.out[0] = it.out[1] = it.out[2] = *it.in(0);
}
}
/* ******** Vector to Color ******** */
ConvertVectorToColorOperation::ConvertVectorToColorOperation() : ConvertBaseOperation()
@@ -193,14 +147,6 @@ void ConvertVectorToColorOperation::executePixelSampled(float output[4],
output[3] = 1.0f;
}
void ConvertVectorToColorOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
{
for (; !it.is_end(); ++it) {
copy_v3_v3(it.out, it.in(0));
it.out[3] = 1.0f;
}
}
/* ******** Vector to Value ******** */
ConvertVectorToValueOperation::ConvertVectorToValueOperation() : ConvertBaseOperation()
@@ -219,14 +165,6 @@ void ConvertVectorToValueOperation::executePixelSampled(float output[4],
output[0] = (input[0] + input[1] + input[2]) / 3.0f;
}
void ConvertVectorToValueOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
{
for (; !it.is_end(); ++it) {
const float *in = it.in(0);
it.out[0] = (in[0] + in[1] + in[2]) / 3.0f;
}
}
/* ******** RGB to YCC ******** */
ConvertRGBToYCCOperation::ConvertRGBToYCCOperation() : ConvertBaseOperation()
@@ -269,18 +207,6 @@ void ConvertRGBToYCCOperation::executePixelSampled(float output[4],
output[3] = inputColor[3];
}
void ConvertRGBToYCCOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
{
for (; !it.is_end(); ++it) {
const float *in = it.in(0);
rgb_to_ycc(in[0], in[1], in[2], &it.out[0], &it.out[1], &it.out[2], this->m_mode);
/* Normalize for viewing (#rgb_to_ycc returns 0-255 values). */
mul_v3_fl(it.out, 1.0f / 255.0f);
it.out[3] = in[3];
}
}
/* ******** YCC to RGB ******** */
ConvertYCCToRGBOperation::ConvertYCCToRGBOperation() : ConvertBaseOperation()
@@ -327,22 +253,6 @@ void ConvertYCCToRGBOperation::executePixelSampled(float output[4],
output[3] = inputColor[3];
}
void ConvertYCCToRGBOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
{
for (; !it.is_end(); ++it) {
const float *in = it.in(0);
/* Multiply by 255 to un-normalize (#ycc_to_rgb needs input values in 0-255 range). */
ycc_to_rgb(in[0] * 255.0f,
in[1] * 255.0f,
in[2] * 255.0f,
&it.out[0],
&it.out[1],
&it.out[2],
this->m_mode);
it.out[3] = in[3];
}
}
/* ******** RGB to YUV ******** */
ConvertRGBToYUVOperation::ConvertRGBToYUVOperation() : ConvertBaseOperation()
@@ -368,15 +278,6 @@ void ConvertRGBToYUVOperation::executePixelSampled(float output[4],
output[3] = inputColor[3];
}
void ConvertRGBToYUVOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
{
for (; !it.is_end(); ++it) {
const float *in = it.in(0);
rgb_to_yuv(in[0], in[1], in[2], &it.out[0], &it.out[1], &it.out[2], BLI_YUV_ITU_BT709);
it.out[3] = in[3];
}
}
/* ******** YUV to RGB ******** */
ConvertYUVToRGBOperation::ConvertYUVToRGBOperation() : ConvertBaseOperation()
@@ -402,15 +303,6 @@ void ConvertYUVToRGBOperation::executePixelSampled(float output[4],
output[3] = inputColor[3];
}
void ConvertYUVToRGBOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
{
for (; !it.is_end(); ++it) {
const float *in = it.in(0);
yuv_to_rgb(in[0], in[1], in[2], &it.out[0], &it.out[1], &it.out[2], BLI_YUV_ITU_BT709);
it.out[3] = in[3];
}
}
/* ******** RGB to HSV ******** */
ConvertRGBToHSVOperation::ConvertRGBToHSVOperation() : ConvertBaseOperation()
@@ -430,15 +322,6 @@ void ConvertRGBToHSVOperation::executePixelSampled(float output[4],
output[3] = inputColor[3];
}
void ConvertRGBToHSVOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
{
for (; !it.is_end(); ++it) {
const float *in = it.in(0);
rgb_to_hsv_v(in, it.out);
it.out[3] = in[3];
}
}
/* ******** HSV to RGB ******** */
ConvertHSVToRGBOperation::ConvertHSVToRGBOperation() : ConvertBaseOperation()
@@ -461,18 +344,6 @@ void ConvertHSVToRGBOperation::executePixelSampled(float output[4],
output[3] = inputColor[3];
}
void ConvertHSVToRGBOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
{
for (; !it.is_end(); ++it) {
const float *in = it.in(0);
hsv_to_rgb_v(in, it.out);
it.out[0] = max_ff(it.out[0], 0.0f);
it.out[1] = max_ff(it.out[1], 0.0f);
it.out[2] = max_ff(it.out[2], 0.0f);
it.out[3] = in[3];
}
}
/* ******** Premul to Straight ******** */
ConvertPremulToStraightOperation::ConvertPremulToStraightOperation() : ConvertBaseOperation()
@@ -492,13 +363,6 @@ void ConvertPremulToStraightOperation::executePixelSampled(float output[4],
copy_v4_v4(output, converted);
}
void ConvertPremulToStraightOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
{
for (; !it.is_end(); ++it) {
copy_v4_v4(it.out, ColorSceneLinear4f<eAlpha::Premultiplied>(it.in(0)).unpremultiply_alpha());
}
}
/* ******** Straight to Premul ******** */
ConvertStraightToPremulOperation::ConvertStraightToPremulOperation() : ConvertBaseOperation()
@@ -518,13 +382,6 @@ void ConvertStraightToPremulOperation::executePixelSampled(float output[4],
copy_v4_v4(output, converted);
}
void ConvertStraightToPremulOperation::update_memory_buffer_partial(BuffersIterator<float> &it)
{
for (; !it.is_end(); ++it) {
copy_v4_v4(it.out, ColorSceneLinear4f<eAlpha::Straight>(it.in(0)).premultiply_alpha());
}
}
/* ******** Separate Channels ******** */
SeparateChannelOperation::SeparateChannelOperation()
@@ -553,15 +410,6 @@ void SeparateChannelOperation::executePixelSampled(float output[4],
output[0] = input[this->m_channel];
}
void SeparateChannelOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
it.out[0] = it.in(0)[this->m_channel];
}
}
/* ******** Combine Channels ******** */
CombineChannelsOperation::CombineChannelsOperation()
@@ -618,16 +466,4 @@ void CombineChannelsOperation::executePixelSampled(float output[4],
}
}
void CombineChannelsOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
it.out[0] = *it.in(0);
it.out[1] = *it.in(1);
it.out[2] = *it.in(2);
it.out[3] = *it.in(3);
}
}
} // namespace blender::compositor

View File

@@ -18,11 +18,11 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
class ConvertBaseOperation : public MultiThreadedOperation {
class ConvertBaseOperation : public NodeOperation {
protected:
SocketReader *m_inputOperation;
@@ -31,13 +31,6 @@ class ConvertBaseOperation : public MultiThreadedOperation {
void initExecution() override;
void deinitExecution() override;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) final;
protected:
virtual void update_memory_buffer_partial(BuffersIterator<float> &it) = 0;
};
class ConvertValueToColorOperation : public ConvertBaseOperation {
@@ -45,9 +38,6 @@ class ConvertValueToColorOperation : public ConvertBaseOperation {
ConvertValueToColorOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
protected:
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertColorToValueOperation : public ConvertBaseOperation {
@@ -55,9 +45,6 @@ class ConvertColorToValueOperation : public ConvertBaseOperation {
ConvertColorToValueOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
protected:
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertColorToBWOperation : public ConvertBaseOperation {
@@ -65,9 +52,6 @@ class ConvertColorToBWOperation : public ConvertBaseOperation {
ConvertColorToBWOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
protected:
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertColorToVectorOperation : public ConvertBaseOperation {
@@ -75,9 +59,6 @@ class ConvertColorToVectorOperation : public ConvertBaseOperation {
ConvertColorToVectorOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
protected:
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertValueToVectorOperation : public ConvertBaseOperation {
@@ -85,9 +66,6 @@ class ConvertValueToVectorOperation : public ConvertBaseOperation {
ConvertValueToVectorOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
protected:
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertVectorToColorOperation : public ConvertBaseOperation {
@@ -95,9 +73,6 @@ class ConvertVectorToColorOperation : public ConvertBaseOperation {
ConvertVectorToColorOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
protected:
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertVectorToValueOperation : public ConvertBaseOperation {
@@ -105,9 +80,6 @@ class ConvertVectorToValueOperation : public ConvertBaseOperation {
ConvertVectorToValueOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
protected:
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertRGBToYCCOperation : public ConvertBaseOperation {
@@ -122,9 +94,6 @@ class ConvertRGBToYCCOperation : public ConvertBaseOperation {
/** Set the YCC mode */
void setMode(int mode);
protected:
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertYCCToRGBOperation : public ConvertBaseOperation {
@@ -139,9 +108,6 @@ class ConvertYCCToRGBOperation : public ConvertBaseOperation {
/** Set the YCC mode */
void setMode(int mode);
protected:
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertRGBToYUVOperation : public ConvertBaseOperation {
@@ -149,9 +115,6 @@ class ConvertRGBToYUVOperation : public ConvertBaseOperation {
ConvertRGBToYUVOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
protected:
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertYUVToRGBOperation : public ConvertBaseOperation {
@@ -159,9 +122,6 @@ class ConvertYUVToRGBOperation : public ConvertBaseOperation {
ConvertYUVToRGBOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
protected:
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertRGBToHSVOperation : public ConvertBaseOperation {
@@ -169,9 +129,6 @@ class ConvertRGBToHSVOperation : public ConvertBaseOperation {
ConvertRGBToHSVOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
protected:
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertHSVToRGBOperation : public ConvertBaseOperation {
@@ -179,9 +136,6 @@ class ConvertHSVToRGBOperation : public ConvertBaseOperation {
ConvertHSVToRGBOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
protected:
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertPremulToStraightOperation : public ConvertBaseOperation {
@@ -189,9 +143,6 @@ class ConvertPremulToStraightOperation : public ConvertBaseOperation {
ConvertPremulToStraightOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
protected:
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class ConvertStraightToPremulOperation : public ConvertBaseOperation {
@@ -199,12 +150,9 @@ class ConvertStraightToPremulOperation : public ConvertBaseOperation {
ConvertStraightToPremulOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
protected:
void update_memory_buffer_partial(BuffersIterator<float> &it) override;
};
class SeparateChannelOperation : public MultiThreadedOperation {
class SeparateChannelOperation : public NodeOperation {
private:
SocketReader *m_inputOperation;
int m_channel;
@@ -220,13 +168,9 @@ class SeparateChannelOperation : public MultiThreadedOperation {
{
this->m_channel = channel;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
class CombineChannelsOperation : public MultiThreadedOperation {
class CombineChannelsOperation : public NodeOperation {
private:
SocketReader *m_inputChannel1Operation;
SocketReader *m_inputChannel2Operation;
@@ -239,10 +183,6 @@ class CombineChannelsOperation : public MultiThreadedOperation {
void initExecution() override;
void deinitExecution() override;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -95,22 +95,6 @@ void CropOperation::executePixelSampled(float output[4], float x, float y, Pixel
}
}
void CropOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
rcti crop_area;
BLI_rcti_init(&crop_area, m_xmin, m_xmax, m_ymin, m_ymax);
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
if (BLI_rcti_isect_pt(&crop_area, it.x, it.y)) {
copy_v4_v4(it.out, it.in(0));
}
else {
zero_v4(it.out);
}
}
}
CropImageOperation::CropImageOperation() : CropBaseOperation()
{
/* pass */
@@ -130,18 +114,6 @@ bool CropImageOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
void CropImageOperation::get_area_of_interest(const int input_idx,
const rcti &output_area,
rcti &r_input_area)
{
BLI_assert(input_idx == 0);
UNUSED_VARS_NDEBUG(input_idx);
r_input_area.xmax = output_area.xmax + this->m_xmin;
r_input_area.xmin = output_area.xmin + this->m_xmin;
r_input_area.ymax = output_area.ymax + this->m_ymin;
r_input_area.ymin = output_area.ymin + this->m_ymin;
}
void CropImageOperation::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
{
@@ -164,21 +136,4 @@ void CropImageOperation::executePixelSampled(float output[4],
}
}
void CropImageOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
rcti op_area;
BLI_rcti_init(&op_area, 0, getWidth(), 0, getHeight());
const MemoryBuffer *input = inputs[0];
for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
if (BLI_rcti_isect_pt(&op_area, it.x, it.y)) {
input->read_elem_checked(it.x + this->m_xmin, it.y + this->m_ymin, it.out);
}
else {
zero_v4(it.out);
}
}
}
} // namespace blender::compositor

View File

@@ -18,11 +18,11 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
class CropBaseOperation : public MultiThreadedOperation {
class CropBaseOperation : public NodeOperation {
protected:
SocketReader *m_inputOperation;
NodeTwoXYs *m_settings;
@@ -53,10 +53,6 @@ class CropOperation : public CropBaseOperation {
public:
CropOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
class CropImageOperation : public CropBaseOperation {
@@ -69,11 +65,6 @@ class CropImageOperation : public CropBaseOperation {
void determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2]) override;
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -71,34 +71,4 @@ void CryptomatteOperation::executePixel(float output[4], int x, int y, void *dat
}
}
void CryptomatteOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
zero_v4(it.out);
for (int i = 0; i < it.get_num_inputs(); i++) {
const float *input = it.in(i);
if (i == 0) {
/* Write the front-most object as false color for picking. */
it.out[0] = input[0];
uint32_t m3hash;
::memcpy(&m3hash, &input[0], sizeof(uint32_t));
/* Since the red channel is likely to be out of display range,
* setting green and blue gives more meaningful images. */
it.out[1] = ((float)(m3hash << 8) / (float)UINT32_MAX);
it.out[2] = ((float)(m3hash << 16) / (float)UINT32_MAX);
}
for (const float hash : m_objectIndex) {
if (input[0] == hash) {
it.out[3] += input[1];
}
if (input[2] == hash) {
it.out[3] += input[3];
}
}
}
}
}
} // namespace blender::compositor

View File

@@ -18,11 +18,11 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
class CryptomatteOperation : public MultiThreadedOperation {
class CryptomatteOperation : public NodeOperation {
private:
Vector<float> m_objectIndex;
@@ -35,10 +35,6 @@ class CryptomatteOperation : public MultiThreadedOperation {
void executePixel(float output[4], int x, int y, void *data) override;
void addObjectIndex(float objectIndex);
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -29,7 +29,6 @@ DifferenceMatteOperation::DifferenceMatteOperation()
this->m_inputImage1Program = nullptr;
this->m_inputImage2Program = nullptr;
flags.can_be_constant = true;
}
void DifferenceMatteOperation::initExecution()
@@ -87,44 +86,4 @@ void DifferenceMatteOperation::executePixelSampled(float output[4],
}
}
void DifferenceMatteOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
const float *color1 = it.in(0);
const float *color2 = it.in(1);
float difference = (fabsf(color2[0] - color1[0]) + fabsf(color2[1] - color1[1]) +
fabsf(color2[2] - color1[2]));
/* Average together the distances. */
difference = difference / 3.0f;
const float tolerance = m_settings->t1;
const float falloff = m_settings->t2;
/* Make 100% transparent. */
if (difference <= tolerance) {
it.out[0] = 0.0f;
}
/* In the falloff region, make partially transparent. */
else if (difference <= falloff + tolerance) {
difference = difference - tolerance;
const float alpha = difference / falloff;
/* Only change if more transparent than before. */
if (alpha < color1[3]) {
it.out[0] = alpha;
}
else { /* Leave as before. */
it.out[0] = color1[3];
}
}
else {
/* Foreground object. */
it.out[0] = color1[3];
}
}
}
} // namespace blender::compositor

View File

@@ -18,7 +18,7 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_MixOperation.h"
namespace blender::compositor {
@@ -26,7 +26,7 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
class DifferenceMatteOperation : public MultiThreadedOperation {
class DifferenceMatteOperation : public NodeOperation {
private:
NodeChroma *m_settings;
SocketReader *m_inputImage1Program;
@@ -50,10 +50,6 @@ class DifferenceMatteOperation : public MultiThreadedOperation {
{
this->m_settings = nodeChroma;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -32,30 +32,20 @@ DisplaceOperation::DisplaceOperation()
this->flags.complex = true;
this->m_inputColorProgram = nullptr;
this->m_inputVectorProgram = nullptr;
this->m_inputScaleXProgram = nullptr;
this->m_inputScaleYProgram = nullptr;
}
void DisplaceOperation::initExecution()
{
this->m_inputColorProgram = this->getInputSocketReader(0);
NodeOperation *vector = this->getInputSocketReader(1);
NodeOperation *scale_x = this->getInputSocketReader(2);
NodeOperation *scale_y = this->getInputSocketReader(3);
if (execution_model_ == eExecutionModel::Tiled) {
vector_read_fn_ = [=](float x, float y, float *out) {
vector->readSampled(out, x, y, PixelSampler::Bilinear);
};
scale_x_read_fn_ = [=](float x, float y, float *out) {
scale_x->readSampled(out, x, y, PixelSampler::Nearest);
};
scale_y_read_fn_ = [=](float x, float y, float *out) {
scale_y->readSampled(out, x, y, PixelSampler::Nearest);
};
}
this->m_inputVectorProgram = this->getInputSocketReader(1);
this->m_inputScaleXProgram = this->getInputSocketReader(2);
this->m_inputScaleYProgram = this->getInputSocketReader(3);
this->m_width_x4 = this->getWidth() * 4;
this->m_height_x4 = this->getHeight() * 4;
input_vector_width_ = vector->getWidth();
input_vector_height_ = vector->getHeight();
}
void DisplaceOperation::executePixelSampled(float output[4],
@@ -79,8 +69,8 @@ void DisplaceOperation::executePixelSampled(float output[4],
bool DisplaceOperation::read_displacement(
float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v)
{
float width = input_vector_width_;
float height = input_vector_height_;
float width = m_inputVectorProgram->getWidth();
float height = m_inputVectorProgram->getHeight();
if (x < 0.0f || x >= width || y < 0.0f || y >= height) {
r_u = 0.0f;
r_v = 0.0f;
@@ -88,7 +78,7 @@ bool DisplaceOperation::read_displacement(
}
float col[4];
vector_read_fn_(x, y, col);
m_inputVectorProgram->readSampled(col, x, y, PixelSampler::Bilinear);
r_u = origin[0] - col[0] * xscale;
r_v = origin[1] - col[1] * yscale;
return true;
@@ -100,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;
scale_x_read_fn_(xy[0], xy[1], col);
m_inputScaleXProgram->readSampled(col, xy[0], xy[1], PixelSampler::Nearest);
float xs = col[0];
scale_y_read_fn_(xy[0], xy[1], col);
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 */
@@ -156,9 +146,9 @@ void DisplaceOperation::pixelTransform(const float xy[2], float r_uv[2], float r
void DisplaceOperation::deinitExecution()
{
this->m_inputColorProgram = nullptr;
vector_read_fn_ = nullptr;
scale_x_read_fn_ = nullptr;
scale_y_read_fn_ = nullptr;
this->m_inputVectorProgram = nullptr;
this->m_inputScaleXProgram = nullptr;
this->m_inputScaleYProgram = nullptr;
}
bool DisplaceOperation::determineDependingAreaOfInterest(rcti *input,
@@ -205,61 +195,4 @@ bool DisplaceOperation::determineDependingAreaOfInterest(rcti *input,
return false;
}
void DisplaceOperation::get_area_of_interest(const int input_idx,
const rcti &output_area,
rcti &r_input_area)
{
switch (input_idx) {
case 0: {
r_input_area.xmin = 0;
r_input_area.ymin = 0;
r_input_area.xmax = getInputOperation(input_idx)->getWidth();
r_input_area.ymax = getInputOperation(input_idx)->getHeight();
break;
}
case 1: {
r_input_area = output_area;
expand_area_for_sampler(r_input_area, PixelSampler::Bilinear);
break;
}
default: {
r_input_area = output_area;
break;
}
}
}
void DisplaceOperation::update_memory_buffer_started(MemoryBuffer *UNUSED(output),
const rcti &UNUSED(area),
Span<MemoryBuffer *> inputs)
{
MemoryBuffer *vector = inputs[1];
MemoryBuffer *scale_x = inputs[2];
MemoryBuffer *scale_y = inputs[3];
vector_read_fn_ = [=](float x, float y, float *out) { vector->read_elem_bilinear(x, y, out); };
scale_x_read_fn_ = [=](float x, float y, float *out) { scale_x->read_elem_checked(x, y, out); };
scale_y_read_fn_ = [=](float x, float y, float *out) { scale_y->read_elem_checked(x, y, out); };
}
void DisplaceOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
const MemoryBuffer *input_color = inputs[0];
for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
const float xy[2] = {(float)it.x, (float)it.y};
float uv[2];
float deriv[2][2];
pixelTransform(xy, uv, deriv);
if (is_zero_v2(deriv[0]) && is_zero_v2(deriv[1])) {
input_color->read_elem_bilinear(uv[0], uv[1], it.out);
}
else {
/* EWA filtering (without nearest it gets blurry with NO distortion). */
input_color->read_elem_filtered(uv[0], uv[1], deriv[0], deriv[1], it.out);
}
}
}
} // namespace blender::compositor

View File

@@ -18,27 +18,23 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
class DisplaceOperation : public MultiThreadedOperation {
class DisplaceOperation : public NodeOperation {
private:
/**
* Cached reference to the inputProgram
*/
SocketReader *m_inputColorProgram;
SocketReader *m_inputVectorProgram;
SocketReader *m_inputScaleXProgram;
SocketReader *m_inputScaleYProgram;
float m_width_x4;
float m_height_x4;
int input_vector_width_;
int input_vector_height_;
std::function<void(float x, float y, float *out)> vector_read_fn_;
std::function<void(float x, float y, float *out)> scale_x_read_fn_;
std::function<void(float x, float y, float *out)> scale_y_read_fn_;
public:
DisplaceOperation();
@@ -66,14 +62,6 @@ class DisplaceOperation : public MultiThreadedOperation {
*/
void deinitExecution() override;
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
void update_memory_buffer_started(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
private:
bool read_displacement(
float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v);

View File

@@ -132,56 +132,4 @@ bool DisplaceSimpleOperation::determineDependingAreaOfInterest(rcti *input,
return false;
}
void DisplaceSimpleOperation::get_area_of_interest(const int input_idx,
const rcti &output_area,
rcti &r_input_area)
{
switch (input_idx) {
case 0: {
r_input_area.xmin = 0;
r_input_area.ymin = 0;
r_input_area.xmax = getInputOperation(input_idx)->getWidth();
r_input_area.ymax = getInputOperation(input_idx)->getHeight();
break;
}
default: {
r_input_area = output_area;
break;
}
}
}
void DisplaceSimpleOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
const float width = this->getWidth();
const float height = this->getHeight();
const MemoryBuffer *input_color = inputs[0];
for (BuffersIterator<float> it = output->iterate_with(inputs.drop_front(1), area); !it.is_end();
++it) {
float scale_x = *it.in(1);
float scale_y = *it.in(2);
/* Clamp x and y displacement to triple image resolution -
* to prevent hangs from huge values mistakenly plugged in eg. z buffers. */
CLAMP(scale_x, -m_width_x4, m_width_x4);
CLAMP(scale_y, -m_height_x4, m_height_x4);
/* Main displacement in pixel space. */
const float *vector = it.in(0);
const float p_dx = vector[0] * scale_x;
const float p_dy = vector[1] * scale_y;
/* Displaced pixel in uv coords, for image sampling. */
/* Clamp nodes to avoid glitches. */
float u = it.x - p_dx + 0.5f;
float v = it.y - p_dy + 0.5f;
CLAMP(u, 0.0f, width - 1.0f);
CLAMP(v, 0.0f, height - 1.0f);
input_color->read_elem_checked(u, v, it.out);
}
}
} // namespace blender::compositor

View File

@@ -18,11 +18,11 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
class DisplaceSimpleOperation : public MultiThreadedOperation {
class DisplaceSimpleOperation : public NodeOperation {
private:
/**
* Cached reference to the inputProgram
@@ -59,11 +59,6 @@ class DisplaceSimpleOperation : public MultiThreadedOperation {
* Deinitialize the execution
*/
void deinitExecution() override;
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -29,7 +29,6 @@ DistanceRGBMatteOperation::DistanceRGBMatteOperation()
this->m_inputImageProgram = nullptr;
this->m_inputKeyProgram = nullptr;
flags.can_be_constant = true;
}
void DistanceRGBMatteOperation::initExecution()
@@ -44,7 +43,7 @@ void DistanceRGBMatteOperation::deinitExecution()
this->m_inputKeyProgram = nullptr;
}
float DistanceRGBMatteOperation::calculateDistance(const float key[4], const float image[4])
float DistanceRGBMatteOperation::calculateDistance(float key[4], float image[4])
{
return len_v3v3(key, image);
}
@@ -94,43 +93,4 @@ void DistanceRGBMatteOperation::executePixelSampled(float output[4],
}
}
void DistanceRGBMatteOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
const float *in_image = it.in(0);
const float *in_key = it.in(1);
float distance = this->calculateDistance(in_key, in_image);
const float tolerance = this->m_settings->t1;
const float falloff = this->m_settings->t2;
/* Store matte(alpha) value in [0] to go with
* COM_SetAlphaMultiplyOperation and the Value output.
*/
/* Make 100% transparent. */
if (distance < tolerance) {
it.out[0] = 0.0f;
}
/* In the falloff region, make partially transparent. */
else if (distance < falloff + tolerance) {
distance = distance - tolerance;
const float alpha = distance / falloff;
/* Only change if more transparent than before. */
if (alpha < in_image[3]) {
it.out[0] = alpha;
}
else { /* Leave as before. */
it.out[0] = in_image[3];
}
}
else {
/* Leave as before. */
it.out[0] = in_image[3];
}
}
}
} // namespace blender::compositor

View File

@@ -18,7 +18,7 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_MixOperation.h"
namespace blender::compositor {
@@ -26,13 +26,13 @@ namespace blender::compositor {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
class DistanceRGBMatteOperation : public MultiThreadedOperation {
class DistanceRGBMatteOperation : public NodeOperation {
protected:
NodeChroma *m_settings;
SocketReader *m_inputImageProgram;
SocketReader *m_inputKeyProgram;
virtual float calculateDistance(const float key[4], const float image[4]);
virtual float calculateDistance(float key[4], float image[4]);
public:
/**
@@ -52,10 +52,6 @@ class DistanceRGBMatteOperation : public MultiThreadedOperation {
{
this->m_settings = nodeChroma;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -21,7 +21,7 @@
namespace blender::compositor {
float DistanceYCCMatteOperation::calculateDistance(const float key[4], const float image[4])
float DistanceYCCMatteOperation::calculateDistance(float key[4], float image[4])
{
/* only measure the second 2 values */
return len_v2v2(key + 1, image + 1);

View File

@@ -29,7 +29,7 @@ namespace blender::compositor {
*/
class DistanceYCCMatteOperation : public DistanceRGBMatteOperation {
protected:
float calculateDistance(const float key[4], const float image[4]) override;
float calculateDistance(float key[4], float image[4]) override;
};
} // namespace blender::compositor

View File

@@ -62,13 +62,6 @@ bool FastGaussianBlurOperation::determineDependingAreaOfInterest(
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
void FastGaussianBlurOperation::init_data()
{
BlurBaseOperation::init_data();
this->m_sx = this->m_data.sizex * this->m_size / 2.0f;
this->m_sy = this->m_data.sizey * this->m_size / 2.0f;
}
void FastGaussianBlurOperation::initExecution()
{
BlurBaseOperation::initExecution();
@@ -124,7 +117,6 @@ void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src,
unsigned int chan,
unsigned int xy)
{
BLI_assert(!src->is_a_single_elem());
double q, q2, sc, cf[4], tsM[9], tsu[3], tsv[3];
double *X, *Y, *W;
const unsigned int src_width = src->getWidth();
@@ -265,64 +257,6 @@ void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src,
#undef YVV
}
void FastGaussianBlurOperation::get_area_of_interest(const int input_idx,
const rcti &output_area,
rcti &r_input_area)
{
switch (input_idx) {
case IMAGE_INPUT_INDEX:
r_input_area.xmin = 0;
r_input_area.xmax = getWidth();
r_input_area.ymin = 0;
r_input_area.ymax = getHeight();
break;
default:
BlurBaseOperation::get_area_of_interest(input_idx, output_area, r_input_area);
return;
}
}
void FastGaussianBlurOperation::update_memory_buffer_started(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
/* TODO(manzanilla): Add a render test and make #IIR_gauss multi-threaded with support for
* an output buffer. */
const MemoryBuffer *input = inputs[IMAGE_INPUT_INDEX];
MemoryBuffer *image = nullptr;
const bool is_full_output = BLI_rcti_compare(&output->get_rect(), &area);
if (is_full_output) {
image = output;
}
else {
image = new MemoryBuffer(getOutputSocket()->getDataType(), area);
}
image->copy_from(input, area);
if ((this->m_sx == this->m_sy) && (this->m_sx > 0.0f)) {
for (const int c : IndexRange(COM_DATA_TYPE_COLOR_CHANNELS)) {
IIR_gauss(image, this->m_sx, c, 3);
}
}
else {
if (this->m_sx > 0.0f) {
for (const int c : IndexRange(COM_DATA_TYPE_COLOR_CHANNELS)) {
IIR_gauss(image, this->m_sx, c, 1);
}
}
if (this->m_sy > 0.0f) {
for (const int c : IndexRange(COM_DATA_TYPE_COLOR_CHANNELS)) {
IIR_gauss(image, this->m_sy, c, 2);
}
}
}
if (!is_full_output) {
output->copy_from(image, area);
delete image;
}
}
FastGaussianBlurValueOperation::FastGaussianBlurValueOperation()
{
this->addInputSocket(DataType::Value);
@@ -407,44 +341,4 @@ void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect)
return this->m_iirgaus;
}
void FastGaussianBlurValueOperation::get_area_of_interest(const int UNUSED(input_idx),
const rcti &UNUSED(output_area),
rcti &r_input_area)
{
r_input_area.xmin = 0;
r_input_area.xmax = getWidth();
r_input_area.ymin = 0;
r_input_area.ymax = getHeight();
}
void FastGaussianBlurValueOperation::update_memory_buffer_started(MemoryBuffer *UNUSED(output),
const rcti &UNUSED(area),
Span<MemoryBuffer *> inputs)
{
if (m_iirgaus == nullptr) {
const MemoryBuffer *image = inputs[0];
MemoryBuffer *gauss = new MemoryBuffer(*image);
FastGaussianBlurOperation::IIR_gauss(gauss, m_sigma, 0, 3);
m_iirgaus = gauss;
}
}
void FastGaussianBlurValueOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
MemoryBuffer *image = inputs[0];
BuffersIterator<float> it = output->iterate_with({image, m_iirgaus}, area);
if (this->m_overlay == FAST_GAUSS_OVERLAY_MIN) {
for (; !it.is_end(); ++it) {
*it.out = MIN2(*it.in(0), *it.in(1));
}
}
else if (this->m_overlay == FAST_GAUSS_OVERLAY_MAX) {
for (; !it.is_end(); ++it) {
*it.out = MAX2(*it.in(0), *it.in(1));
}
}
}
} // namespace blender::compositor

View File

@@ -38,19 +38,8 @@ class FastGaussianBlurOperation : public BlurBaseOperation {
static void IIR_gauss(MemoryBuffer *src, float sigma, unsigned int channel, unsigned int xy);
void *initializeTileData(rcti *rect) override;
void init_data() override;
void deinitExecution() override;
void initExecution() override;
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
void update_memory_buffer_started(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
void update_memory_buffer_partial(MemoryBuffer *UNUSED(output),
const rcti &UNUSED(area),
Span<MemoryBuffer *> UNUSED(inputs)) override
{
}
};
enum {
@@ -59,7 +48,7 @@ enum {
FAST_GAUSS_OVERLAY_MAX = 1,
};
class FastGaussianBlurValueOperation : public MultiThreadedOperation {
class FastGaussianBlurValueOperation : public NodeOperation {
private:
float m_sigma;
MemoryBuffer *m_iirgaus;
@@ -91,14 +80,6 @@ class FastGaussianBlurValueOperation : public MultiThreadedOperation {
{
this->m_overlay = overlay;
}
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
void update_memory_buffer_started(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -75,42 +75,4 @@ bool FlipOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
void FlipOperation::get_area_of_interest(const int input_idx,
const rcti &output_area,
rcti &r_input_area)
{
BLI_assert(input_idx == 0);
UNUSED_VARS_NDEBUG(input_idx);
if (this->m_flipX) {
const int w = (int)this->getWidth() - 1;
r_input_area.xmax = (w - output_area.xmin) + 1;
r_input_area.xmin = (w - output_area.xmax) - 1;
}
else {
r_input_area.xmin = output_area.xmin;
r_input_area.xmax = output_area.xmax;
}
if (this->m_flipY) {
const int h = (int)this->getHeight() - 1;
r_input_area.ymax = (h - output_area.ymin) + 1;
r_input_area.ymin = (h - output_area.ymax) - 1;
}
else {
r_input_area.ymin = output_area.ymin;
r_input_area.ymax = output_area.ymax;
}
}
void FlipOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
const MemoryBuffer *input_img = inputs[0];
for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
const int nx = this->m_flipX ? ((int)this->getWidth() - 1) - it.x : it.x;
const int ny = this->m_flipY ? ((int)this->getHeight() - 1) - it.y : it.y;
input_img->read_elem(nx, ny, it.out);
}
}
} // namespace blender::compositor

View File

@@ -18,11 +18,11 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
class FlipOperation : public MultiThreadedOperation {
class FlipOperation : public NodeOperation {
private:
SocketReader *m_inputOperation;
bool m_flipX;
@@ -45,11 +45,6 @@ class FlipOperation : public MultiThreadedOperation {
{
this->m_flipY = flipY;
}
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -26,7 +26,6 @@ GammaCorrectOperation::GammaCorrectOperation()
this->addInputSocket(DataType::Color);
this->addOutputSocket(DataType::Color);
this->m_inputProgram = nullptr;
flags.can_be_constant = true;
}
void GammaCorrectOperation::initExecution()
{
@@ -59,34 +58,6 @@ void GammaCorrectOperation::executePixelSampled(float output[4],
}
}
void GammaCorrectOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
const MemoryBuffer *input = inputs[0];
for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
float color[4];
input->read_elem(it.x, it.y, color);
if (color[3] > 0.0f) {
color[0] /= color[3];
color[1] /= color[3];
color[2] /= color[3];
}
/* Check for negative to avoid nan's. */
it.out[0] = color[0] > 0.0f ? color[0] * color[0] : 0.0f;
it.out[1] = color[1] > 0.0f ? color[1] * color[1] : 0.0f;
it.out[2] = color[2] > 0.0f ? color[2] * color[2] : 0.0f;
it.out[3] = color[3];
if (color[3] > 0.0f) {
it.out[0] *= color[3];
it.out[1] *= color[3];
it.out[2] *= color[3];
}
}
}
void GammaCorrectOperation::deinitExecution()
{
this->m_inputProgram = nullptr;
@@ -97,7 +68,6 @@ GammaUncorrectOperation::GammaUncorrectOperation()
this->addInputSocket(DataType::Color);
this->addOutputSocket(DataType::Color);
this->m_inputProgram = nullptr;
flags.can_be_constant = true;
}
void GammaUncorrectOperation::initExecution()
{
@@ -130,33 +100,6 @@ void GammaUncorrectOperation::executePixelSampled(float output[4],
}
}
void GammaUncorrectOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
const MemoryBuffer *input = inputs[0];
for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
float color[4];
input->read_elem(it.x, it.y, color);
if (color[3] > 0.0f) {
color[0] /= color[3];
color[1] /= color[3];
color[2] /= color[3];
}
it.out[0] = color[0] > 0.0f ? sqrtf(color[0]) : 0.0f;
it.out[1] = color[1] > 0.0f ? sqrtf(color[1]) : 0.0f;
it.out[2] = color[2] > 0.0f ? sqrtf(color[2]) : 0.0f;
it.out[3] = color[3];
if (color[3] > 0.0f) {
it.out[0] *= color[3];
it.out[1] *= color[3];
it.out[2] *= color[3];
}
}
}
void GammaUncorrectOperation::deinitExecution()
{
this->m_inputProgram = nullptr;

View File

@@ -18,11 +18,11 @@
#pragma once
#include "COM_MultiThreadedOperation.h"
#include "COM_NodeOperation.h"
namespace blender::compositor {
class GammaCorrectOperation : public MultiThreadedOperation {
class GammaCorrectOperation : public NodeOperation {
private:
/**
* Cached reference to the inputProgram
@@ -46,13 +46,9 @@ class GammaCorrectOperation : public MultiThreadedOperation {
* Deinitialize the execution
*/
void deinitExecution() override;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
class GammaUncorrectOperation : public MultiThreadedOperation {
class GammaUncorrectOperation : public NodeOperation {
private:
/**
* Cached reference to the inputProgram
@@ -76,10 +72,6 @@ class GammaUncorrectOperation : public MultiThreadedOperation {
* Deinitialize the execution
*/
void deinitExecution() override;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@@ -1,168 +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 2021, Blender Foundation.
*/
#include "COM_GaussianAlphaBlurBaseOperation.h"
namespace blender::compositor {
GaussianAlphaBlurBaseOperation::GaussianAlphaBlurBaseOperation(eDimension dim)
: BlurBaseOperation(DataType::Value)
{
this->m_gausstab = nullptr;
this->m_filtersize = 0;
this->m_falloff = -1; /* Intentionally invalid, so we can detect uninitialized values. */
dimension_ = dim;
}
void GaussianAlphaBlurBaseOperation::init_data()
{
BlurBaseOperation::init_data();
if (execution_model_ == eExecutionModel::FullFrame) {
rad_ = max_ff(m_size * this->get_blur_size(dimension_), 0.0f);
rad_ = min_ff(rad_, MAX_GAUSSTAB_RADIUS);
m_filtersize = min_ii(ceil(rad_), MAX_GAUSSTAB_RADIUS);
}
}
void GaussianAlphaBlurBaseOperation::initExecution()
{
BlurBaseOperation::initExecution();
if (execution_model_ == eExecutionModel::FullFrame) {
m_gausstab = BlurBaseOperation::make_gausstab(rad_, m_filtersize);
m_distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad_, m_filtersize, m_falloff);
}
}
void GaussianAlphaBlurBaseOperation::deinitExecution()
{
BlurBaseOperation::deinitExecution();
if (this->m_gausstab) {
MEM_freeN(this->m_gausstab);
this->m_gausstab = nullptr;
}
if (this->m_distbuf_inv) {
MEM_freeN(this->m_distbuf_inv);
this->m_distbuf_inv = nullptr;
}
}
void GaussianAlphaBlurBaseOperation::get_area_of_interest(const int input_idx,
const rcti &output_area,
rcti &r_input_area)
{
if (input_idx != IMAGE_INPUT_INDEX) {
BlurBaseOperation::get_area_of_interest(input_idx, output_area, r_input_area);
return;
}
r_input_area = output_area;
switch (dimension_) {
case eDimension::X:
r_input_area.xmin = output_area.xmin - m_filtersize - 1;
r_input_area.xmax = output_area.xmax + m_filtersize + 1;
break;
case eDimension::Y:
r_input_area.ymin = output_area.ymin - m_filtersize - 1;
r_input_area.ymax = output_area.ymax + m_filtersize + 1;
break;
}
}
BLI_INLINE float finv_test(const float f, const bool test)
{
return (LIKELY(test == false)) ? f : 1.0f - f;
}
void GaussianAlphaBlurBaseOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
MemoryBuffer *input = inputs[IMAGE_INPUT_INDEX];
const rcti &input_rect = input->get_rect();
BuffersIterator<float> it = output->iterate_with({input}, area);
int min_input_coord = -1;
int max_input_coord = -1;
int elem_stride = -1;
std::function<int()> get_current_coord;
switch (dimension_) {
case eDimension::X:
min_input_coord = input_rect.xmin;
max_input_coord = input_rect.xmax;
get_current_coord = [&] { return it.x; };
elem_stride = input->elem_stride;
break;
case eDimension::Y:
min_input_coord = input_rect.ymin;
max_input_coord = input_rect.ymax;
get_current_coord = [&] { return it.y; };
elem_stride = input->row_stride;
break;
}
for (; !it.is_end(); ++it) {
const int coord = get_current_coord();
const int coord_min = max_ii(coord - m_filtersize, min_input_coord);
const int coord_max = min_ii(coord + m_filtersize + 1, max_input_coord);
/* *** This is the main part which is different to #GaussianBlurBaseOperation. *** */
/* Gauss. */
float alpha_accum = 0.0f;
float multiplier_accum = 0.0f;
/* Dilate. */
const bool do_invert = m_do_subtract;
/* Init with the current color to avoid unneeded lookups. */
float value_max = finv_test(*it.in(0), do_invert);
float distfacinv_max = 1.0f; /* 0 to 1 */
const int step = QualityStepHelper::getStep();
const float *in = it.in(0) + ((intptr_t)coord_min - coord) * elem_stride;
const int in_stride = elem_stride * step;
int index = (coord_min - coord) + m_filtersize;
const int index_end = index + (coord_max - coord_min);
for (; index < index_end; in += in_stride, index += step) {
float value = finv_test(*in, do_invert);
/* Gauss. */
float multiplier = m_gausstab[index];
alpha_accum += value * multiplier;
multiplier_accum += multiplier;
/* Dilate - find most extreme color. */
if (value > value_max) {
multiplier = m_distbuf_inv[index];
value *= multiplier;
if (value > value_max) {
value_max = value;
distfacinv_max = multiplier;
}
}
}
/* Blend between the max value and gauss blue - gives nice feather. */
const float value_blur = alpha_accum / multiplier_accum;
const float value_final = (value_max * distfacinv_max) +
(value_blur * (1.0f - distfacinv_max));
*it.out = finv_test(value_final, do_invert);
}
}
} // namespace blender::compositor

View File

@@ -1,62 +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 2021, Blender Foundation.
*/
#pragma once
#include "COM_BlurBaseOperation.h"
namespace blender::compositor {
class GaussianAlphaBlurBaseOperation : public BlurBaseOperation {
protected:
float *m_gausstab;
float *m_distbuf_inv;
int m_falloff; /* Falloff for #distbuf_inv. */
bool m_do_subtract;
int m_filtersize;
float rad_;
eDimension dimension_;
public:
GaussianAlphaBlurBaseOperation(eDimension dim);
virtual void init_data() override;
virtual void initExecution() override;
virtual void deinitExecution() override;
void get_area_of_interest(const int input_idx,
const rcti &output_area,
rcti &r_input_area) final;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) final;
/**
* Set subtract for Dilate/Erode functionality
*/
void setSubtract(bool subtract)
{
this->m_do_subtract = subtract;
}
void setFalloff(int falloff)
{
this->m_falloff = falloff;
}
};
} // namespace blender::compositor

Some files were not shown because too many files have changed in this diff Show More