Compare commits
513 Commits
temp-geome
...
soc-2021-p
Author | SHA1 | Date | |
---|---|---|---|
38b12c763f | |||
49a16a1ca8 | |||
7ac9f9a97f | |||
cb66eb8da2 | |||
bfaf97dec9 | |||
8137c1be09 | |||
c674adb6f4 | |||
2fb714443c | |||
529a132cc9 | |||
6e58f6b304 | |||
9e4e3b5f5f | |||
844d975972 | |||
f5f2e685f5 | |||
7649b84462 | |||
6dda3a7f2e | |||
4a5d913d1d | |||
038b87b8b2 | |||
9887dac2fb | |||
33c35c9340 | |||
fad55ce70b | |||
ce4420e803 | |||
4bab2cca5d | |||
fb8c049232 | |||
45904e2dd1 | |||
ec0ebcdcc4 | |||
ee7b2e2678 | |||
bcb7f4c172 | |||
c54bdc7fb6 | |||
a28e518917 | |||
b60fa77678 | |||
4de8acc88d | |||
7df84749ad | |||
20d2c92119 | |||
745ff852f5 | |||
a7dc3d1e90 | |||
6fd836f53b | |||
991f6b15f3 | |||
aef45a4ef2 | |||
504e3c563f | |||
b5573bfbf4 | |||
ba9561ab0d | |||
c659af0c13 | |||
41f75384e7 | |||
383a8e519b | |||
6d2cc371b5 | |||
7a2994a741 | |||
326d86f23f | |||
17b7cbe975 | |||
94210c3186 | |||
9d2342fd28 | |||
86e359b03b | |||
4c8def9895 | |||
5e198321c2 | |||
c24be2dd44 | |||
3f29b8ec64 | |||
0b060a585d | |||
e5c7f12f8b | |||
5466552a42 | |||
ba06899b2a | |||
b23cdd5737 | |||
df5551fb15 | |||
11012a8fc1 | |||
300632742c | |||
17fba21226 | |||
4b0255238d | |||
83d537c950 | |||
ab66f1d792 | |||
4c97a026e7 | |||
6d296ff00b | |||
db796922c8 | |||
350d32f6d5 | |||
d917311776 | |||
3a5fd9713e | |||
![]() |
efee24c34e | ||
f68e8e4f23 | |||
35a4cef6b5 | |||
695dd31e34 | |||
5b0dfca417 | |||
9a9c533631 | |||
![]() |
f49bf8d05c | ||
48b6ccecb0 | |||
ce1e226b7c | |||
a4db9318fb | |||
03368c5344 | |||
9f8e938900 | |||
490b36b289 | |||
f36b7c0c8c | |||
660bcfc32d | |||
b4ee5b7934 | |||
a645d990d9 | |||
d13c3ac5d9 | |||
ae4affa280 | |||
49240bcd25 | |||
9ce2fc8a17 | |||
db5110e9d3 | |||
a8eb36b7ef | |||
b0e3e55036 | |||
![]() |
2bcdb4a19e | ||
641dade2be | |||
0f7254199b | |||
![]() |
7fa2e087f5 | ||
d19528020f | |||
c67137ab0d | |||
43f0494929 | |||
2c9e8a2f29 | |||
ffdf9fa1bf | |||
d360c5d8da | |||
3e6fd42290 | |||
c2087da3d3 | |||
31d0434344 | |||
b1602da72f | |||
8105cc6692 | |||
12298a5251 | |||
![]() |
5b6ced1346 | ||
6a5df54477 | |||
![]() |
d7f228a394 | ||
8c06fb2267 | |||
53ed446f1f | |||
8311cc98db | |||
cac41070c0 | |||
c4c2f117ff | |||
b9658d548c | |||
6bae63d69d | |||
7eb08a7ab0 | |||
122bad7f7a | |||
![]() |
a7ac6c014e | ||
1e35b59443 | |||
![]() |
3f55b127e7 | ||
4822a11bdd | |||
f79ac72208 | |||
f464c18540 | |||
7482a56554 | |||
035cf075e2 | |||
![]() |
26f3c8717d | ||
a2b0f4bc32 | |||
43111cdfdf | |||
e7694f68a1 | |||
9b13a5759b | |||
7ec4a83a6c | |||
![]() |
57c04b3165 | ||
59a9c07d09 | |||
f488c7ee69 | |||
9d1ce7d5a9 | |||
55fe618254 | |||
d7aa608ab7 | |||
04001b2b02 | |||
ba98a976cb | |||
![]() |
a2877c0caf | ||
947c098519 | |||
![]() |
95b6beb8d8 | ||
b85e249875 | |||
6c0f7276dc | |||
6333be56d9 | |||
0888a0af14 | |||
511f6ff09a | |||
b829b0b555 | |||
27b5d234ae | |||
62a84f0995 | |||
8bdbfee9d7 | |||
![]() |
9e56b50e9f | ||
77feb1dcac | |||
5c729d4c26 | |||
6e4f6f94e4 | |||
121e854ee2 | |||
f90cd854ec | |||
70b2d56e8d | |||
21d8d5279c | |||
![]() |
b6f5841d23 | ||
253d0ffe97 | |||
![]() |
370a3cf599 | ||
462c91debd | |||
0bc2620854 | |||
b18d421924 | |||
24011d3e9e | |||
ce1a4929c3 | |||
ee07416685 | |||
fc91ec92a3 | |||
5efb0d1d2e | |||
7ce8fce0fe | |||
ee10b21c55 | |||
e68767640e | |||
c19eea1d93 | |||
3d4454e641 | |||
dd3e69ea7a | |||
2933a0ec9b | |||
da860d5d1b | |||
426ac092ec | |||
9162d9827e | |||
![]() |
4fdfcde98d | ||
b1f3d49296 | |||
164e0ada87 | |||
e089f41bcd | |||
![]() |
8fb5731173 | ||
f137a3409b | |||
4c251dd864 | |||
5ab90b1052 | |||
63d957c645 | |||
2aac74b657 | |||
a109435043 | |||
1bdc33cc2a | |||
33569fc1f1 | |||
![]() |
4d25d74a1a | ||
b652f01504 | |||
ee367eecf4 | |||
01aa9f34af | |||
cf243cd302 | |||
![]() |
41f6c7b298 | ||
![]() |
292724c389 | ||
e16982fe94 | |||
3115e957d6 | |||
![]() |
aa23609f14 | ||
49e72bf3b0 | |||
ff7563fb57 | |||
76dbc9a0e9 | |||
e775f2239a | |||
46eeaa0544 | |||
b7ad67082b | |||
9848426848 | |||
209a07e3b5 | |||
![]() |
7a9822ace1 | ||
93e7fb464a | |||
0220c85f47 | |||
118f4dc93b | |||
5f35c9c3cd | |||
f4a30c2c20 | |||
7a129b0a6f | |||
5a0a69166b | |||
55e603a5bb | |||
c127093820 | |||
405c41e431 | |||
e9b69bbd85 | |||
![]() |
e18f76a0cb | ||
![]() |
61aca25ee2 | ||
7da330e57a | |||
5355f00f41 | |||
5d91724656 | |||
9eda619105 | |||
2610e7480b | |||
b2bfadf511 | |||
9b0c917f8a | |||
1dd6775ad7 | |||
3ac14e4220 | |||
b18e973f54 | |||
616816c694 | |||
b1c09892ad | |||
bcbc626a05 | |||
16ec757b94 | |||
![]() |
9744ca099e | ||
2c75332d4f | |||
12a26c3381 | |||
d2b00a5774 | |||
5e5b471789 | |||
3e179144a4 | |||
69c623ab16 | |||
9b4afce6a2 | |||
024e169d0f | |||
![]() |
e2c52ea2e7 | ||
a113eca4d4 | |||
26e15daa7a | |||
5b77e167ab | |||
9f0fad8b6d | |||
0c211e94f2 | |||
63acac2cf4 | |||
fb91ddeb9c | |||
8bfceff845 | |||
1af5e8cab1 | |||
3852211d2c | |||
49e4e4c08d | |||
40d270248d | |||
4f27228b0c | |||
84f565ed4f | |||
45f4c8ed78 | |||
55898b107e | |||
a7bf4ce629 | |||
60af1ead0c | |||
9f2a38db45 | |||
3e9f20ae90 | |||
eba3086802 | |||
7b03da863a | |||
41cc9fa930 | |||
8d88c7c811 | |||
c051cdc3df | |||
9150ba6845 | |||
879c922f2b | |||
212aa101a1 | |||
2c731304c3 | |||
9ae685bc97 | |||
2be5b2fcf0 | |||
745f6ac101 | |||
243d8df588 | |||
da79efd820 | |||
ccbd93299d | |||
bd0af14c16 | |||
4aa3f06f1f | |||
57e639caa1 | |||
ceb42e4cc5 | |||
![]() |
54c69bf729 | ||
8725fc5087 | |||
2b3f1fe2f2 | |||
![]() |
f0a98f14f0 | ||
88f33af4ac | |||
![]() |
41d4a7b55e | ||
43a0d4eecb | |||
8c8597a623 | |||
8ac3b212ef | |||
05b2831ff1 | |||
a6d9100505 | |||
956e41db7b | |||
0415578ce1 | |||
c155315698 | |||
8d79fe22ca | |||
e2ffe9d630 | |||
5c7968ab0d | |||
9a58acb71c | |||
233862ed04 | |||
58e2f62483 | |||
30f431aeac | |||
7a29a37e7b | |||
105850b750 | |||
1caf30a6a9 | |||
b3602acd22 | |||
38dd4ac4dd | |||
91b76b38be | |||
8428aec80e | |||
![]() |
c1bd9ecd01 | ||
![]() |
54c46ca4c1 | ||
ce382eec94 | |||
ae8cf5ecfd | |||
2e297933ca | |||
a0a35f78f3 | |||
c58b00a6af | |||
081638638c | |||
c0d5c13b46 | |||
9987a2b11e | |||
75feaceab8 | |||
e3b1fb44b4 | |||
612ac59fc9 | |||
33d495399f | |||
0a35fee6bc | |||
3c76c983aa | |||
7083656da3 | |||
fb797b18d5 | |||
dd7c341c32 | |||
58d1fe4790 | |||
caacb0f7bd | |||
135d1bd9ec | |||
a4cf4273fd | |||
4812ad4d26 | |||
e8d00e507a | |||
393fd9168f | |||
727d58dedd | |||
d0a2763b04 | |||
ab7046ab1c | |||
0d889f1f4c | |||
91b3814301 | |||
fada98c621 | |||
675536fd4b | |||
![]() |
5f4edeb367 | ||
f993802456 | |||
![]() |
8225cca4fb | ||
![]() |
5d7bb20b17 | ||
2b49389786 | |||
12e8ecd09c | |||
27d0c21eeb | |||
68e06b10d8 | |||
da777ab2e5 | |||
021eb28836 | |||
56ce9c8ff2 | |||
34e273c2ed | |||
eb525f8466 | |||
19e5a0783a | |||
9c4b18dd96 | |||
04d5bac6e6 | |||
1f30133770 | |||
1a1955776b | |||
d5d8f1f6cc | |||
0dbfb40d20 | |||
b7de6735c1 | |||
98f92c807a | |||
4aa2187dce | |||
694249940a | |||
e3d8f427d5 | |||
d948bd616d | |||
239bf16cc7 | |||
529913b2df | |||
2c6aeb6240 | |||
9503e34e99 | |||
5c79a2953b | |||
7f33ff779f | |||
80870aebd0 | |||
aaee6e13d4 | |||
096d6017cc | |||
18f45f874c | |||
607119dd3f | |||
d777efbf5c | |||
7425af128f | |||
9823ac0767 | |||
226ae2e69f | |||
0b654b04cb | |||
474828bf25 | |||
c21f9930bc | |||
906347042d | |||
0d8bb5f898 | |||
bcd1a5af89 | |||
de9dda76ab | |||
6beb133315 | |||
f9f3ece427 | |||
db07041c44 | |||
62ecb33642 | |||
e1f9b7442b | |||
7bad25040a | |||
c7a1eeaf7b | |||
b191448bcb | |||
0a75579e1f | |||
80f6798191 | |||
60c84d0a64 | |||
ef0e0af332 | |||
344b59b66c | |||
77116c1841 | |||
950f1bf476 | |||
d2b9cc41e7 | |||
1512c5c973 | |||
402422e8ab | |||
126026c63c | |||
79f8e7137d | |||
54a45d1c1b | |||
bcc1b614d8 | |||
7cacec80e5 | |||
d85d59afc9 | |||
703bdbe492 | |||
328084acb6 | |||
78322cbee6 | |||
9722c8348d | |||
f0f26b3fcb | |||
28ee6ef31a | |||
6afd66c2eb | |||
5379633e59 | |||
051ce30390 | |||
1f70e8b748 | |||
ecc67c10e1 | |||
75df5d34d3 | |||
aedf0f3efa | |||
97aab4245e | |||
897838a2cc | |||
0766941f8f | |||
bfbeabeb39 | |||
efcab1bc1b | |||
4a4445124e | |||
a58a4cfc14 | |||
c71b4ee3f6 | |||
496e3b2b1a | |||
fa06eb9b97 | |||
7d2b039942 | |||
a13e9edfbb | |||
00a3241095 | |||
171a1feeb3 | |||
c17b1601b7 | |||
931b1ed7c7 | |||
b51602996e | |||
1cc5ab539b | |||
f12f0f0cd9 | |||
2869ee328c | |||
84ecc6c3e1 | |||
0176d404f1 | |||
821b17be25 | |||
751679edc2 | |||
fd9932d380 | |||
da94c057fd | |||
a44785c4dc | |||
ef51c65775 | |||
b4ff2ce85d | |||
1640c3536f | |||
08fc5f1d8e | |||
339b7a7b03 | |||
5af6c35dd1 | |||
a33076f769 | |||
7026eca6e3 | |||
0291553d70 | |||
48fc1bde95 | |||
48dc0c6fd6 | |||
95bd8e494c | |||
328406cf60 | |||
3ecf0753e8 | |||
dbeb2a7724 | |||
f07aa393bf | |||
68a28e1982 | |||
f23bb03cbb | |||
1fcbade10c | |||
cbe359bbf2 | |||
3493fefb74 | |||
8f600e8256 | |||
607eef0ae7 | |||
035ee22a50 | |||
e39543a64d | |||
a97bfc4e31 | |||
30ea058694 | |||
6fad4ce981 | |||
c718d169a9 | |||
0a96b035cf | |||
39f1908ba9 | |||
1f38c1f3b2 | |||
5444335e44 | |||
531c65fd93 | |||
1e07e070fc | |||
29c0528eb6 | |||
174052e1de | |||
caac062b55 | |||
2f65eed0e7 | |||
ff8ad9b24b | |||
641d268d59 | |||
d82bda7b44 | |||
ded679d866 | |||
0ddfdb0dbf |
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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:
|
||||
|
@@ -37,7 +37,7 @@ if(WITH_AUDASPACE)
|
||||
add_subdirectory(audaspace)
|
||||
endif()
|
||||
|
||||
if(WITH_MOD_REMESH)
|
||||
if(WITH_REMESH_DUALCON)
|
||||
add_subdirectory(dualcon)
|
||||
endif()
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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)
|
||||
|
@@ -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"),
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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 */
|
||||
}
|
||||
|
@@ -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) {
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
@@ -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
|
@@ -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;
|
||||
|
@@ -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. */
|
||||
|
@@ -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:
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@@ -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
|
||||
|
@@ -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();
|
||||
}
|
@@ -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 ¤t_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);
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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");
|
||||
|
@@ -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());
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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},
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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();
|
||||
|
@@ -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. */
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
|
@@ -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'}},
|
||||
},
|
||||
|
@@ -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);
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -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) {
|
||||
|
@@ -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,
|
||||
|
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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) {
|
||||
|
@@ -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
|
||||
|
@@ -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(
|
||||
|
@@ -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));
|
||||
}
|
||||
|
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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
|
@@ -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
Reference in New Issue
Block a user