Compare commits

..

139 Commits

Author SHA1 Message Date
24d1c352e8 Make branch compile after recent multifunction network removal 2021-08-23 14:41:44 -05:00
b3639670ee Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-23 14:10:39 -05:00
ea3ee04fa8 Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-20 12:42:11 +02:00
4838436387 fix extrude node 2021-08-20 12:42:07 +02:00
62d485e470 initial evaluate curve node 2021-08-18 14:53:34 +02:00
cd6eb65482 cleanup 2021-08-18 14:44:16 +02:00
d337c20cf9 fix use after free in socket inspection
For now I just evaluate constant fields immediately. The issue was that
parts of the fields was freed already when socket inspection runs.
2021-08-18 13:31:41 +02:00
a715aec6a3 initial sample mesh surface
This is a field based alternative for the attribute transfer node.
The main goal here is to experiment with how attribute transfer
should be done with fields.
2021-08-18 12:53:23 +02:00
eba32b5f4a cleanup 2021-08-18 10:29:40 +02:00
1d859c9183 fix after merge 2021-08-18 10:20:59 +02:00
a3d02965da fix after merge 2021-08-18 10:17:28 +02:00
45e58a7e92 Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-18 10:17:15 +02:00
c920b83b84 Fix curve parameter node with multiple splines 2021-08-10 12:09:19 -05:00
34e0d8079f Add 1D noise to noise texture node 2021-08-10 11:58:11 -05:00
a376073f1e Fix curve length node (output a field, otherwise it crashes) 2021-08-10 11:57:42 -05:00
29ac510198 Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-10 10:56:57 -05:00
d7cf8babf2 Merge branch 'temp-geometry-nodes-fields-prototype' of git.blender.org:blender into temp-geometry-nodes-fields-prototype 2021-08-10 10:56:23 -05:00
3becd4cb61 Fix curve parameter field with cyclic poly splines 2021-08-10 10:56:17 -05:00
52bb0d42b3 correct socket shape 2021-08-10 17:23:15 +02:00
acae8f430d simplify switching between value and attribute in modifier 2021-08-10 16:55:41 +02:00
bbb692ffb5 add Set Position node 2021-08-10 16:10:06 +02:00
df6a819982 rename to Attribute Freeze 2021-08-10 15:53:41 +02:00
48f2643556 remove dead code 2021-08-10 15:42:15 +02:00
d4b441851f new Position node 2021-08-10 15:33:19 +02:00
e0406d029d Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-10 15:11:56 +02:00
c5c82f801a Merge remote-tracking branch 'origin/temp-geometry-nodes-fields-prototype' into temp-geometry-nodes-fields-prototype 2021-08-10 10:45:30 +02:00
78c0e7c015 Fix: Extrude and Move Edge out selection 2021-08-10 10:45:23 +02:00
fd0ac1aec5 fix node id 2021-08-10 10:08:06 +02:00
0827cce9de Merge remote-tracking branch 'origin/temp-geometry-nodes-fields-prototype' into temp-geometry-nodes-fields-prototype
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
2021-08-10 09:34:04 +02:00
2bba77045f Extrude and Move Node
This adds an additional version of the extrude node, which operates on
vertices, edges and faces and moves the extruded region by a given
offset vector.
2021-08-10 09:33:24 +02:00
00ecf29ec4 fix curve parameter type 2021-08-10 08:25:33 +02:00
172e713cc6 Add curve parameter node 2021-08-09 17:12:19 -05:00
5c32227025 Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-09 15:35:06 -05:00
fa9d1cb2a9 properly adapt selection domain 2021-08-09 19:31:32 +02:00
577a12f840 add Normal node 2021-08-09 11:29:04 +02:00
8dad29d0ea new Attribute Extract node 2021-08-09 11:10:57 +02:00
4eda4fd49a support field in point separate node 2021-08-09 09:49:53 +02:00
1db53a8923 Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-09 09:12:48 +02:00
20aba8a4c0 Merge remote-tracking branch 'origin/temp-geometry-nodes-fields-prototype' into temp-geometry-nodes-fields-prototype 2021-08-08 04:59:25 +02:00
1d53bf0412 Cleanup: Remove unused variable 2021-08-06 19:00:58 -05:00
1177debb01 Support selection in the point translate node 2021-08-06 17:56:41 -05:00
047daf5442 Don't draw special "constant" sockets in more cases 2021-08-06 17:33:58 -05:00
f2112199a4 Add utilities to enable and disable output sockets with a type 2021-08-06 17:08:22 -05:00
36de290807 Fix incorrect SOCK_FIELD cases 2021-08-06 16:58:24 -05:00
c09a535333 Cleanup: Rename flag
This tends to fit on one line more often
2021-08-06 16:24:22 -05:00
4e78bb3f0c Draw constant input sockets that don't support fields differently
This is a really incomplete way to do this (it doesn't propogate to
linked nodes, and I haven't though about outputs), but it still provides
a very nice benefit to readability.
2021-08-06 16:23:34 -05:00
49f33e9820 Merge remote-tracking branch 'origin/temp-geometry-nodes-fields-prototype' into temp-geometry-nodes-fields-prototype
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
#	source/blender/bmesh/intern/bmesh_mesh.h
#	source/blender/nodes/geometry/nodes/node_geo_extrude.cc
2021-08-06 22:36:31 +02:00
6f525e0d98 Upgrade extrude node with field inputs and selection outputs 2021-08-06 14:55:32 -05:00
963448a2af Cleanup: Remove unused code 2021-08-06 14:53:35 -05:00
9506ef320e Merge branch 'soc-2021-porting-modifiers-to-nodes-extrude' into temp-geometry-nodes-fields-prototype
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
#	source/blender/blenkernel/intern/node.cc
#	source/blender/bmesh/intern/bmesh_mesh.c
#	source/blender/bmesh/intern/bmesh_mesh.h
#	source/blender/nodes/CMakeLists.txt
#	source/blender/nodes/NOD_geometry.h
#	source/blender/nodes/NOD_static_types.h
#	source/blender/nodes/geometry/nodes/node_geo_extrude.cc
2021-08-06 20:25:44 +02:00
1700fde0dc Output anonymous attribute in select by handle node 2021-08-06 12:45:21 -05:00
d5a83a5a32 Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-06 12:33:00 -05:00
a7dc3d1e90 Merge remote-tracking branch 'origin/soc-2021-porting-modifiers-to-nodes-extrude' into soc-2021-porting-modifiers-to-nodes-extrude 2021-08-06 07:53:56 +02:00
6fd836f53b Merged Master 2021-08-06 07:48:40 +02:00
40455c21fa Support switching between two fields in the switch node 2021-08-05 18:10:28 -05:00
2d0442e943 Use "true" defaults for selection fields 2021-08-05 17:50:33 -05:00
d55046b167 Support field for curve set spline type selection 2021-08-05 17:50:23 -05:00
4233128fa5 Add a node to store a field in a geometry and output an anonymous attribute 2021-08-05 17:43:15 -05:00
798496233a Rename the "Attribute Fill" node to "Store Persistent Attribute" 2021-08-05 17:42:57 -05:00
991f6b15f3 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-extrude
# Conflicts:
#	source/blender/blenkernel/BKE_node.h
2021-08-05 23:50:08 +02:00
aef45a4ef2 Merge remote-tracking branch 'origin/soc-2021-porting-modifiers-to-nodes-extrude' into soc-2021-porting-modifiers-to-nodes-extrude
# Conflicts:
#	source/blender/bmesh/intern/bmesh_mesh.c
#	source/blender/bmesh/intern/bmesh_mesh.h
#	source/blender/nodes/NOD_static_types.h
#	source/blender/nodes/geometry/nodes/node_geo_extrude.cc
2021-08-05 23:48:58 +02:00
504e3c563f added side selection. 2021-08-05 23:47:44 +02:00
8645ea16de Remove attribute nodes that have been made redundant 2021-08-05 14:48:18 -05:00
5e292d923f Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-05 14:13:16 -05:00
1ab1d6665c Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-04 18:13:45 -05:00
b1c98ad8ee Fix compile warning 2021-08-03 16:51:01 -04:00
e9d95fddf9 Add tweaked mesh extrude node from Fabian 2021-08-03 16:30:48 -04:00
782d240a1b Fix crash in the Is Viewport node 2021-08-03 16:12:18 -04:00
36055ba366 Remove density max socket from the point distribute node 2021-08-03 16:05:10 -04:00
236576fc91 Support anonymous attributes in the proximity node 2021-08-03 15:49:20 -04:00
e7d57e84bb Move "Align Rotation to Vector" to a function node without geometry
The node is still slightly finnicky, I may have done something wrong here.
But it generally works.
2021-08-03 15:07:55 -04:00
b5573bfbf4 Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-extrude 2021-08-03 21:02:56 +02:00
3b2522650b Don't show face corner domain in the geometry delete node 2021-08-03 12:56:26 -04:00
eacc1f1ff4 Fix raycast and geometry delete node for multi-spline curves 2021-08-03 12:51:13 -04:00
9562a90632 Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-03 09:01:23 -04:00
2ceeaf95a1 Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-03 10:44:41 +02:00
c8de9dc2a4 Cleanup: Unused variable warning 2021-08-03 00:28:03 -04:00
f8f2873b44 Support fields in the curve set handles node 2021-08-03 00:11:20 -04:00
648fa6d89e Support fields in the curve subdivide node 2021-08-02 23:58:33 -04:00
d24419564e Fix unhandled switch cases 2021-08-02 23:58:19 -04:00
184be40aa1 Support field selection in the mesh to curve node 2021-08-02 23:49:33 -04:00
6131506689 Support anonymous attributse in the select by material node 2021-08-02 23:42:01 -04:00
e5f43cf4b7 Support fields in the material assign node 2021-08-02 23:33:36 -04:00
770d70127f Support fields and anonymous attributes in the raycast node 2021-08-02 23:29:32 -04:00
801034ba6a Support field selection in the geometry delete node 2021-08-02 22:42:34 -04:00
17442bcb7b Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-02 21:54:16 -04:00
ba9561ab0d Geometry Nodes: Extrude
Differential Revision: https://developer.blender.org/D12108
2021-08-02 19:04:04 +02:00
c659af0c13 Geometry Nodes: Extrude 2021-08-02 19:02:38 +02:00
dd8be48466 cleanup after merge 2021-08-02 13:07:31 +02:00
5914b8ed6b Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-02 12:56:18 +02:00
50da3cfbd6 Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-02 10:39:37 +02:00
131e8c0d59 Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-08-02 10:00:49 +02:00
aedd43b33f support field in Points to Volume node 2021-07-30 17:37:07 +02:00
adb437ad3f support socket inspection for fields 2021-07-30 17:16:00 +02:00
c106ed8fcd fix 2021-07-30 15:22:03 +02:00
11a6a56982 support fields in point translate node 2021-07-30 15:10:41 +02:00
0a7ab583a5 fix noise node 2021-07-30 15:04:14 +02:00
09009ce062 automatically change type in attribute node when selecting attribute 2021-07-30 13:56:40 +02:00
dc502fad43 support passing attribute field from modifier 2021-07-30 13:42:07 +02:00
3abce9e633 support modifier inputs again 2021-07-30 12:30:32 +02:00
dad5c3991c cleanup 2021-07-30 12:23:19 +02:00
dab3a07659 cleanup 2021-07-30 12:02:05 +02:00
53a724c804 Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-07-30 11:39:59 +02:00
bacde38b67 refactor point distribute node 2021-07-29 21:41:01 +02:00
d9b128baf2 don't show anonymous attributes in attribute search 2021-07-29 21:40:50 +02:00
ae6c063b33 don't show anonymous attributes in spreadsheet 2021-07-29 21:03:52 +02:00
67e7aee853 fixes 2021-07-29 20:56:59 +02:00
302ab3ff7c cleanup 2021-07-29 19:56:54 +02:00
4352d1beb5 support anonymous attribute field input 2021-07-29 19:38:39 +02:00
32cb953b9b anonymous attribute fields 2021-07-29 19:28:58 +02:00
1d92a4d1a0 initial anonymous attributes implementation 2021-07-29 19:16:09 +02:00
2472b0f0ef Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-07-29 10:21:22 +02:00
626be25646 support attribute search in Attribute node 2021-07-28 15:41:00 +02:00
8132383662 new index node and fixes 2021-07-28 15:12:53 +02:00
f95214e9ae support implicit conversion of fields 2021-07-28 14:04:14 +02:00
dde42e19e3 support cpptype inheritance for templates 2021-07-28 13:37:29 +02:00
f90a83f816 support field in Point Instance node 2021-07-28 12:30:56 +02:00
433b4ae22a better field support in attribute fill node 2021-07-28 12:05:53 +02:00
23e217eafc support position input in noise node 2021-07-28 11:49:30 +02:00
87153cf019 progress 2021-07-28 11:33:00 +02:00
08122a7794 Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-07-28 10:54:16 +02:00
58af171bc0 initial support for noise node 2021-07-27 17:15:13 +02:00
c98a535f5f fix 2021-07-27 17:06:57 +02:00
8262e6a0c1 progress 2021-07-27 17:00:37 +02:00
c00cc9fd60 improve 2021-07-27 16:29:34 +02:00
0a31b1f044 initial attribute field 2021-07-27 16:01:37 +02:00
5e3b33dfe8 Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-07-27 15:49:46 +02:00
f716060408 improve 2021-07-27 14:33:35 +02:00
aa092f4e6f Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-07-27 13:54:17 +02:00
ad8dfb3823 cleanup 2021-07-26 18:18:11 +02:00
bb0e0fde32 cleanup 2021-07-26 17:17:23 +02:00
3472f83f00 cleanup 2021-07-26 17:07:45 +02:00
1b2b07fb18 progress 2021-07-26 16:34:28 +02:00
64a11ba6a2 progress 2021-07-26 15:21:15 +02:00
26d8d2884c Merge branch 'master' into temp-geometry-nodes-fields-prototype 2021-07-26 11:44:31 +02:00
12014ccfbc progress 2021-07-10 12:14:48 +02:00
34cebfbb78 progress 2021-07-10 11:22:48 +02:00
2cc4e1572a progress 2021-07-09 18:32:57 +02:00
ceb9e7d71e initial commit 2021-07-09 17:48:51 +02:00
707 changed files with 13256 additions and 22498 deletions

View File

@@ -151,8 +151,8 @@ if(MSVC_CLANG) # Clangs version of cl doesn't support all flags
string(APPEND CMAKE_CXX_FLAGS " ${CXX_WARN_FLAGS} /nologo /J /Gd /EHsc -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference ")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference")
else()
string(APPEND CMAKE_CXX_FLAGS " /nologo /J /Gd /MP /EHsc /bigobj /Zc:inline")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP /bigobj /Zc:inline")
string(APPEND CMAKE_CXX_FLAGS " /nologo /J /Gd /MP /EHsc /bigobj")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP /bigobj")
endif()
# X64 ASAN is available and usable on MSVC 16.9 preview 4 and up)

View File

@@ -31,7 +31,6 @@ def parse_arguments():
parser.add_argument("--no-submodules", action="store_true")
parser.add_argument("--use-tests", action="store_true")
parser.add_argument("--svn-command", default="svn")
parser.add_argument("--svn-branch", default=None)
parser.add_argument("--git-command", default="git")
parser.add_argument("--use-centos-libraries", action="store_true")
return parser.parse_args()
@@ -47,7 +46,7 @@ def svn_update(args, release_version):
svn_non_interactive = [args.svn_command, '--non-interactive']
lib_dirpath = os.path.join(get_blender_git_root(), '..', 'lib')
svn_url = make_utils.svn_libraries_base_url(release_version, args.svn_branch)
svn_url = make_utils.svn_libraries_base_url(release_version)
# Checkout precompiled libraries
if sys.platform == 'darwin':
@@ -171,28 +170,26 @@ def submodules_update(args, release_version, branch):
sys.stderr.write("git not found, can't update code\n")
sys.exit(1)
# Update submodules to appropriate given branch,
# falling back to master if none is given and/or found in a sub-repository.
branch_fallback = "master"
if not branch:
branch = branch_fallback
# Update submodules to latest master or appropriate release branch.
if not release_version:
branch = "master"
submodules = [
("release/scripts/addons", branch, branch_fallback),
("release/scripts/addons_contrib", branch, branch_fallback),
("release/datafiles/locale", branch, branch_fallback),
("source/tools", branch, branch_fallback),
("release/scripts/addons", branch),
("release/scripts/addons_contrib", branch),
("release/datafiles/locale", branch),
("source/tools", branch),
]
# Initialize submodules only if needed.
for submodule_path, submodule_branch, submodule_branch_fallback in submodules:
for submodule_path, submodule_branch in submodules:
if not os.path.exists(os.path.join(submodule_path, ".git")):
call([args.git_command, "submodule", "update", "--init", "--recursive"])
break
# Checkout appropriate branch and pull changes.
skip_msg = ""
for submodule_path, submodule_branch, submodule_branch_fallback in submodules:
for submodule_path, submodule_branch in submodules:
cwd = os.getcwd()
try:
os.chdir(submodule_path)
@@ -204,11 +201,6 @@ def submodules_update(args, release_version, branch):
call([args.git_command, "fetch", "origin"])
call([args.git_command, "checkout", submodule_branch])
call([args.git_command, "pull", "--rebase", "origin", submodule_branch])
# If we cannot find the specified branch for this submodule, fallback to default one (aka master).
if make_utils.git_branch(args.git_command) != submodule_branch:
call([args.git_command, "fetch", "origin"])
call([args.git_command, "checkout", submodule_branch_fallback])
call([args.git_command, "pull", "--rebase", "origin", submodule_branch_fallback])
finally:
os.chdir(cwd)

View File

@@ -70,11 +70,9 @@ def git_branch_release_version(branch, tag):
return release_version
def svn_libraries_base_url(release_version, branch):
def svn_libraries_base_url(release_version):
if release_version:
svn_branch = "tags/blender-" + release_version + "-release"
elif branch:
svn_branch = "branches/" + branch
else:
svn_branch = "trunk"
return "https://svn.blender.org/svnroot/bf-blender/" + svn_branch + "/lib/"

View File

@@ -1,4 +1,4 @@
if EXIST "%PYTHON%" (
if EXIST %PYTHON% (
goto detect_python_done
)

View File

@@ -1039,17 +1039,13 @@ context_type_map = {
# context_member: (RNA type, is_collection)
"active_annotation_layer": ("GPencilLayer", False),
"active_bone": ("EditBone", False),
"active_file": ("FileSelectEntry", False),
"active_gpencil_frame": ("GreasePencilLayer", True),
"active_gpencil_layer": ("GPencilLayer", True),
"active_node": ("Node", False),
"active_object": ("Object", False),
"active_operator": ("Operator", False),
"active_pose_bone": ("PoseBone", False),
"active_sequence_strip": ("Sequence", False),
"active_editable_fcurve": ("FCurve", False),
"active_nla_strip": ("NlaStrip", False),
"active_nla_track": ("NlaTrack", False),
"annotation_data": ("GreasePencil", False),
"annotation_data_owner": ("ID", False),
"armature": ("Armature", False),
@@ -1078,7 +1074,6 @@ context_type_map = {
"gpencil_data": ("GreasePencil", False),
"gpencil_data_owner": ("ID", False),
"hair": ("Hair", False),
"id": ("ID", False),
"image_paint_object": ("Object", False),
"lattice": ("Lattice", False),
"light": ("Light", False),
@@ -1107,7 +1102,6 @@ context_type_map = {
"selected_editable_keyframes": ("Keyframe", True),
"selected_editable_objects": ("Object", True),
"selected_editable_sequences": ("Sequence", True),
"selected_files": ("FileSelectEntry", True),
"selected_nla_strips": ("NlaStrip", True),
"selected_nodes": ("Node", True),
"selected_objects": ("Object", True),
@@ -1204,7 +1198,6 @@ def pycontext2sphinx(basepath):
"text_context_dir",
"clip_context_dir",
"sequencer_context_dir",
"file_context_dir",
)
unique = set()
@@ -2002,7 +1995,7 @@ def write_rst_importable_modules(basepath):
"blf": "Font Drawing",
"imbuf": "Image Buffer",
"imbuf.types": "Image Buffer Types",
"gpu": "GPU Module",
"gpu": "GPU Shader Module",
"gpu.types": "GPU Types",
"gpu.matrix": "GPU Matrix Utilities",
"gpu.select": "GPU Select Utilities",

View File

@@ -8,7 +8,7 @@
# YOUR INSTALLATION PATHS GO HERE:
MANTA_INSTALLATION=/Users/sebbas/Developer/Mantaflow/mantaflowDevelop
BLENDER_INSTALLATION=/Users/sebbas/Developer/Blender
BLENDER_INSTALLATION=/Users/sebbas/Developer/Blender/fluid-mantaflow
# Try to check out Mantaflow repository before building?
CLEAN_REPOSITORY=0

View File

@@ -28,13 +28,11 @@ extern PyTypeObject PbVec3Type;
extern PyTypeObject PbVec4Type;
struct PbVec3 {
PyObject_HEAD
float data[3];
PyObject_HEAD float data[3];
};
struct PbVec4 {
PyObject_HEAD
float data[4];
PyObject_HEAD float data[4];
};
PyObject *getPyNone()

View File

@@ -25,8 +25,7 @@ namespace Manta {
extern PyTypeObject PbVec3Type;
struct PbVec3 {
PyObject_HEAD
float data[3];
PyObject_HEAD float data[3];
};
static void PbVec3Dealloc(PbVec3 *self)
@@ -294,8 +293,7 @@ inline PyObject *castPy(PyTypeObject *p)
extern PyTypeObject PbVec4Type;
struct PbVec4 {
PyObject_HEAD
float data[4];
PyObject_HEAD float data[4];
};
static PyMethodDef PbVec4Methods[] = {

View File

@@ -76,8 +76,7 @@ struct ClassData {
};
struct PbObject {
PyObject_HEAD
Manta::PbClass *instance;
PyObject_HEAD Manta::PbClass *instance;
ClassData *classdef;
};

View File

@@ -874,136 +874,6 @@ static const Vec3i nb[6] = {Vec3i(1, 0, 0),
Vec3i(0, 0, 1),
Vec3i(0, 0, -1)};
struct knMarkSkipCells : public KernelBase {
knMarkSkipCells(Grid<Real> &phi, Grid<int> &tmp, bool inside)
: KernelBase(&phi, 1), phi(phi), tmp(tmp), inside(inside)
{
runMessage();
run();
}
inline void op(int i, int j, int k, Grid<Real> &phi, Grid<int> &tmp, bool inside) const
{
if (!inside && phi(i, j, k) < 0.) {
tmp(i, j, k) = 1;
}
if (inside && phi(i, j, k) > 0.) {
tmp(i, j, k) = 1;
}
}
inline Grid<Real> &getArg0()
{
return phi;
}
typedef Grid<Real> type0;
inline Grid<int> &getArg1()
{
return tmp;
}
typedef Grid<int> type1;
inline bool &getArg2()
{
return inside;
}
typedef bool type2;
void runMessage()
{
debMsg("Executing kernel knMarkSkipCells ", 3);
debMsg("Kernel range"
<< " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
const int _maxX = maxX;
const int _maxY = maxY;
if (maxZ > 1) {
for (int k = __r.begin(); k != (int)__r.end(); k++)
for (int j = 1; j < _maxY; j++)
for (int i = 1; i < _maxX; i++)
op(i, j, k, phi, tmp, inside);
}
else {
const int k = 0;
for (int j = __r.begin(); j != (int)__r.end(); j++)
for (int i = 1; i < _maxX; i++)
op(i, j, k, phi, tmp, inside);
}
}
void run()
{
if (maxZ > 1)
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
else
tbb::parallel_for(tbb::blocked_range<IndexInt>(1, maxY), *this);
}
Grid<Real> &phi;
Grid<int> &tmp;
bool inside;
};
struct knSetFirstLayer : public KernelBase {
knSetFirstLayer(Grid<int> &tmp, int dim) : KernelBase(&tmp, 1), tmp(tmp), dim(dim)
{
runMessage();
run();
}
inline void op(int i, int j, int k, Grid<int> &tmp, int dim) const
{
Vec3i p(i, j, k);
if (tmp(p))
return;
for (int n = 0; n < 2 * dim; ++n) {
if (tmp(p + nb[n]) == 1) {
tmp(i, j, k) = 2;
break;
}
}
}
inline Grid<int> &getArg0()
{
return tmp;
}
typedef Grid<int> type0;
inline int &getArg1()
{
return dim;
}
typedef int type1;
void runMessage()
{
debMsg("Executing kernel knSetFirstLayer ", 3);
debMsg("Kernel range"
<< " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
const int _maxX = maxX;
const int _maxY = maxY;
if (maxZ > 1) {
for (int k = __r.begin(); k != (int)__r.end(); k++)
for (int j = 1; j < _maxY; j++)
for (int i = 1; i < _maxX; i++)
op(i, j, k, tmp, dim);
}
else {
const int k = 0;
for (int j = __r.begin(); j != (int)__r.end(); j++)
for (int i = 1; i < _maxX; i++)
op(i, j, k, tmp, dim);
}
}
void run()
{
if (maxZ > 1)
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
else
tbb::parallel_for(tbb::blocked_range<IndexInt>(1, maxY), *this);
}
Grid<int> &tmp;
int dim;
};
template<class S> struct knExtrapolateLsSimple : public KernelBase {
knExtrapolateLsSimple(Grid<S> &val, int distance, Grid<int> &tmp, const int d, S direction)
: KernelBase(&val, 1), val(val), distance(distance), tmp(tmp), d(d), direction(direction)
@@ -1173,12 +1043,39 @@ void extrapolateLsSimple(Grid<Real> &phi, int distance = 4, bool inside = false)
tmp.clear();
const int dim = (phi.is3D() ? 3 : 2);
// by default, march outside (ie mark all inside to be skipped)
Real direction = (inside) ? -1. : 1.;
knMarkSkipCells(phi, tmp, inside);
// by default, march outside
Real direction = 1.;
if (!inside) {
// mark all inside
FOR_IJK_BND(phi, 1)
{
if (phi(i, j, k) < 0.) {
tmp(i, j, k) = 1;
}
}
}
else {
direction = -1.;
FOR_IJK_BND(phi, 1)
{
if (phi(i, j, k) > 0.) {
tmp(i, j, k) = 1;
}
}
}
// + first layer around
knSetFirstLayer(tmp, dim);
FOR_IJK_BND(phi, 1)
{
Vec3i p(i, j, k);
if (tmp(p))
continue;
for (int n = 0; n < 2 * dim; ++n) {
if (tmp(p + nb[n]) == 1) {
tmp(i, j, k) = 2;
n = 2 * dim;
}
}
}
// extrapolate for distance
for (int d = 2; d < 1 + distance; ++d) {
@@ -1229,12 +1126,37 @@ void extrapolateVec3Simple(Grid<Vec3> &vel, Grid<Real> &phi, int distance = 4, b
tmp.clear();
const int dim = (vel.is3D() ? 3 : 2);
// mark initial cells, by default, march outside (ie mark all inside to be skipped)
Real direction = (inside) ? -1. : 1.;
knMarkSkipCells(phi, tmp, inside);
// mark initial cells, by default, march outside
if (!inside) {
// mark all inside
FOR_IJK_BND(phi, 1)
{
if (phi(i, j, k) < 0.) {
tmp(i, j, k) = 1;
}
}
}
else {
FOR_IJK_BND(phi, 1)
{
if (phi(i, j, k) > 0.) {
tmp(i, j, k) = 1;
}
}
}
// + first layer next to initial cells
knSetFirstLayer(tmp, dim);
FOR_IJK_BND(vel, 1)
{
Vec3i p(i, j, k);
if (tmp(p))
continue;
for (int n = 0; n < 2 * dim; ++n) {
if (tmp(p + nb[n]) == 1) {
tmp(i, j, k) = 2;
n = 2 * dim;
}
}
}
for (int d = 2; d < 1 + distance; ++d) {
knExtrapolateLsSimple<Vec3>(vel, distance, tmp, d, Vec3(0.));

View File

@@ -1,3 +1,3 @@
#define MANTA_GIT_VERSION "commit d5d9a6c28daa8f21426d7a285f48639c0d8fd13f"
#define MANTA_GIT_VERSION "commit 8fbebe02459b7f72575872c20961f7cb757db408"

View File

@@ -60,108 +60,9 @@
# define JE_FORCE_SYNC_COMPARE_AND_SWAP_8
#endif
/* Define the `ATOMIC_FORCE_USE_FALLBACK` to force lock-based fallback implementation to be used
* (even on platforms where there is native implementation available via compiler.
* Useful for development purposes. */
#undef ATOMIC_FORCE_USE_FALLBACK
/* -------------------------------------------------------------------- */
/** \name Spin-lock implementation
*
* Used to implement atomics on unsupported platforms.
* The spin implementation is shared for all platforms to make sure it compiles and tested.
* \{ */
typedef struct AtomicSpinLock {
volatile int lock;
/* Pad the structure size to a cache-line, to avoid unwanted sharing with other data. */
int pad[32 - sizeof(int)];
} __attribute__((aligned(32))) AtomicSpinLock;
ATOMIC_INLINE void atomic_spin_lock(volatile AtomicSpinLock *lock)
{
while (__sync_lock_test_and_set(&lock->lock, 1)) {
while (lock->lock) {
}
}
}
ATOMIC_INLINE void atomic_spin_unlock(volatile AtomicSpinLock *lock)
{
__sync_lock_release(&lock->lock);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Common part of locking fallback implementation
* \{ */
/* Global lock, shared by all atomic operations implementations.
*
* Could be split into per-size locks, although added complexity and being more error-proone does
* not seem to worth it for a fall-back implementation. */
static _ATOMIC_MAYBE_UNUSED AtomicSpinLock _atomic_global_lock = {0};
#define ATOMIC_LOCKING_OP_AND_FETCH_DEFINE(_type, _op_name, _op) \
ATOMIC_INLINE _type##_t atomic_##_op_name##_and_fetch_##_type(_type##_t *p, _type##_t x) \
{ \
atomic_spin_lock(&_atomic_global_lock); \
const _type##_t original_value = *(p); \
const _type##_t new_value = original_value _op(x); \
*(p) = new_value; \
atomic_spin_unlock(&_atomic_global_lock); \
return new_value; \
}
#define ATOMIC_LOCKING_FETCH_AND_OP_DEFINE(_type, _op_name, _op) \
ATOMIC_INLINE _type##_t atomic_fetch_and_##_op_name##_##_type(_type##_t *p, _type##_t x) \
{ \
atomic_spin_lock(&_atomic_global_lock); \
const _type##_t original_value = *(p); \
*(p) = original_value _op(x); \
atomic_spin_unlock(&_atomic_global_lock); \
return original_value; \
}
#define ATOMIC_LOCKING_ADD_AND_FETCH_DEFINE(_type) \
ATOMIC_LOCKING_OP_AND_FETCH_DEFINE(_type, add, +)
#define ATOMIC_LOCKING_SUB_AND_FETCH_DEFINE(_type) \
ATOMIC_LOCKING_OP_AND_FETCH_DEFINE(_type, sub, -)
#define ATOMIC_LOCKING_FETCH_AND_ADD_DEFINE(_type) \
ATOMIC_LOCKING_FETCH_AND_OP_DEFINE(_type, add, +)
#define ATOMIC_LOCKING_FETCH_AND_SUB_DEFINE(_type) \
ATOMIC_LOCKING_FETCH_AND_OP_DEFINE(_type, sub, -)
#define ATOMIC_LOCKING_FETCH_AND_OR_DEFINE(_type) ATOMIC_LOCKING_FETCH_AND_OP_DEFINE(_type, or, |)
#define ATOMIC_LOCKING_FETCH_AND_AND_DEFINE(_type) \
ATOMIC_LOCKING_FETCH_AND_OP_DEFINE(_type, and, &)
#define ATOMIC_LOCKING_CAS_DEFINE(_type) \
ATOMIC_INLINE _type##_t atomic_cas_##_type(_type##_t *v, _type##_t old, _type##_t _new) \
{ \
atomic_spin_lock(&_atomic_global_lock); \
const _type##_t original_value = *v; \
if (*v == old) { \
*v = _new; \
} \
atomic_spin_unlock(&_atomic_global_lock); \
return original_value; \
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name 64-bit operations
* \{ */
#if !defined(ATOMIC_FORCE_USE_FALLBACK) && \
(defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_8))
/******************************************************************************/
/* 64-bit operations. */
#if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_8))
/* Unsigned */
ATOMIC_INLINE uint64_t atomic_add_and_fetch_uint64(uint64_t *p, uint64_t x)
{
@@ -214,7 +115,7 @@ ATOMIC_INLINE int64_t atomic_cas_int64(int64_t *v, int64_t old, int64_t _new)
return __sync_val_compare_and_swap(v, old, _new);
}
#elif !defined(ATOMIC_FORCE_USE_FALLBACK) && (defined(__amd64__) || defined(__x86_64__))
#elif (defined(__amd64__) || defined(__x86_64__))
/* Unsigned */
ATOMIC_INLINE uint64_t atomic_fetch_and_add_uint64(uint64_t *p, uint64_t x)
{
@@ -289,36 +190,12 @@ ATOMIC_INLINE int64_t atomic_cas_int64(int64_t *v, int64_t old, int64_t _new)
return ret;
}
#else
/* Unsigned */
ATOMIC_LOCKING_ADD_AND_FETCH_DEFINE(uint64)
ATOMIC_LOCKING_SUB_AND_FETCH_DEFINE(uint64)
ATOMIC_LOCKING_FETCH_AND_ADD_DEFINE(uint64)
ATOMIC_LOCKING_FETCH_AND_SUB_DEFINE(uint64)
ATOMIC_LOCKING_CAS_DEFINE(uint64)
/* Signed */
ATOMIC_LOCKING_ADD_AND_FETCH_DEFINE(int64)
ATOMIC_LOCKING_SUB_AND_FETCH_DEFINE(int64)
ATOMIC_LOCKING_FETCH_AND_ADD_DEFINE(int64)
ATOMIC_LOCKING_FETCH_AND_SUB_DEFINE(int64)
ATOMIC_LOCKING_CAS_DEFINE(int64)
# error "Missing implementation for 64-bit atomic operations"
#endif
/** \} */
/* -------------------------------------------------------------------- */
/** \name 32-bit operations
* \{ */
#if !defined(ATOMIC_FORCE_USE_FALLBACK) && \
(defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4))
/******************************************************************************/
/* 32-bit operations. */
#if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4))
/* Unsigned */
ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x)
{
@@ -351,8 +228,7 @@ ATOMIC_INLINE int32_t atomic_cas_int32(int32_t *v, int32_t old, int32_t _new)
return __sync_val_compare_and_swap(v, old, _new);
}
#elif !defined(ATOMIC_FORCE_USE_FALLBACK) && \
(defined(__i386__) || defined(__amd64__) || defined(__x86_64__))
#elif (defined(__i386__) || defined(__amd64__) || defined(__x86_64__))
/* Unsigned */
ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x)
{
@@ -410,25 +286,10 @@ ATOMIC_INLINE int32_t atomic_cas_int32(int32_t *v, int32_t old, int32_t _new)
}
#else
/* Unsigned */
ATOMIC_LOCKING_ADD_AND_FETCH_DEFINE(uint32)
ATOMIC_LOCKING_SUB_AND_FETCH_DEFINE(uint32)
ATOMIC_LOCKING_CAS_DEFINE(uint32)
/* Signed */
ATOMIC_LOCKING_ADD_AND_FETCH_DEFINE(int32)
ATOMIC_LOCKING_SUB_AND_FETCH_DEFINE(int32)
ATOMIC_LOCKING_CAS_DEFINE(int32)
# error "Missing implementation for 32-bit atomic operations"
#endif
#if !defined(ATOMIC_FORCE_USE_FALLBACK) && \
(defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4))
#if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4))
/* Unsigned */
ATOMIC_INLINE uint32_t atomic_fetch_and_add_uint32(uint32_t *p, uint32_t x)
{
@@ -462,27 +323,12 @@ ATOMIC_INLINE int32_t atomic_fetch_and_and_int32(int32_t *p, int32_t x)
}
#else
/* Unsigned */
ATOMIC_LOCKING_FETCH_AND_ADD_DEFINE(uint32)
ATOMIC_LOCKING_FETCH_AND_OR_DEFINE(uint32)
ATOMIC_LOCKING_FETCH_AND_AND_DEFINE(uint32)
/* Signed */
ATOMIC_LOCKING_FETCH_AND_ADD_DEFINE(int32)
ATOMIC_LOCKING_FETCH_AND_OR_DEFINE(int32)
ATOMIC_LOCKING_FETCH_AND_AND_DEFINE(int32)
# error "Missing implementation for 32-bit atomic operations"
#endif
/** \} */
/* -------------------------------------------------------------------- */
/** \name 16-bit operations
* \{ */
#if !defined(ATOMIC_FORCE_USE_FALLBACK) && \
(defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_2))
/******************************************************************************/
/* 16-bit operations. */
#if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_2))
/* Signed */
ATOMIC_INLINE int16_t atomic_fetch_and_and_int16(int16_t *p, int16_t b)
@@ -495,21 +341,12 @@ ATOMIC_INLINE int16_t atomic_fetch_and_or_int16(int16_t *p, int16_t b)
}
#else
ATOMIC_LOCKING_FETCH_AND_AND_DEFINE(int16)
ATOMIC_LOCKING_FETCH_AND_OR_DEFINE(int16)
# error "Missing implementation for 16-bit atomic operations"
#endif
/** \} */
/* -------------------------------------------------------------------- */
/** \name 8-bit operations
* \{ */
#if !defined(ATOMIC_FORCE_USE_FALLBACK) && \
(defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_1))
/******************************************************************************/
/* 8-bit operations. */
#if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_1))
/* Unsigned */
ATOMIC_INLINE uint8_t atomic_fetch_and_and_uint8(uint8_t *p, uint8_t b)
{
@@ -531,27 +368,7 @@ ATOMIC_INLINE int8_t atomic_fetch_and_or_int8(int8_t *p, int8_t b)
}
#else
/* Unsigned */
ATOMIC_LOCKING_FETCH_AND_AND_DEFINE(uint8)
ATOMIC_LOCKING_FETCH_AND_OR_DEFINE(uint8)
/* Signed */
ATOMIC_LOCKING_FETCH_AND_AND_DEFINE(int8)
ATOMIC_LOCKING_FETCH_AND_OR_DEFINE(int8)
# error "Missing implementation for 8-bit atomic operations"
#endif
/** \} */
#undef ATOMIC_LOCKING_OP_AND_FETCH_DEFINE
#undef ATOMIC_LOCKING_FETCH_AND_OP_DEFINE
#undef ATOMIC_LOCKING_ADD_AND_FETCH_DEFINE
#undef ATOMIC_LOCKING_SUB_AND_FETCH_DEFINE
#undef ATOMIC_LOCKING_FETCH_AND_ADD_DEFINE
#undef ATOMIC_LOCKING_FETCH_AND_SUB_DEFINE
#undef ATOMIC_LOCKING_FETCH_AND_OR_DEFINE
#undef ATOMIC_LOCKING_FETCH_AND_AND_DEFINE
#undef ATOMIC_LOCKING_CAS_DEFINE
#endif /* __ATOMIC_OPS_UNIX_H__ */

View File

@@ -64,11 +64,9 @@
#ifdef __GNUC__
# define _ATOMIC_LIKELY(x) __builtin_expect(!!(x), 1)
# define _ATOMIC_UNLIKELY(x) __builtin_expect(!!(x), 0)
# define _ATOMIC_MAYBE_UNUSED __attribute__((unused))
#else
# define _ATOMIC_LIKELY(x) (x)
# define _ATOMIC_UNLIKELY(x) (x)
# define _ATOMIC_MAYBE_UNUSED
#endif
#if defined(__SIZEOF_POINTER__)

View File

@@ -526,13 +526,8 @@ bool BlenderSync::object_has_particle_hair(BL::Object b_ob)
/* Old particle hair. */
void BlenderSync::sync_particle_hair(
Hair *hair, BL::Mesh &b_mesh, BObjectInfo &b_ob_info, bool motion, int motion_step)
Hair *hair, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step)
{
if (!b_ob_info.is_real_object_data()) {
return;
}
BL::Object b_ob = b_ob_info.real_object;
/* obtain general settings */
if (b_ob.mode() == b_ob.mode_PARTICLE_EDIT || b_ob.mode() == b_ob.mode_EDIT) {
return;
@@ -793,10 +788,10 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
}
/* Hair object. */
void BlenderSync::sync_hair(Hair *hair, BObjectInfo &b_ob_info, bool motion, int motion_step)
void BlenderSync::sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motion_step)
{
/* Convert Blender hair to Cycles curves. */
BL::Hair b_hair(b_ob_info.object_data);
BL::Hair b_hair(b_ob.data());
if (motion) {
export_hair_curves_motion(hair, b_hair, motion_step);
}
@@ -805,16 +800,16 @@ void BlenderSync::sync_hair(Hair *hair, BObjectInfo &b_ob_info, bool motion, int
}
}
#else
void BlenderSync::sync_hair(Hair *hair, BObjectInfo &b_ob_info, bool motion, int motion_step)
void BlenderSync::sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motion_step)
{
(void)hair;
(void)b_ob_info;
(void)b_ob;
(void)motion;
(void)motion_step;
}
#endif
void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Hair *hair)
void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair)
{
/* make a copy of the shaders as the caller in the main thread still need them for syncing the
* attributes */
@@ -824,19 +819,19 @@ void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, H
new_hair.set_used_shaders(used_shaders);
if (view_layer.use_hair) {
if (b_ob_info.object_data.is_a(&RNA_Hair)) {
if (b_ob.type() == BL::Object::type_HAIR) {
/* Hair object. */
sync_hair(&new_hair, b_ob_info, false);
sync_hair(&new_hair, b_ob, false);
}
else {
/* Particle hair. */
bool need_undeformed = new_hair.need_attribute(scene, ATTR_STD_GENERATED);
BL::Mesh b_mesh = object_to_mesh(
b_data, b_ob_info, b_depsgraph, need_undeformed, Mesh::SUBDIVISION_NONE);
b_data, b_ob, b_depsgraph, need_undeformed, Mesh::SUBDIVISION_NONE);
if (b_mesh) {
sync_particle_hair(&new_hair, b_mesh, b_ob_info, false);
free_object_to_mesh(b_data, b_ob_info, b_mesh);
sync_particle_hair(&new_hair, b_mesh, b_ob, false);
free_object_to_mesh(b_data, b_ob, b_mesh);
}
}
}
@@ -864,7 +859,7 @@ void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, H
}
void BlenderSync::sync_hair_motion(BL::Depsgraph b_depsgraph,
BObjectInfo &b_ob_info,
BL::Object b_ob,
Hair *hair,
int motion_step)
{
@@ -874,19 +869,18 @@ void BlenderSync::sync_hair_motion(BL::Depsgraph b_depsgraph,
}
/* Export deformed coordinates. */
if (ccl::BKE_object_is_deform_modified(b_ob_info, b_scene, preview)) {
if (b_ob_info.object_data.is_a(&RNA_Hair)) {
if (ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) {
if (b_ob.type() == BL::Object::type_HAIR) {
/* Hair object. */
sync_hair(hair, b_ob_info, true, motion_step);
sync_hair(hair, b_ob, true, motion_step);
return;
}
else {
/* Particle hair. */
BL::Mesh b_mesh = object_to_mesh(
b_data, b_ob_info, b_depsgraph, false, Mesh::SUBDIVISION_NONE);
BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_depsgraph, false, Mesh::SUBDIVISION_NONE);
if (b_mesh) {
sync_particle_hair(hair, b_mesh, b_ob_info, true, motion_step);
free_object_to_mesh(b_data, b_ob_info, b_mesh);
sync_particle_hair(hair, b_mesh, b_ob, true, motion_step);
free_object_to_mesh(b_data, b_ob, b_mesh);
return;
}
}

View File

@@ -29,15 +29,13 @@
CCL_NAMESPACE_BEGIN
static Geometry::Type determine_geom_type(BObjectInfo &b_ob_info, bool use_particle_hair)
static Geometry::Type determine_geom_type(BL::Object &b_ob, bool use_particle_hair)
{
if (b_ob_info.object_data.is_a(&RNA_Hair) || use_particle_hair) {
if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) {
return Geometry::HAIR;
}
if (b_ob_info.object_data.is_a(&RNA_Volume) ||
(b_ob_info.object_data == b_ob_info.real_object.data() &&
object_fluid_gas_domain_find(b_ob_info.real_object))) {
if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) {
return Geometry::VOLUME;
}
@@ -73,17 +71,20 @@ array<Node *> BlenderSync::find_used_shaders(BL::Object &b_ob)
}
Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
BObjectInfo &b_ob_info,
BL::Object &b_ob,
BL::Object &b_ob_instance,
bool object_updated,
bool use_particle_hair,
TaskPool *task_pool)
{
/* Test if we can instance or if the object is modified. */
Geometry::Type geom_type = determine_geom_type(b_ob_info, use_particle_hair);
GeometryKey key(b_ob_info.object_data, geom_type);
BL::ID b_ob_data = b_ob.data();
BL::ID b_key_id = (BKE_object_is_modified(b_ob)) ? b_ob_instance : b_ob_data;
Geometry::Type geom_type = determine_geom_type(b_ob, use_particle_hair);
GeometryKey key(b_key_id.ptr.data, geom_type);
/* Find shader indices. */
array<Node *> used_shaders = find_used_shaders(b_ob_info.iter_object);
array<Node *> used_shaders = find_used_shaders(b_ob);
/* Ensure we only sync instanced geometry once. */
Geometry *geom = geometry_map.find(key);
@@ -110,7 +111,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
}
else {
/* Test if we need to update existing geometry. */
sync = geometry_map.update(geom, b_ob_info.object_data);
sync = geometry_map.update(geom, b_key_id);
}
if (!sync) {
@@ -143,7 +144,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
geometry_synced.insert(geom);
geom->name = ustring(b_ob_info.object_data.name().c_str());
geom->name = ustring(b_ob_data.name().c_str());
/* Store the shaders immediately for the object attribute code. */
geom->set_used_shaders(used_shaders);
@@ -152,19 +153,19 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
if (progress.get_cancel())
return;
progress.set_sync_status("Synchronizing object", b_ob_info.real_object.name());
progress.set_sync_status("Synchronizing object", b_ob.name());
if (geom_type == Geometry::HAIR) {
Hair *hair = static_cast<Hair *>(geom);
sync_hair(b_depsgraph, b_ob_info, hair);
sync_hair(b_depsgraph, b_ob, hair);
}
else if (geom_type == Geometry::VOLUME) {
Volume *volume = static_cast<Volume *>(geom);
sync_volume(b_ob_info, volume);
sync_volume(b_ob, volume);
}
else {
Mesh *mesh = static_cast<Mesh *>(geom);
sync_mesh(b_depsgraph, b_ob_info, mesh);
sync_mesh(b_depsgraph, b_ob, mesh);
}
};
@@ -180,7 +181,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
}
void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
BObjectInfo &b_ob_info,
BL::Object &b_ob,
Object *object,
float motion_time,
bool use_particle_hair,
@@ -209,17 +210,16 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
if (progress.get_cancel())
return;
if (b_ob_info.object_data.is_a(&RNA_Hair) || use_particle_hair) {
if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) {
Hair *hair = static_cast<Hair *>(geom);
sync_hair_motion(b_depsgraph, b_ob_info, hair, motion_step);
sync_hair_motion(b_depsgraph, b_ob, hair, motion_step);
}
else if (b_ob_info.object_data.is_a(&RNA_Volume) ||
object_fluid_gas_domain_find(b_ob_info.real_object)) {
else if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) {
/* No volume motion blur support yet. */
}
else {
Mesh *mesh = static_cast<Mesh *>(geom);
sync_mesh_motion(b_depsgraph, b_ob_info, mesh, motion_step);
sync_mesh_motion(b_depsgraph, b_ob, mesh, motion_step);
}
};

View File

@@ -27,14 +27,15 @@ CCL_NAMESPACE_BEGIN
void BlenderSync::sync_light(BL::Object &b_parent,
int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
BObjectInfo &b_ob_info,
BL::Object &b_ob,
BL::Object &b_ob_instance,
int random_id,
Transform &tfm,
bool *use_portal)
{
/* test if we need to sync */
ObjectKey key(b_parent, persistent_id, b_ob_info.real_object, false);
BL::Light b_light(b_ob_info.object_data);
ObjectKey key(b_parent, persistent_id, b_ob_instance, false);
BL::Light b_light(b_ob.data());
Light *light = light_map.find(key);
@@ -43,7 +44,7 @@ void BlenderSync::sync_light(BL::Object &b_parent,
const bool tfm_updated = (light && light->get_tfm() != tfm);
/* Update if either object or light data changed. */
if (!light_map.add_or_update(&light, b_ob_info.real_object, b_parent, key) && !tfm_updated) {
if (!light_map.add_or_update(&light, b_ob, b_parent, key) && !tfm_updated) {
Shader *shader;
if (!shader_map.add_or_update(&shader, b_light)) {
if (light->get_is_portal())
@@ -138,11 +139,11 @@ void BlenderSync::sync_light(BL::Object &b_parent,
light->set_max_bounces(get_int(clight, "max_bounces"));
if (b_ob_info.real_object != b_ob_info.iter_object) {
if (b_ob != b_ob_instance) {
light->set_random_id(random_id);
}
else {
light->set_random_id(hash_uint2(hash_string(b_ob_info.real_object.name().c_str()), 0));
light->set_random_id(hash_uint2(hash_string(b_ob.name().c_str()), 0));
}
if (light->get_light_type() == LIGHT_AREA)
@@ -154,7 +155,7 @@ void BlenderSync::sync_light(BL::Object &b_parent,
*use_portal = true;
/* visibility */
uint visibility = object_ray_visibility(b_ob_info.real_object);
uint visibility = object_ray_visibility(b_ob);
light->set_use_diffuse((visibility & PATH_RAY_DIFFUSE) != 0);
light->set_use_glossy((visibility & PATH_RAY_GLOSSY) != 0);
light->set_use_transmission((visibility & PATH_RAY_TRANSMIT) != 0);

View File

@@ -999,14 +999,12 @@ static void create_mesh(Scene *scene,
static void create_subd_mesh(Scene *scene,
Mesh *mesh,
BObjectInfo &b_ob_info,
BL::Object &b_ob,
BL::Mesh &b_mesh,
const array<Node *> &used_shaders,
float dicing_rate,
int max_subdivisions)
{
BL::Object b_ob = b_ob_info.real_object;
BL::SubsurfModifier subsurf_mod(b_ob.modifiers[b_ob.modifiers.length() - 1]);
bool subdivide_uvs = subsurf_mod.uv_smooth() != BL::SubsurfModifier::uv_smooth_NONE;
@@ -1045,7 +1043,7 @@ static void create_subd_mesh(Scene *scene,
*
* NOTE: This code is run prior to object motion blur initialization. so can not access properties
* set by `sync_object_motion_init()`. */
static bool mesh_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene)
static bool mesh_need_motion_attribute(BL::Object &b_ob, Scene *scene)
{
const Scene::MotionType need_motion = scene->need_motion();
if (need_motion == Scene::MOTION_NONE) {
@@ -1062,7 +1060,7 @@ static bool mesh_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene)
* - Motion attribute expects non-zero time steps.
*
* Avoid adding motion attributes if the motion blur will enforce 0 motion steps. */
PointerRNA cobject = RNA_pointer_get(&b_ob_info.real_object.ptr, "cycles");
PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
const bool use_motion = get_boolean(cobject, "use_motion_blur");
if (!use_motion) {
return false;
@@ -1074,13 +1072,12 @@ static bool mesh_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene)
return true;
}
static void sync_mesh_cached_velocities(BObjectInfo &b_ob_info, Scene *scene, Mesh *mesh)
static void sync_mesh_cached_velocities(BL::Object &b_ob, Scene *scene, Mesh *mesh)
{
if (!mesh_need_motion_attribute(b_ob_info, scene)) {
if (!mesh_need_motion_attribute(b_ob, scene)) {
return;
}
BL::Object b_ob = b_ob_info.real_object;
BL::MeshSequenceCacheModifier b_mesh_cache = object_mesh_cache_find(b_ob, true, nullptr);
if (!b_mesh_cache) {
@@ -1121,16 +1118,12 @@ static void sync_mesh_cached_velocities(BObjectInfo &b_ob_info, Scene *scene, Me
}
}
static void sync_mesh_fluid_motion(BObjectInfo &b_ob_info, Scene *scene, Mesh *mesh)
static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh)
{
if (!b_ob_info.is_real_object_data()) {
return;
}
if (!mesh_need_motion_attribute(b_ob_info, scene)) {
if (!mesh_need_motion_attribute(b_ob, scene)) {
return;
}
BL::Object b_ob = b_ob_info.real_object;
BL::FluidDomainSettings b_fluid_domain = object_fluid_liquid_domain_find(b_ob);
if (!b_fluid_domain)
@@ -1164,7 +1157,7 @@ static void sync_mesh_fluid_motion(BObjectInfo &b_ob_info, Scene *scene, Mesh *m
}
}
void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Mesh *mesh)
void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh)
{
/* make a copy of the shaders as the caller in the main thread still need them for syncing the
* attributes */
@@ -1177,21 +1170,20 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, M
/* Adaptive subdivision setup. Not for baking since that requires
* exact mapping to the Blender mesh. */
if (!scene->bake_manager->get_baking()) {
new_mesh.set_subdivision_type(
object_subdivision_type(b_ob_info.real_object, preview, experimental));
new_mesh.set_subdivision_type(object_subdivision_type(b_ob, preview, experimental));
}
/* For some reason, meshes do not need this... */
bool need_undeformed = new_mesh.need_attribute(scene, ATTR_STD_GENERATED);
BL::Mesh b_mesh = object_to_mesh(
b_data, b_ob_info, b_depsgraph, need_undeformed, new_mesh.get_subdivision_type());
b_data, b_ob, b_depsgraph, need_undeformed, new_mesh.get_subdivision_type());
if (b_mesh) {
/* Sync mesh itself. */
if (new_mesh.get_subdivision_type() != Mesh::SUBDIVISION_NONE)
create_subd_mesh(scene,
&new_mesh,
b_ob_info,
b_ob,
b_mesh,
new_mesh.get_used_shaders(),
dicing_rate,
@@ -1199,15 +1191,15 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, M
else
create_mesh(scene, &new_mesh, b_mesh, new_mesh.get_used_shaders(), false);
free_object_to_mesh(b_data, b_ob_info, b_mesh);
free_object_to_mesh(b_data, b_ob, b_mesh);
}
}
/* cached velocities (e.g. from alembic archive) */
sync_mesh_cached_velocities(b_ob_info, scene, &new_mesh);
sync_mesh_cached_velocities(b_ob, scene, &new_mesh);
/* mesh fluid motion mantaflow */
sync_mesh_fluid_motion(b_ob_info, scene, &new_mesh);
sync_mesh_fluid_motion(b_ob, scene, &new_mesh);
/* update original sockets */
@@ -1238,19 +1230,18 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, M
}
void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
BObjectInfo &b_ob_info,
BL::Object b_ob,
Mesh *mesh,
int motion_step)
{
/* Fluid motion blur already exported. */
BL::FluidDomainSettings b_fluid_domain = object_fluid_liquid_domain_find(b_ob_info.real_object);
BL::FluidDomainSettings b_fluid_domain = object_fluid_liquid_domain_find(b_ob);
if (b_fluid_domain) {
return;
}
/* Cached motion blur already exported. */
BL::MeshSequenceCacheModifier mesh_cache = object_mesh_cache_find(
b_ob_info.real_object, true, nullptr);
BL::MeshSequenceCacheModifier mesh_cache = object_mesh_cache_find(b_ob, true, nullptr);
if (mesh_cache) {
return;
}
@@ -1264,13 +1255,11 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
/* Skip objects without deforming modifiers. this is not totally reliable,
* would need a more extensive check to see which objects are animated. */
BL::Mesh b_mesh(PointerRNA_NULL);
if (ccl::BKE_object_is_deform_modified(b_ob_info, b_scene, preview)) {
if (ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) {
/* get derived mesh */
b_mesh = object_to_mesh(b_data, b_ob_info, b_depsgraph, false, Mesh::SUBDIVISION_NONE);
b_mesh = object_to_mesh(b_data, b_ob, b_depsgraph, false, Mesh::SUBDIVISION_NONE);
}
const std::string ob_name = b_ob_info.real_object.name();
/* TODO(sergey): Perform preliminary check for number of vertices. */
if (b_mesh) {
/* Export deformed coordinates. */
@@ -1306,17 +1295,17 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
memcmp(mP, &mesh->get_verts()[0], sizeof(float3) * numverts) == 0) {
/* no motion, remove attributes again */
if (b_mesh.vertices.length() != numverts) {
VLOG(1) << "Topology differs, disabling motion blur for object " << ob_name;
VLOG(1) << "Topology differs, disabling motion blur for object " << b_ob.name();
}
else {
VLOG(1) << "No actual deformation motion for object " << ob_name;
VLOG(1) << "No actual deformation motion for object " << b_ob.name();
}
mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
if (attr_mN)
mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_NORMAL);
}
else if (motion_step > 0) {
VLOG(1) << "Filling deformation motion for object " << ob_name;
VLOG(1) << "Filling deformation motion for object " << b_ob.name();
/* motion, fill up previous steps that we might have skipped because
* they had no motion, but we need them anyway now */
float3 *P = &mesh->get_verts()[0];
@@ -1330,8 +1319,8 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
}
else {
if (b_mesh.vertices.length() != numverts) {
VLOG(1) << "Topology differs, discarding motion blur for object " << ob_name << " at time "
<< motion_step;
VLOG(1) << "Topology differs, discarding motion blur for object " << b_ob.name()
<< " at time " << motion_step;
memcpy(mP, &mesh->get_verts()[0], sizeof(float3) * numverts);
if (mN != NULL) {
memcpy(mN, attr_N->data_float3(), sizeof(float3) * numverts);
@@ -1339,7 +1328,7 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
}
}
free_object_to_mesh(b_data, b_ob_info, b_mesh);
free_object_to_mesh(b_data, b_ob, b_mesh);
return;
}

View File

@@ -154,7 +154,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
const bool is_instance = b_instance.is_instance();
BL::Object b_ob = b_instance.object();
BL::Object b_parent = is_instance ? b_instance.parent() : b_instance.object();
BObjectInfo b_ob_info{b_ob, is_instance ? b_instance.instance_object() : b_ob, b_ob.data()};
BL::Object b_ob_instance = is_instance ? b_instance.instance_object() : b_ob;
const bool motion = motion_time != 0.0f;
/*const*/ Transform tfm = get_transform(b_ob.matrix_world());
int *persistent_id = NULL;
@@ -178,7 +178,8 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
{
sync_light(b_parent,
persistent_id,
b_ob_info,
b_ob,
b_ob_instance,
is_instance ? b_instance.random_id() : 0,
tfm,
use_portal);
@@ -230,7 +231,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
TaskPool *object_geom_task_pool = (is_instance) ? NULL : geom_task_pool;
/* key to lookup object */
ObjectKey key(b_parent, persistent_id, b_ob_info.real_object, use_particle_hair);
ObjectKey key(b_parent, persistent_id, b_ob_instance, use_particle_hair);
Object *object;
/* motion vector case */
@@ -248,8 +249,12 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
/* mesh deformation */
if (object->get_geometry())
sync_geometry_motion(
b_depsgraph, b_ob_info, object, motion_time, use_particle_hair, object_geom_task_pool);
sync_geometry_motion(b_depsgraph,
b_ob_instance,
object,
motion_time,
use_particle_hair,
object_geom_task_pool);
}
return object;
@@ -260,8 +265,15 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
(tfm != object->get_tfm());
/* mesh sync */
Geometry *geometry = sync_geometry(
b_depsgraph, b_ob_info, object_updated, use_particle_hair, object_geom_task_pool);
/* b_ob is owned by the iterator and will go out of scope at the end of the block.
* b_ob_instance is the original object and will remain valid for deferred geometry
* sync. */
Geometry *geometry = sync_geometry(b_depsgraph,
b_ob_instance,
b_ob_instance,
object_updated,
use_particle_hair,
object_geom_task_pool);
object->set_geometry(geometry);
/* special case not tracked by object update flags */
@@ -364,7 +376,7 @@ static bool lookup_property(BL::ID b_id, const string &name, float4 *r_value)
if (type == PROP_FLOAT)
value = RNA_property_float_get(&ptr, prop);
else if (type == PROP_INT)
value = static_cast<float>(RNA_property_int_get(&ptr, prop));
value = RNA_property_int_get(&ptr, prop);
else
return false;
@@ -492,14 +504,14 @@ void BlenderSync::sync_procedural(BL::Object &b_ob,
procedural_map.used(procedural);
}
float current_frame = static_cast<float>(b_scene.frame_current());
float current_frame = b_scene.frame_current();
if (cache_file.override_frame()) {
current_frame = cache_file.frame();
}
if (!cache_file.override_frame()) {
procedural->set_start_frame(static_cast<float>(b_scene.frame_start()));
procedural->set_end_frame(static_cast<float>(b_scene.frame_end()));
procedural->set_start_frame(b_scene.frame_start());
procedural->set_end_frame(b_scene.frame_end());
}
procedural->set_frame(current_frame);
@@ -535,7 +547,6 @@ void BlenderSync::sync_procedural(BL::Object &b_ob,
#else
(void)b_ob;
(void)b_mesh_cache;
(void)has_subdivision_modifier;
#endif
}

View File

@@ -23,7 +23,6 @@
#include "RNA_types.h"
#include "blender/blender_id_map.h"
#include "blender/blender_util.h"
#include "blender/blender_viewport.h"
#include "render/scene.h"
@@ -159,24 +158,18 @@ class BlenderSync {
bool sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object);
/* Volume */
void sync_volume(BObjectInfo &b_ob_info, Volume *volume);
void sync_volume(BL::Object &b_ob, Volume *volume);
/* Mesh */
void sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Mesh *mesh);
void sync_mesh_motion(BL::Depsgraph b_depsgraph,
BObjectInfo &b_ob_info,
Mesh *mesh,
int motion_step);
void sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh);
void sync_mesh_motion(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh, int motion_step);
/* Hair */
void sync_hair(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Hair *hair);
void sync_hair_motion(BL::Depsgraph b_depsgraph,
BObjectInfo &b_ob_info,
Hair *hair,
int motion_step);
void sync_hair(Hair *hair, BObjectInfo &b_ob_info, bool motion, int motion_step = 0);
void sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair);
void sync_hair_motion(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair, int motion_step);
void sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motion_step = 0);
void sync_particle_hair(
Hair *hair, BL::Mesh &b_mesh, BObjectInfo &b_ob_info, bool motion, int motion_step = 0);
Hair *hair, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step = 0);
bool object_has_particle_hair(BL::Object b_ob);
/* Camera */
@@ -185,13 +178,14 @@ class BlenderSync {
/* Geometry */
Geometry *sync_geometry(BL::Depsgraph &b_depsgrpah,
BObjectInfo &b_ob_info,
BL::Object &b_ob,
BL::Object &b_ob_instance,
bool object_updated,
bool use_particle_hair,
TaskPool *task_pool);
void sync_geometry_motion(BL::Depsgraph &b_depsgraph,
BObjectInfo &b_ob_info,
BL::Object &b_ob,
Object *object,
float motion_time,
bool use_particle_hair,
@@ -200,7 +194,8 @@ class BlenderSync {
/* Light */
void sync_light(BL::Object &b_parent,
int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
BObjectInfo &b_ob_info,
BL::Object &b_ob,
BL::Object &b_ob_instance,
int random_id,
Transform &tfm,
bool *use_portal);

View File

@@ -40,28 +40,6 @@ float *BKE_image_get_float_pixels_for_frame(void *image, int frame, int tile);
CCL_NAMESPACE_BEGIN
struct BObjectInfo {
/* Object directly provided by the depsgraph iterator. This object is only valid during one
* iteration and must not be accessed afterwards. Transforms and visibility should be checked on
* this object. */
BL::Object iter_object;
/* This object remains alive even after the object iterator is done. It corresponds to one
* original object. It is the object that owns the object data below. */
BL::Object real_object;
/* The object-data referenced by the iter object. This is still valid after the depsgraph
* iterator is done. It might have a different type compared to real_object.data(). */
BL::ID object_data;
/* True when the current geometry is the data of the referenced object. False when it is a
* geometry instance that does not have a 1-to-1 relationship with an object. */
bool is_real_object_data() const
{
return const_cast<BL::Object &>(real_object).data() == object_data;
}
};
typedef BL::ShaderNodeAttribute::attribute_type_enum BlenderAttributeType;
BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_real_name);
@@ -69,7 +47,7 @@ void python_thread_state_save(void **python_thread_state);
void python_thread_state_restore(void **python_thread_state);
static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/,
BObjectInfo &b_ob_info,
BL::Object &object,
BL::Depsgraph & /*depsgraph*/,
bool /*calc_undeformed*/,
Mesh::SubdivisionType subdivision_type)
@@ -91,9 +69,9 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/,
#endif
BL::Mesh mesh(PointerRNA_NULL);
if (b_ob_info.object_data.is_a(&RNA_Mesh)) {
if (object.type() == BL::Object::type_MESH) {
/* TODO: calc_undeformed is not used. */
mesh = BL::Mesh(b_ob_info.object_data);
mesh = BL::Mesh(object.data());
/* Make a copy to split faces if we use autosmooth, otherwise not needed.
* Also in edit mode do we need to make a copy, to ensure data layers like
@@ -101,15 +79,12 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/,
if (mesh.is_editmode() ||
(mesh.use_auto_smooth() && subdivision_type == Mesh::SUBDIVISION_NONE)) {
BL::Depsgraph depsgraph(PointerRNA_NULL);
assert(b_ob_info.is_real_object_data());
mesh = b_ob_info.real_object.to_mesh(false, depsgraph);
mesh = object.to_mesh(false, depsgraph);
}
}
else {
BL::Depsgraph depsgraph(PointerRNA_NULL);
if (b_ob_info.is_real_object_data()) {
mesh = b_ob_info.real_object.to_mesh(false, depsgraph);
}
mesh = object.to_mesh(false, depsgraph);
}
#if 0
@@ -133,14 +108,10 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/,
}
static inline void free_object_to_mesh(BL::BlendData & /*data*/,
BObjectInfo &b_ob_info,
BL::Object &object,
BL::Mesh &mesh)
{
if (!b_ob_info.is_real_object_data()) {
return;
}
/* Free mesh if we didn't just use the existing one. */
BL::Object object = b_ob_info.real_object;
if (object.data().ptr.data != mesh.ptr.data) {
object.to_mesh_clear();
}
@@ -248,13 +219,9 @@ static inline bool BKE_object_is_modified(BL::Object &self, BL::Scene &scene, bo
return self.is_modified(scene, (preview) ? (1 << 0) : (1 << 1)) ? true : false;
}
static inline bool BKE_object_is_deform_modified(BObjectInfo &self, BL::Scene &scene, bool preview)
static inline bool BKE_object_is_deform_modified(BL::Object &self, BL::Scene &scene, bool preview)
{
if (!self.is_real_object_data()) {
return false;
}
return self.real_object.is_deform_modified(scene, (preview) ? (1 << 0) : (1 << 1)) ? true :
false;
return self.is_deform_modified(scene, (preview) ? (1 << 0) : (1 << 1)) ? true : false;
}
static inline int render_resolution_x(BL::RenderSettings &b_render)

View File

@@ -181,12 +181,9 @@ class BlenderSmokeLoader : public ImageLoader {
AttributeStandard attribute;
};
static void sync_smoke_volume(Scene *scene, BObjectInfo &b_ob_info, Volume *volume, float frame)
static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Volume *volume, float frame)
{
if (!b_ob_info.is_real_object_data()) {
return;
}
BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob_info.real_object);
BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob);
if (!b_domain) {
return;
}
@@ -209,7 +206,7 @@ static void sync_smoke_volume(Scene *scene, BObjectInfo &b_ob_info, Volume *volu
Attribute *attr = volume->attributes.add(std);
ImageLoader *loader = new BlenderSmokeLoader(b_ob_info.real_object, std);
ImageLoader *loader = new BlenderSmokeLoader(b_ob, std);
ImageParams params;
params.frame = frame;
@@ -247,11 +244,11 @@ class BlenderVolumeLoader : public VDBImageLoader {
};
static void sync_volume_object(BL::BlendData &b_data,
BObjectInfo &b_ob_info,
BL::Object &b_ob,
Scene *scene,
Volume *volume)
{
BL::Volume b_volume(b_ob_info.object_data);
BL::Volume b_volume(b_ob.data());
b_volume.grids.load(b_data.ptr.data);
BL::VolumeRender b_render(b_volume.render());
@@ -299,19 +296,19 @@ static void sync_volume_object(BL::BlendData &b_data,
}
}
void BlenderSync::sync_volume(BObjectInfo &b_ob_info, Volume *volume)
void BlenderSync::sync_volume(BL::Object &b_ob, Volume *volume)
{
volume->clear(true);
if (view_layer.use_volumes) {
if (b_ob_info.object_data.is_a(&RNA_Volume)) {
if (b_ob.type() == BL::Object::type_VOLUME) {
/* Volume object. Create only attributes, bounding mesh will then
* be automatically generated later. */
sync_volume_object(b_data, b_ob_info, scene, volume);
sync_volume_object(b_data, b_ob, scene, volume);
}
else {
/* Smoke domain. */
sync_smoke_volume(scene, b_ob_info, volume, b_scene.frame_current());
sync_smoke_volume(scene, b_ob, volume, b_scene.frame_current());
}
}

View File

@@ -1050,7 +1050,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg,
float D, G1i;
if (alpha_x == alpha_y) {
/* Isotropic distribution. */
/* istropic distribution */
float cosThetaM2 = cosThetaM * cosThetaM;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
float tanThetaM2 = 1 / (cosThetaM2)-1;

View File

@@ -107,8 +107,8 @@ triangle_smooth_normal(KernelGlobals *kg, float3 Ng, int prim, float u, float v)
return is_zero(N) ? Ng : N;
}
ccl_device_inline float3 triangle_smooth_normal_unnormalized(
KernelGlobals *kg, ShaderData *sd, float3 Ng, int prim, float u, float v)
ccl_device_inline float3
triangle_smooth_normal_unnormalized(KernelGlobals *kg, float3 Ng, int prim, float u, float v)
{
/* load triangle vertices */
const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
@@ -116,13 +116,6 @@ ccl_device_inline float3 triangle_smooth_normal_unnormalized(
float3 n1 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.y));
float3 n2 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.z));
/* ensure that the normals are in object space */
if (sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED) {
object_inverse_normal_transform(kg, sd, &n0);
object_inverse_normal_transform(kg, sd, &n1);
object_inverse_normal_transform(kg, sd, &n2);
}
float3 N = (1.0f - u - v) * n2 + u * n0 + v * n1;
return is_zero(N) ? Ng : N;

View File

@@ -289,7 +289,7 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
float3 normal;
if (sd->shader & SHADER_SMOOTH_NORMAL) {
normal = triangle_smooth_normal_unnormalized(kg, sd, sd->Ng, sd->prim, sd->u, sd->v);
normal = triangle_smooth_normal_unnormalized(kg, sd->Ng, sd->prim, sd->u, sd->v);
}
else {
normal = sd->Ng;

View File

@@ -410,39 +410,38 @@ void LightManager::device_update_distribution(Device *,
}
float trianglearea = totarea;
/* point lights */
float lightarea = (totarea > 0.0f) ? totarea / num_lights : 1.0f;
bool use_lamp_mis = false;
int light_index = 0;
if (num_lights > 0) {
float lightarea = (totarea > 0.0f) ? totarea / num_lights : 1.0f;
foreach (Light *light, scene->lights) {
if (!light->is_enabled)
continue;
foreach (Light *light, scene->lights) {
if (!light->is_enabled)
continue;
distribution[offset].totarea = totarea;
distribution[offset].prim = ~light_index;
distribution[offset].lamp.pad = 1.0f;
distribution[offset].lamp.size = light->size;
totarea += lightarea;
distribution[offset].totarea = totarea;
distribution[offset].prim = ~light_index;
distribution[offset].lamp.pad = 1.0f;
distribution[offset].lamp.size = light->size;
totarea += lightarea;
if (light->light_type == LIGHT_DISTANT) {
use_lamp_mis |= (light->angle > 0.0f && light->use_mis);
}
else if (light->light_type == LIGHT_POINT || light->light_type == LIGHT_SPOT) {
use_lamp_mis |= (light->size > 0.0f && light->use_mis);
}
else if (light->light_type == LIGHT_AREA) {
use_lamp_mis |= light->use_mis;
}
else if (light->light_type == LIGHT_BACKGROUND) {
num_background_lights++;
background_mis |= light->use_mis;
}
light_index++;
offset++;
if (light->light_type == LIGHT_DISTANT) {
use_lamp_mis |= (light->angle > 0.0f && light->use_mis);
}
else if (light->light_type == LIGHT_POINT || light->light_type == LIGHT_SPOT) {
use_lamp_mis |= (light->size > 0.0f && light->use_mis);
}
else if (light->light_type == LIGHT_AREA) {
use_lamp_mis |= light->use_mis;
}
else if (light->light_type == LIGHT_BACKGROUND) {
num_background_lights++;
background_mis |= light->use_mis;
}
light_index++;
offset++;
}
/* normalize cumulative distribution functions */

View File

@@ -424,7 +424,7 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG])
{
/* TODO: implement graceful termination through Cocoa mechanism
* to avoid session log off to be canceled. */
/* Note that Cmd+Q is already handled by key-handler. */
/* Note that Cmd+Q is already handled by keyhandler. */
systemCocoa->handleQuitRequest();
return NSTerminateCancel;
}

View File

@@ -1922,7 +1922,7 @@ static GHOST_TKey ghost_key_from_keycode(const XkbDescPtr xkb_descr, const KeyCo
#undef MAKE_ID
/* From `xclip.c` #xcout() v0.11. */
/* from xclip.c xcout() v0.11 */
#define XCLIB_XCOUT_NONE 0 /* no context */
#define XCLIB_XCOUT_SENTCONVSEL 1 /* sent a request */

View File

@@ -410,11 +410,6 @@ void GHOST_XrContext::getExtensionsToEnable(
try_ext.push_back(XR_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
/* Try enabling interaction profile extensions. */
try_ext.push_back(XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME);
try_ext.push_back(XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME);
try_ext.push_back(XR_HUAWEI_CONTROLLER_INTERACTION_EXTENSION_NAME);
r_ext_names.reserve(try_ext.size() + graphics_binding_types.size());
/* Add graphics binding extensions (may be multiple ones, we'll settle for one to use later, once

View File

@@ -148,12 +148,13 @@ static void create_reference_spaces(OpenXRSessionData &oxr, const GHOST_XrPose &
if (XR_FAILED(result)) {
/* One of the rare cases where we don't want to immediately throw an exception on failure,
* since runtimes are not required to support the stage reference space. If the runtime
* doesn't support it then just fall back to the local space. */
* since run-times are not required to support the stage reference space. Although we need the
* stage reference space for absolute tracking, if the runtime doesn't support it then just
* fallback to the local space. */
if (result == XR_ERROR_REFERENCE_SPACE_UNSUPPORTED) {
printf(
"Warning: XR runtime does not support stage reference space, falling back to local "
"reference space.\n");
"Warning: XR runtime does not support stage reference space, disabling absolute "
"tracking.\n");
create_info.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
CHECK_XR(xrCreateReferenceSpace(oxr.session, &create_info, &oxr.reference_space),
@@ -171,9 +172,8 @@ static void create_reference_spaces(OpenXRSessionData &oxr, const GHOST_XrPose &
"Failed to get stage reference space bounds.");
if (extents.width == 0.0f || extents.height == 0.0f) {
printf(
"Warning: Invalid stage reference space bounds, falling back to local reference space. "
"To use the stage reference space, please define a tracking space via the XR "
"runtime.\n");
"Warning: Invalid stage reference space bounds, disabling absolute tracking. To enable "
"absolute tracking, please define a tracking space via the XR runtime.\n");
/* Fallback to local space. */
if (oxr.reference_space != XR_NULL_HANDLE) {

View File

@@ -74,9 +74,8 @@ size_t count_utf_16_from_8(const char *string8)
char type = 0;
unsigned int u32 = 0;
if (!string8) {
if (!string8)
return 0;
}
for (; (u = *string8); string8++) {
if (type == 0) {
@@ -102,22 +101,22 @@ size_t count_utf_16_from_8(const char *string8)
} // 4 utf-8 char
continue;
}
if ((u & 0xC0) == 0x80) {
u32 = (u32 << 6) | (u & 0x3F);
type--;
}
else {
u32 = 0;
type = 0;
if ((u & 0xC0) == 0x80) {
u32 = (u32 << 6) | (u & 0x3F);
type--;
}
else {
u32 = 0;
type = 0;
}
}
if (type == 0) {
if ((0 < u32 && u32 < 0xD800) || (0xE000 <= u32 && u32 < 0x10000)) {
if ((0 < u32 && u32 < 0xD800) || (0xE000 <= u32 && u32 < 0x10000))
count++;
}
else if (0x10000 <= u32 && u32 < 0x110000) {
else if (0x10000 <= u32 && u32 < 0x110000)
count += 2;
}
u32 = 0;
}
}
@@ -130,9 +129,8 @@ int conv_utf_16_to_8(const wchar_t *in16, char *out8, size_t size8)
char *out8end = out8 + size8;
wchar_t u = 0;
int err = 0;
if (!size8 || !in16 || !out8) {
if (!size8 || !in16 || !out8)
return UTF_ERROR_NULL_IN;
}
out8end--;
for (; out8 < out8end && (u = *in16); in16++, out8++) {
@@ -140,16 +138,14 @@ int conv_utf_16_to_8(const wchar_t *in16, char *out8, size_t size8)
*out8 = u;
}
else if (u < 0x0800) {
if (out8 + 1 >= out8end) {
if (out8 + 1 >= out8end)
break;
}
*out8++ = (0x3 << 6) | (0x1F & (u >> 6));
*out8 = (0x1 << 7) | (0x3F & (u));
}
else if (u < 0xD800 || u >= 0xE000) {
if (out8 + 2 >= out8end) {
if (out8 + 2 >= out8end)
break;
}
*out8++ = (0x7 << 5) | (0xF & (u >> 12));
*out8++ = (0x1 << 7) | (0x3F & (u >> 6));
*out8 = (0x1 << 7) | (0x3F & (u));
@@ -157,19 +153,19 @@ int conv_utf_16_to_8(const wchar_t *in16, char *out8, size_t size8)
else if (u < 0xDC00) {
wchar_t u2 = *++in16;
if (!u2) {
if (!u2)
break;
}
if (u2 >= 0xDC00 && u2 < 0xE000) {
if (out8 + 3 >= out8end) {
if (out8 + 3 >= out8end)
break;
}
unsigned int uc = 0x10000 + (u2 - 0xDC00) + ((u - 0xD800) << 10);
else {
unsigned int uc = 0x10000 + (u2 - 0xDC00) + ((u - 0xD800) << 10);
*out8++ = (0xF << 4) | (0x7 & (uc >> 18));
*out8++ = (0x1 << 7) | (0x3F & (uc >> 12));
*out8++ = (0x1 << 7) | (0x3F & (uc >> 6));
*out8 = (0x1 << 7) | (0x3F & (uc));
*out8++ = (0xF << 4) | (0x7 & (uc >> 18));
*out8++ = (0x1 << 7) | (0x3F & (uc >> 12));
*out8++ = (0x1 << 7) | (0x3F & (uc >> 6));
*out8 = (0x1 << 7) | (0x3F & (uc));
}
}
else {
out8--;
@@ -184,9 +180,8 @@ int conv_utf_16_to_8(const wchar_t *in16, char *out8, size_t size8)
*out8 = *out8end = 0;
if (*in16) {
if (*in16)
err |= UTF_ERROR_SMALL;
}
return err;
}
@@ -198,9 +193,8 @@ int conv_utf_8_to_16(const char *in8, wchar_t *out16, size_t size16)
unsigned int u32 = 0;
wchar_t *out16end = out16 + size16;
int err = 0;
if (!size16 || !in8 || !out16) {
if (!size16 || !in8 || !out16)
return UTF_ERROR_NULL_IN;
}
out16end--;
for (; out16 < out16end && (u = *in8); in8++) {
@@ -229,25 +223,25 @@ int conv_utf_8_to_16(const char *in8, wchar_t *out16, size_t size16)
err |= UTF_ERROR_ILLCHAR;
continue;
}
if ((u & 0xC0) == 0x80) {
u32 = (u32 << 6) | (u & 0x3F);
type--;
}
else {
u32 = 0;
type = 0;
err |= UTF_ERROR_ILLSEQ;
if ((u & 0xC0) == 0x80) {
u32 = (u32 << 6) | (u & 0x3F);
type--;
}
else {
u32 = 0;
type = 0;
err |= UTF_ERROR_ILLSEQ;
}
}
if (type == 0) {
if ((0 < u32 && u32 < 0xD800) || (0xE000 <= u32 && u32 < 0x10000)) {
*out16 = u32;
out16++;
}
else if (0x10000 <= u32 && u32 < 0x110000) {
if (out16 + 1 >= out16end) {
if (out16 + 1 >= out16end)
break;
}
u32 -= 0x10000;
*out16 = 0xD800 + (u32 >> 10);
out16++;
@@ -260,9 +254,8 @@ int conv_utf_8_to_16(const char *in8, wchar_t *out16, size_t size16)
*out16 = *out16end = 0;
if (*in8) {
if (*in8)
err |= UTF_ERROR_SMALL;
}
return err;
}
@@ -293,9 +286,8 @@ char *alloc_utf_8_from_16(const wchar_t *in16, size_t add)
{
size_t bsize = count_utf_8_from_16(in16);
char *out8 = NULL;
if (!bsize) {
if (!bsize)
return NULL;
}
out8 = (char *)malloc(sizeof(char) * (bsize + add));
conv_utf_16_to_8(in16, out8, bsize);
return out8;
@@ -305,9 +297,8 @@ wchar_t *alloc_utf16_from_8(const char *in8, size_t add)
{
size_t bsize = count_utf_16_from_8(in8);
wchar_t *out16 = NULL;
if (!bsize) {
if (!bsize)
return NULL;
}
out16 = (wchar_t *)malloc(sizeof(wchar_t) * (bsize + add));
conv_utf_8_to_16(in8, out16, bsize);
return out16;

View File

@@ -17321,58 +17321,6 @@
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new"
d="m 368.30892,141.58547 c -0.27613,4e-5 -0.49997,0.22388 -0.5,0.5 v 1.26473 h -4.76715 v 1.4911 h 4.76715 v 1.24417 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 0.63583,0.004 3.43318,-0.006 3.9995,-0.006 0.24106,0 0.46127,-0.0485 0.46127,-0.50967 4e-5,-0.85242 -8.9e-4,-2.98571 -8.9e-4,-3.95935 0,-0.30244 -0.19636,-0.51552 -0.46153,-0.51552 -0.82724,0 -3.36276,-0.009 -3.99823,-0.009 v 2e-5 z m 2.30359,-4.68113 -0.005,4.25868 c 0.48989,0.002 1.39549,0.005 1.88538,0.007 0.44541,0.0357 0.71675,0.47423 0.71675,0.85988 -6.6e-4,1.00616 -0.009,2.97018 -0.009,4.15122 0,0.46073 -0.24756,0.84994 -0.6533,0.84994 -0.48399,0.0143 -1.44986,-1.1e-4 -1.93405,-1.6e-4 v 3.87356 l -7.75691,-0.0669 v -14.00001 z"
sodipodi:nodetypes="cccccccccccccccccccccccccc" />
<g
transform="translate(230.76791,210.17135)"
style="display:inline;enable-background:new"
id="g4087_GP_lineart">
<g
id="g4082">
<path
sodipodi:nodetypes="cccccccccccccccccccc"
inkscape:connector-curvature="0"
id="path12456-6"
mask="none"
d="m 198.0253,98.27163 v 1.5 h 1 v -1.5 z m 0,2.5 v 2 h 1 v -2 z m 0,3 v 1.2793 l -2.58594,2.35156 0.67188,0.73828 2.60351,-2.36719 0.49027,-0.002 c 0.82475,0 0.82408,-1 0,-1 h -0.17972 v -1 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
id="path4185"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.10423;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 207.2397,99.568306 c -0.33768,-0.02992 -0.70751,0.105959 -1.01625,0.406518 l -0.51139,0.495896 c -0.13287,0.12942 -0.13287,0.34092 0,0.47035 l 2.04339,1.98784 c 0.13292,0.12938 0.3479,0.12938 0.48082,0 l 0.50922,-0.49802 c 0.3087,-0.30067 0.44811,-0.65869 0.41741,-0.98755 -0.0307,-0.32884 -0.20718,-0.60186 -0.41741,-0.80663 l -0.67969,-0.661886 c -0.21026,-0.204768 -0.48842,-0.37662 -0.8261,-0.406518 z m -2.31222,1.800554 c -0.0883,9.4e-4 -0.17353,0.0367 -0.23603,0.0979 l -4.25293,4.14168 c -0.0434,0.0426 -0.0749,0.095 -0.0896,0.15324 l -0.67969,2.65189 c -0.0614,0.24217 0.16235,0.46285 0.41088,0.40225 l 2.72308,-0.66402 c 0.0599,-0.0144 0.11363,-0.0428 0.15735,-0.0851 l 4.2551,-4.14382 c 0.13286,-0.12943 0.13286,-0.33881 0,-0.46825 l -2.0434,-1.98784 c -0.0651,-0.0634 -0.15267,-0.0994 -0.24478,-0.0979 z" />
<path
id="path12458-7"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 198.52539,94.771484 c -0.1326,2.7e-5 -0.25978,0.05272 -0.35351,0.146485 l -3,3 c -0.0938,0.09376 -0.14646,0.220915 -0.14649,0.353515 v 9.999996 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 2.50158 c 0.72806,0 0.76638,-1.01916 0,-1 h -2.00158 v -8.999996 h 9 v 0.186392 c 0,0.766385 1,0.767345 1,0 v -0.47936 l 2,-2 v 0.907841 c 0,0.708905 1,0.709935 1,0 v -2.114873 c -3e-5,-0.276131 -0.22387,-0.499972 -0.5,-0.5 z m 0.20703,1 h 8.58594 l -2,2 h -8.58594 z"
sodipodi:nodetypes="ccccccsccccssccsscccccccc" />
</g>
</g>
<g
transform="translate(167.42608,209.69482)"
style="display:inline;enable-background:new"
id="g7880_GP_lenght">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 224.38607,100.78271 c -0.15574,0.005 -0.30353,0.0699 -0.41211,0.18164 l -2.05673,2.00254 c -0.62065,0.56444 0.28322,1.46831 0.84766,0.84765 l 2.05673,-2.00254 c 0.39088,-0.38144 0.1104,-1.04428 -0.43555,-1.02929 z"
id="path15289-7-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
<path
sodipodi:nodetypes="ccccccccccc"
inkscape:connector-curvature="0"
id="path15289-7-6-5"
d="m 225.6621,95.349988 c -0.67621,-0.0096 -0.67621,1.009611 0,1 h 2.79493 c -1.0479,1.117288 -1.7641,1.668027 -2.82812,2.732043 -0.62065,0.56444 0.28321,1.468319 0.84765,0.847657 1.06063,-1.101282 1.59202,-1.777197 2.68554,-2.870716 v 2.791016 c -0.01,0.676162 1.00956,0.676162 1,0 v -4 c -3e-5,-0.276131 -0.22387,-0.499973 -0.5,-0.5 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
sodipodi:nodetypes="ccccccccccc"
inkscape:connector-curvature="0"
id="path15289-7-6-5-2"
d="m 221.03217,109.33958 c 0.67621,0.01 0.67621,-1.00961 0,-1 h -2.79493 c 1.0479,-1.11729 1.7641,-1.66802 2.82812,-2.73204 0.62065,-0.56444 -0.28321,-1.46832 -0.84765,-0.84766 -1.06063,1.10128 -1.59202,1.7772 -2.68554,2.87072 v -2.79102 c 0.01,-0.67616 -1.00956,-0.67616 -1,0 v 4 c 3e-5,0.27613 0.22387,0.49998 0.5,0.5 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</g>
<path
sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
d="m 417.92349,304.73964 c -0.7818,-0.0644 -0.86293,1.09626 -0.0796,1.1383 l 0.41758,0.0202 c 0.78182,0.0644 0.86296,-1.09626 0.0796,-1.13831 z m -7.87437,1.29265 c -0.65325,0.42724 0.0163,1.38626 0.65667,0.94062 l 0.34001,-0.23929 c 0.65327,-0.42727 -0.0163,-1.38631 -0.65662,-0.94061 z m 5.26412,-0.10772 c 0.785,-0.0185 0.73895,-1.18175 -0.0451,-1.14009 -0.6811,-0.0652 -1.43225,-0.0213 -2.22341,0.0851 -0.785,0.0185 -0.73896,1.18176 0.0451,1.14011 0.8585,-0.10954 1.60282,-0.14009 2.22342,-0.0852 z m -5.74172,5.34858 c -0.17789,-0.75187 -1.32618,-0.47161 -1.12597,0.27482 -0.008,0.72815 0.18352,1.43475 0.53595,2.12392 0.17789,0.75187 1.32617,0.47159 1.12598,-0.27483 -0.40688,-0.70818 -0.47775,-1.41605 -0.53596,-2.12391 z m 1.14987,4.81425 c 0.55238,0.5479 1.3799,-0.2833 0.81165,-0.81524 l -0.30437,-0.28193 c -0.55238,-0.54789 -1.37991,0.2833 -0.81163,0.81524 z m 2.55883,0.11471 c -0.78112,0.0716 -0.65484,1.22767 0.12391,1.13446 0.79706,0.0708 1.5429,0.0136 2.2124,-0.23372 0.7811,-0.0716 0.65482,-1.22768 -0.12391,-1.13445 -0.66955,0.35373 -1.42049,0.37687 -2.2124,0.23371 z m 4.35036,-1.24066 c 0.39775,-0.66505 -0.63058,-1.23994 -1.00859,-0.56384 l -0.19953,0.36135 c -0.39776,0.66506 0.63057,1.23995 1.00857,0.56383 z m -1.53457,-4.82813 c -0.44444,-0.63566 -1.409,0.0364 -0.94666,0.65956 0.53116,0.53126 0.99257,1.10609 1.28624,1.78569 0.44445,0.63565 1.40902,-0.0364 0.94667,-0.65956 -0.24301,-0.74231 -0.69323,-1.32054 -1.28625,-1.78569 z m -2.73483,-1.49223 c -0.72218,-0.30138 -1.16808,0.7761 -0.43732,1.05681 l 0.39025,0.14758 c 0.7222,0.30141 1.1681,-0.7761 0.43732,-1.0568 z m -7.60223,1.91562 c -0.52109,0.57678 0.37464,1.33651 0.87855,0.74515 l 0.26685,-0.31654 c 0.52111,-0.57679 -0.37465,-1.33654 -0.87854,-0.74516 z m 1.15912,7.09355 c -0.1906,-0.74845 -1.33363,-0.44917 -1.12109,0.29354 l 0.11543,0.39523 c 0.19062,0.74845 1.33365,0.44917 1.12109,-0.29354 z m -0.68592,-4.36328 c -0.0858,-0.76698 -1.25912,-0.62352 -1.15127,0.14077 -0.065,0.75431 -0.008,1.50847 0.28594,2.26232 0.0859,0.76696 1.25912,0.62352 1.15129,-0.14076 -0.28468,-0.81162 -0.29126,-1.53878 -0.28596,-2.26233 z m 1.97398,-4.7241 c -0.77314,0.13162 -0.55483,1.27463 0.21417,1.12135 0.7762,-0.30633 1.5005,-0.42412 2.18687,-0.40397 0.77313,-0.13163 0.55482,-1.27462 -0.21418,-1.12137 -0.74152,0.0229 -1.4733,0.13255 -2.18686,0.40399 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.15052;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:2.2;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new"
id="path4101-2-6-9-1_GP_dotdash" />
</g>
<g
inkscape:groupmode="layer"

Before

Width:  |  Height:  |  Size: 2.5 MiB

After

Width:  |  Height:  |  Size: 2.5 MiB

View File

@@ -33,8 +33,8 @@
const UserDef U_default = {
.versionfile = BLENDER_FILE_VERSION,
.subversionfile = BLENDER_FILE_SUBVERSION,
.flag = (USER_AUTOSAVE | USER_TOOLTIPS | USER_RELPATHS | USER_RELEASECONFIRM |
USER_SCRIPT_AUTOEXEC_DISABLE | USER_NONEGFRAMES),
.flag = (USER_AUTOSAVE | USER_TOOLTIPS | USER_SAVE_PREVIEWS | USER_RELPATHS |
USER_RELEASECONFIRM | USER_SCRIPT_AUTOEXEC_DISABLE | USER_NONEGFRAMES),
.dupflag = USER_DUP_MESH | USER_DUP_CURVE | USER_DUP_SURF | USER_DUP_FONT | USER_DUP_MBALL |
USER_DUP_LAMP | USER_DUP_ARM | USER_DUP_ACT | USER_DUP_LIGHTPROBE |
USER_DUP_GPENCIL,
@@ -231,7 +231,6 @@ const UserDef U_default = {
.collection_instance_empty_size = 1.0f,
.statusbar_flag = STATUSBAR_SHOW_VERSION,
.file_preview_type = USER_FILE_PREVIEW_CAMERA,
.runtime =
{

View File

@@ -22,7 +22,6 @@
# Export Functions
__all__ = (
"_init_properties_from_data", # Shared with gizmo default property initialization.
"keyconfig_export_as_data",
"keyconfig_import_from_data",
"keyconfig_init_from_data",
@@ -245,24 +244,20 @@ def keyconfig_export_as_data(wm, kc, filepath, *, all_keymaps=False):
# -----------------------------------------------------------------------------
# Import Functions
#
# NOTE: unlike export, this runs on startup.
# Take care making changes that could impact performance.
def _init_properties_from_data(base_props, base_value):
assert(type(base_value) is list)
for attr, value in base_value:
if type(value) is list:
base_props.property_unset(attr)
props = getattr(base_props, attr)
_init_properties_from_data(props, value)
else:
try:
setattr(base_props, attr, value)
except AttributeError:
print(f"Warning: property '{attr}' not found in item '{base_props.__class__.__name__}'")
except Exception as ex:
print(f"Warning: {ex!r}")
def _kmi_props_setattr(kmi_props, attr, value):
if type(value) is list:
kmi_subprop = getattr(kmi_props, attr)
for subattr, subvalue in value:
_kmi_props_setattr(kmi_subprop, subattr, subvalue)
return
try:
setattr(kmi_props, attr, value)
except AttributeError:
print(f"Warning: property '{attr}' not found in keymap item '{kmi_props.__class__.__name__}'")
except Exception as ex:
print(f"Warning: {ex!r}")
def keymap_init_from_data(km, km_items, is_modal=False):
@@ -276,7 +271,8 @@ def keymap_init_from_data(km, km_items, is_modal=False):
if kmi_props_data is not None:
kmi_props = kmi.properties
assert type(kmi_props_data) is list
_init_properties_from_data(kmi_props, kmi_props_data)
for attr, value in kmi_props_data:
_kmi_props_setattr(kmi_props, attr, value)
def keyconfig_init_from_data(kc, keyconfig_data):

View File

@@ -859,7 +859,6 @@ def register_tool(tool_cls, *, after=None, separator=False, group=False):
"icon": getattr(tool_cls, "bl_icon", None),
"cursor": getattr(tool_cls, "bl_cursor", None),
"widget": getattr(tool_cls, "bl_widget", None),
"widget_properties": getattr(tool_cls, "bl_widget_properties", None),
"keymap": getattr(tool_cls, "bl_keymap", None),
"data_block": getattr(tool_cls, "bl_data_block", None),
"operator": getattr(tool_cls, "bl_operator", None),

View File

@@ -30,6 +30,24 @@ ARRAY_TYPES = (list, tuple, IDPropertyArray, Vector)
MAX_DISPLAY_ROWS = 4
def rna_idprop_ui_get(item, *, create=True):
try:
return item['_RNA_UI']
except:
if create:
item['_RNA_UI'] = {}
return item['_RNA_UI']
else:
return None
def rna_idprop_ui_del(item):
try:
del item['_RNA_UI']
except KeyError:
pass
def rna_idprop_quote_path(prop):
return "[\"%s\"]" % bpy.utils.escape_identifier(prop)
@@ -41,9 +59,32 @@ def rna_idprop_ui_prop_update(item, prop):
prop_rna.update()
def rna_idprop_ui_prop_clear(item, prop):
ui_data = item.id_properties_ui(prop)
ui_data.clear()
def rna_idprop_ui_prop_get(item, prop, *, create=True):
rna_ui = rna_idprop_ui_get(item, create=create)
if rna_ui is None:
return None
try:
return rna_ui[prop]
except:
rna_ui[prop] = {}
return rna_ui[prop]
def rna_idprop_ui_prop_clear(item, prop, *, remove=True):
rna_ui = rna_idprop_ui_get(item, create=False)
if rna_ui is None:
return
try:
del rna_ui[prop]
except KeyError:
pass
if remove and len(item.keys()) == 1:
rna_idprop_ui_del(item)
def rna_idprop_context_value(context, context_member, property_type):
@@ -65,7 +106,8 @@ def rna_idprop_context_value(context, context_member, property_type):
def rna_idprop_has_properties(rna_item):
keys = rna_item.keys()
return bool(keys)
nbr_props = len(keys)
return (nbr_props > 1) or (nbr_props and '_RNA_UI' not in keys)
def rna_idprop_value_to_python(value):
@@ -84,8 +126,31 @@ def rna_idprop_value_item_type(value):
def rna_idprop_ui_prop_default_set(item, prop, value):
ui_data = item.id_properties_ui(prop)
ui_data.update(default=value)
defvalue = None
try:
prop_type, is_array = rna_idprop_value_item_type(item[prop])
if prop_type in {int, float, str}:
if is_array and isinstance(value, ARRAY_TYPES):
value = [prop_type(item) for item in value]
if any(value):
defvalue = value
else:
defvalue = prop_type(value)
except KeyError:
pass
except ValueError:
pass
if defvalue:
rna_ui = rna_idprop_ui_prop_get(item, prop, create=True)
rna_ui["default"] = defvalue
else:
rna_ui = rna_idprop_ui_prop_get(item, prop)
if rna_ui:
rna_ui.pop("default", None)
return defvalue
def rna_idprop_ui_create(
@@ -98,7 +163,7 @@ def rna_idprop_ui_create(
):
"""Create and initialize a custom property with limits, defaults and other settings."""
proptype, _ = rna_idprop_value_item_type(default)
proptype, is_array = rna_idprop_value_item_type(default)
# Sanitize limits
if proptype is bool:
@@ -115,22 +180,35 @@ def rna_idprop_ui_create(
rna_idprop_ui_prop_update(item, prop)
# Update the UI settings.
ui_data = item.id_properties_ui(prop)
ui_data.update(
subtype=subtype,
min=min,
max=max,
soft_min=soft_min,
soft_max=soft_max,
description=description,
default=default,
)
# Clear the UI settings
rna_ui_group = rna_idprop_ui_get(item, create=True)
rna_ui_group[prop] = {}
rna_ui = rna_ui_group[prop]
# Assign limits and default
if proptype in {int, float, bool}:
# The type must be exactly the same
rna_ui["min"] = proptype(min)
rna_ui["soft_min"] = proptype(soft_min)
rna_ui["max"] = proptype(max)
rna_ui["soft_max"] = proptype(soft_max)
if default and (not is_array or any(default)):
rna_ui["default"] = default
if is_array and subtype and subtype != 'NONE':
rna_ui["subtype"] = subtype
# Assign other settings
if description is not None:
rna_ui["description"] = description
prop_path = rna_idprop_quote_path(prop)
item.property_overridable_library_set(prop_path, overridable)
return rna_ui
def draw(layout, context, context_member, property_type, *, use_edit=True):
@@ -176,6 +254,10 @@ def draw(layout, context, context_member, property_type, *, use_edit=True):
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
for key, val in items:
if key == '_RNA_UI':
continue
is_rna = (key in rna_properties)
# only show API defined for developers

View File

@@ -796,11 +796,11 @@ def km_outliner(params):
("outliner.item_rename", {"type": 'F2', "value": 'PRESS'},
{"properties": [("use_active", True)]}),
("outliner.item_activate", {"type": 'LEFTMOUSE', "value": 'CLICK'},
{"properties": [("deselect_all", not params.legacy)]}),
{"properties": [("extend", False), ("deselect_all", not params.legacy)]}),
("outliner.item_activate", {"type": 'LEFTMOUSE', "value": 'CLICK', "ctrl": True},
{"properties": [("extend", True), ("deselect_all", not params.legacy)]}),
("outliner.item_activate", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True},
{"properties": [("extend_range", True), ("deselect_all", not params.legacy)]}),
{"properties": [("extend", False), ("extend_range", True), ("deselect_all", not params.legacy)]}),
("outliner.item_activate", {"type": 'LEFTMOUSE', "value": 'CLICK', "ctrl": True, "shift": True},
{"properties": [("extend", True), ("extend_range", True), ("deselect_all", not params.legacy)]}),
("outliner.select_box", {"type": 'B', "value": 'PRESS'}, None),
@@ -884,13 +884,15 @@ def km_uv_editor(params):
*_template_items_uv_select_mode(params),
("uv.mark_seam", {"type": 'E', "value": 'PRESS', "ctrl": True}, None),
("uv.select", {"type": params.select_mouse, "value": params.select_mouse_value},
{"properties": [("deselect_all", not params.legacy)]}),
{"properties": [("extend", False), ("deselect_all", not params.legacy)]}),
("uv.select", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True},
{"properties": [("extend", True)]}),
("uv.select_loop", {"type": params.select_mouse, "value": params.select_mouse_value, "alt": True}, None),
("uv.select_loop", {"type": params.select_mouse, "value": params.select_mouse_value, "alt": True},
{"properties": [("extend", False)]}),
("uv.select_loop", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True, "alt": True},
{"properties": [("extend", True)]}),
("uv.select_edge_ring", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "alt": True}, None),
("uv.select_edge_ring", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "alt": True},
{"properties": [("extend", False)]}),
("uv.select_edge_ring", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "shift": True, "alt": True},
{"properties": [("extend", True)]}),
("uv.shortest_path_pick", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True},
@@ -911,7 +913,7 @@ def km_uv_editor(params):
("uv.select_linked_pick", {"type": 'L', "value": 'PRESS'},
{"properties": [("extend", True), ("deselect", False)]}),
("uv.select_linked_pick", {"type": 'L', "value": 'PRESS', "shift": True},
{"properties": [("deselect", True)]}),
{"properties": [("extend", False), ("deselect", True)]}),
("uv.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None),
("uv.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None),
*_template_items_select_actions(params, "uv.select_all"),
@@ -955,7 +957,8 @@ def km_uv_editor(params):
# Fallback for MMB emulation
if params.use_mouse_emulate_3_button and params.select_mouse == 'LEFTMOUSE':
items.extend([
("uv.select_loop", {"type": params.select_mouse, "value": 'DOUBLE_CLICK'}, None),
("uv.select_loop", {"type": params.select_mouse, "value": 'DOUBLE_CLICK'},
{"properties": [("extend", False)]}),
("uv.select_loop", {"type": params.select_mouse, "value": 'DOUBLE_CLICK', "alt": True},
{"properties": [("extend", True)]}),
])
@@ -1351,7 +1354,9 @@ def km_mask_editing(params):
# click select keymap it's fine to have the context menu instead.
items.extend([
("mask.select", {"type": 'RIGHTMOUSE', "value": 'PRESS'},
{"properties": [("deselect_all", not params.legacy)]}),
{"properties": [
("extend", False), ("deselect", False), ("toggle", False),
("deselect_all", not params.legacy)]}),
("transform.translate", {"type": 'EVT_TWEAK_R', "value": 'ANY'}, None),
])
@@ -1365,7 +1370,7 @@ def km_mask_editing(params):
("mask.delete", {"type": 'X', "value": 'PRESS'}, None),
("mask.delete", {"type": 'DEL', "value": 'PRESS'}, None),
("mask.select", {"type": params.select_mouse, "value": 'PRESS', "shift": True},
{"properties": [("toggle", True)]}),
{"properties": [("extend", False), ("deselect", False), ("toggle", True)]}),
*_template_items_select_actions(params, "mask.select_all"),
("mask.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
("mask.select_linked_pick", {"type": 'L', "value": 'PRESS'},
@@ -1385,7 +1390,8 @@ def km_mask_editing(params):
{"properties": [("unselected", False)]}),
("mask.hide_view_set", {"type": 'H', "value": 'PRESS', "shift": True},
{"properties": [("unselected", True)]}),
("clip.select", {"type": params.select_mouse, "value": 'PRESS', "ctrl": True}, None),
("clip.select", {"type": params.select_mouse, "value": 'PRESS', "ctrl": True},
{"properties": [("extend", False)]}),
("mask.cyclic_toggle", {"type": 'C', "value": 'PRESS', "alt": True}, None),
("mask.slide_point", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
("mask.slide_spline_curvature", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
@@ -1440,7 +1446,7 @@ def km_markers(params):
("marker.select", {"type": params.select_mouse, "value": 'PRESS', "shift": True},
{"properties": [("extend", True)]}),
("marker.select", {"type": params.select_mouse, "value": 'PRESS', "ctrl": True},
{"properties": [("camera", True)]}),
{"properties": [("extend", False), ("camera", True)]}),
("marker.select", {"type": params.select_mouse, "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("extend", True), ("camera", True)]}),
("marker.select_box", {"type": params.select_tweak, "value": 'ANY'},
@@ -1525,27 +1531,29 @@ def km_graph_editor(params):
("wm.context_toggle", {"type": 'H', "value": 'PRESS', "ctrl": True},
{"properties": [("data_path", 'space_data.show_handles')]}),
("graph.clickselect", {"type": params.select_mouse, "value": 'PRESS'},
{"properties": [("deselect_all", not params.legacy)]}),
{"properties": [
("extend", False), ("deselect_all", not params.legacy),
("column", False), ("curves", False)]}),
("graph.clickselect", {"type": params.select_mouse, "value": 'PRESS', "alt": True},
{"properties": [("column", True)]}),
{"properties": [("extend", False), ("column", True), ("curves", False)]}),
("graph.clickselect", {"type": params.select_mouse, "value": 'PRESS', "shift": True},
{"properties": [("extend", True)]}),
{"properties": [("extend", True), ("column", False), ("curves", False)]}),
("graph.clickselect", {"type": params.select_mouse, "value": 'PRESS', "shift": True, "alt": True},
{"properties": [("extend", True), ("column", True)]}),
{"properties": [("extend", True), ("column", True), ("curves", False)]}),
("graph.clickselect", {"type": params.select_mouse, "value": 'PRESS', "ctrl": True, "alt": True},
{"properties": [("curves", True)]}),
{"properties": [("extend", False), ("column", False), ("curves", True)]}),
("graph.clickselect", {"type": params.select_mouse, "value": 'PRESS', "shift": True, "ctrl": True, "alt": True},
{"properties": [("extend", True), ("curves", True)]}),
{"properties": [("extend", True), ("column", False), ("curves", True)]}),
("graph.select_leftright",
{"type": params.select_mouse, "value": 'PRESS' if params.legacy else 'CLICK', "ctrl": True},
{"properties": [("mode", 'CHECK')]}),
{"properties": [("mode", 'CHECK'), ("extend", False)]}),
("graph.select_leftright",
{"type": params.select_mouse, "value": 'PRESS' if params.legacy else 'CLICK', "ctrl": True, "shift": True},
{"properties": [("mode", 'CHECK'), ("extend", True)]}),
("graph.select_leftright", {"type": 'LEFT_BRACKET', "value": 'PRESS'},
{"properties": [("mode", 'LEFT')]}),
{"properties": [("mode", 'LEFT'), ("extend", False)]}),
("graph.select_leftright", {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
{"properties": [("mode", 'RIGHT')]}),
{"properties": [("mode", 'RIGHT'), ("extend", False)]}),
*_template_items_select_actions(params, "graph.select_all"),
("graph.select_box", {"type": 'B', "value": 'PRESS'}, None),
("graph.select_box", {"type": 'B', "value": 'PRESS', "alt": True},
@@ -1589,7 +1597,8 @@ def km_graph_editor(params):
("graph.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("confirm", False)]}),
("graph.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
("graph.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None),
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "ctrl": True}, None),
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "ctrl": True},
{"properties": [("extend", False)]}),
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "shift": True, "ctrl": True},
{"properties": [("extend", True)]}),
("graph.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
@@ -1795,10 +1804,13 @@ def km_node_editor(params):
def node_select_ops(select_mouse):
return [
("node.select", {"type": select_mouse, "value": 'PRESS'},
{"properties": [("deselect_all", True)]}),
("node.select", {"type": select_mouse, "value": 'PRESS', "ctrl": True}, None),
("node.select", {"type": select_mouse, "value": 'PRESS', "alt": True}, None),
("node.select", {"type": select_mouse, "value": 'PRESS', "ctrl": True, "alt": True}, None),
{"properties": [("extend", False), ("deselect_all", True)]}),
("node.select", {"type": select_mouse, "value": 'PRESS', "ctrl": True},
{"properties": [("extend", False)]}),
("node.select", {"type": select_mouse, "value": 'PRESS', "alt": True},
{"properties": [("extend", False)]}),
("node.select", {"type": select_mouse, "value": 'PRESS', "ctrl": True, "alt": True},
{"properties": [("extend", False)]}),
("node.select", {"type": select_mouse, "value": 'PRESS', "shift": True},
{"properties": [("extend", True)]}),
("node.select", {"type": select_mouse, "value": 'PRESS', "shift": True, "ctrl": True},
@@ -1820,7 +1832,7 @@ def km_node_editor(params):
items.extend(node_select_ops('RIGHTMOUSE'))
items.extend([
("node.select", {"type": 'LEFTMOUSE', "value": 'PRESS'},
{"properties": [("deselect_all", False)]}),
{"properties": [("extend", False), ("deselect_all", False)]}),
("node.select", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
{"properties": [("extend", True)]}),
])
@@ -1875,7 +1887,8 @@ def km_node_editor(params):
*_template_items_select_actions(params, "node.select_all"),
("node.select_linked_to", {"type": 'L', "value": 'PRESS', "shift": True}, None),
("node.select_linked_from", {"type": 'L', "value": 'PRESS'}, None),
("node.select_grouped", {"type": 'G', "value": 'PRESS', "shift": True}, None),
("node.select_grouped", {"type": 'G', "value": 'PRESS', "shift": True},
{"properties": [("extend", False)]}),
("node.select_grouped", {"type": 'G', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("extend", True)]}),
("node.select_same_type_step", {"type": 'RIGHT_BRACKET', "value": 'PRESS', "shift": True},
@@ -1896,19 +1909,19 @@ def km_node_editor(params):
("node.clipboard_paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
("node.viewer_border", {"type": 'B', "value": 'PRESS', "ctrl": True}, None),
("node.clear_viewer_border", {"type": 'B', "value": 'PRESS', "ctrl": True, "alt": True}, None),
("node.translate_attach", {"type": 'G', "value": 'PRESS'}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
("node.translate_attach", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
("node.translate_attach", {"type": params.select_tweak, "value": 'ANY'}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
("transform.translate", {"type": 'G', "value": 'PRESS'}, {"properties": [("view2d_edge_pan", True)]}),
("node.translate_attach", {"type": 'G', "value": 'PRESS'}, None),
("node.translate_attach", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, None),
("node.translate_attach", {"type": params.select_tweak, "value": 'ANY'}, None),
("transform.translate", {"type": 'G', "value": 'PRESS'}, None),
("transform.translate", {"type": 'EVT_TWEAK_L', "value": 'ANY'},
{"properties": [("release_confirm", True), ("view2d_edge_pan", True)]}),
{"properties": [("release_confirm", True)]}),
("transform.translate", {"type": params.select_tweak, "value": 'ANY'},
{"properties": [("release_confirm", True), ("view2d_edge_pan", True)]}),
{"properties": [("release_confirm", True)]}),
("transform.rotate", {"type": 'R', "value": 'PRESS'}, None),
("transform.resize", {"type": 'S', "value": 'PRESS'}, None),
("node.move_detach_links", {"type": 'D', "value": 'PRESS', "alt": True}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
("node.move_detach_links_release", {"type": params.action_tweak, "value": 'ANY', "alt": True}, {"properties": [("NODE_OT_translate_attach", [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])])]}),
("node.move_detach_links", {"type": params.select_tweak, "value": 'ANY', "alt": True}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
("node.move_detach_links", {"type": 'D', "value": 'PRESS', "alt": True}, None),
("node.move_detach_links_release", {"type": params.action_tweak, "value": 'ANY', "alt": True}, None),
("node.move_detach_links", {"type": params.select_tweak, "value": 'ANY', "alt": True}, None),
("wm.context_toggle", {"type": 'TAB', "value": 'PRESS', "shift": True},
{"properties": [("data_path", 'tool_settings.use_snap')]}),
("wm.context_menu_enum", {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True},
@@ -2118,27 +2131,29 @@ def km_dopesheet(params):
items.extend([
("action.clickselect", {"type": params.select_mouse, "value": 'PRESS'},
{"properties": [("deselect_all", not params.legacy)]}),
{"properties": [
("extend", False), ("deselect_all", not params.legacy),
("column", False), ("channel", False)]}),
("action.clickselect", {"type": params.select_mouse, "value": 'PRESS', "alt": True},
{"properties": [("column", True)]}),
{"properties": [("extend", False), ("column", True), ("channel", False)]}),
("action.clickselect", {"type": params.select_mouse, "value": 'PRESS', "shift": True},
{"properties": [("extend", True)]}),
{"properties": [("extend", True), ("column", False), ("channel", False)]}),
("action.clickselect", {"type": params.select_mouse, "value": 'PRESS', "shift": True, "alt": True},
{"properties": [("extend", True), ("column", True)]}),
{"properties": [("extend", True), ("column", True), ("channel", False)]}),
("action.clickselect", {"type": params.select_mouse, "value": 'PRESS', "ctrl": True, "alt": True},
{"properties": [("channel", True)]}),
{"properties": [("extend", False), ("column", False), ("channel", True)]}),
("action.clickselect", {"type": params.select_mouse, "value": 'PRESS', "shift": True, "ctrl": True, "alt": True},
{"properties": [("extend", True), ("channel", True)]}),
{"properties": [("extend", True), ("column", False), ("channel", True)]}),
("action.select_leftright",
{"type": params.select_mouse, "value": 'PRESS' if params.legacy else 'CLICK', "ctrl": True},
{"properties": [("mode", 'CHECK')]}),
{"properties": [("mode", 'CHECK'), ("extend", False)]}),
("action.select_leftright",
{"type": params.select_mouse, "value": 'PRESS' if params.legacy else 'CLICK', "ctrl": True, "shift": True},
{"properties": [("mode", 'CHECK'), ("extend", True)]}),
("action.select_leftright", {"type": 'LEFT_BRACKET', "value": 'PRESS'},
{"properties": [("mode", 'LEFT')]}),
{"properties": [("mode", 'LEFT'), ("extend", False)]}),
("action.select_leftright", {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
{"properties": [("mode", 'RIGHT')]}),
{"properties": [("mode", 'RIGHT'), ("extend", False)]}),
*_template_items_select_actions(params, "action.select_all"),
("action.select_box", {"type": 'B', "value": 'PRESS'},
{"properties": [("axis_range", False)]}),
@@ -2249,7 +2264,8 @@ def km_nla_channels(params):
)
items.extend([
("nla.channels_click", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
("nla.channels_click", {"type": 'LEFTMOUSE', "value": 'PRESS'},
{"properties": [("extend", False)]}),
("nla.channels_click", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
{"properties": [("extend", True)]}),
("nla.tracks_add", {"type": 'A', "value": 'PRESS', "shift": True},
@@ -2274,19 +2290,19 @@ def km_nla_editor(params):
items.extend([
("nla.click_select", {"type": params.select_mouse, "value": 'PRESS'},
{"properties": [("deselect_all", not params.legacy)]}),
{"properties": [("extend", False), ("deselect_all", not params.legacy)]}),
("nla.click_select", {"type": params.select_mouse, "value": 'PRESS', "shift": True},
{"properties": [("extend", True)]}),
("nla.select_leftright",
{"type": params.select_mouse, "value": 'PRESS' if params.legacy else 'CLICK', "ctrl": True},
{"properties": [("mode", 'CHECK')]}),
{"properties": [("mode", 'CHECK'), ("extend", False)]}),
("nla.select_leftright",
{"type": params.select_mouse, "value": 'PRESS' if params.legacy else 'CLICK', "ctrl": True, "shift": True},
{"properties": [("mode", 'CHECK'), ("extend", True)]}),
("nla.select_leftright", {"type": 'LEFT_BRACKET', "value": 'PRESS'},
{"properties": [("mode", 'LEFT')]}),
{"properties": [("mode", 'LEFT'), ("extend", False)]}),
("nla.select_leftright", {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
{"properties": [("mode", 'RIGHT')]}),
{"properties": [("mode", 'RIGHT'), ("extend", False)]}),
*_template_items_select_actions(params, "nla.select_all"),
("nla.select_box", {"type": 'B', "value": 'PRESS'},
{"properties": [("axis_range", False)]}),
@@ -2482,7 +2498,7 @@ def km_text(params):
{"properties": [("type", 'PREVIOUS_CHARACTER')]}),
("text.delete", {"type": 'DEL', "value": 'PRESS', "ctrl": True, "repeat": True},
{"properties": [("type", 'NEXT_WORD')]}),
("text.delete", {"type": 'BACK_SPACE', "value": 'PRESS', "ctrl": True, "repeat": True},
("text.delete", {"type": 'BACK_SPACE', "value": 'PRESS', "ctrl": True},
{"properties": [("type", 'PREVIOUS_WORD')]}),
("text.overwrite_toggle", {"type": 'INSERT', "value": 'PRESS'}, None),
("text.scroll_bar", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
@@ -2606,7 +2622,8 @@ def km_sequencer(params):
for i in range(10)
)
),
("sequencer.select", {"type": params.select_mouse, "value": 'PRESS'}, None),
("sequencer.select", {"type": params.select_mouse, "value": 'PRESS'},
{"properties": [("deselect_all", True)]}),
("sequencer.select", {"type": params.select_mouse, "value": 'PRESS', "shift": True},
{"properties": [("extend", True)]}),
("sequencer.select", {"type": params.select_mouse, "value": 'PRESS', "alt": True},
@@ -2621,7 +2638,8 @@ def km_sequencer(params):
{"properties": [("side_of_frame", True), ("linked_time", True), ("extend", True)]}),
("sequencer.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None),
("sequencer.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None),
("sequencer.select_linked_pick", {"type": 'L', "value": 'PRESS'}, None),
("sequencer.select_linked_pick", {"type": 'L', "value": 'PRESS'},
{"properties": [("extend", False)]}),
("sequencer.select_linked_pick", {"type": 'L', "value": 'PRESS', "shift": True},
{"properties": [("extend", True)]}),
("sequencer.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
@@ -2844,7 +2862,7 @@ def km_clip_editor(params):
{"properties": [("position", 'PATHSTART')]}),
("clip.change_frame", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
("clip.select", {"type": params.select_mouse, "value": 'PRESS'},
{"properties": [("deselect_all", not params.legacy)]}),
{"properties": [("extend", False), ("deselect_all", not params.legacy)]}),
("clip.select", {"type": params.select_mouse, "value": 'PRESS', "shift": True},
{"properties": [("extend", True)]}),
*_template_items_select_actions(params, "clip.select_all"),
@@ -2930,7 +2948,8 @@ def km_clip_graph_editor(params):
)
items.extend([
("clip.graph_select", {"type": params.select_mouse, "value": 'PRESS'}, None),
("clip.graph_select", {"type": params.select_mouse, "value": 'PRESS'},
{"properties": [("extend", False)]}),
("clip.graph_select", {"type": params.select_mouse, "value": 'PRESS', "shift": True},
{"properties": [("extend", True)]}),
*_template_items_select_actions(params, "clip.graph_select_all_markers"),
@@ -4222,7 +4241,8 @@ def km_paint_curve(params):
items.extend([
("paintcurve.add_point_slide", {"type": params.action_mouse, "value": 'PRESS', "ctrl": True}, None),
("paintcurve.select", {"type": params.select_mouse, "value": 'PRESS'}, None),
("paintcurve.select", {"type": params.select_mouse, "value": 'PRESS'},
{"properties": [("extend", False)]}),
("paintcurve.select", {"type": params.select_mouse, "value": 'PRESS', "shift": True},
{"properties": [("extend", True)]}),
("paintcurve.slide", {"type": params.action_mouse, "value": 'PRESS'},
@@ -4644,13 +4664,15 @@ def km_mesh(params):
# Selection modes.
*_template_items_editmode_mesh_select_mode(params),
# Loop Select with alt. Double click in case MMB emulation is on (below).
("mesh.loop_select", {"type": params.select_mouse, "value": params.select_mouse_value, "alt": True}, None),
("mesh.loop_select", {"type": params.select_mouse, "value": params.select_mouse_value, "alt": True},
{"properties": [("extend", False), ("deselect", False), ("toggle", False)]}),
("mesh.loop_select", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True, "alt": True},
{"properties": [("toggle", True)]}),
{"properties": [("extend", False), ("deselect", False), ("toggle", True)]}),
# Selection
("mesh.edgering_select", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "alt": True}, None),
("mesh.edgering_select", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "alt": True},
{"properties": [("extend", False), ("deselect", False), ("toggle", False)]}),
("mesh.edgering_select", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True, "ctrl": True, "alt": True},
{"properties": [("toggle", True)]}),
{"properties": [("extend", False), ("deselect", False), ("toggle", True)]}),
("mesh.shortest_path_pick", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True},
{"properties": [("use_fill", False)]}),
("mesh.shortest_path_pick", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True, "ctrl": True},
@@ -4732,14 +4754,16 @@ def km_mesh(params):
if params.use_mouse_emulate_3_button and params.select_mouse == 'LEFTMOUSE':
items.extend([
("mesh.loop_select", {"type": params.select_mouse, "value": 'DOUBLE_CLICK'}, None),
("mesh.loop_select", {"type": params.select_mouse, "value": 'DOUBLE_CLICK'},
{"properties": [("extend", False), ("deselect", False), ("toggle", False)]}),
("mesh.loop_select", {"type": params.select_mouse, "value": 'DOUBLE_CLICK', "shift": True},
{"properties": [("extend", True)]}),
{"properties": [("extend", True), ("deselect", False), ("toggle", False)]}),
("mesh.loop_select", {"type": params.select_mouse, "value": 'DOUBLE_CLICK', "alt": True},
{"properties": [("deselect", True)]}),
("mesh.edgering_select", {"type": params.select_mouse, "value": 'DOUBLE_CLICK', "ctrl": True}, None),
{"properties": [("extend", False), ("deselect", True), ("toggle", False)]}),
("mesh.edgering_select", {"type": params.select_mouse, "value": 'DOUBLE_CLICK', "ctrl": True},
{"properties": [("extend", False), ("deselect", False), ("toggle", False)]}),
("mesh.edgering_select", {"type": params.select_mouse, "value": 'DOUBLE_CLICK', "shift": True, "ctrl": True},
{"properties": [("toggle", True)]}),
{"properties": [("extend", False), ("deselect", False), ("toggle", True)]}),
])
if params.legacy:
@@ -5929,7 +5953,7 @@ def km_node_editor_tool_select(params):
{"space_type": 'NODE_EDITOR', "region_type": 'WINDOW'},
{"items": [
("node.select", {"type": params.select_mouse, "value": 'PRESS'},
{"properties": [("deselect_all", not params.legacy)]}),
{"properties": [("extend", False), ("deselect_all", not params.legacy)]}),
]},
)
@@ -6996,7 +7020,8 @@ def km_sequencer_editor_tool_select(params):
"Sequencer Tool: Select",
{"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'},
{"items": [
("sequencer.select", {"type": params.select_mouse, "value": 'PRESS'}, None),
("sequencer.select", {"type": params.select_mouse, "value": 'PRESS'},
{"properties": [("extend", False), ("deselect_all", not params.legacy)]}),
*_template_items_change_frame(params),
]},
)

View File

@@ -1814,7 +1814,8 @@ def km_sequencer(params):
for i in range(10)
)
),
("sequencer.select", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
("sequencer.select", {"type": 'LEFTMOUSE', "value": 'PRESS'},
{"properties": [("deselect_all", True)]}),
("sequencer.select", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
{"properties": [("extend", True)]}),
("sequencer.select", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True},

View File

@@ -46,7 +46,6 @@ def update_factory_startup_screens():
def update_factory_startup_scenes():
for scene in bpy.data.scenes:
scene.tool_settings.use_keyframe_insert_auto = True
scene.tool_settings.gpencil_sculpt.use_scale_thickness = True
def update_factory_startup_grease_pencils():

View File

@@ -29,28 +29,9 @@ def update_factory_startup_screens():
params.use_filter_folder = True
def update_factory_startup_ffmpeg_preset():
preset = "H264_in_MP4"
preset_filepath = bpy.utils.preset_find(preset, preset_path="ffmpeg")
if not preset_filepath:
print("Preset %r not found" % preset)
for scene in bpy.data.scenes:
render = scene.render
render.image_settings.file_format = 'FFMPEG'
if preset_filepath:
bpy.ops.script.python_file_run({"scene": scene}, filepath=preset_filepath)
render.ffmpeg.audio_codec = 'AAC'
render.ffmpeg.audio_bitrate = 256
@persistent
def load_handler(_):
update_factory_startup_screens()
if bpy.app.build_options.codec_ffmpeg:
update_factory_startup_ffmpeg_preset()
def register():

View File

@@ -970,7 +970,7 @@ class OBJECT_OT_assign_property_defaults(Operator):
def assign_defaults(obj):
from rna_prop_ui import rna_idprop_ui_prop_default_set
rna_properties = {prop.identifier for prop in obj.bl_rna.properties if prop.is_runtime}
rna_properties = {'_RNA_UI'} | {prop.identifier for prop in obj.bl_rna.properties if prop.is_runtime}
for prop, value in obj.items():
if prop not in rna_properties:

View File

@@ -37,19 +37,20 @@ class SequencerCrossfadeSounds(Operator):
@classmethod
def poll(cls, context):
strip = context.active_sequence_strip
return strip and (strip.type == 'SOUND')
if context.scene and context.scene.sequence_editor and context.scene.sequence_editor.active_strip:
return context.scene.sequence_editor.active_strip.type == 'SOUND'
else:
return False
def execute(self, context):
scene = context.scene
seq1 = None
seq2 = None
for strip in scene.sequence_editor.sequences:
if strip.select and strip.type == 'SOUND':
for s in context.scene.sequence_editor.sequences:
if s.select and s.type == 'SOUND':
if seq1 is None:
seq1 = strip
seq1 = s
elif seq2 is None:
seq2 = strip
seq2 = s
else:
seq2 = None
break
@@ -57,19 +58,21 @@ class SequencerCrossfadeSounds(Operator):
self.report({'ERROR'}, "Select 2 sound strips")
return {'CANCELLED'}
if seq1.frame_final_start > seq2.frame_final_start:
seq1, seq2 = seq2, seq1
s = seq1
seq1 = seq2
seq2 = s
if seq1.frame_final_end > seq2.frame_final_start:
tempcfra = scene.frame_current
scene.frame_current = seq2.frame_final_start
tempcfra = context.scene.frame_current
context.scene.frame_current = seq2.frame_final_start
seq1.keyframe_insert("volume")
scene.frame_current = seq1.frame_final_end
context.scene.frame_current = seq1.frame_final_end
seq1.volume = 0
seq1.keyframe_insert("volume")
seq2.keyframe_insert("volume")
scene.frame_current = seq2.frame_final_start
context.scene.frame_current = seq2.frame_final_start
seq2.volume = 0
seq2.keyframe_insert("volume")
scene.frame_current = tempcfra
context.scene.frame_current = tempcfra
return {'FINISHED'}
else:
self.report({'ERROR'}, "The selected strips don't overlap")
@@ -92,27 +95,28 @@ class SequencerSplitMulticam(Operator):
@classmethod
def poll(cls, context):
strip = context.active_sequence_strip
return strip and (strip.type == 'MULTICAM')
if context.scene and context.scene.sequence_editor and context.scene.sequence_editor.active_strip:
return context.scene.sequence_editor.active_strip.type == 'MULTICAM'
else:
return False
def execute(self, context):
scene = context.scene
camera = self.camera
strip = context.active_sequence_strip
s = context.scene.sequence_editor.active_strip
if strip.multicam_source == camera or camera >= strip.channel:
if s.multicam_source == camera or camera >= s.channel:
return {'FINISHED'}
cfra = scene.frame_current
right_strip = strip.split(frame=cfra, split_method='SOFT')
cfra = context.scene.frame_current
right_strip = s.split(frame=cfra, split_method='SOFT')
if right_strip:
strip.select = False
s.select = False
right_strip.select = True
scene.sequence_editor.active_strip = right_strip
context.scene.sequence_editor.active_strip = right_strip
context.active_sequence_strip.multicam_source = camera
context.scene.sequence_editor.active_strip.multicam_source = camera
return {'FINISHED'}
@@ -125,13 +129,12 @@ class SequencerDeinterlaceSelectedMovies(Operator):
@classmethod
def poll(cls, context):
scene = context.scene
return (scene and scene.sequence_editor)
return (context.scene and context.scene.sequence_editor)
def execute(self, context):
for strip in context.scene.sequence_editor.sequences_all:
if strip.select and strip.type == 'MOVIE':
strip.use_deinterlace = True
for s in context.scene.sequence_editor.sequences_all:
if s.select and s.type == 'MOVIE':
s.use_deinterlace = True
return {'FINISHED'}
@@ -144,12 +147,10 @@ class SequencerFadesClear(Operator):
@classmethod
def poll(cls, context):
strip = context.active_sequence_strip
return strip is not None
return context.scene and context.scene.sequence_editor and context.scene.sequence_editor.active_strip
def execute(self, context):
scene = context.scene
animation_data = scene.animation_data
animation_data = context.scene.animation_data
if animation_data is None:
return {'CANCELLED'}
action = animation_data.action
@@ -201,8 +202,7 @@ class SequencerFadesAdd(Operator):
@classmethod
def poll(cls, context):
# Can't use context.selected_sequences as it can have an impact on performances
strip = context.active_sequence_strip
return strip is not None
return context.scene and context.scene.sequence_editor and context.scene.sequence_editor.active_strip
def execute(self, context):
from math import floor
@@ -218,11 +218,11 @@ class SequencerFadesAdd(Operator):
sequences = context.selected_sequences
if self.type in {'CURSOR_TO', 'CURSOR_FROM'}:
sequences = [
strip for strip in sequences
if strip.frame_final_start < scene.frame_current < strip.frame_final_end
s for s in sequences
if s.frame_final_start < context.scene.frame_current < s.frame_final_end
]
max_duration = min(sequences, key=lambda strip: strip.frame_final_duration).frame_final_duration
max_duration = min(sequences, key=lambda s: s.frame_final_duration).frame_final_duration
max_duration = floor(max_duration / 2.0) if self.type == 'IN_OUT' else max_duration
faded_sequences = []
@@ -245,15 +245,14 @@ class SequencerFadesAdd(Operator):
return {'FINISHED'}
def calculate_fade_duration(self, context, sequence):
scene = context.scene
frame_current = scene.frame_current
frame_current = context.scene.frame_current
duration = 0.0
if self.type == 'CURSOR_TO':
duration = abs(frame_current - sequence.frame_final_start)
elif self.type == 'CURSOR_FROM':
duration = abs(sequence.frame_final_end - frame_current)
else:
duration = calculate_duration_frames(scene, self.duration_seconds)
duration = calculate_duration_frames(context, self.duration_seconds)
return max(1, duration)
def is_long_enough(self, sequence, duration=0.0):
@@ -279,9 +278,8 @@ class SequencerFadesAdd(Operator):
that corresponds to the sequence.
Returns the matching FCurve or creates a new one if the function can't find a match.
"""
scene = context.scene
fade_fcurve = None
fcurves = scene.animation_data.action.fcurves
fcurves = context.scene.animation_data.action.fcurves
searched_data_path = sequence.path_from_id(animated_property)
for fcurve in fcurves:
if fcurve.data_path == searched_data_path:
@@ -374,8 +372,8 @@ class Fade:
return "Fade %r: %r to %r" % (self.type, self.start, self.end)
def calculate_duration_frames(scene, duration_seconds):
return round(duration_seconds * scene.render.fps / scene.render.fps_base)
def calculate_duration_frames(context, duration_seconds):
return round(duration_seconds * context.scene.render.fps / context.scene.render.fps_base)
classes = (

View File

@@ -1367,32 +1367,31 @@ class WM_OT_properties_edit(Operator):
}
def get_value_eval(self):
failed = False
try:
value_eval = eval(self.value)
# assert else None -> None, not "None", see T33431.
assert(type(value_eval) in {str, float, int, bool, tuple, list})
except:
failed = True
value_eval = self.value
return value_eval, failed
return value_eval
def get_default_eval(self):
failed = False
try:
default_eval = eval(self.default)
# assert else None -> None, not "None", see T33431.
assert(type(default_eval) in {str, float, int, bool, tuple, list})
except:
failed = True
default_eval = self.default
return default_eval, failed
return default_eval
def execute(self, context):
from rna_prop_ui import (
rna_idprop_ui_prop_get,
rna_idprop_ui_prop_clear,
rna_idprop_ui_prop_update,
rna_idprop_ui_prop_default_set,
rna_idprop_value_item_type,
)
@@ -1406,8 +1405,8 @@ class WM_OT_properties_edit(Operator):
self.report({'ERROR'}, "Direct execution not supported")
return {'CANCELLED'}
value_eval, value_failed = self.get_value_eval()
default_eval, default_failed = self.get_default_eval()
value_eval = self.get_value_eval()
default_eval = self.get_default_eval()
# First remove
item = eval("context.%s" % data_path)
@@ -1418,7 +1417,7 @@ class WM_OT_properties_edit(Operator):
prop_type_old = type(item[prop_old])
# Deleting the property will also remove the UI data.
rna_idprop_ui_prop_clear(item, prop_old)
del item[prop_old]
# Reassign
@@ -1432,43 +1431,27 @@ class WM_OT_properties_edit(Operator):
prop_type_new = type(prop_value)
prop_type, is_array = rna_idprop_value_item_type(prop_value)
if prop_type == int:
ui_data = item.id_properties_ui(prop)
if type(default_eval) == str:
self.report({'WARNING'}, "Could not evaluate number from default value")
default_eval = None
elif hasattr(default_eval, "__len__"):
default_eval = [int(round(value)) for value in default_eval]
ui_data.update(
min=int(round(self.min)),
max=int(round(self.max)),
soft_min=int(round(self.soft_min)),
soft_max=int(round(self.soft_max)),
default=default_eval,
subtype=self.subtype,
description=self.description
)
elif prop_type == float:
ui_data = item.id_properties_ui(prop)
if type(default_eval) == str:
self.report({'WARNING'}, "Could not evaluate number from default value")
default_eval = None
ui_data.update(
min=self.min,
max=self.max,
soft_min=self.soft_min,
soft_max=self.soft_max,
default=default_eval,
subtype=self.subtype,
description=self.description
)
elif prop_type == str and not is_array and not default_failed: # String arrays do not support UI data.
ui_data = item.id_properties_ui(prop)
ui_data.update(
default=self.default,
subtype=self.subtype,
description=self.description
)
prop_ui = rna_idprop_ui_prop_get(item, prop)
if prop_type in {float, int}:
prop_ui["min"] = prop_type(self.min)
prop_ui["max"] = prop_type(self.max)
if self.use_soft_limits:
prop_ui["soft_min"] = prop_type(self.soft_min)
prop_ui["soft_max"] = prop_type(self.soft_max)
else:
prop_ui["soft_min"] = prop_type(self.min)
prop_ui["soft_max"] = prop_type(self.max)
if prop_type == float and is_array and self.subtype != 'NONE':
prop_ui["subtype"] = self.subtype
else:
prop_ui.pop("subtype", None)
prop_ui["description"] = self.description
rna_idprop_ui_prop_default_set(item, prop, default_eval)
# If we have changed the type of the property, update its potential anim curves!
if prop_type_old != prop_type_new:
@@ -1509,6 +1492,7 @@ class WM_OT_properties_edit(Operator):
def invoke(self, context, _event):
from rna_prop_ui import (
rna_idprop_ui_prop_get,
rna_idprop_value_to_python,
rna_idprop_value_item_type
)
@@ -1535,34 +1519,35 @@ class WM_OT_properties_edit(Operator):
self.is_overridable_library = bool(is_overridable)
# default default value
value, value_failed = self.get_value_eval()
prop_type, is_array = rna_idprop_value_item_type(value)
prop_type, is_array = rna_idprop_value_item_type(self.get_value_eval())
if prop_type in {int, float}:
self.default = str(prop_type(0))
else:
self.default = ""
# setup defaults
if prop_type in {int, float}:
ui_data = item.id_properties_ui(prop)
rna_data = ui_data.as_dict()
self.subtype = rna_data["subtype"]
self.min = rna_data["min"]
self.max = rna_data["max"]
self.soft_min = rna_data["soft_min"]
self.soft_max = rna_data["soft_max"]
prop_ui = rna_idprop_ui_prop_get(item, prop, create=False)
if prop_ui:
self.min = prop_ui.get("min", -1000000000)
self.max = prop_ui.get("max", 1000000000)
self.description = prop_ui.get("description", "")
defval = prop_ui.get("default", None)
if defval is not None:
self.default = str(rna_idprop_value_to_python(defval))
self.soft_min = prop_ui.get("soft_min", self.min)
self.soft_max = prop_ui.get("soft_max", self.max)
self.use_soft_limits = (
self.min != self.soft_min or
self.max != self.soft_max
)
self.default = str(rna_data["default"])
if prop_type == str and not is_array and not value_failed: # String arrays do not support UI data.
ui_data = item.id_properties_ui(prop)
rna_data = ui_data.as_dict()
self.subtype = rna_data["subtype"]
self.default = str(rna_data["default"])
self._init_subtype(prop_type, is_array, self.subtype)
subtype = prop_ui.get("subtype", None)
else:
subtype = None
self._init_subtype(prop_type, is_array, subtype)
# store for comparison
self._cmp_props = self._cmp_props_get()
@@ -1703,6 +1688,7 @@ class WM_OT_properties_remove(Operator):
def execute(self, context):
from rna_prop_ui import (
rna_idprop_ui_prop_clear,
rna_idprop_ui_prop_update,
)
data_path = self.data_path
@@ -1715,6 +1701,7 @@ class WM_OT_properties_remove(Operator):
prop = self.property
rna_idprop_ui_prop_update(item, prop)
del item[prop]
rna_idprop_ui_prop_clear(item, prop)
return {'FINISHED'}

View File

@@ -342,11 +342,6 @@ class DATA_PT_gpencil_vertex_groups(ObjectButtonsPanel, Panel):
col.operator("object.vertex_group_add", icon='ADD', text="")
col.operator("object.vertex_group_remove", icon='REMOVE', text="").all = False
if group:
col.separator()
col.operator("object.vertex_group_move", icon='TRIA_UP', text="").direction = 'UP'
col.operator("object.vertex_group_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
if ob.vertex_groups:
row = layout.row()

View File

@@ -85,6 +85,9 @@ class GreasePencilSculptOptionsPanel:
layout.prop(gp_settings, "use_edit_strength", text="Affect Strength")
layout.prop(gp_settings, "use_edit_thickness", text="Affect Thickness")
if tool == 'SMOOTH':
layout.prop(gp_settings, "use_edit_pressure")
layout.prop(gp_settings, "use_edit_uv", text="Affect UV")
@@ -451,7 +454,7 @@ class AnnotationDataPanel:
tool_settings = context.tool_settings
if gpd and gpl:
layout.prop(gpl, "annotation_opacity", text="Opacity", slider=True)
layout.prop(gpl, "opacity", text="Opacity", slider=True)
layout.prop(gpl, "thickness")
else:
layout.prop(tool_settings, "annotation_thickness", text="Thickness")

View File

@@ -25,8 +25,8 @@ from bl_ui.utils import PresetPanel
from bpy.app.translations import pgettext_tip as tip_
class RENDER_PT_format_presets(PresetPanel, Panel):
bl_label = "Format Presets"
class RENDER_PT_presets(PresetPanel, Panel):
bl_label = "Render Presets"
preset_subdir = "render"
preset_operator = "script.execute_preset"
preset_add_operator = "render.preset_add"
@@ -56,21 +56,21 @@ class RenderOutputButtonsPanel:
return (context.engine in cls.COMPAT_ENGINES)
class RENDER_PT_format(RenderOutputButtonsPanel, Panel):
bl_label = "Format"
class RENDER_PT_dimensions(RenderOutputButtonsPanel, Panel):
bl_label = "Dimensions"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
_frame_rate_args_prev = None
_preset_class = None
def draw_header_preset(self, _context):
RENDER_PT_format_presets.draw_panel_header(self.layout)
RENDER_PT_presets.draw_panel_header(self.layout)
@staticmethod
def _draw_framerate_label(*args):
# avoids re-creating text string each draw
if RENDER_PT_format._frame_rate_args_prev == args:
return RENDER_PT_format._frame_rate_ret
if RENDER_PT_dimensions._frame_rate_args_prev == args:
return RENDER_PT_dimensions._frame_rate_ret
fps, fps_base, preset_label = args
@@ -89,17 +89,17 @@ class RENDER_PT_format(RenderOutputButtonsPanel, Panel):
fps_label_text = tip_("%.4g fps") % fps_rate
show_framerate = (preset_label == "Custom")
RENDER_PT_format._frame_rate_args_prev = args
RENDER_PT_format._frame_rate_ret = args = (fps_label_text, show_framerate)
RENDER_PT_dimensions._frame_rate_args_prev = args
RENDER_PT_dimensions._frame_rate_ret = args = (fps_label_text, show_framerate)
return args
@staticmethod
def draw_framerate(layout, rd):
if RENDER_PT_format._preset_class is None:
RENDER_PT_format._preset_class = bpy.types.RENDER_MT_framerate_presets
if RENDER_PT_dimensions._preset_class is None:
RENDER_PT_dimensions._preset_class = bpy.types.RENDER_MT_framerate_presets
args = rd.fps, rd.fps_base, RENDER_PT_format._preset_class.bl_label
fps_label_text, show_framerate = RENDER_PT_format._draw_framerate_label(*args)
args = rd.fps, rd.fps_base, RENDER_PT_dimensions._preset_class.bl_label
fps_label_text, show_framerate = RENDER_PT_dimensions._draw_framerate_label(*args)
layout.menu("RENDER_MT_framerate_presets", text=fps_label_text)
@@ -113,7 +113,8 @@ class RENDER_PT_format(RenderOutputButtonsPanel, Panel):
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
rd = context.scene.render
scene = context.scene
rd = scene.render
col = layout.column(align=True)
col.prop(rd, "resolution_x", text="Resolution X")
@@ -130,30 +131,18 @@ class RENDER_PT_format(RenderOutputButtonsPanel, Panel):
sub.active = rd.use_border
sub.prop(rd, "use_crop_to_border")
col = layout.column(heading="Frame Rate")
self.draw_framerate(col, rd)
class RENDER_PT_frame_range(RenderOutputButtonsPanel, Panel):
bl_label = "Frame Range"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
scene = context.scene
col = layout.column(align=True)
col.prop(scene, "frame_start", text="Frame Start")
col.prop(scene, "frame_end", text="End")
col.prop(scene, "frame_step", text="Step")
col = layout.column(heading="Frame Rate")
self.draw_framerate(col, rd)
class RENDER_PT_time_stretching(RenderOutputButtonsPanel, Panel):
bl_label = "Time Stretching"
bl_parent_id = "RENDER_PT_frame_range"
class RENDER_PT_frame_remapping(RenderOutputButtonsPanel, Panel):
bl_label = "Time Remapping"
bl_parent_id = "RENDER_PT_dimensions"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@@ -492,12 +481,11 @@ class RENDER_PT_stereoscopy(RenderOutputButtonsPanel, Panel):
classes = (
RENDER_PT_format_presets,
RENDER_PT_presets,
RENDER_PT_ffmpeg_presets,
RENDER_MT_framerate_presets,
RENDER_PT_format,
RENDER_PT_frame_range,
RENDER_PT_time_stretching,
RENDER_PT_dimensions,
RENDER_PT_frame_remapping,
RENDER_PT_stereoscopy,
RENDER_PT_output,
RENDER_PT_output_views,

View File

@@ -655,10 +655,7 @@ class ASSETBROWSER_PT_navigation_bar(asset_utils.AssetBrowserPanel, Panel):
@classmethod
def poll(cls, context):
return (
asset_utils.AssetBrowserPanel.poll(context) and
context.preferences.experimental.use_extended_asset_browser
)
return context.preferences.experimental.use_extended_asset_browser
def draw(self, context):
layout = self.layout

View File

@@ -1453,7 +1453,7 @@ class IMAGE_PT_udim_grid(Panel):
def poll(cls, context):
sima = context.space_data
return sima.show_uvedit
return sima.show_uvedit and sima.image is None
def draw(self, context):
layout = self.layout

View File

@@ -37,6 +37,13 @@ from bl_ui.space_toolsystem_common import (
from rna_prop_ui import PropertyPanel
def act_strip(context):
try:
return context.scene.sequence_editor.active_strip
except AttributeError:
return None
def selected_sequences_len(context):
selected_sequences = getattr(context, "selected_sequences", None)
if selected_sequences is None:
@@ -143,9 +150,6 @@ class SEQUENCER_HT_header(Header):
if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
tool_settings = context.tool_settings
sequencer_tool_settings = tool_settings.sequencer_tool_settings
row = layout.row(align=True)
row.prop(sequencer_tool_settings, "overlap_mode", text="")
row = layout.row(align=True)
row.prop(tool_settings, "use_snap_sequencer", text="")
sub = row.row(align=True)
@@ -526,7 +530,7 @@ class SEQUENCER_MT_change(Menu):
def draw(self, context):
layout = self.layout
strip = context.active_sequence_strip
strip = act_strip(context)
layout.operator_context = 'INVOKE_REGION_WIN'
@@ -753,7 +757,7 @@ class SEQUENCER_MT_strip_input(Menu):
def draw(self, context):
layout = self.layout
strip = context.active_sequence_strip
strip = act_strip(context)
layout.operator("sequencer.reload", text="Reload Strips")
layout.operator("sequencer.reload", text="Reload Strips and Adjust Length").adjust_length = True
@@ -832,7 +836,7 @@ class SEQUENCER_MT_strip(Menu):
layout.operator("sequencer.duplicate_move")
layout.operator("sequencer.delete", text="Delete")
strip = context.active_sequence_strip
strip = act_strip(context)
if strip:
strip_type = strip.type
@@ -913,7 +917,7 @@ class SEQUENCER_MT_context_menu(Menu):
layout.separator()
strip = context.active_sequence_strip
strip = act_strip(context)
if strip:
strip_type = strip.type
@@ -981,7 +985,7 @@ class SequencerButtonsPanel:
@classmethod
def poll(cls, context):
return cls.has_sequencer(context) and (context.active_sequence_strip is not None)
return cls.has_sequencer(context) and (act_strip(context) is not None)
class SequencerButtonsPanel_Output:
@@ -1005,7 +1009,7 @@ class SEQUENCER_PT_strip(SequencerButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
strip = context.active_sequence_strip
strip = act_strip(context)
strip_type = strip.type
if strip_type in {
@@ -1057,14 +1061,15 @@ class SEQUENCER_PT_adjust_crop(SequencerButtonsPanel, Panel):
if not cls.has_sequencer(context):
return False
strip = context.active_sequence_strip
strip = act_strip(context)
if not strip:
return False
strip = act_strip(context)
return strip.type != 'SOUND'
def draw(self, context):
strip = context.active_sequence_strip
strip = act_strip(context)
layout = self.layout
layout.use_property_split = True
layout.active = not strip.mute
@@ -1085,7 +1090,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
if not cls.has_sequencer(context):
return False
strip = context.active_sequence_strip
strip = act_strip(context)
if not strip:
return False
@@ -1100,7 +1105,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
layout = self.layout
layout.use_property_split = True
strip = context.active_sequence_strip
strip = act_strip(context)
layout.active = not strip.mute
@@ -1245,11 +1250,11 @@ class SEQUENCER_PT_effect_text_layout(SequencerButtonsPanel, Panel):
@classmethod
def poll(cls, context):
strip = context.active_sequence_strip
strip = act_strip(context)
return strip.type == 'TEXT'
def draw(self, context):
strip = context.active_sequence_strip
strip = act_strip(context)
layout = self.layout
layout.use_property_split = True
col = layout.column()
@@ -1265,11 +1270,11 @@ class SEQUENCER_PT_effect_text_style(SequencerButtonsPanel, Panel):
@classmethod
def poll(cls, context):
strip = context.active_sequence_strip
strip = act_strip(context)
return strip.type == 'TEXT'
def draw(self, context):
strip = context.active_sequence_strip
strip = act_strip(context)
layout = self.layout
layout.use_property_split = True
col = layout.column()
@@ -1317,7 +1322,7 @@ class SEQUENCER_PT_source(SequencerButtonsPanel, Panel):
if not cls.has_sequencer(context):
return False
strip = context.active_sequence_strip
strip = act_strip(context)
if not strip:
return False
@@ -1329,7 +1334,7 @@ class SEQUENCER_PT_source(SequencerButtonsPanel, Panel):
layout.use_property_decorate = False
scene = context.scene
strip = context.active_sequence_strip
strip = act_strip(context)
strip_type = strip.type
layout.active = not strip.mute
@@ -1421,14 +1426,14 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel):
if not cls.has_sequencer(context):
return False
strip = context.active_sequence_strip
strip = act_strip(context)
if not strip:
return False
return (strip.type == 'SCENE')
def draw(self, context):
strip = context.active_sequence_strip
strip = act_strip(context)
scene = strip.scene
layout = self.layout
@@ -1470,7 +1475,7 @@ class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel):
if not cls.has_sequencer(context):
return False
strip = context.active_sequence_strip
strip = act_strip(context)
if not strip:
return False
@@ -1480,7 +1485,7 @@ class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel):
layout = self.layout
layout.use_property_split = True
strip = context.active_sequence_strip
strip = act_strip(context)
layout.active = not strip.mute
@@ -1504,7 +1509,7 @@ class SEQUENCER_PT_time(SequencerButtonsPanel, Panel):
if not cls.has_sequencer(context):
return False
strip = context.active_sequence_strip
strip = act_strip(context)
if not strip:
return False
@@ -1513,7 +1518,7 @@ class SEQUENCER_PT_time(SequencerButtonsPanel, Panel):
def draw_header_preset(self, context):
layout = self.layout
layout.alignment = 'RIGHT'
strip = context.active_sequence_strip
strip = act_strip(context)
layout.prop(strip, "lock", text="", icon_only=True, emboss=False)
@@ -1526,7 +1531,7 @@ class SEQUENCER_PT_time(SequencerButtonsPanel, Panel):
scene = context.scene
frame_current = scene.frame_current
strip = context.active_sequence_strip
strip = act_strip(context)
is_effect = isinstance(strip, bpy.types.EffectSequence)
@@ -1651,10 +1656,11 @@ class SEQUENCER_PT_adjust_sound(SequencerButtonsPanel, Panel):
if not cls.has_sequencer(context):
return False
strip = context.active_sequence_strip
strip = act_strip(context)
if not strip:
return False
strip = act_strip(context)
return strip.type == 'SOUND'
def draw(self, context):
@@ -1662,7 +1668,7 @@ class SEQUENCER_PT_adjust_sound(SequencerButtonsPanel, Panel):
layout.use_property_split = True
st = context.space_data
strip = context.active_sequence_strip
strip = act_strip(context)
sound = strip.sound
layout.active = not strip.mute
@@ -1692,17 +1698,18 @@ class SEQUENCER_PT_adjust_comp(SequencerButtonsPanel, Panel):
if not cls.has_sequencer(context):
return False
strip = context.active_sequence_strip
strip = act_strip(context)
if not strip:
return False
strip = act_strip(context)
return strip.type != 'SOUND'
def draw(self, context):
layout = self.layout
layout.use_property_split = True
strip = context.active_sequence_strip
strip = act_strip(context)
layout.active = not strip.mute
@@ -1721,14 +1728,15 @@ class SEQUENCER_PT_adjust_transform(SequencerButtonsPanel, Panel):
if not cls.has_sequencer(context):
return False
strip = context.active_sequence_strip
strip = act_strip(context)
if not strip:
return False
strip = act_strip(context)
return strip.type != 'SOUND'
def draw(self, context):
strip = context.active_sequence_strip
strip = act_strip(context)
layout = self.layout
layout.use_property_split = True
layout.active = not strip.mute
@@ -1760,7 +1768,7 @@ class SEQUENCER_PT_adjust_video(SequencerButtonsPanel, Panel):
if not cls.has_sequencer(context):
return False
strip = context.active_sequence_strip
strip = act_strip(context)
if not strip:
return False
@@ -1779,7 +1787,7 @@ class SEQUENCER_PT_adjust_video(SequencerButtonsPanel, Panel):
col = layout.column()
strip = context.active_sequence_strip
strip = act_strip(context)
layout.active = not strip.mute
@@ -1808,7 +1816,7 @@ class SEQUENCER_PT_adjust_color(SequencerButtonsPanel, Panel):
if not cls.has_sequencer(context):
return False
strip = context.active_sequence_strip
strip = act_strip(context)
if not strip:
return False
@@ -1824,7 +1832,7 @@ class SEQUENCER_PT_adjust_color(SequencerButtonsPanel, Panel):
layout = self.layout
layout.use_property_split = True
strip = context.active_sequence_strip
strip = act_strip(context)
layout.active = not strip.mute
@@ -1892,14 +1900,14 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel):
if not cls.has_sequencer(context) and context.scene.sequence_editor:
return False
strip = context.active_sequence_strip
strip = act_strip(context)
if not strip:
return False
return strip.type in {'MOVIE', 'IMAGE'}
def draw_header(self, context):
strip = context.active_sequence_strip
strip = act_strip(context)
self.layout.prop(strip, "use_proxy", text="")
@@ -1910,7 +1918,7 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel):
ed = context.scene.sequence_editor
strip = context.active_sequence_strip
strip = act_strip(context)
if strip.proxy:
proxy = strip.proxy
@@ -1954,12 +1962,12 @@ class SEQUENCER_PT_strip_cache(SequencerButtonsPanel, Panel):
show_developer_ui = context.preferences.view.show_developer_ui
if not cls.has_sequencer(context):
return False
if context.active_sequence_strip is not None and show_developer_ui:
if act_strip(context) is not None and show_developer_ui:
return True
return False
def draw_header(self, context):
strip = context.active_sequence_strip
strip = act_strip(context)
self.layout.prop(strip, "override_cache_settings", text="")
def draw(self, context):
@@ -1967,7 +1975,7 @@ class SEQUENCER_PT_strip_cache(SequencerButtonsPanel, Panel):
layout.use_property_split = True
layout.use_property_decorate = False
strip = context.active_sequence_strip
strip = act_strip(context)
layout.active = strip.override_cache_settings
col = layout.column(heading="Cache")
@@ -2133,7 +2141,7 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
layout = self.layout
layout.use_property_split = True
strip = context.active_sequence_strip
strip = act_strip(context)
ed = context.scene.sequence_editor
layout.prop(strip, "use_linear_modifiers")
@@ -2251,7 +2259,7 @@ class SEQUENCER_PT_annotation_onion(AnnotationOnionSkin, SequencerButtonsPanel_O
class SEQUENCER_PT_custom_props(SequencerButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
_context_path = "active_sequence_strip"
_context_path = "scene.sequence_editor.active_strip"
_property_type = (bpy.types.Sequence,)
bl_category = "Strip"

View File

@@ -75,8 +75,6 @@ ToolDef = namedtuple(
"icon",
# An optional cursor to use when this tool is active.
"cursor",
# The properties to use for the widget.
"widget_properties",
# An optional gizmo group to activate when the tool is set or None for no gizmo.
"widget",
# Optional key-map for tool, possible values are:
@@ -134,7 +132,6 @@ def from_dict(kw_args):
"icon": None,
"cursor": None,
"widget": None,
"widget_properties": None,
"keymap": None,
"data_block": None,
"operator": None,
@@ -986,13 +983,11 @@ def _activate_by_item(context, space_type, item, index, *, as_fallback=False):
item_fallback, _index = cls._tool_get_active_by_index(context, select_index)
# End calculating fallback.
gizmo_group = item.widget or ""
tool.setup(
idname=item.idname,
keymap=item.keymap[0] if item.keymap is not None else "",
cursor=item.cursor or 'DEFAULT',
gizmo_group=gizmo_group,
gizmo_group=item.widget or "",
data_block=item.data_block or "",
operator=item.operator or "",
index=index,
@@ -1000,24 +995,6 @@ def _activate_by_item(context, space_type, item, index, *, as_fallback=False):
keymap_fallback=(item_fallback and item_fallback.keymap and item_fallback.keymap[0]) or "",
)
if (
(gizmo_group != "") and
(props := tool.gizmo_group_properties(gizmo_group))
):
if props is None:
print("Error:", gizmo_group, "could not access properties!")
else:
for key in props.bl_rna.properties.keys():
props.property_unset(key)
gizmo_properties = item.widget_properties
if gizmo_properties is not None:
if not isinstance(gizmo_properties, list):
raise Exception("expected a list, not a %r" % type(gizmo_properties))
from bl_keymap_utils.io import _init_properties_from_data
_init_properties_from_data(props, gizmo_properties)
WindowManager = bpy.types.WindowManager
handle_map = _activate_by_item._cursor_draw_handle

View File

@@ -824,11 +824,7 @@ class _defs_edit_mesh:
idname="builtin.inset_faces",
label="Inset Faces",
icon="ops.mesh.inset",
widget="VIEW3D_GGT_tool_generic_handle_free",
widget_properties=[
("radius", 75.0),
("backdrop_fill_alpha", 0.0),
],
widget="VIEW3D_GGT_tool_generic_handle_normal",
keymap=(),
draw_settings=draw_settings,
)

View File

@@ -809,7 +809,7 @@ class TOPBAR_PT_name(Panel):
found = False
if space_type == 'SEQUENCE_EDITOR':
layout.label(text="Sequence Strip Name")
item = context.active_sequence_strip
item = getattr(scene.sequence_editor, "active_strip")
if item:
row = row_with_icon(layout, 'SEQUENCE')
row.prop(item, "name", text="")

View File

@@ -1414,7 +1414,7 @@ class USERPREF_PT_saveload_blend(SaveLoadPanel, CenterAlignMixIn, Panel):
col = layout.column(heading="Save")
col.prop(view, "use_save_prompt")
col.prop(paths, "file_preview_type")
col.prop(paths, "use_save_preview_images")
col = layout.column(heading="Default To")
col.prop(paths, "use_relative_paths")
@@ -2254,7 +2254,6 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
({"property": "use_sculpt_tools_tilt"}, "T82877"),
({"property": "use_extended_asset_browser"}, ("project/view/130/", "Project Page")),
({"property": "use_override_templates"}, ("T73318", "Milestone 4")),
({"property": "use_geometry_nodes_fields"}, "T91274"),
),
)

View File

@@ -523,6 +523,10 @@ class WholeCharacterMixin:
# go over all custom properties for bone
for prop in bone.keys():
# ignore special "_RNA_UI" used for UI editing
if prop == "_RNA_UI":
continue
# for now, just add all of 'em
prop_rna = type(bone).bl_rna.properties.get(prop, None)
if prop_rna is None:

View File

@@ -180,10 +180,6 @@ def object_eevee_cycles_shader_nodes_poll(context):
eevee_cycles_shader_nodes_poll(context))
def geometry_nodes_fields_poll(context):
return context.preferences.experimental.use_geometry_nodes_fields
# All standard node categories currently used in nodes.
shader_node_categories = [
@@ -337,7 +333,6 @@ compositor_node_categories = [
NodeItem("CompositorNodeGamma"),
NodeItem("CompositorNodeExposure"),
NodeItem("CompositorNodeColorCorrection"),
NodeItem("CompositorNodePosterize"),
NodeItem("CompositorNodeTonemap"),
NodeItem("CompositorNodeZcombine"),
]),
@@ -480,25 +475,15 @@ texture_node_categories = [
geometry_node_categories = [
# Geometry Nodes
GeometryNodeCategory("GEO_ATTRIBUTE", "Attribute", items=[
NodeItem("GeometryNodeAttributeRandomize"),
NodeItem("GeometryNodeAttributeMath"),
NodeItem("GeometryNodeAttributeCapture", poll=geometry_nodes_fields_poll),
NodeItem("GeometryNodeAttributeClamp"),
NodeItem("GeometryNodeAttributeCompare"),
NodeItem("GeometryNodeAttributeConvert"),
NodeItem("GeometryNodeAttributeCurveMap"),
NodeItem("GeometryNodeAttributeFill"),
NodeItem("GeometryNodeAttributeMix"),
NodeItem("GeometryNodeAttributeProximity"),
NodeItem("GeometryNodeAttributeColorRamp"),
NodeItem("GeometryNodeAttributeVectorMath"),
NodeItem("GeometryNodeAttributeVectorRotate"),
NodeItem("GeometryNodeAttributeSampleTexture"),
NodeItem("GeometryNodeAttributeCombineXYZ"),
NodeItem("GeometryNodeAttributeSeparateXYZ"),
NodeItem("GeometryNodeAttributeRemove"),
NodeItem("GeometryNodeAttributeMapRange"),
NodeItem("GeometryNodeAttributeTransfer"),
NodeItem("GeometryNodeAttributeExtract"),
NodeItem("GeometryNodeAttributeFreeze"),
]),
GeometryNodeCategory("GEO_COLOR", "Color", items=[
NodeItem("ShaderNodeMixRGB"),
@@ -514,13 +499,13 @@ geometry_node_categories = [
NodeItem("GeometryNodeMeshToCurve"),
NodeItem("GeometryNodeCurveToPoints"),
NodeItem("GeometryNodeCurveEndpoints"),
NodeItem("GeometryNodeCurveFill"),
NodeItem("GeometryNodeCurveTrim"),
NodeItem("GeometryNodeCurveLength"),
NodeItem("GeometryNodeCurveReverse"),
NodeItem("GeometryNodeCurveSplineType"),
NodeItem("GeometryNodeCurveSetHandles"),
NodeItem("GeometryNodeCurveSelectHandles"),
NodeItem("GeometryNodeEvaluateCurve"),
]),
GeometryNodeCategory("GEO_PRIMITIVES_CURVE", "Curve Primitives", items=[
NodeItem("GeometryNodeCurvePrimitiveLine"),
@@ -539,7 +524,8 @@ geometry_node_categories = [
NodeItem("GeometryNodeJoinGeometry"),
NodeItem("GeometryNodeSeparateComponents"),
NodeItem("GeometryNodeRaycast"),
NodeItem("GeometryNodeSetPosition", poll=geometry_nodes_fields_poll),
NodeItem("GeometryNodeAttributeProximity"),
NodeItem("GeometryNodeSetPosition"),
]),
GeometryNodeCategory("GEO_INPUT", "Input", items=[
NodeItem("GeometryNodeObjectInfo"),
@@ -550,9 +536,11 @@ geometry_node_categories = [
NodeItem("FunctionNodeInputVector"),
NodeItem("GeometryNodeInputMaterial"),
NodeItem("GeometryNodeIsViewport"),
NodeItem("GeometryNodeInputPosition", poll=geometry_nodes_fields_poll),
NodeItem("GeometryNodeInputIndex", poll=geometry_nodes_fields_poll),
NodeItem("GeometryNodeInputNormal", poll=geometry_nodes_fields_poll),
NodeItem("GeometryNodeAttribute"),
NodeItem("GeometryNodeIndex"),
NodeItem("GeometryNodeNormal"),
NodeItem("GeometryNodePosition"),
NodeItem("GeometryNodeCurveParameter"),
]),
GeometryNodeCategory("GEO_MATERIAL", "Material", items=[
NodeItem("GeometryNodeMaterialAssign"),
@@ -565,6 +553,9 @@ geometry_node_categories = [
NodeItem("GeometryNodeEdgeSplit"),
NodeItem("GeometryNodeSubdivisionSurface"),
NodeItem("GeometryNodeMeshSubdivide"),
NodeItem("GeometryNodeExtrude"),
NodeItem("GeometryNodeExtrudeAndMove"),
NodeItem("GeometryNodeSampleMeshSurface"),
]),
GeometryNodeCategory("GEO_PRIMITIVES_MESH", "Mesh Primitives", items=[
NodeItem("GeometryNodeMeshCircle"),
@@ -576,7 +567,6 @@ geometry_node_categories = [
NodeItem("GeometryNodeMeshLine"),
NodeItem("GeometryNodeMeshUVSphere"),
]),
GeometryNodeCategory("GEO_POINT", "Point", items=[
NodeItem("GeometryNodePointDistribute"),
NodeItem("GeometryNodePointInstance"),
@@ -584,7 +574,6 @@ geometry_node_categories = [
NodeItem("GeometryNodePointScale"),
NodeItem("GeometryNodePointTranslate"),
NodeItem("GeometryNodeRotatePoints"),
NodeItem("GeometryNodeAlignRotationToVector"),
]),
GeometryNodeCategory("GEO_UTILITIES", "Utilities", items=[
NodeItem("ShaderNodeMapRange"),
@@ -594,6 +583,7 @@ geometry_node_categories = [
NodeItem("FunctionNodeFloatCompare"),
NodeItem("FunctionNodeFloatToInt"),
NodeItem("GeometryNodeSwitch"),
NodeItem("ShaderNodeTexNoise"),
]),
GeometryNodeCategory("GEO_VECTOR", "Vector", items=[
NodeItem("ShaderNodeVectorCurve"),
@@ -601,6 +591,7 @@ geometry_node_categories = [
NodeItem("ShaderNodeCombineXYZ"),
NodeItem("ShaderNodeVectorMath"),
NodeItem("ShaderNodeVectorRotate"),
NodeItem("FunctionNodeAlignRotationToVector"),
]),
GeometryNodeCategory("GEO_OUTPUT", "Output", items=[
NodeItem("GeometryNodeViewer"),

View File

@@ -53,38 +53,14 @@ class MyOtherTool(WorkSpaceTool):
layout.prop(props, "mode")
class MyWidgetTool(WorkSpaceTool):
bl_space_type = 'VIEW_3D'
bl_context_mode = 'OBJECT'
bl_idname = "my_template.my_gizmo_translate"
bl_label = "My Gizmo Tool"
bl_description = "Short description"
bl_icon = "ops.transform.translate"
bl_widget="VIEW3D_GGT_tool_generic_handle_free"
bl_widget_properties=[
("radius", 75.0),
("backdrop_fill_alpha", 0.0),
]
bl_keymap = (
("transform.translate", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
)
def draw_settings(context, layout, tool):
props = tool.operator_properties("transform.translate")
layout.prop(props, "mode")
def register():
bpy.utils.register_tool(MyTool, after={"builtin.scale_cage"}, separator=True, group=True)
bpy.utils.register_tool(MyOtherTool, after={MyTool.bl_idname})
bpy.utils.register_tool(MyWidgetTool, after={MyTool.bl_idname})
def unregister():
bpy.utils.unregister_tool(MyTool)
bpy.utils.unregister_tool(MyOtherTool)
bpy.utils.unregister_tool(MyWidgetTool)
if __name__ == "__main__":

View File

@@ -101,6 +101,9 @@ void BLF_batch_draw_end(void);
void BLF_draw_ex(int fontid, const char *str, size_t str_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)
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);
typedef bool (*BLF_GlyphBoundsFn)(const char *str,
@@ -254,6 +257,8 @@ 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();
/* Set size and DPI, and return default font ID. */
int BLF_set_default(void);

View File

@@ -550,6 +550,34 @@ void BLF_draw(int fontid, const char *str, const size_t str_len)
BLF_draw_ex(fontid, str, str_len, NULL);
}
void BLF_draw_ascii_ex(int fontid, const char *str, const size_t str_len, struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
BLF_RESULT_CHECK_INIT(r_info);
if (font) {
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);
}
else {
blf_font_draw_ascii(font, str, str_len, r_info);
}
blf_draw_gl__end(font);
}
}
void BLF_draw_ascii(int fontid, const char *str, const size_t str_len)
{
if (str_len == 0 || str[0] == '\0') {
return;
}
BLF_draw_ascii_ex(fontid, str, str_len, NULL);
}
int BLF_draw_mono(int fontid, const char *str, const size_t str_len, int cwidth)
{
if (str_len == 0 || str[0] == '\0') {

View File

@@ -77,3 +77,14 @@ void BLF_draw_default(float x, float y, float z, const char *str, const size_t s
BLF_position(global_font_default, x, y, z);
BLF_draw(global_font_default, str, 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)
{
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 */
}

View File

@@ -47,6 +47,9 @@
#include "blf_internal.h"
#include "blf_internal_types.h"
#include "BKE_global.h"
#include "BKE_main.h"
static ListBase global_font_dir = {NULL, NULL};
static DirBLF *blf_dir_find(const char *path)
@@ -124,8 +127,6 @@ void BLF_dir_free(char **dirs, int count)
char *blf_dir_search(const char *file)
{
BLI_assert_msg(!BLI_path_is_rel(file), "Relative paths must always be expanded!");
DirBLF *dir;
char full_path[FILE_MAX];
char *s = NULL;
@@ -139,9 +140,11 @@ char *blf_dir_search(const char *file)
}
if (!s) {
/* This may be an absolute path which exists. */
if (BLI_exists(file)) {
s = BLI_strdup(file);
/* Assume file is either an absolute path, or a relative path to current directory. */
BLI_strncpy(full_path, file, sizeof(full_path));
BLI_path_abs(full_path, BKE_main_blendfile_path(G_MAIN));
if (BLI_exists(full_path)) {
s = BLI_strdup(full_path);
}
}
@@ -169,12 +172,12 @@ char *blf_dir_metrics_search(const char *filename)
s[1] = 'f';
s[2] = 'm';
/* First check `.afm`. */
/* first check .afm */
if (BLI_exists(mfile)) {
return mfile;
}
/* And now check `.pfm`. */
/* and now check .pfm */
s[0] = 'p';
if (BLI_exists(mfile)) {

View File

@@ -298,7 +298,7 @@ static void blf_batch_draw_end(void)
*/
BLI_INLINE GlyphBLF *blf_utf8_next_fast(
FontBLF *font, GlyphCacheBLF *gc, const char *str, size_t str_len, size_t *i_p, uint *r_c)
FontBLF *font, GlyphCacheBLF *gc, const char *str, size_t *i_p, uint *r_c)
{
GlyphBLF *g;
if ((*r_c = str[*i_p]) < GLYPH_ASCII_TABLE_SIZE) {
@@ -309,13 +309,15 @@ BLI_INLINE GlyphBLF *blf_utf8_next_fast(
}
(*i_p)++;
}
else {
*r_c = BLI_str_utf8_as_unicode_step(str, str_len, i_p);
else if ((*r_c = BLI_str_utf8_as_unicode_step(str, i_p)) != BLI_UTF8_ERR) {
g = blf_glyph_search(gc, *r_c);
if (UNLIKELY(g == NULL)) {
g = blf_glyph_add(font, gc, FT_Get_Char_Index(font->face, *r_c), *r_c);
}
}
else {
g = NULL;
}
return g;
}
@@ -380,7 +382,7 @@ static void blf_font_draw_ex(FontBLF *font,
blf_batch_draw_begin(font);
while ((i < str_len) && str[i]) {
g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
g = blf_utf8_next_fast(font, gc, str, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -412,6 +414,56 @@ void blf_font_draw(FontBLF *font, const char *str, const size_t str_len, struct
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)
{
unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev = NULL;
int pen_x = 0;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
blf_batch_draw_begin(font);
while ((c = *(str++)) && str_len--) {
BLI_assert(c < GLYPH_ASCII_TABLE_SIZE);
g = gc->glyph_ascii_table[c];
if (UNLIKELY(g == NULL)) {
g = blf_glyph_add(font, gc, FT_Get_Char_Index((font)->face, c), c);
gc->glyph_ascii_table[c] = g;
if (UNLIKELY(g == NULL)) {
continue;
}
}
blf_kerning_step_fast(font, g_prev, g, c_prev, c, &pen_x);
/* do not return this loop if clipped, we want every character tested */
blf_glyph_render(font, gc, g, (float)pen_x, (float)pen_y);
pen_x += g->advance_i;
g_prev = g;
c_prev = c;
}
blf_batch_draw_end();
if (r_info) {
r_info->lines = 1;
r_info->width = pen_x;
}
blf_glyph_cache_release(font);
}
void blf_font_draw_ascii(FontBLF *font,
const char *str,
const size_t str_len,
struct ResultBLF *r_info)
{
blf_font_draw_ascii_ex(font, str, 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)
{
@@ -426,7 +478,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]) {
g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
g = blf_utf8_next_fast(font, gc, str, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -456,7 +508,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int
/** \} */
/* -------------------------------------------------------------------- */
/** \name Text Drawing: Buffer
/** \name Text Drawgin: Buffer
* \{ */
/* Sanity checks are done by BLF_draw_buffer() */
@@ -483,7 +535,7 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
/* another buffer specific call for color conversion */
while ((i < str_len) && str[i]) {
g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
g = blf_utf8_next_fast(font, gc, str, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -651,7 +703,7 @@ size_t blf_font_width_to_strlen(
for (i_prev = i = 0, width_new = pen_x = 0, g_prev = NULL, c_prev = 0; (i < str_len) && str[i];
i_prev = i, width_new = pen_x, c_prev = c, g_prev = g) {
g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
g = blf_utf8_next_fast(font, gc, str, &i, &c);
if (blf_font_width_to_strlen_glyph_process(font, c_prev, c, g_prev, g, &pen_x, width_i)) {
break;
@@ -673,27 +725,27 @@ size_t blf_font_width_to_rstrlen(
GlyphBLF *g, *g_prev;
int pen_x, width_new;
size_t i, i_prev, i_tmp;
const char *s, *s_prev;
char *s, *s_prev;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
const int width_i = (int)width;
i = BLI_strnlen(str, str_len);
s = BLI_str_find_prev_char_utf8(&str[i], str);
i = (size_t)(s - str);
s_prev = BLI_str_find_prev_char_utf8(s, str);
i_prev = (size_t)(s_prev - str);
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);
i_prev = (size_t)((s_prev != NULL) ? s_prev - str : 0);
i_tmp = i;
g = blf_utf8_next_fast(font, gc, str, str_len, &i_tmp, &c);
g = blf_utf8_next_fast(font, gc, str, &i_tmp, &c);
for (width_new = pen_x = 0; (s != NULL);
i = i_prev, s = s_prev, c = c_prev, g = g_prev, g_prev = NULL, width_new = pen_x) {
s_prev = BLI_str_find_prev_char_utf8(s, str);
i_prev = (size_t)(s_prev - str);
s_prev = BLI_str_find_prev_char_utf8(str, s);
i_prev = (size_t)((s_prev != NULL) ? s_prev - str : 0);
if (s_prev != NULL) {
i_tmp = i_prev;
g_prev = blf_utf8_next_fast(font, gc, str, str_len, &i_tmp, &c_prev);
g_prev = blf_utf8_next_fast(font, gc, str, &i_tmp, &c_prev);
BLI_assert(i_tmp == i);
}
@@ -736,7 +788,7 @@ static void blf_font_boundbox_ex(FontBLF *font,
box->ymax = -32000.0f;
while ((i < str_len) && str[i]) {
g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
g = blf_utf8_next_fast(font, gc, str, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -909,7 +961,7 @@ static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
while ((i < str_len) && str[i]) {
i_curr = i;
g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
g = blf_utf8_next_fast(font, gc, str, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -999,7 +1051,7 @@ static void blf_font_wrap_apply(FontBLF *font,
size_t i_curr = i;
bool do_draw = false;
g = blf_utf8_next_fast(font, gc, str, str_len, &i, &c);
g = blf_utf8_next_fast(font, gc, str, &i, &c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -1150,8 +1202,7 @@ int blf_font_count_missing_chars(FontBLF *font,
if ((c = str[i]) < GLYPH_ASCII_TABLE_SIZE) {
i++;
}
else {
c = BLI_str_utf8_as_unicode_step(str, str_len, &i);
else if ((c = BLI_str_utf8_as_unicode_step(str, &i)) != BLI_UTF8_ERR) {
if (FT_Get_Char_Index((font)->face, c) == 0) {
missing++;
}

View File

@@ -24,8 +24,8 @@
#include "BLI_function_ref.hh"
struct FCurve;
struct bAction;
struct FCurve;
namespace blender::bke {

View File

@@ -1,43 +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
/** \file
* \ingroup bke
*
* An #AnonymousAttributeID is used to identify attributes that are not explicitly named.
*/
#ifdef __cplusplus
extern "C" {
#endif
typedef struct AnonymousAttributeID AnonymousAttributeID;
AnonymousAttributeID *BKE_anonymous_attribute_id_new_weak(const char *debug_name);
AnonymousAttributeID *BKE_anonymous_attribute_id_new_strong(const char *debug_name);
bool BKE_anonymous_attribute_id_has_strong_references(const AnonymousAttributeID *anonymous_id);
void BKE_anonymous_attribute_id_increment_weak(const AnonymousAttributeID *anonymous_id);
void BKE_anonymous_attribute_id_increment_strong(const AnonymousAttributeID *anonymous_id);
void BKE_anonymous_attribute_id_decrement_weak(const AnonymousAttributeID *anonymous_id);
void BKE_anonymous_attribute_id_decrement_strong(const AnonymousAttributeID *anonymous_id);
const char *BKE_anonymous_attribute_id_debug_name(const AnonymousAttributeID *anonymous_id);
const char *BKE_anonymous_attribute_id_internal_name(const AnonymousAttributeID *anonymous_id);
#ifdef __cplusplus
}
#endif

View File

@@ -1,169 +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 {
/**
* Wrapper for #AnonymousAttributeID with RAII semantics.
* This class should typically not be used directly. Instead use #StrongAnonymousAttributeID or
* #WeakAnonymousAttributeID.
*/
template<bool IsStrongReference> class OwnedAnonymousAttributeID {
private:
const AnonymousAttributeID *data_ = nullptr;
template<bool OtherIsStrongReference> friend class OwnedAnonymousAttributeID;
public:
OwnedAnonymousAttributeID() = default;
/** Create a new anonymous attribute id. */
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.
* The caller has to make sure that it owned the anonymous id.
*/
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_);
}
/** Extract the onwership of the currently wrapped anonymous id. */
const AnonymousAttributeID *extract()
{
const AnonymousAttributeID *extracted_data = data_;
/* Don't decref because the caller becomes the new owner. */
data_ = nullptr;
return extracted_data;
}
/** Get the wrapped anonymous id, without taking ownership. */
const AnonymousAttributeID *get() const
{
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>;
} // namespace blender::bke

View File

@@ -22,7 +22,6 @@
#include "FN_generic_span.hh"
#include "FN_generic_virtual_array.hh"
#include "BKE_anonymous_attribute.hh"
#include "BKE_attribute.h"
#include "BLI_color.hh"
@@ -30,81 +29,6 @@
#include "BLI_float3.hh"
#include "BLI_function_ref.hh"
namespace blender::bke {
/**
* Identifies an attribute that is either named or anonymous.
* It does not own the identifier, so it is just a reference.
*/
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
/**
* Contains information about an attribute in a geometry component.
* More information can be added in the future. E.g. whether the attribute is builtin and how it is
@@ -113,10 +37,12 @@ class AttributeIDRef {
struct AttributeMetaData {
AttributeDomain domain;
CustomDataType data_type;
const AnonymousCustomDataLayerID *anonymous_layer_id = nullptr;
constexpr friend bool operator==(AttributeMetaData a, AttributeMetaData b)
{
return (a.domain == b.domain) && (a.data_type == b.data_type);
return (a.domain == b.domain) && (a.data_type == b.data_type) &&
(a.anonymous_layer_id == b.anonymous_layer_id);
}
};
@@ -180,8 +106,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 {
@@ -409,28 +335,32 @@ class CustomDataAttributes {
void reallocate(const int size);
std::optional<blender::fn::GSpan> get_for_read(const 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 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 AttributeIDRef &attribute_id);
bool create(const AttributeIDRef &attribute_id, const CustomDataType data_type);
bool create_by_move(const AttributeIDRef &attribute_id,
const CustomDataType data_type,
void *buffer);
bool remove(const 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 create_anonymous(const AnonymousCustomDataLayerID &id, const CustomDataType data_type);
std::optional<blender::fn::GSpan> get_anonymous_for_read(
const AnonymousCustomDataLayerID &id) const;
std::optional<blender::fn::GMutableSpan> get_anonymous_for_write(
const AnonymousCustomDataLayerID &id);
bool foreach_attribute(const AttributeForeachCallback callback,
const AttributeDomain domain) const;

View File

@@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 21
#define BLENDER_FILE_SUBVERSION 18
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file

View File

@@ -256,11 +256,9 @@ int /*eContextResult*/ CTX_data_get(
const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb, short *r_type);
void CTX_data_id_pointer_set(bContextDataResult *result, struct ID *id);
void CTX_data_pointer_set_ptr(bContextDataResult *result, const PointerRNA *ptr);
void CTX_data_pointer_set(bContextDataResult *result, struct ID *id, StructRNA *type, void *data);
void CTX_data_id_list_add(bContextDataResult *result, struct ID *id);
void CTX_data_list_add_ptr(bContextDataResult *result, const PointerRNA *ptr);
void CTX_data_list_add(bContextDataResult *result, struct ID *id, StructRNA *type, void *data);
void CTX_data_dir_set(bContextDataResult *result, const char **dir);

View File

@@ -33,7 +33,6 @@
extern "C" {
#endif
struct AnonymousAttributeID;
struct BMesh;
struct BlendDataReader;
struct BlendWriter;
@@ -194,12 +193,6 @@ void *CustomData_add_layer_named(struct CustomData *data,
void *layer,
int totelem,
const char *name);
void *CustomData_add_layer_anonymous(struct CustomData *data,
int type,
eCDAllocType alloctype,
void *layer,
int totelem,
const struct AnonymousAttributeID *anonymous_id);
/* frees the active or first data layer with the give type.
* returns 1 on success, 0 if no layer with the given type is found
@@ -238,11 +231,6 @@ void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
const int type,
const char *name,
const int totelem);
void *CustomData_duplicate_referenced_layer_anonymous(
CustomData *data,
const int type,
const struct AnonymousAttributeID *anonymous_id,
const int totelem);
bool CustomData_is_referenced_layer(struct CustomData *data, int type);
/* Duplicate all the layers with flag NOFREE, and remove the flag from duplicated layers. */
@@ -494,6 +482,14 @@ void CustomData_external_reload(struct CustomData *data,
CustomDataMask mask,
int totelem);
/* Anonymous layers. */
struct AnonymousCustomDataLayerID *CustomData_anonymous_id_new(const char *debug_name);
void CustomData_anonymous_id_strong_decrement(const struct AnonymousCustomDataLayerID *layer_id);
void CustomData_anonymous_id_strong_increment(const struct AnonymousCustomDataLayerID *layer_id);
void CustomData_anonymous_id_weak_decrement(const struct AnonymousCustomDataLayerID *layer_id);
void CustomData_anonymous_id_weak_increment(const struct AnonymousCustomDataLayerID *layer_id);
bool CustomData_layer_is_unused_anonymous(const struct CustomDataLayer *layer);
/* Mesh-to-mesh transfer data. */
struct CustomDataTransferLayerMap;

View File

@@ -31,7 +31,6 @@ struct ListBase;
struct Object;
struct ParticleSystem;
struct Scene;
struct ID;
/* ---------------------------------------------------- */
/* Dupli-Geometry */
@@ -43,10 +42,7 @@ void free_object_duplilist(struct ListBase *lb);
typedef struct DupliObject {
struct DupliObject *next, *prev;
/* Object whose geometry is instanced. */
struct Object *ob;
/* Data owned by the object above that is instanced. This might not be the same as `ob->data`. */
struct ID *ob_data;
float mat[4][4];
float orco[3], uv[2];

View File

@@ -78,11 +78,6 @@ typedef struct BMEditMesh {
/** Temp variables for x-mirror editing (-1 when the layer does not exist). */
int mirror_cdlayer;
/**
* Enable for evaluated copies, causes the edit-mesh to free the memory, not it's contents.
*/
char is_shallow_copy;
/**
* ID data is older than edit-mode data.
* Set #Main.is_memfile_undo_flush_needed when enabling.

View File

@@ -0,0 +1,553 @@
/*
* 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
/** \file
* \ingroup bke
*/
#include <atomic>
#include "BLI_function_ref.hh"
#include "BLI_map.hh"
#include "BLI_optional_ptr.hh"
#include "BLI_user_counter.hh"
#include "BLI_vector.hh"
#include "BLI_virtual_array.hh"
#include "FN_cpp_type.hh"
#include "FN_cpp_type_make.hh"
#include "FN_multi_function.hh"
#include "BKE_customdata.h"
namespace blender::bke {
using fn::CPPType;
using fn::GMutableSpan;
using fn::GVArray;
using fn::GVArrayPtr;
using fn::MultiFunction;
class FieldInputKey {
public:
virtual ~FieldInputKey() = default;
virtual uint64_t hash() const = 0;
virtual const CPPType &type() const = 0;
friend bool operator==(const FieldInputKey &a, const FieldInputKey &b)
{
return a.is_same_as(b);
}
private:
virtual bool is_same_as(const FieldInputKey &other) const
{
UNUSED_VARS(other);
return false;
}
};
class FieldInputValue {
public:
virtual ~FieldInputValue() = default;
};
class IndexFieldInputKey : public FieldInputKey {
public:
uint64_t hash() const override
{
/* Arbitrary number. */
return 78582029;
}
const CPPType &type() const override
{
return CPPType::get<int>();
}
private:
bool is_same_as(const FieldInputKey &other) const override
{
return dynamic_cast<const IndexFieldInputKey *>(&other) != nullptr;
}
};
class CurveParameterFieldInputKey : public FieldInputKey {
public:
uint64_t hash() const override
{
/* Arbitrary number. */
return 928347504059;
}
const CPPType &type() const override
{
return CPPType::get<float>();
}
private:
bool is_same_as(const FieldInputKey &other) const override
{
return dynamic_cast<const CurveParameterFieldInputKey *>(&other) != nullptr;
}
};
class AnonymousAttributeFieldInputKey : public FieldInputKey {
private:
AnonymousCustomDataLayerID *layer_id_;
const CPPType &type_;
public:
AnonymousAttributeFieldInputKey(AnonymousCustomDataLayerID &layer_id, const CPPType &type)
: layer_id_(&layer_id), type_(type)
{
CustomData_anonymous_id_strong_increment(layer_id_);
}
~AnonymousAttributeFieldInputKey()
{
CustomData_anonymous_id_strong_decrement(layer_id_);
}
const CPPType &type() const override
{
return type_;
}
uint64_t hash() const override
{
return get_default_hash(layer_id_);
}
const AnonymousCustomDataLayerID &layer_id() const
{
return *layer_id_;
}
private:
bool is_same_as(const FieldInputKey &other) const override
{
if (const AnonymousAttributeFieldInputKey *other_typed =
dynamic_cast<const AnonymousAttributeFieldInputKey *>(&other)) {
return layer_id_ == other_typed->layer_id_ && type_ == other_typed->type_;
}
return false;
}
};
class PersistentAttributeFieldInputKey : public FieldInputKey {
private:
std::string name_;
const CPPType *type_;
public:
PersistentAttributeFieldInputKey(std::string name, const CPPType &type)
: name_(std::move(name)), type_(&type)
{
}
uint64_t hash() const override
{
return get_default_hash_2(name_, type_);
}
const CPPType &type() const override
{
return *type_;
}
StringRefNull name() const
{
return name_;
}
private:
bool is_same_as(const FieldInputKey &other) const override
{
if (const PersistentAttributeFieldInputKey *other_typed =
dynamic_cast<const PersistentAttributeFieldInputKey *>(&other)) {
return other_typed->type_ == type_ && other_typed->name_ == name_;
}
return false;
}
};
class GVArrayFieldInputValue : public FieldInputValue {
private:
optional_ptr<GVArray> varray_;
public:
GVArrayFieldInputValue(optional_ptr<GVArray> varray) : varray_(std::move(varray))
{
}
const GVArray &varray() const
{
return *varray_;
}
};
class FieldInputs {
private:
using InputMap = Map<std::reference_wrapper<const FieldInputKey>, const FieldInputValue *>;
InputMap inputs_;
friend class Field;
public:
InputMap::KeyIterator begin() const
{
return inputs_.keys().begin();
}
InputMap::KeyIterator end() const
{
return inputs_.keys().end();
}
int tot_inputs() const
{
return inputs_.size();
}
void set_input(const FieldInputKey &key, const FieldInputValue &value)
{
*inputs_.lookup_ptr(key) = &value;
}
const FieldInputValue *get(const FieldInputKey &key) const
{
return inputs_.lookup_default(key, nullptr);
}
template<typename ValueT> const ValueT *get(const FieldInputKey &key) const
{
return dynamic_cast<const ValueT *>(this->get(key));
}
};
class FieldOutput {
private:
optional_ptr<const GVArray> varray_;
public:
FieldOutput(optional_ptr<const GVArray> varray) : varray_(std::move(varray))
{
}
const GVArray &varray_ref() const
{
return *varray_;
}
};
class Field {
private:
mutable std::atomic<int> users_ = 1;
public:
virtual ~Field() = default;
FieldInputs prepare_inputs() const
{
FieldInputs inputs;
this->foreach_input_key([&](const FieldInputKey &key) { inputs.inputs_.add(key, nullptr); });
return inputs;
}
virtual void foreach_input_key(FunctionRef<void(const FieldInputKey &key)> callback) const
{
UNUSED_VARS(callback);
}
virtual const CPPType &output_type() const = 0;
virtual FieldOutput evaluate(IndexMask mask, const FieldInputs &inputs) const = 0;
void user_add() const
{
users_.fetch_add(1);
}
void user_remove() const
{
const int new_users = users_.fetch_sub(1) - 1;
if (new_users == 0) {
delete this;
}
}
};
using FieldPtr = UserCounter<Field>;
template<typename T> class ConstantField : public Field {
private:
T value_;
public:
ConstantField(T value) : value_(std::move(value))
{
}
const CPPType &output_type() const override
{
return CPPType::get<T>();
}
FieldOutput evaluate(IndexMask mask, const FieldInputs &UNUSED(inputs)) const
{
return optional_ptr<const GVArray>{std::make_unique<fn::GVArray_For_SingleValue>(
CPPType::get<T>(), mask.min_array_size(), &value_)};
}
};
template<typename KeyT> class GVArrayInputField : public Field {
private:
KeyT key_;
public:
template<typename... Args> GVArrayInputField(Args &&...args) : key_(std::forward<Args>(args)...)
{
}
void foreach_input_key(FunctionRef<void(const FieldInputKey &key)> callback) const override
{
callback(key_);
}
const CPPType &output_type() const override
{
return key_.type();
}
FieldOutput evaluate(IndexMask mask, const FieldInputs &inputs) const override
{
const GVArrayFieldInputValue *input = inputs.get<GVArrayFieldInputValue>(key_);
if (input == nullptr) {
return FieldOutput{
optional_ptr<const GVArray>{std::make_unique<fn::GVArray_For_SingleValueRef>(
key_.type(), mask.min_array_size(), key_.type().default_value())}};
}
return FieldOutput{optional_ptr<const GVArray>{input->varray()}};
}
};
class MultiFunctionField : public Field {
private:
Vector<FieldPtr> input_fields_;
optional_ptr<const MultiFunction> fn_;
const int output_param_index_;
public:
MultiFunctionField(Vector<FieldPtr> input_fields,
optional_ptr<const MultiFunction> fn,
const int output_param_index)
: input_fields_(std::move(input_fields)),
fn_(std::move(fn)),
output_param_index_(output_param_index)
{
}
const CPPType &output_type() const override
{
return fn_->param_type(output_param_index_).data_type().single_type();
}
void foreach_input_key(FunctionRef<void(const FieldInputKey &key)> callback) const override
{
for (const FieldPtr &field : input_fields_) {
field->foreach_input_key(callback);
}
}
FieldOutput evaluate(IndexMask mask, const FieldInputs &inputs) const final
{
fn::MFParamsBuilder params{*fn_, mask.min_array_size()};
fn::MFContextBuilder context;
ResourceScope &scope = params.resource_scope();
Vector<GMutableSpan> outputs;
int output_span_index = -1;
int input_index = 0;
for (const int param_index : fn_->param_indices()) {
fn::MFParamType param_type = fn_->param_type(param_index);
switch (param_type.category()) {
case fn::MFParamType::SingleInput: {
const Field &field = *input_fields_[input_index];
FieldOutput &output = scope.add_value(field.evaluate(mask, inputs), __func__);
params.add_readonly_single_input(output.varray_ref());
input_index++;
break;
}
case fn::MFParamType::SingleOutput: {
const CPPType &type = param_type.data_type().single_type();
void *buffer = MEM_mallocN_aligned(
mask.min_array_size() * type.size(), type.alignment(), __func__);
GMutableSpan span{type, buffer, mask.min_array_size()};
outputs.append(span);
params.add_uninitialized_single_output(span);
if (param_index == output_param_index_) {
output_span_index = outputs.size() - 1;
}
break;
}
case fn::MFParamType::SingleMutable:
case fn::MFParamType::VectorInput:
case fn::MFParamType::VectorMutable:
case fn::MFParamType::VectorOutput:
BLI_assert_unreachable();
break;
}
}
fn_->call(mask, params, context);
GMutableSpan output_span = outputs[output_span_index];
outputs.remove(output_span_index);
for (GMutableSpan span : outputs) {
span.type().destruct_indices(span.data(), mask);
MEM_freeN(span.data());
}
std::unique_ptr<GVArray> out_array = std::make_unique<fn::GVArray_For_OwnedGSpan>(output_span,
mask);
return FieldOutput{optional_ptr<const GVArray>{std::move(out_array)}};
}
};
class PersistentAttributeField : public GVArrayInputField<PersistentAttributeFieldInputKey> {
public:
PersistentAttributeField(std::string name, const CPPType &type)
: GVArrayInputField<PersistentAttributeFieldInputKey>(std::move(name), type)
{
}
};
class AnonymousAttributeField : public GVArrayInputField<AnonymousAttributeFieldInputKey> {
public:
AnonymousAttributeField(AnonymousCustomDataLayerID &layer_id, const CPPType &type)
: GVArrayInputField<AnonymousAttributeFieldInputKey>(layer_id, type)
{
}
};
class IndexField : public GVArrayInputField<IndexFieldInputKey> {
};
class CurveParameterField : public GVArrayInputField<CurveParameterFieldInputKey> {
};
class FieldRefBase {
protected:
FieldPtr field_;
public:
const FieldPtr &field() const
{
return field_;
}
};
template<typename T> class FieldRef : public FieldRefBase {
public:
FieldRef()
{
field_ = new ConstantField<T>(T());
}
FieldRef(FieldPtr field)
{
field_ = std::move(field);
}
const Field *operator->() const
{
return &*field_;
}
uint64_t hash() const
{
return get_default_hash(&*field_);
}
friend bool operator==(const FieldRef &a, const FieldRef &b)
{
return &*a.field_ == &*b.field_;
}
friend std::ostream &operator<<(std::ostream &stream, const FieldRef &a)
{
stream << &*a.field_;
return stream;
}
};
template<typename T> struct FieldRefCPPTypeParam {
};
class FieldRefCPPType : public CPPType {
private:
const CPPType &field_type_;
FieldPtr (*get_field_)(const void *field_ref);
void (*construct_)(void *dst, FieldPtr field);
public:
template<typename T>
FieldRefCPPType(FieldRefCPPTypeParam<FieldRef<T>> /* unused */, StringRef debug_name)
: CPPType(fn::CPPTypeParam<FieldRef<T>, CPPTypeFlags::BasicType>(), debug_name),
field_type_(CPPType::get<T>())
{
get_field_ = [](const void *field_ref) {
return ((const blender::bke::FieldRef<T> *)field_ref)->field();
};
construct_ = [](void *dst, blender::bke::FieldPtr field) {
new (dst) blender::bke::FieldRef<T>(std::move(field));
};
}
const CPPType &field_type() const
{
return field_type_;
};
FieldPtr get_field(const void *field_ref) const
{
return get_field_(field_ref);
}
void construct(void *dst, FieldPtr field) const
{
construct_(dst, std::move(field));
}
};
} // namespace blender::bke
#define MAKE_FIELD_REF_CPP_TYPE(DEBUG_NAME, FIELD_TYPE) \
template<> \
const blender::fn::CPPType & \
blender::fn::CPPType::get_impl<blender::bke::FieldRef<FIELD_TYPE>>() \
{ \
static blender::bke::FieldRefCPPType cpp_type{ \
blender::bke::FieldRefCPPTypeParam<blender::bke::FieldRef<FIELD_TYPE>>(), \
STRINGIFY(DEBUG_NAME)}; \
return cpp_type; \
}

View File

@@ -41,7 +41,7 @@ typedef enum GeometryComponentType {
void BKE_geometry_set_free(struct GeometrySet *geometry_set);
bool BKE_object_has_geometry_set_instances(const struct Object *ob);
bool BKE_geometry_set_has_instances(const struct GeometrySet *geometry_set);
#ifdef __cplusplus
}

View File

@@ -31,12 +31,9 @@
#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"
#include "FN_field.hh"
struct Collection;
struct Curve;
struct CurveEval;
@@ -91,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;
@@ -107,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.
@@ -123,29 +120,51 @@ 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);
bool attribute_try_create_anonymous(const AnonymousCustomDataLayerID &layer_id,
const AttributeDomain domain,
const CustomDataType data_type,
const AttributeInit &initializer);
blender::bke::ReadAttributeLookup attribute_try_get_anonymous_for_read(
const AnonymousCustomDataLayerID &layer_id) const;
blender::fn::GVArrayPtr attribute_try_get_anonymous_for_read(
const AnonymousCustomDataLayerID &id,
const AttributeDomain domain,
const CustomDataType data_type) const;
blender::fn::GVArrayPtr attribute_try_get_anonymous_for_read(
const AnonymousCustomDataLayerID &id,
const AttributeDomain domain,
const CustomDataType data_type,
const void *default_value) const;
blender::bke::WriteAttributeLookup attribute_try_get_anonymous_for_write(
const AnonymousCustomDataLayerID &layer_id);
/* Try to create the builtin attribute with the given name. No data type or domain has to be
* provided, because those are fixed for builtin attributes. */
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;
/* Get a virtual array to read the data of an attribute on the given domain and data type.
* Returns null when the attribute does not exist or cannot be converted to the requested domain
* and data type. */
* 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;
@@ -153,18 +172,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;
@@ -172,62 +191,88 @@ 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));
}
/**
* Returns an "output attribute", which is essentially a mutable virtual array with some commonly
* used convince features. The returned output attribute might be empty if requested attribute
* cannot exist on the geometry.
* Returns an "output attribute", which is essentially a mutable virtual array with some
* commonly used convince features. The returned output attribute might be empty if requested
* attribute cannot exist on the geometry.
*
* The included convenience features are:
* - Implicit type conversion when writing to builtin attributes.
* - If the attribute name exists already, but has a different type/domain, a temporary attribute
* is created that will overwrite the existing attribute in the end.
* - If the attribute name exists already, but has a different type/domain, a temporary
* attribute 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);
/* Same as attribute_try_get_for_output, but should be used when the original values in the
* 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. */
* 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);
}
blender::bke::OutputAttribute attribute_try_get_anonymous_for_output(
const AnonymousCustomDataLayerID &id,
const AttributeDomain domain,
const CustomDataType data_type,
const void *default_value = nullptr);
blender::bke::OutputAttribute attribute_try_get_anonymous_for_output_only(
const AnonymousCustomDataLayerID &id,
const AttributeDomain domain,
const CustomDataType data_type);
template<typename T>
blender::bke::OutputAttribute_Typed<T> attribute_try_get_anonymous_for_output(
const AnonymousCustomDataLayerID &id, 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_anonymous_for_output(id, domain, data_type, &default_value);
}
template<typename T>
blender::bke::OutputAttribute_Typed<T> attribute_try_get_anonymous_for_output_only(
const AnonymousCustomDataLayerID &id, 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_anonymous_for_output_only(id, domain, data_type);
}
private:
@@ -238,12 +283,12 @@ template<typename T>
inline constexpr bool is_geometry_component_v = std::is_base_of_v<GeometryComponent, T>;
/**
* A geometry set contains zero or more geometry components. There is at most one component of each
* type. Individual components might be shared between multiple geometries. Shared components are
* copied automatically when write access is requested.
* A geometry set contains zero or more geometry components. There is at most one component of
* each type. Individual components might be shared between multiple geometries. Shared
* components are copied automatically when write access is requested.
*
* Copying a geometry set is a relatively cheap operation, because it does not copy the referenced
* geometry components.
* Copying a geometry set is a relatively cheap operation, because it does not copy the
* referenced geometry components.
*/
struct GeometrySet {
private:
@@ -289,7 +334,6 @@ struct GeometrySet {
void clear();
bool owns_direct_data() const;
void ensure_owns_direct_data();
/* Utility methods for creation. */
@@ -352,6 +396,10 @@ class MeshComponent : public GeometryComponent {
const AttributeDomain from_domain,
const AttributeDomain to_domain) const final;
blender::VArrayPtr<bool> adapt_selection(blender::VArrayPtr<bool> selection,
AttributeDomain from_domain,
AttributeDomain to_domain) const;
bool is_empty() const final;
bool owns_direct_data() const override;
@@ -448,20 +496,18 @@ class InstanceReference {
enum class Type {
/**
* An empty instance. This allows an `InstanceReference` to be default constructed without
* being in an invalid state. There might also be other use cases that we haven't explored much
* yet (such as changing the instance later on, and "disabling" some instances).
* being in an invalid state. There might also be other use cases that we haven't explored
* much yet (such as changing the instance later on, and "disabling" some instances).
*/
None,
Object,
Collection,
GeometrySet,
};
private:
Type type_ = Type::None;
/** Depending on the type this is either null, an Object or Collection pointer. */
void *data_ = nullptr;
std::unique_ptr<GeometrySet> geometry_set_;
public:
InstanceReference() = default;
@@ -474,19 +520,6 @@ class InstanceReference {
{
}
InstanceReference(GeometrySet geometry_set)
: type_(Type::GeometrySet),
geometry_set_(std::make_unique<GeometrySet>(std::move(geometry_set)))
{
}
InstanceReference(const InstanceReference &src) : type_(src.type_), data_(src.data_)
{
if (src.type_ == Type::GeometrySet) {
geometry_set_ = std::make_unique<GeometrySet>(*src.geometry_set_);
}
}
Type type() const
{
return type_;
@@ -504,37 +537,14 @@ class InstanceReference {
return *(Collection *)data_;
}
const GeometrySet &geometry_set() const
{
BLI_assert(type_ == Type::GeometrySet);
return *geometry_set_;
}
bool owns_direct_data() const
{
if (type_ != Type::GeometrySet) {
/* The object and collection instances are not direct data. */
return true;
}
return geometry_set_->owns_direct_data();
}
void ensure_owns_direct_data()
{
if (type_ != Type::GeometrySet) {
return;
}
geometry_set_->ensure_owns_direct_data();
}
uint64_t hash() const
{
return blender::get_default_hash_2(data_, geometry_set_.get());
return blender::get_default_hash(data_);
}
friend bool operator==(const InstanceReference &a, const InstanceReference &b)
{
return a.data_ == b.data_ && a.geometry_set_.get() == b.geometry_set_.get();
return a.data_ == b.data_;
}
};
@@ -558,8 +568,8 @@ class InstancesComponent : public GeometryComponent {
blender::Vector<int> instance_ids_;
/* These almost unique ids are generated based on `ids_`, which might not contain unique ids at
* all. They are *almost* unique, because under certain very unlikely circumstances, they are not
* unique. Code using these ids should not crash when they are not unique but can generally
* all. They are *almost* unique, because under certain very unlikely circumstances, they are
* not unique. Code using these ids should not crash when they are not unique but can generally
* expect them to be unique. */
mutable std::mutex almost_unique_ids_mutex_;
mutable blender::Array<int> almost_unique_ids_;
@@ -574,7 +584,7 @@ class InstancesComponent : public GeometryComponent {
void reserve(int min_capacity);
void resize(int capacity);
int add_reference(const InstanceReference &reference);
int add_reference(InstanceReference reference);
void add_instance(int instance_handle, const blender::float4x4 &transform, const int id = -1);
blender::Span<InstanceReference> references() const;
@@ -622,69 +632,3 @@ class VolumeComponent : public GeometryComponent {
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_VOLUME;
};
namespace blender::bke {
class GeometryComponentFieldContext : public fn::FieldContext {
private:
const GeometryComponent &component_;
const AttributeDomain domain_;
public:
GeometryComponentFieldContext(const GeometryComponent &component, const AttributeDomain domain)
: component_(component), domain_(domain)
{
}
const GeometryComponent &geometry_component() const
{
return component_;
}
AttributeDomain domain() const
{
return domain_;
}
};
class AttributeFieldInput : public fn::FieldInput {
private:
std::string name_;
public:
AttributeFieldInput(std::string name, const CPPType &type)
: fn::FieldInput(type, name), name_(std::move(name))
{
}
const GVArray *get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const override;
uint64_t hash() const override;
bool is_equal_to(const fn::FieldNode &other) const override;
};
class AnonymousAttributeFieldInput : public fn::FieldInput {
private:
/**
* A strong reference is required to make sure that the referenced attribute is not removed
* automatically.
*/
StrongAnonymousAttributeID anonymous_id_;
public:
AnonymousAttributeFieldInput(StrongAnonymousAttributeID anonymous_id, const CPPType &type)
: fn::FieldInput(type, anonymous_id.debug_name()), anonymous_id_(std::move(anonymous_id))
{
}
const GVArray *get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const override;
uint64_t hash() const override;
bool is_equal_to(const fn::FieldNode &other) const override;
};
} // namespace blender::bke

View File

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

View File

@@ -101,7 +101,7 @@ bool BKE_gpencil_stroke_sample(struct bGPdata *gpd,
struct bGPDstroke *gps,
const float dist,
const bool select);
bool BKE_gpencil_stroke_smooth_point(struct bGPDstroke *gps, int i, float inf);
bool BKE_gpencil_stroke_smooth(struct bGPDstroke *gps, int i, float inf);
bool BKE_gpencil_stroke_smooth_strength(struct bGPDstroke *gps, int point_index, float influence);
bool BKE_gpencil_stroke_smooth_thickness(struct bGPDstroke *gps, int point_index, float influence);
bool BKE_gpencil_stroke_smooth_uv(struct bGPDstroke *gps, int point_index, float influence);
@@ -151,8 +151,7 @@ void BKE_gpencil_stroke_set_random_color(struct bGPDstroke *gps);
void BKE_gpencil_stroke_join(struct bGPDstroke *gps_a,
struct bGPDstroke *gps_b,
const bool leave_gaps,
const bool fit_thickness,
const bool smooth);
const bool fit_thickness);
void BKE_gpencil_stroke_copy_to_keyframes(struct bGPdata *gpd,
struct bGPDlayer *gpl,
struct bGPDframe *gpf,

View File

@@ -32,7 +32,6 @@ struct BlendLibReader;
struct BlendWriter;
struct ID;
struct IDProperty;
struct IDPropertyUIData;
typedef union IDPropertyTemplate {
int i;
@@ -184,10 +183,6 @@ void IDP_Reset(struct IDProperty *prop, const struct IDProperty *reference);
# define IDP_Id(prop) ((ID *)(prop)->data.pointer)
#endif
int IDP_coerce_to_int_or_zero(const struct IDProperty *prop);
float IDP_coerce_to_float_or_zero(const struct IDProperty *prop);
double IDP_coerce_to_double_or_zero(const struct IDProperty *prop);
/**
* Call a callback for each idproperty in the hierarchy under given root one (included).
*
@@ -214,28 +209,6 @@ void IDP_BlendReadData_impl(struct BlendDataReader *reader,
void IDP_BlendReadLib(struct BlendLibReader *reader, struct IDProperty *prop);
void IDP_BlendReadExpand(struct BlendExpander *expander, struct IDProperty *prop);
typedef enum eIDPropertyUIDataType {
/** Other properties types that don't support RNA UI data. */
IDP_UI_DATA_TYPE_UNSUPPORTED = -1,
/** IDP_INT or IDP_ARRAY with subtype IDP_INT. */
IDP_UI_DATA_TYPE_INT = 0,
/** IDP_FLOAT and IDP_DOUBLE or IDP_ARRAY properties with a float or double subtypes. */
IDP_UI_DATA_TYPE_FLOAT = 1,
/** IDP_STRING properties. */
IDP_UI_DATA_TYPE_STRING = 2,
/** IDP_ID. */
IDP_UI_DATA_TYPE_ID = 3,
} eIDPropertyUIDataType;
bool IDP_ui_data_supported(const struct IDProperty *prop);
eIDPropertyUIDataType IDP_ui_data_type(const struct IDProperty *prop);
void IDP_ui_data_free(struct IDProperty *prop);
void IDP_ui_data_free_unique_contents(struct IDPropertyUIData *ui_data,
eIDPropertyUIDataType type,
const struct IDPropertyUIData *other);
struct IDPropertyUIData *IDP_ui_data_ensure(struct IDProperty *prop);
struct IDPropertyUIData *IDP_ui_data_copy(const struct IDProperty *prop);
#ifdef __cplusplus
}
#endif

View File

@@ -114,8 +114,8 @@ typedef struct IDTypeInfo {
/* ********** General IDType data. ********** */
/**
* Unique identifier of this type, either as a short or an array of two chars, see
* DNA_ID_enums.h's ID_XX enums.
* Unique identifier of this type, either as a short or an array of two chars, see DNA_ID.h's
* ID_XX enums.
*/
short id_code;
/**

View File

@@ -166,14 +166,8 @@ struct ID *BKE_libblock_find_name(struct Main *bmain,
*/
typedef enum eLibIDDuplicateFlags {
/** This call to a duplicate function is part of another call for some parent ID.
* Therefore, this sub-process should not clear `newid` pointers, nor handle remapping itself.
* NOTE: In some cases (like Object one), the duplicate function may be called on the root ID
* with this flag set, as remapping and/or other similar tasks need to be handled by the caller.
*/
* Therefore, this sub-process should not clear `newid` pointers, nor handle remapping itself. */
LIB_ID_DUPLICATE_IS_SUBPROCESS = 1 << 0,
/** This call is performed on a 'root' ID, and should therefore perform some decisions regarding
* sub-IDs (dependencies), check for linked vs. locale data, etc. */
LIB_ID_DUPLICATE_IS_ROOT_ID = 1 << 1,
} eLibIDDuplicateFlags;
/* lib_remap.c (keep here since they're general functions) */
@@ -237,11 +231,6 @@ enum {
/** Making that ID local is part of making local a whole library. */
LIB_ID_MAKELOCAL_FULL_LIBRARY = 1 << 0,
/** In case caller code already knows this ID should be made local without copying. */
LIB_ID_MAKELOCAL_FORCE_LOCAL = 1 << 1,
/** In case caller code already knows this ID should be made local using copying. */
LIB_ID_MAKELOCAL_FORCE_COPY = 1 << 2,
/* Special type-specific options. */
/** For Objects, do not clear the proxy pointers while making the data-block local. */
LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING = 1 << 16,

View File

@@ -143,6 +143,11 @@ int BKE_mesh_mface_index_validate(struct MFace *mface,
struct Mesh *BKE_mesh_from_object(struct Object *ob);
void BKE_mesh_assign_object(struct Main *bmain, struct Object *ob, struct Mesh *me);
void BKE_mesh_from_metaball(struct ListBase *lb, struct Mesh *me);
void BKE_mesh_from_nurbs_displist(struct Main *bmain,
struct Object *ob,
struct ListBase *dispbase,
const char *obdata_name,
bool temporary);
void BKE_mesh_to_curve_nurblist(const struct Mesh *me,
struct ListBase *nurblist,
const int edge_users_test);

View File

@@ -113,7 +113,6 @@ namespace blender {
namespace nodes {
class NodeMultiFunctionBuilder;
class GeoNodeExecParams;
class NodeDeclarationBuilder;
} // namespace nodes
namespace fn {
class CPPType;
@@ -123,7 +122,6 @@ class MFDataType;
using NodeMultiFunctionBuildFunction = void (*)(blender::nodes::NodeMultiFunctionBuilder &builder);
using NodeGeometryExecFunction = void (*)(blender::nodes::GeoNodeExecParams params);
using NodeDeclareFunction = void (*)(blender::nodes::NodeDeclarationBuilder &builder);
using SocketGetCPPTypeFunction = const blender::fn::CPPType *(*)();
using SocketGetCPPValueFunction = void (*)(const struct bNodeSocket &socket, void *r_value);
using SocketGetGeometryNodesCPPTypeFunction = const blender::fn::CPPType *(*)();
@@ -133,7 +131,6 @@ using SocketGetGeometryNodesCPPValueFunction = void (*)(const struct bNodeSocket
#else
typedef void *NodeMultiFunctionBuildFunction;
typedef void *NodeGeometryExecFunction;
typedef void *NodeDeclareFunction;
typedef void *SocketGetCPPTypeFunction;
typedef void *SocketGetGeometryNodesCPPTypeFunction;
typedef void *SocketGetGeometryNodesCPPValueFunction;
@@ -337,9 +334,6 @@ typedef struct bNodeType {
NodeGeometryExecFunction geometry_node_execute;
bool geometry_node_execute_supports_laziness;
/* Declares which sockets the node has. */
NodeDeclareFunction declare;
/* RNA integration */
ExtensionRNA rna_ext;
} bNodeType;
@@ -621,10 +615,6 @@ struct bNodeSocket *nodeInsertStaticSocket(struct bNodeTree *ntree,
const char *identifier,
const char *name);
void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
void nodeRemoveSocketEx(struct bNodeTree *ntree,
struct bNode *node,
struct bNodeSocket *sock,
bool do_id_user);
void nodeRemoveAllSockets(struct bNodeTree *ntree, struct bNode *node);
void nodeModifySocketType(struct bNodeTree *ntree,
struct bNode *node,
@@ -1255,7 +1245,6 @@ void ntreeGPUMaterialNodes(struct bNodeTree *localtree,
#define CMP_NODE_DENOISE 324
#define CMP_NODE_EXPOSURE 325
#define CMP_NODE_CRYPTOMATTE 326
#define CMP_NODE_POSTERIZE 327
/* channel toggles */
#define CMP_CHAN_RGB 1
@@ -1426,7 +1415,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_ATTRIBUTE_COMPARE 1015
#define GEO_NODE_POINT_ROTATE 1016
#define GEO_NODE_ATTRIBUTE_VECTOR_MATH 1017
#define GEO_NODE_ALIGN_ROTATION_TO_VECTOR 1018
// #define GEO_NODE_ALIGN_ROTATION_TO_VECTOR 1018
#define GEO_NODE_POINT_TRANSLATE 1019
#define GEO_NODE_POINT_SCALE 1020
#define GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE 1021
@@ -1483,12 +1472,18 @@ 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_CURVE_FILL 1075
#define GEO_NODE_INPUT_POSITION 1076
#define GEO_NODE_SET_POSITION 1077
#define GEO_NODE_INPUT_INDEX 1078
#define GEO_NODE_INPUT_NORMAL 1079
#define GEO_NODE_ATTRIBUTE_CAPTURE 1080
#define GEO_NODE_ATTRIBUTE 1075
#define GEO_NODE_INDEX 1076
#define GEO_NODE_EXTRUDE 1077
#define GEO_NODE_ATTRIBUTE_FREEZE 1078
#define GEO_NODE_ATTRIBUTE_EXTRACT 1079
#define GEO_NODE_NORMAL 1080
#define GEO_NODE_CURVE_PARAMETER 1081
#define GEO_NODE_EXTRUDE_AND_MOVE 1082
#define GEO_NODE_POSITION 1083
#define GEO_NODE_SET_POSITION 1084
#define GEO_NODE_SAMPLE_MESH_SURFACE 1085
#define GEO_NODE_EVALUATE_CURVE 1086
/** \} */
@@ -1502,6 +1497,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define FN_NODE_INPUT_VECTOR 1207
#define FN_NODE_INPUT_STRING 1208
#define FN_NODE_FLOAT_TO_INT 1209
#define FN_NODE_ALIGN_ROTATION_TO_VECTOR 1210
/** \} */

View File

@@ -458,13 +458,9 @@ void BKE_object_modifiers_lib_link_common(void *userData,
struct ID **idpoin,
int cb_flag);
void BKE_object_replace_data_on_shallow_copy(struct Object *ob, struct ID *new_data);
struct PartEff;
struct PartEff *BKE_object_do_version_give_parteff_245(struct Object *ob);
bool BKE_object_supports_material_slots(struct Object *ob);
#ifdef __cplusplus
}
#endif

View File

@@ -368,10 +368,7 @@ struct ModifierData *object_copy_particle_system(struct Main *bmain,
struct Scene *scene,
struct Object *ob,
const struct ParticleSystem *psys_orig);
void object_remove_particle_system(struct Main *bmain,
struct Scene *scene,
struct Object *ob,
struct ParticleSystem *psys);
void object_remove_particle_system(struct Main *bmain, struct Scene *scene, struct Object *ob);
struct ParticleSettings *BKE_particlesettings_add(struct Main *bmain, const char *name);
void psys_reset(struct ParticleSystem *psys, int mode);

View File

@@ -264,6 +264,14 @@ void BKE_scene_cursor_from_mat4(struct View3DCursor *cursor,
const float mat[4][4],
bool use_compat);
/* Dependency graph evaluation. */
/* Evaluate parts of sequences which needs to be done as a part of a dependency graph evaluation.
* This does NOT include actual rendering of the strips, but rather makes them up-to-date for
* animation playback and makes them ready for the sequencer's rendering pipeline to render them.
*/
void BKE_scene_eval_sequencer_sequences(struct Depsgraph *depsgraph, struct Scene *scene);
#ifdef __cplusplus
}
#endif

View File

@@ -61,7 +61,8 @@ struct bSound *BKE_sound_new_file_exists_ex(struct Main *bmain,
bool *r_exists);
struct bSound *BKE_sound_new_file_exists(struct Main *bmain, const char *filepath);
#if 0 /* UNUSED */
// XXX unused currently
#if 0
struct bSound *BKE_sound_new_buffer(struct Main *bmain, struct bSound *source);
struct bSound *BKE_sound_new_limiter(struct Main *bmain,

View File

@@ -76,12 +76,11 @@ 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
intern/armature_deform.c
intern/armature_pose.cc
intern/armature_selection.cc
intern/armature_update.c
intern/asset.cc
intern/attribute.c
@@ -296,8 +295,6 @@ set(SRC
BKE_anim_path.h
BKE_anim_visualization.h
BKE_animsys.h
BKE_anonymous_attribute.h
BKE_anonymous_attribute.hh
BKE_appdir.h
BKE_armature.h
BKE_armature.hh

View File

@@ -1991,7 +1991,7 @@ void BKE_pose_blend_read_lib(BlendLibReader *reader, Object *ob, bPose *pose)
if (UNLIKELY(pchan->bone == NULL)) {
rebuild = true;
}
else if (!ID_IS_LINKED(ob) && ID_IS_LINKED(arm)) {
else if ((ob->id.lib == NULL) && arm->id.lib) {
/* local pose selection copied to armature, bit hackish */
pchan->bone->flag &= ~BONE_SELECTED;
pchan->bone->flag |= pchan->selectflag;

View File

@@ -28,7 +28,6 @@
#include "DNA_action_types.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "MEM_guardedalloc.h"
@@ -37,11 +36,12 @@ namespace blender::bke {
void BKE_action_find_fcurves_with_bones(const bAction *action, FoundFCurveCallback callback)
{
LISTBASE_FOREACH (FCurve *, fcu, &action->curves) {
char bone_name[MAXBONENAME];
if (!BLI_str_quoted_substr(fcu->rna_path, "pose.bones[", bone_name, sizeof(bone_name))) {
char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
if (!bone_name) {
continue;
}
callback(fcu, bone_name);
MEM_freeN(bone_name);
}
}

View File

@@ -1,118 +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;
/**
* A struct that identifies an attribute. It's lifetime is managed by an atomic reference count.
*
* Additionally, this struct can be strongly or weakly owned. The difference is that strong
* ownership means that attributes with this id will be kept around. Weak ownership just makes sure
* that the struct itself stays alive, but corresponding attributes might still be removed
* automatically.
*/
struct AnonymousAttributeID {
/**
* Total number of references to this attribute id. Once this reaches zero, the struct can be
* freed. This includes strong and weak references.
*/
mutable std::atomic<int> refcount_tot = 0;
/**
* Number of strong references to this attribute id. When this is zero, the corresponding
* attributes can be removed from geometries automatically.
*/
mutable std::atomic<int> refcount_strong = 0;
/**
* Only used to identify this struct in a debugging session.
*/
std::string debug_name;
/**
* Unique name of the this attribute id during the current session.
*/
std::string internal_name;
};
/** Every time this function is called, it outputs a different 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_tot.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_tot.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_tot.fetch_add(1);
}
void BKE_anonymous_attribute_id_increment_strong(const AnonymousAttributeID *anonymous_id)
{
anonymous_id->refcount_tot.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_tot.fetch_sub(1) - 1;
if (new_refcount == 0) {
delete anonymous_id;
}
}
void BKE_anonymous_attribute_id_decrement_strong(const AnonymousAttributeID *anonymous_id)
{
anonymous_id->refcount_strong.fetch_sub(1);
BKE_anonymous_attribute_id_decrement_weak(anonymous_id);
}
const char *BKE_anonymous_attribute_id_debug_name(const AnonymousAttributeID *anonymous_id)
{
return anonymous_id->debug_name.c_str();
}
const char *BKE_anonymous_attribute_id_internal_name(const AnonymousAttributeID *anonymous_id)
{
return anonymous_id->internal_name.c_str();
}

View File

@@ -176,9 +176,9 @@ class BKE_armature_find_selected_bones_test : public testing::Test {
bone2.childbase = {nullptr, nullptr};
bone3.childbase = {nullptr, nullptr};
BLI_addtail(&arm.bonebase, &bone1); /* bone1 is root bone. */
BLI_addtail(&arm.bonebase, &bone2); /* bone2 is root bone. */
BLI_addtail(&bone2.childbase, &bone3); /* bone3 has bone2 as parent. */
BLI_addtail(&arm.bonebase, &bone1); // bone1 is root bone
BLI_addtail(&arm.bonebase, &bone2); // bone2 is root bone
BLI_addtail(&bone2.childbase, &bone3); // bone3 has bone2 as parent
/* Make sure the armature & its bones are visible, to make them selectable. */
arm.layer = bone1.layer = bone2.layer = bone3.layer = 1;

File diff suppressed because it is too large Load Diff

View File

@@ -116,13 +116,12 @@ class BuiltinAttributeProvider {
class DynamicAttributesProvider {
public:
virtual ReadAttributeLookup try_get_for_read(const GeometryComponent &component,
const AttributeIDRef &attribute_id) const = 0;
const StringRef attribute_name) const = 0;
virtual WriteAttributeLookup try_get_for_write(GeometryComponent &component,
const AttributeIDRef &attribute_id) const = 0;
virtual bool try_delete(GeometryComponent &component,
const AttributeIDRef &attribute_id) const = 0;
const StringRef attribute_name) const = 0;
virtual bool try_delete(GeometryComponent &component, const StringRef attribute_name) const = 0;
virtual bool try_create(GeometryComponent &UNUSED(component),
const AttributeIDRef &UNUSED(attribute_id),
const StringRef UNUSED(attribute_name),
const AttributeDomain UNUSED(domain),
const CustomDataType UNUSED(data_type),
const AttributeInit &UNUSED(initializer)) const
@@ -131,6 +130,30 @@ class DynamicAttributesProvider {
return false;
};
/** Returns the id of the new anonymous or null if no new attribute was created. */
virtual bool try_create_anonymous(GeometryComponent &UNUSED(component),
const AnonymousCustomDataLayerID &UNUSED(layer_id),
const AttributeDomain UNUSED(domain),
const CustomDataType UNUSED(data_type),
const AttributeInit &UNUSED(initializer)) const
{
return false;
}
virtual ReadAttributeLookup try_get_anonymous_for_read(
const GeometryComponent &UNUSED(component),
const AnonymousCustomDataLayerID &UNUSED(layer_id)) const
{
return {};
}
virtual WriteAttributeLookup try_get_anonymous_for_write(
GeometryComponent &UNUSED(component),
const AnonymousCustomDataLayerID &UNUSED(layer_id)) const
{
return {};
}
virtual bool foreach_attribute(const GeometryComponent &component,
const AttributeForeachCallback callback) const = 0;
virtual void foreach_domain(const FunctionRef<void(AttributeDomain)> callback) const = 0;
@@ -155,19 +178,31 @@ 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;
bool try_create_anonymous(GeometryComponent &component,
const AnonymousCustomDataLayerID &layer_id,
const AttributeDomain domain,
const CustomDataType data_type,
const AttributeInit &initializer) const final;
ReadAttributeLookup try_get_anonymous_for_read(
const GeometryComponent &component, const AnonymousCustomDataLayerID &layer_id) const final;
WriteAttributeLookup try_get_anonymous_for_write(
GeometryComponent &component, const AnonymousCustomDataLayerID &layer_id) const final;
bool foreach_attribute(const GeometryComponent &component,
const AttributeForeachCallback callback) const final;
@@ -177,6 +212,9 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
}
private:
ReadAttributeLookup layer_to_read_attribute(const CustomDataLayer &layer,
const int domain_size) const;
template<typename T>
ReadAttributeLookup layer_to_read_attribute(const CustomDataLayer &layer,
const int domain_size) const
@@ -186,6 +224,9 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
domain_};
}
WriteAttributeLookup layer_to_write_attribute(CustomDataLayer &layer,
const int domain_size) const;
template<typename T>
WriteAttributeLookup layer_to_write_attribute(CustomDataLayer &layer,
const int domain_size) const
@@ -232,10 +273,10 @@ class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider {
}
ReadAttributeLookup try_get_for_read(const GeometryComponent &component,
const AttributeIDRef &attribute_id) const final;
const StringRef attribute_name) const final;
WriteAttributeLookup try_get_for_write(GeometryComponent &component,
const AttributeIDRef &attribute_id) const final;
bool try_delete(GeometryComponent &component, const AttributeIDRef &attribute_id) const final;
const StringRef attribute_name) const final;
bool try_delete(GeometryComponent &component, const StringRef attribute_name) const final;
bool foreach_attribute(const GeometryComponent &component,
const AttributeForeachCallback callback) const final;
void foreach_domain(const FunctionRef<void(AttributeDomain)> callback) const final;

View File

@@ -534,46 +534,6 @@ static bool rewrite_path_alloc(char **path,
return false;
}
typedef struct Seq_callback_data {
const char *absbase;
void *bpath_user_data;
BPathVisitor visit_cb;
const int flag;
} Seq_callback_data;
static bool seq_rewrite_path_callback(Sequence *seq, void *user_data)
{
if (SEQ_HAS_PATH(seq)) {
StripElem *se = seq->strip->stripdata;
Seq_callback_data *cd = (Seq_callback_data *)user_data;
if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM) && se) {
rewrite_path_fixed_dirfile(
seq->strip->dir, se->name, cd->visit_cb, cd->absbase, cd->bpath_user_data);
}
else if ((seq->type == SEQ_TYPE_IMAGE) && se) {
/* might want an option not to loop over all strips */
unsigned int len = (unsigned int)MEM_allocN_len(se) / (unsigned int)sizeof(*se);
unsigned int i;
if (cd->flag & BKE_BPATH_TRAVERSE_SKIP_MULTIFILE) {
/* only operate on one path */
len = MIN2(1u, len);
}
for (i = 0; i < len; i++, se++) {
rewrite_path_fixed_dirfile(
seq->strip->dir, se->name, cd->visit_cb, cd->absbase, cd->bpath_user_data);
}
}
else {
/* simple case */
rewrite_path_fixed(seq->strip->dir, cd->visit_cb, cd->absbase, cd->bpath_user_data);
}
}
return true;
}
/**
* Run visitor function 'visit' on all paths contained in 'id'.
*/
@@ -741,8 +701,38 @@ void BKE_bpath_traverse_id(
case ID_SCE: {
Scene *scene = (Scene *)id;
if (scene->ed) {
Seq_callback_data user_data = {absbase, bpath_user_data, visit_cb, flag};
SEQ_for_each_callback(&scene->ed->seqbase, seq_rewrite_path_callback, &user_data);
Sequence *seq;
SEQ_ALL_BEGIN (scene->ed, seq) {
if (SEQ_HAS_PATH(seq)) {
StripElem *se = seq->strip->stripdata;
if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM) && se) {
rewrite_path_fixed_dirfile(
seq->strip->dir, se->name, visit_cb, absbase, bpath_user_data);
}
else if ((seq->type == SEQ_TYPE_IMAGE) && se) {
/* might want an option not to loop over all strips */
unsigned int len = (unsigned int)MEM_allocN_len(se) / (unsigned int)sizeof(*se);
unsigned int i;
if (flag & BKE_BPATH_TRAVERSE_SKIP_MULTIFILE) {
/* only operate on one path */
len = MIN2(1u, len);
}
for (i = 0; i < len; i++, se++) {
rewrite_path_fixed_dirfile(
seq->strip->dir, se->name, visit_cb, absbase, bpath_user_data);
}
}
else {
/* simple case */
rewrite_path_fixed(seq->strip->dir, visit_cb, absbase, bpath_user_data);
}
}
}
SEQ_ALL_END;
}
break;
}

View File

@@ -142,16 +142,8 @@ static void brush_free_data(ID *id)
static void brush_make_local(Main *bmain, ID *id, const int flags)
{
if (!ID_IS_LINKED(id)) {
return;
}
Brush *brush = (Brush *)id;
const bool lib_local = (flags & LIB_ID_MAKELOCAL_FULL_LIBRARY) != 0;
const bool force_local = (flags & LIB_ID_MAKELOCAL_FORCE_LOCAL) != 0;
const bool force_copy = (flags & LIB_ID_MAKELOCAL_FORCE_COPY) != 0;
BLI_assert(force_copy == false || force_copy != force_local);
bool is_local = false, is_lib = false;
/* - only lib users: do nothing (unless force_local is set)
@@ -159,17 +151,19 @@ static void brush_make_local(Main *bmain, ID *id, const int flags)
* - mixed: make copy
*/
if (!ID_IS_LINKED(brush)) {
return;
}
if (brush->clone.image) {
/* Special case: ima always local immediately. Clone image should only have one user anyway. */
BKE_lib_id_make_local(bmain, &brush->clone.image->id, false, 0);
}
if (!force_local && !force_copy) {
BKE_library_ID_test_usages(bmain, brush, &is_local, &is_lib);
}
BKE_library_ID_test_usages(bmain, brush, &is_local, &is_lib);
if (lib_local || is_local || force_copy || force_local) {
if (!is_lib || force_local) {
if (lib_local || is_local) {
if (!is_lib) {
BKE_lib_id_clear_library_data(bmain, &brush->id);
BKE_lib_id_expand_local(bmain, &brush->id);
@@ -1133,7 +1127,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->draw_strength = 0.3f;
brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE;
brush->gpencil_settings->sculpt_flag = GP_SCULPT_FLAGMODE_APPLY_THICKNESS;
brush->gpencil_settings->sculpt_flag = GP_SCULPT_FLAG_SMOOTH_PRESSURE;
brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
break;
@@ -1147,6 +1141,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->draw_strength = 0.3f;
brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE;
brush->gpencil_settings->sculpt_flag = GP_SCULPT_FLAG_SMOOTH_PRESSURE;
brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
break;

View File

@@ -92,6 +92,11 @@ static void camera_copy_data(Main *UNUSED(bmain),
BLI_duplicatelist(&cam_dst->bg_images, &cam_src->bg_images);
}
static void camera_make_local(Main *bmain, ID *id, const int flags)
{
BKE_lib_id_make_local_generic(bmain, id, flags);
}
/** Free (or release) any data used by this camera (does not free the camera itself). */
static void camera_free_data(ID *id)
{
@@ -187,7 +192,7 @@ IDTypeInfo IDType_ID_CA = {
.init_data = camera_init_data,
.copy_data = camera_copy_data,
.free_data = camera_free_data,
.make_local = NULL,
.make_local = camera_make_local,
.foreach_id = camera_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,

View File

@@ -692,18 +692,14 @@ Collection *BKE_collection_duplicate(Main *bmain,
eLibIDDuplicateFlags duplicate_options)
{
const bool is_subprocess = (duplicate_options & LIB_ID_DUPLICATE_IS_SUBPROCESS) != 0;
const bool is_root_id = (duplicate_options & LIB_ID_DUPLICATE_IS_ROOT_ID) != 0;
if (!is_subprocess) {
BKE_main_id_newptr_and_tag_clear(bmain);
}
if (is_root_id) {
/* In case root duplicated ID is linked, assume we want to get a local copy of it and duplicate
* all expected linked data. */
if (ID_IS_LINKED(collection)) {
duplicate_flags |= USER_DUP_LINKED_ID;
}
duplicate_options &= ~LIB_ID_DUPLICATE_IS_ROOT_ID;
}
Collection *collection_new = collection_duplicate_recursive(

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