Compare commits
139 Commits
temp-geome
...
temp-geome
Author | SHA1 | Date | |
---|---|---|---|
24d1c352e8 | |||
b3639670ee | |||
ea3ee04fa8 | |||
4838436387 | |||
62d485e470 | |||
cd6eb65482 | |||
d337c20cf9 | |||
a715aec6a3 | |||
eba32b5f4a | |||
1d859c9183 | |||
a3d02965da | |||
45e58a7e92 | |||
c920b83b84 | |||
34e0d8079f | |||
a376073f1e | |||
29ac510198 | |||
d7cf8babf2 | |||
3becd4cb61 | |||
52bb0d42b3 | |||
acae8f430d | |||
bbb692ffb5 | |||
df6a819982 | |||
48f2643556 | |||
d4b441851f | |||
e0406d029d | |||
c5c82f801a | |||
78c0e7c015 | |||
fd0ac1aec5 | |||
0827cce9de | |||
2bba77045f | |||
00ecf29ec4 | |||
172e713cc6 | |||
5c32227025 | |||
fa9d1cb2a9 | |||
577a12f840 | |||
8dad29d0ea | |||
4eda4fd49a | |||
1db53a8923 | |||
20aba8a4c0 | |||
1d53bf0412 | |||
1177debb01 | |||
047daf5442 | |||
f2112199a4 | |||
36de290807 | |||
c09a535333 | |||
4e78bb3f0c | |||
49f33e9820 | |||
6f525e0d98 | |||
963448a2af | |||
9506ef320e | |||
1700fde0dc | |||
d5a83a5a32 | |||
a7dc3d1e90 | |||
6fd836f53b | |||
40455c21fa | |||
2d0442e943 | |||
d55046b167 | |||
4233128fa5 | |||
798496233a | |||
991f6b15f3 | |||
aef45a4ef2 | |||
504e3c563f | |||
8645ea16de | |||
5e292d923f | |||
1ab1d6665c | |||
b1c98ad8ee | |||
e9d95fddf9 | |||
782d240a1b | |||
36055ba366 | |||
236576fc91 | |||
e7d57e84bb | |||
b5573bfbf4 | |||
3b2522650b | |||
eacc1f1ff4 | |||
9562a90632 | |||
2ceeaf95a1 | |||
c8de9dc2a4 | |||
f8f2873b44 | |||
648fa6d89e | |||
d24419564e | |||
184be40aa1 | |||
6131506689 | |||
e5f43cf4b7 | |||
770d70127f | |||
801034ba6a | |||
17442bcb7b | |||
ba9561ab0d | |||
c659af0c13 | |||
dd8be48466 | |||
5914b8ed6b | |||
50da3cfbd6 | |||
131e8c0d59 | |||
aedd43b33f | |||
adb437ad3f | |||
c106ed8fcd | |||
11a6a56982 | |||
0a7ab583a5 | |||
09009ce062 | |||
dc502fad43 | |||
3abce9e633 | |||
dad5c3991c | |||
dab3a07659 | |||
53a724c804 | |||
bacde38b67 | |||
d9b128baf2 | |||
ae6c063b33 | |||
67e7aee853 | |||
302ab3ff7c | |||
4352d1beb5 | |||
32cb953b9b | |||
1d92a4d1a0 | |||
2472b0f0ef | |||
626be25646 | |||
8132383662 | |||
f95214e9ae | |||
dde42e19e3 | |||
f90a83f816 | |||
433b4ae22a | |||
23e217eafc | |||
87153cf019 | |||
08122a7794 | |||
58af171bc0 | |||
c98a535f5f | |||
8262e6a0c1 | |||
c00cc9fd60 | |||
0a31b1f044 | |||
5e3b33dfe8 | |||
f716060408 | |||
aa092f4e6f | |||
ad8dfb3823 | |||
bb0e0fde32 | |||
3472f83f00 | |||
1b2b07fb18 | |||
64a11ba6a2 | |||
26d8d2884c | |||
12014ccfbc | |||
34cebfbb78 | |||
2cc4e1572a | |||
ceb9e7d71e |
@@ -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)
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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/"
|
||||
|
@@ -1,4 +1,4 @@
|
||||
if EXIST "%PYTHON%" (
|
||||
if EXIST %PYTHON% (
|
||||
goto detect_python_done
|
||||
)
|
||||
|
||||
|
@@ -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",
|
||||
|
2
extern/mantaflow/UPDATE.sh
vendored
2
extern/mantaflow/UPDATE.sh
vendored
@@ -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
|
||||
|
@@ -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()
|
||||
|
6
extern/mantaflow/helper/pwrapper/pvec3.cpp
vendored
6
extern/mantaflow/helper/pwrapper/pvec3.cpp
vendored
@@ -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[] = {
|
||||
|
@@ -76,8 +76,7 @@ struct ClassData {
|
||||
};
|
||||
|
||||
struct PbObject {
|
||||
PyObject_HEAD
|
||||
Manta::PbClass *instance;
|
||||
PyObject_HEAD Manta::PbClass *instance;
|
||||
ClassData *classdef;
|
||||
};
|
||||
|
||||
|
202
extern/mantaflow/preprocessed/fastmarch.cpp
vendored
202
extern/mantaflow/preprocessed/fastmarch.cpp
vendored
@@ -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> φ
|
||||
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.));
|
||||
|
2
extern/mantaflow/preprocessed/gitinfo.h
vendored
2
extern/mantaflow/preprocessed/gitinfo.h
vendored
@@ -1,3 +1,3 @@
|
||||
|
||||
|
||||
#define MANTA_GIT_VERSION "commit d5d9a6c28daa8f21426d7a285f48639c0d8fd13f"
|
||||
#define MANTA_GIT_VERSION "commit 8fbebe02459b7f72575872c20961f7cb757db408"
|
||||
|
@@ -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__ */
|
||||
|
@@ -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__)
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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 */
|
||||
|
@@ -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
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
|
@@ -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 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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 =
|
||||
{
|
||||
|
@@ -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):
|
||||
|
@@ -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),
|
||||
|
@@ -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
|
||||
|
@@ -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),
|
||||
]},
|
||||
)
|
||||
|
@@ -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},
|
||||
|
@@ -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():
|
||||
|
@@ -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():
|
||||
|
@@ -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:
|
||||
|
@@ -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 = (
|
||||
|
@@ -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'}
|
||||
|
||||
|
@@ -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()
|
||||
|
||||
|
@@ -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")
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
)
|
||||
|
@@ -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="")
|
||||
|
@@ -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"),
|
||||
),
|
||||
)
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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"),
|
||||
|
@@ -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__":
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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') {
|
||||
|
@@ -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 */
|
||||
}
|
||||
|
@@ -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)) {
|
||||
|
@@ -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++;
|
||||
}
|
||||
|
@@ -24,8 +24,8 @@
|
||||
|
||||
#include "BLI_function_ref.hh"
|
||||
|
||||
struct FCurve;
|
||||
struct bAction;
|
||||
struct FCurve;
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
|
@@ -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
|
@@ -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
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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];
|
||||
|
||||
|
@@ -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.
|
||||
|
553
source/blender/blenkernel/BKE_field.hh
Normal file
553
source/blender/blenkernel/BKE_field.hh
Normal 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; \
|
||||
}
|
@@ -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
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
/**
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
}
|
@@ -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
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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,
|
||||
|
@@ -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
Reference in New Issue
Block a user