Fix #119909: Unkeyable custom properties receive keyframes #119914
|
@ -0,0 +1,119 @@
|
|||
# SPDX-FileCopyrightText: 2024 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import time
|
||||
|
||||
|
||||
# These are substituted when this file is copied to the build directory.
|
||||
BLENDER_VERSION_STRING = "${BLENDER_VERSION_STRING}"
|
||||
BLENDER_VERSION_DOTS = "${BLENDER_VERSION_DOTS}"
|
||||
BLENDER_REVISION = "${BLENDER_REVISION}"
|
||||
BLENDER_REVISION_TIMESTAMP = "${BLENDER_REVISION_TIMESTAMP}"
|
||||
BLENDER_VERSION_DATE = time.strftime(
|
||||
"%d/%m/%Y",
|
||||
time.localtime(int(BLENDER_REVISION_TIMESTAMP) if BLENDER_REVISION_TIMESTAMP != "0" else None),
|
||||
)
|
||||
|
||||
if BLENDER_REVISION != "Unknown":
|
||||
# SHA1 GIT hash.
|
||||
BLENDER_VERSION_HASH = BLENDER_REVISION
|
||||
BLENDER_VERSION_HASH_HTML_LINK = "<a href=https://projects.blender.org/blender/blender/commit/%s>%s</a>" % (
|
||||
BLENDER_VERSION_HASH, BLENDER_VERSION_HASH)
|
||||
else:
|
||||
# Fallback: Should not be used.
|
||||
BLENDER_VERSION_HASH = "Hash Unknown"
|
||||
BLENDER_VERSION_HASH_HTML_LINK = BLENDER_VERSION_HASH
|
||||
|
||||
extensions = ["sphinx.ext.intersphinx"]
|
||||
intersphinx_mapping = {"blender_manual": ("https://docs.blender.org/manual/en/dev/", None)}
|
||||
project = "Blender %s Python API" % BLENDER_VERSION_STRING
|
||||
root_doc = "index"
|
||||
copyright = "Blender Authors"
|
||||
version = BLENDER_VERSION_DOTS
|
||||
release = BLENDER_VERSION_DOTS
|
||||
|
||||
# Set this as the default is a super-set of Python3.
|
||||
highlight_language = "python3"
|
||||
# No need to detect encoding.
|
||||
highlight_options = {"default": {"encoding": "utf-8"}}
|
||||
|
||||
# Quiet file not in table-of-contents warnings.
|
||||
exclude_patterns = [
|
||||
"include__bmesh.rst",
|
||||
]
|
||||
|
||||
html_title = "Blender Python API"
|
||||
|
||||
# The fallback to a built-in theme when `furo` is not found.
|
||||
html_theme = "default"
|
||||
|
||||
try:
|
||||
import furo
|
||||
html_theme = "furo"
|
||||
del furo
|
||||
except ModuleNotFoundError:
|
||||
pass
|
||||
|
||||
if html_theme == "furo":
|
||||
html_theme_options = {
|
||||
"light_css_variables": {
|
||||
"color-brand-primary": "#265787",
|
||||
"color-brand-content": "#265787",
|
||||
},
|
||||
}
|
||||
|
||||
html_sidebars = {
|
||||
"**": [
|
||||
"sidebar/brand.html",
|
||||
"sidebar/search.html",
|
||||
"sidebar/scroll-start.html",
|
||||
"sidebar/navigation.html",
|
||||
"sidebar/scroll-end.html",
|
||||
"sidebar/variant-selector.html",
|
||||
]
|
||||
}
|
||||
|
||||
# Not helpful since the source is generated, adds to upload size.
|
||||
html_copy_source = False
|
||||
html_show_sphinx = False
|
||||
html_baseurl = "https://docs.blender.org/api/current/"
|
||||
html_use_opensearch = "https://docs.blender.org/api/current"
|
||||
html_show_search_summary = True
|
||||
html_split_index = True
|
||||
html_static_path = ["static"]
|
||||
templates_path = ["templates"]
|
||||
html_context = {"commit": "%s - %s" % (BLENDER_VERSION_HASH_HTML_LINK, BLENDER_VERSION_DATE)}
|
||||
html_extra_path = ["static"]
|
||||
html_favicon = "static/favicon.ico"
|
||||
html_logo = "static/blender_logo.svg"
|
||||
# Disable default `last_updated` value, since this is the date of doc generation, not the one of the source commit.
|
||||
html_last_updated_fmt = None
|
||||
if html_theme == "furo":
|
||||
html_css_files = ["css/theme_overrides.css", "css/version_switch.css"]
|
||||
html_js_files = ["js/version_switch.js"]
|
||||
|
||||
# Needed for latex, PDF generation.
|
||||
latex_elements = {
|
||||
"papersize": "a4paper",
|
||||
}
|
||||
|
||||
latex_documents = [
|
||||
("contents", "contents.tex", "Blender Index", "Blender Foundation", "manual"),
|
||||
]
|
||||
|
||||
# Workaround for useless links leading to compile errors
|
||||
# See https://github.com/sphinx-doc/sphinx/issues/3866
|
||||
from sphinx.domains.python import PythonDomain
|
||||
|
||||
|
||||
class PatchedPythonDomain(PythonDomain):
|
||||
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
|
||||
if "refspecific" in node:
|
||||
del node["refspecific"]
|
||||
return super(PatchedPythonDomain, self).resolve_xref(
|
||||
env, fromdocname, builder, typ, target, node, contnode)
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_domain(PatchedPythonDomain, override=True)
|
|
@ -1,9 +1,9 @@
|
|||
sphinx==7.1.2
|
||||
sphinx==7.2.6
|
||||
|
||||
# Sphinx dependencies that are important
|
||||
Jinja2==3.1.2
|
||||
Pygments==2.16.1
|
||||
docutils==0.18.1
|
||||
Jinja2==3.1.3
|
||||
Pygments==2.17.2
|
||||
docutils==0.20.1
|
||||
snowballstemmer==2.2.0
|
||||
requests==2.31.0
|
||||
|
||||
|
|
|
@ -61,7 +61,6 @@ import os
|
|||
import sys
|
||||
import inspect
|
||||
import shutil
|
||||
import time
|
||||
import logging
|
||||
import warnings
|
||||
|
||||
|
@ -486,19 +485,6 @@ BLENDER_REVISION_TIMESTAMP = bpy.app.build_commit_timestamp
|
|||
BLENDER_VERSION_STRING = bpy.app.version_string
|
||||
BLENDER_VERSION_DOTS = "%d.%d" % (bpy.app.version[0], bpy.app.version[1])
|
||||
|
||||
if BLENDER_REVISION != "Unknown":
|
||||
# SHA1 Git hash
|
||||
BLENDER_VERSION_HASH = BLENDER_REVISION
|
||||
BLENDER_VERSION_HASH_HTML_LINK = "<a href=https://projects.blender.org/blender/blender/commit/%s>%s</a>" % (
|
||||
BLENDER_VERSION_HASH, BLENDER_VERSION_HASH,
|
||||
)
|
||||
BLENDER_VERSION_DATE = time.strftime("%d/%m/%Y", time.localtime(BLENDER_REVISION_TIMESTAMP))
|
||||
else:
|
||||
# Fallback: Should not be used
|
||||
BLENDER_VERSION_HASH = "Hash Unknown"
|
||||
BLENDER_VERSION_HASH_HTML_LINK = BLENDER_VERSION_HASH
|
||||
BLENDER_VERSION_DATE = time.strftime("%Y-%m-%d")
|
||||
|
||||
# Example: `2_83`.
|
||||
BLENDER_VERSION_PATH = "%d_%d" % (bpy.app.version[0], bpy.app.version[1])
|
||||
|
||||
|
@ -1895,110 +1881,6 @@ def pyrna2sphinx(basepath):
|
|||
write_ops()
|
||||
|
||||
|
||||
def write_sphinx_conf_py(basepath):
|
||||
"""
|
||||
Write sphinx's ``conf.py``.
|
||||
"""
|
||||
filepath = os.path.join(basepath, "conf.py")
|
||||
file = open(filepath, "w", encoding="utf-8")
|
||||
fw = file.write
|
||||
|
||||
fw("import sys, os\n\n")
|
||||
fw("extensions = ['sphinx.ext.intersphinx']\n\n")
|
||||
fw("intersphinx_mapping = {'blender_manual': ('https://docs.blender.org/manual/en/dev/', None)}\n\n")
|
||||
fw("project = 'Blender %s Python API'\n" % BLENDER_VERSION_STRING)
|
||||
fw("root_doc = 'index'\n")
|
||||
fw("copyright = 'Blender Authors'\n")
|
||||
fw("version = '%s'\n" % BLENDER_VERSION_DOTS)
|
||||
fw("release = '%s'\n" % BLENDER_VERSION_DOTS)
|
||||
|
||||
# Set this as the default is a super-set of Python3.
|
||||
fw("highlight_language = 'python3'\n")
|
||||
# No need to detect encoding.
|
||||
fw("highlight_options = {'default': {'encoding': 'utf-8'}}\n\n")
|
||||
|
||||
# Quiet file not in table-of-contents warnings.
|
||||
fw("exclude_patterns = [\n")
|
||||
fw(" 'include__bmesh.rst',\n")
|
||||
fw("]\n\n")
|
||||
|
||||
fw("html_title = 'Blender Python API'\n")
|
||||
|
||||
fw("html_theme = 'default'\n")
|
||||
# The theme 'sphinx_rtd_theme' is no longer distributed with sphinx by default, only use when available.
|
||||
fw(r"""
|
||||
try:
|
||||
import furo
|
||||
html_theme = "furo"
|
||||
del furo
|
||||
except ModuleNotFoundError:
|
||||
pass
|
||||
if html_theme == "furo":
|
||||
html_theme_options = {
|
||||
"light_css_variables": {
|
||||
"color-brand-primary": "#265787",
|
||||
"color-brand-content": "#265787",
|
||||
},
|
||||
}
|
||||
|
||||
html_sidebars = {
|
||||
"**": [
|
||||
"sidebar/brand.html",
|
||||
"sidebar/search.html",
|
||||
"sidebar/scroll-start.html",
|
||||
"sidebar/navigation.html",
|
||||
"sidebar/scroll-end.html",
|
||||
"sidebar/variant-selector.html",
|
||||
]
|
||||
}
|
||||
""")
|
||||
|
||||
# not helpful since the source is generated, adds to upload size.
|
||||
fw("html_copy_source = False\n")
|
||||
fw("html_show_sphinx = False\n")
|
||||
fw("html_baseurl = 'https://docs.blender.org/api/current/'\n")
|
||||
fw("html_use_opensearch = 'https://docs.blender.org/api/current'\n")
|
||||
fw("html_show_search_summary = True\n")
|
||||
fw("html_split_index = True\n")
|
||||
fw("html_static_path = ['static']\n")
|
||||
fw("templates_path = ['templates']\n")
|
||||
fw("html_context = {'commit': '%s - %s'}\n" % (BLENDER_VERSION_HASH_HTML_LINK, BLENDER_VERSION_DATE))
|
||||
fw("html_extra_path = ['static']\n")
|
||||
fw("html_favicon = 'static/favicon.ico'\n")
|
||||
fw("html_logo = 'static/blender_logo.svg'\n")
|
||||
# Disable default `last_updated` value, since this is the date of doc generation, not the one of the source commit.
|
||||
fw("html_last_updated_fmt = None\n\n")
|
||||
fw("if html_theme == 'furo':\n")
|
||||
fw(" html_css_files = ['css/theme_overrides.css', 'css/version_switch.css']\n")
|
||||
fw(" html_js_files = ['js/version_switch.js']\n")
|
||||
|
||||
# needed for latex, pdf gen
|
||||
fw("latex_elements = {\n")
|
||||
fw(" 'papersize': 'a4paper',\n")
|
||||
fw("}\n\n")
|
||||
|
||||
fw("latex_documents = [ ('contents', 'contents.tex', 'Blender Index', 'Blender Foundation', 'manual'), ]\n")
|
||||
|
||||
# Workaround for useless links leading to compile errors
|
||||
# See https://github.com/sphinx-doc/sphinx/issues/3866
|
||||
fw(r"""
|
||||
from sphinx.domains.python import PythonDomain
|
||||
|
||||
class PatchedPythonDomain(PythonDomain):
|
||||
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
|
||||
if 'refspecific' in node:
|
||||
del node['refspecific']
|
||||
return super(PatchedPythonDomain, self).resolve_xref(
|
||||
env, fromdocname, builder, typ, target, node, contnode)
|
||||
|
||||
def setup(app):
|
||||
app.add_domain(PatchedPythonDomain, override=True)
|
||||
""")
|
||||
# end workaround
|
||||
|
||||
file.close()
|
||||
|
||||
|
||||
def write_rst_index(basepath):
|
||||
"""
|
||||
Write the RST file of the main page, needed for sphinx: ``index.html``.
|
||||
|
@ -2411,7 +2293,7 @@ def copy_handwritten_extra(basepath):
|
|||
shutil.copy2(f_src, f_dst)
|
||||
|
||||
|
||||
def copy_theme_assets(basepath):
|
||||
def copy_sphinx_files(basepath):
|
||||
shutil.copytree(
|
||||
os.path.join(SCRIPT_DIR, "static"),
|
||||
os.path.join(basepath, "static"),
|
||||
|
@ -2423,17 +2305,38 @@ def copy_theme_assets(basepath):
|
|||
copy_function=shutil.copy,
|
||||
)
|
||||
|
||||
shutil.copy2(os.path.join(SCRIPT_DIR, "conf.py"), basepath, )
|
||||
|
||||
|
||||
def format_config(basepath):
|
||||
"""
|
||||
Updates ``conf.py`` with context information from Blender.
|
||||
"""
|
||||
from string import Template
|
||||
|
||||
# Ensure the string literals can contain any characters by closing the surrounding quotes
|
||||
# and declare a separate literal via `repr()`.
|
||||
def declare_in_quotes(string):
|
||||
return "\" %r \"" % (string)
|
||||
|
||||
substitutions = {
|
||||
"BLENDER_VERSION_STRING": declare_in_quotes(BLENDER_VERSION_STRING),
|
||||
"BLENDER_VERSION_DOTS": declare_in_quotes(BLENDER_VERSION_DOTS),
|
||||
"BLENDER_REVISION_TIMESTAMP": declare_in_quotes(str(BLENDER_REVISION_TIMESTAMP)),
|
||||
"BLENDER_REVISION": declare_in_quotes(BLENDER_REVISION),
|
||||
}
|
||||
|
||||
filepath = os.path.join(basepath, "conf.py")
|
||||
|
||||
# Read the template string from the template file.
|
||||
with open(filepath, 'r', encoding="utf-8") as fh:
|
||||
template_file = fh.read()
|
||||
|
||||
with open(filepath, 'w', encoding="utf-8") as fh:
|
||||
fh.write(Template(template_file).substitute(substitutions))
|
||||
|
||||
|
||||
def rna2sphinx(basepath):
|
||||
|
||||
try:
|
||||
os.mkdir(basepath)
|
||||
except:
|
||||
pass
|
||||
|
||||
# sphinx setup
|
||||
write_sphinx_conf_py(basepath)
|
||||
|
||||
# main page
|
||||
write_rst_index(basepath)
|
||||
|
||||
|
@ -2460,9 +2363,6 @@ def rna2sphinx(basepath):
|
|||
# copy source files referenced
|
||||
copy_handwritten_extra(basepath)
|
||||
|
||||
# copy extra files needed for theme
|
||||
copy_theme_assets(basepath)
|
||||
|
||||
|
||||
def align_sphinx_in_to_sphinx_in_tmp(dir_src, dir_dst):
|
||||
"""
|
||||
|
@ -2583,10 +2483,22 @@ def main():
|
|||
copy_function=shutil.copy,
|
||||
)
|
||||
|
||||
# Dump the API in RST files.
|
||||
# start from a clean directory everytime
|
||||
if os.path.exists(SPHINX_IN_TMP):
|
||||
shutil.rmtree(SPHINX_IN_TMP, True)
|
||||
|
||||
try:
|
||||
os.mkdir(SPHINX_IN_TMP)
|
||||
except:
|
||||
pass
|
||||
|
||||
# copy extra files needed for theme
|
||||
copy_sphinx_files(SPHINX_IN_TMP)
|
||||
|
||||
# write infromation needed for 'conf.py'
|
||||
format_config(SPHINX_IN_TMP)
|
||||
|
||||
# Dump the API in RST files.
|
||||
rna2sphinx(SPHINX_IN_TMP)
|
||||
|
||||
if ARGS.changelog:
|
||||
|
|
|
@ -235,8 +235,8 @@ def enum_preview_denoiser(self, context):
|
|||
items = [
|
||||
('AUTO',
|
||||
"Automatic",
|
||||
("Use the fastest available denoiser for viewport rendering "
|
||||
"(OptiX if available, OpenImageDenoise otherwise)"),
|
||||
("Use GPU accelerated denoising if supported, for the best performance. "
|
||||
"Prefer OpenImageDenoise over OptiX"),
|
||||
0)]
|
||||
else:
|
||||
items = [('AUTO', "None", "Blender was compiled without a viewport denoiser", 0)]
|
||||
|
|
|
@ -124,7 +124,8 @@ class DeviceInfo {
|
|||
/* Multiple Devices with the same ID would be very bad. */
|
||||
assert(id != info.id ||
|
||||
(type == info.type && num == info.num && description == info.description));
|
||||
return id == info.id;
|
||||
return id == info.id && use_hardware_raytracing == info.use_hardware_raytracing &&
|
||||
kernel_optimization_level == info.kernel_optimization_level;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -944,9 +944,9 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
|
|||
INTEGRATOR_STATE_WRITE(state, ray, P) = sd->P;
|
||||
INTEGRATOR_STATE_WRITE(state, ray, D) = normalize(phase_wo);
|
||||
INTEGRATOR_STATE_WRITE(state, ray, tmin) = 0.0f;
|
||||
#ifdef __LIGHT_TREE__
|
||||
# ifdef __LIGHT_TREE__
|
||||
INTEGRATOR_STATE_WRITE(state, ray, previous_dt) = ray->tmax - ray->tmin;
|
||||
#endif
|
||||
# endif
|
||||
INTEGRATOR_STATE_WRITE(state, ray, tmax) = FLT_MAX;
|
||||
# ifdef __RAY_DIFFERENTIALS__
|
||||
INTEGRATOR_STATE_WRITE(state, ray, dP) = differential_make_compact(sd->dP);
|
||||
|
|
|
@ -492,13 +492,11 @@ ccl_device_forceinline bool area_light_tree_parameters(const ccl_global KernelLi
|
|||
ccl_private float2 &distance,
|
||||
ccl_private float3 &point_to_centroid)
|
||||
{
|
||||
if (!in_volume_segment) {
|
||||
/* TODO: a cheap substitute for minimal distance between point and primitive. Does it
|
||||
* worth the overhead to compute the accurate minimal distance? */
|
||||
float min_distance;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &min_distance);
|
||||
distance = make_float2(min_distance, min_distance);
|
||||
}
|
||||
/* TODO: a cheap substitute for minimal distance between point and primitive. Does it worth the
|
||||
* overhead to compute the accurate minimal distance? */
|
||||
float min_distance;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &min_distance);
|
||||
distance = make_float2(min_distance, min_distance);
|
||||
|
||||
cos_theta_u = FLT_MAX;
|
||||
|
||||
|
|
|
@ -196,21 +196,22 @@ ccl_device_forceinline bool point_light_tree_parameters(const ccl_global KernelL
|
|||
ccl_private float2 &distance,
|
||||
ccl_private float3 &point_to_centroid)
|
||||
{
|
||||
float min_distance;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &min_distance);
|
||||
distance = min_distance * one_float2();
|
||||
|
||||
if (in_volume_segment) {
|
||||
cos_theta_u = 1.0f; /* Any value in [-1, 1], irrelevant since theta = 0 */
|
||||
return true;
|
||||
}
|
||||
|
||||
float dist_point_to_centroid;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &dist_point_to_centroid);
|
||||
|
||||
const float radius = klight->spot.radius;
|
||||
|
||||
if (klight->spot.is_sphere) {
|
||||
if (dist_point_to_centroid > radius) {
|
||||
if (min_distance > radius) {
|
||||
/* Equivalent to a disk light with the same angular span. */
|
||||
cos_theta_u = cos_from_sin(radius / dist_point_to_centroid);
|
||||
distance = dist_point_to_centroid * make_float2(1.0f / cos_theta_u, 1.0f);
|
||||
cos_theta_u = cos_from_sin(radius / min_distance);
|
||||
distance.x = min_distance / cos_theta_u;
|
||||
}
|
||||
else {
|
||||
/* Similar to background light. */
|
||||
|
@ -220,10 +221,10 @@ ccl_device_forceinline bool point_light_tree_parameters(const ccl_global KernelL
|
|||
}
|
||||
}
|
||||
else {
|
||||
const float hypotenus = sqrtf(sqr(radius) + sqr(dist_point_to_centroid));
|
||||
cos_theta_u = dist_point_to_centroid / hypotenus;
|
||||
const float hypotenus = sqrtf(sqr(radius) + sqr(min_distance));
|
||||
cos_theta_u = min_distance / hypotenus;
|
||||
|
||||
distance = make_float2(hypotenus, dist_point_to_centroid);
|
||||
distance.x = hypotenus;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -291,35 +291,32 @@ ccl_device_forceinline bool spot_light_tree_parameters(const ccl_global KernelLi
|
|||
ccl_private float2 &distance,
|
||||
ccl_private float3 &point_to_centroid)
|
||||
{
|
||||
float dist_point_to_centroid;
|
||||
const float3 point_to_centroid_ = safe_normalize_len(centroid - P, &dist_point_to_centroid);
|
||||
float min_distance;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &min_distance);
|
||||
distance = min_distance * one_float2();
|
||||
|
||||
const float radius = klight->spot.radius;
|
||||
|
||||
if (klight->spot.is_sphere) {
|
||||
cos_theta_u = (dist_point_to_centroid > radius) ?
|
||||
cos_from_sin(radius / dist_point_to_centroid) :
|
||||
-1.0f;
|
||||
cos_theta_u = (min_distance > radius) ? cos_from_sin(radius / min_distance) : -1.0f;
|
||||
|
||||
if (in_volume_segment) {
|
||||
return true;
|
||||
}
|
||||
|
||||
distance = (dist_point_to_centroid > radius) ?
|
||||
dist_point_to_centroid * make_float2(1.0f / cos_theta_u, 1.0f) :
|
||||
one_float2() * radius / M_SQRT2_F;
|
||||
distance = (min_distance > radius) ? min_distance * make_float2(1.0f / cos_theta_u, 1.0f) :
|
||||
one_float2() * radius / M_SQRT2_F;
|
||||
}
|
||||
else {
|
||||
const float hypotenus = sqrtf(sqr(radius) + sqr(dist_point_to_centroid));
|
||||
cos_theta_u = dist_point_to_centroid / hypotenus;
|
||||
const float hypotenus = sqrtf(sqr(radius) + sqr(min_distance));
|
||||
cos_theta_u = min_distance / hypotenus;
|
||||
|
||||
if (in_volume_segment) {
|
||||
return true;
|
||||
}
|
||||
|
||||
distance = make_float2(hypotenus, dist_point_to_centroid);
|
||||
distance.x = hypotenus;
|
||||
}
|
||||
point_to_centroid = point_to_centroid_;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -194,7 +194,7 @@ ccl_device void light_tree_importance(const float3 N_or_D,
|
|||
float cos_min_outgoing_angle;
|
||||
if ((cos_theta >= cos_theta_u) || (cos_theta_minus_theta_u >= cos_theta_o)) {
|
||||
/* theta - theta_o - theta_u <= 0 */
|
||||
kernel_assert((fast_acosf(cos_theta) - bcone.theta_o - fast_acosf(cos_theta_u)) < 5e-4f);
|
||||
kernel_assert((fast_acosf(cos_theta) - bcone.theta_o - fast_acosf(cos_theta_u)) < 1e-3f);
|
||||
cos_min_outgoing_angle = 1.0f;
|
||||
}
|
||||
else if ((bcone.theta_o + bcone.theta_e > M_PI_F) ||
|
||||
|
@ -333,14 +333,14 @@ ccl_device void light_tree_node_importance(KernelGlobals kg,
|
|||
|
||||
if (in_volume_segment) {
|
||||
const float3 D = N_or_D;
|
||||
const float3 closest_point = P + dot(centroid - P, D) * D;
|
||||
const float closest_t = clamp(dot(centroid - P, D), 0.0f, t);
|
||||
const float3 closest_point = P + D * closest_t;
|
||||
/* Minimal distance of the ray to the cluster. */
|
||||
distance = len(centroid - closest_point);
|
||||
/* Vector that forms a minimal angle with the emitter centroid. */
|
||||
point_to_centroid = -compute_v(centroid, P, D, bcone.axis, t);
|
||||
/* FIXME(weizhen): it is not clear from which point the `cos_theta_u` should be computed in
|
||||
* volume segment. We could use `closest_point` as a conservative measure, but then
|
||||
* `point_to_centroid` should also use `closest_point`. */
|
||||
cos_theta_u = light_tree_cos_bounding_box_angle(bbox, closest_point, point_to_centroid);
|
||||
cos_theta_u = light_tree_cos_bounding_box_angle(
|
||||
bbox, closest_point, normalize(centroid - closest_point));
|
||||
}
|
||||
else {
|
||||
const float3 N = N_or_D;
|
||||
|
@ -405,8 +405,8 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
|
|||
bcone.theta_o = kemitter->theta_o;
|
||||
bcone.theta_e = kemitter->theta_e;
|
||||
float cos_theta_u;
|
||||
float2 distance; /* distance.x = max_distance, distance.y = mix_distance */
|
||||
float3 centroid, point_to_centroid, P_c;
|
||||
float2 distance; /* distance.x = max_distance, distance.y = min_distance */
|
||||
float3 centroid, point_to_centroid, P_c = P;
|
||||
|
||||
if (!compute_emitter_centroid_and_dir<in_volume_segment>(kg, kemitter, P, centroid, bcone.axis))
|
||||
{
|
||||
|
@ -415,15 +415,9 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
|
|||
|
||||
if (in_volume_segment) {
|
||||
const float3 D = N_or_D;
|
||||
/* Closest point. */
|
||||
P_c = P + dot(centroid - P, D) * D;
|
||||
/* Minimal distance of the ray to the cluster. */
|
||||
distance.x = len(centroid - P_c);
|
||||
distance.y = distance.x;
|
||||
point_to_centroid = -compute_v(centroid, P, D, bcone.axis, t);
|
||||
}
|
||||
else {
|
||||
P_c = P;
|
||||
/* Closest point from ray to the emitter centroid. */
|
||||
const float closest_t = clamp(dot(centroid - P, D), 0.0f, t);
|
||||
P_c += D * closest_t;
|
||||
}
|
||||
|
||||
/* Early out if the emitter is guaranteed to be invisible. */
|
||||
|
@ -457,6 +451,9 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
|
|||
case LIGHT_DISTANT:
|
||||
is_visible = distant_light_tree_parameters(
|
||||
centroid, bcone.theta_e, cos_theta_u, distance, point_to_centroid);
|
||||
if (in_volume_segment) {
|
||||
centroid = P - bcone.axis;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
@ -468,6 +465,11 @@ ccl_device void light_tree_emitter_importance(KernelGlobals kg,
|
|||
return;
|
||||
}
|
||||
|
||||
if (in_volume_segment) {
|
||||
/* Vector that forms a minimal angle with the emitter centroid. */
|
||||
point_to_centroid = -compute_v(centroid, P, N_or_D, bcone.axis, t);
|
||||
}
|
||||
|
||||
light_tree_importance<in_volume_segment>(N_or_D,
|
||||
has_transmission,
|
||||
point_to_centroid,
|
||||
|
|
|
@ -301,13 +301,11 @@ ccl_device_forceinline bool triangle_light_tree_parameters(
|
|||
ccl_private float2 &distance,
|
||||
ccl_private float3 &point_to_centroid)
|
||||
{
|
||||
if (!in_volume_segment) {
|
||||
/* TODO: a cheap substitute for minimal distance between point and primitive. Does it
|
||||
* worth the overhead to compute the accurate minimal distance? */
|
||||
float min_distance;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &min_distance);
|
||||
distance = make_float2(min_distance, min_distance);
|
||||
}
|
||||
/* TODO: a cheap substitute for minimal distance between point and primitive. Does it worth the
|
||||
* overhead to compute the accurate minimal distance? */
|
||||
float min_distance;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &min_distance);
|
||||
distance = make_float2(min_distance, min_distance);
|
||||
|
||||
cos_theta_u = FLT_MAX;
|
||||
|
||||
|
|
|
@ -903,14 +903,14 @@ static void background_cdf(
|
|||
for (int i = start; i < end; i++) {
|
||||
float sin_theta = sinf(M_PI_F * (i + 0.5f) / res_y);
|
||||
float3 env_color = (*pixels)[i * res_x];
|
||||
float ave_luminance = average(env_color);
|
||||
float ave_luminance = average(fabs(env_color));
|
||||
|
||||
cond_cdf[i * cdf_width].x = ave_luminance * sin_theta;
|
||||
cond_cdf[i * cdf_width].y = 0.0f;
|
||||
|
||||
for (int j = 1; j < res_x; j++) {
|
||||
env_color = (*pixels)[i * res_x + j];
|
||||
ave_luminance = average(env_color);
|
||||
ave_luminance = average(fabs(env_color));
|
||||
|
||||
cond_cdf[i * cdf_width + j].x = ave_luminance * sin_theta;
|
||||
cond_cdf[i * cdf_width + j].y = cond_cdf[i * cdf_width + j - 1].y +
|
||||
|
|
|
@ -39,7 +39,7 @@ static std::atomic<uint64_t> g_instance_index = 0;
|
|||
/* Construct names of EXR channels which will ensure order of all channels to match exact offsets
|
||||
* in render buffers corresponding to the given passes.
|
||||
*
|
||||
* Returns `std` datatypes so that it can be assigned directly to the OIIO's `ImageSpec`. */
|
||||
* Returns `std` data-types so that it can be assigned directly to the OIIO's `ImageSpec`. */
|
||||
static std::vector<std::string> exr_channel_names_for_passes(const BufferParams &buffer_params)
|
||||
{
|
||||
static const char *component_suffixes[] = {"R", "G", "B", "A"};
|
||||
|
|
|
@ -1879,6 +1879,23 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
|
||||
xdg_toplevel *toplevel = libdecor_frame_get_xdg_toplevel(decor.frame);
|
||||
gwl_window_state_set_for_xdg(toplevel, state, gwl_window_state_get(window_));
|
||||
|
||||
/* NOTE(@ideasman42): Round trips are necessary with LIBDECOR on GNOME
|
||||
* because resizing later on and redrawing does *not* update as it should, see #119871.
|
||||
*
|
||||
* Without the round-trip here:
|
||||
* - The window will be created and this function will return using the requested buffer size,
|
||||
* instead of the window size which ends up being used (causing a visible flicker).
|
||||
* This has the down side that Blender's internal window state has the outdated size
|
||||
* which then gets immediately resized, causing a noticeable glitch.
|
||||
* - The window decorations will be displayed at the wrong size before refreshing
|
||||
* at the new size.
|
||||
* - On GNOME-Shell 46 shows the previous buffer-size under some conditions.
|
||||
*
|
||||
* In principle this could be used with XDG too however it causes problems with KDE
|
||||
* and some WLROOTS based compositors.
|
||||
*/
|
||||
wl_display_roundtrip(system_->wl_display_get());
|
||||
}
|
||||
else
|
||||
#endif /* WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
|
@ -1886,30 +1903,6 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
gwl_window_state_set(window_, state);
|
||||
}
|
||||
|
||||
/* NOTE(@ideasman42): Round trips are important before committing.
|
||||
* This is needed because setting the state is likely to resize the window
|
||||
* (in the case of maximized & full-screen), "normal" windows may still be resized when
|
||||
* they are too large or with tiling window-managers.
|
||||
*
|
||||
* The additional updates allow for the actual size to be configured by the window manager
|
||||
* which is read back before committing the surface. This avoids displaying the buffer
|
||||
* before it's resized (avoiding flickering).
|
||||
*
|
||||
* Without the round-trip here:
|
||||
* - The window will be created and this function will return using the requested buffer size,
|
||||
* instead of the window size which ends up being used (causing a visible flicker).
|
||||
* This has the down side that Blender's internal window state has the outdated size
|
||||
* which then gets immediately resized, causing a noticeable glitch.
|
||||
* - The window decorations will be displayed at the wrong size before refreshing
|
||||
* at the new size.
|
||||
* - On GNOME-Shell 46 shows the previous buffer-size under some conditions, see #119871.
|
||||
* - 2x updates are needed for RIVER & HYPRLAND.
|
||||
*/
|
||||
for (int i = 0; i < 2; i++) {
|
||||
wl_display_flush(system->wl_display_get());
|
||||
wl_display_dispatch(system->wl_display_get());
|
||||
}
|
||||
|
||||
/* Commit after setting the buffer.
|
||||
* While postponing until after the buffer drawing is context is set
|
||||
* isn't essential, it reduces flickering. */
|
||||
|
|
|
@ -18,7 +18,7 @@ extern "C" {
|
|||
* Currently, this API is optimized for Bullet RigidBodies, and doesn't
|
||||
* take into account other Physics Engines. Some tweaking may be necessary
|
||||
* to allow other systems to be used, in particular there may be references
|
||||
* to datatypes that aren't used here...
|
||||
* to data-types that aren't used here...
|
||||
*
|
||||
* -- Joshua Leung (22 June 2010)
|
||||
*/
|
||||
|
|
|
@ -588,6 +588,54 @@ class RemovePresetInterfaceTheme(AddPresetBase, Operator):
|
|||
return context.window_manager.invoke_confirm(self, event, title="Remove Custom Theme", confirm_text="Delete")
|
||||
|
||||
|
||||
class SavePresetInterfaceTheme(AddPresetBase, Operator):
|
||||
"""Save a custom theme in the preset list"""
|
||||
bl_idname = "wm.interface_theme_preset_save"
|
||||
bl_label = "Save Theme"
|
||||
preset_menu = "USERPREF_MT_interface_theme_presets"
|
||||
preset_subdir = "interface_theme"
|
||||
|
||||
remove_active: BoolProperty(
|
||||
default=True,
|
||||
options={'HIDDEN', 'SKIP_SAVE'},
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
from bpy.utils import is_path_builtin
|
||||
|
||||
preset_menu_class = getattr(bpy.types, cls.preset_menu)
|
||||
name = preset_menu_class.bl_label
|
||||
filepath = bpy.utils.preset_find(name, cls.preset_subdir, ext=".xml")
|
||||
if (not filepath) or is_path_builtin(filepath):
|
||||
cls.poll_message_set("Built-in themes cannot be overwritten")
|
||||
return False
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
from bpy.utils import is_path_builtin
|
||||
import rna_xml
|
||||
preset_menu_class = getattr(bpy.types, self.preset_menu)
|
||||
name = preset_menu_class.bl_label
|
||||
filepath = bpy.utils.preset_find(name, self.preset_subdir, ext=".xml")
|
||||
if not bool(filepath) or is_path_builtin(filepath):
|
||||
self.report({'ERROR'}, "Built-in themes cannot be overwritten")
|
||||
return {'CANCELLED'}
|
||||
|
||||
try:
|
||||
rna_xml.xml_file_write(context, filepath, preset_menu_class.preset_xml_map)
|
||||
except BaseException as ex:
|
||||
self.report({'ERROR'}, "Unable to overwrite preset: %s" % str(ex))
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {'CANCELLED'}
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
return context.window_manager.invoke_confirm(self, event, title="Overwrite Custom Theme?", confirm_text="Save")
|
||||
|
||||
|
||||
class AddPresetKeyconfig(AddPresetBase, Operator):
|
||||
"""Add a custom keymap configuration to the preset list"""
|
||||
bl_idname = "wm.keyconfig_preset_add"
|
||||
|
@ -857,6 +905,7 @@ classes = (
|
|||
AddPresetHairDynamics,
|
||||
AddPresetInterfaceTheme,
|
||||
RemovePresetInterfaceTheme,
|
||||
SavePresetInterfaceTheme,
|
||||
AddPresetKeyconfig,
|
||||
RemovePresetKeyconfig,
|
||||
AddPresetNodeColor,
|
||||
|
|
|
@ -3,12 +3,20 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import bpy
|
||||
from bpy.types import Operator
|
||||
from bpy.types import (
|
||||
Operator,
|
||||
FileHandler,
|
||||
)
|
||||
from bpy.props import (
|
||||
BoolProperty,
|
||||
EnumProperty,
|
||||
)
|
||||
|
||||
bl_file_extensions_image_and_movie = ";".join((
|
||||
*bpy.path.extensions_image,
|
||||
*bpy.path.extensions_movie,
|
||||
))
|
||||
|
||||
|
||||
class VIEW3D_OT_edit_mesh_extrude_individual_move(Operator):
|
||||
"""Extrude each individual face separately along local normals"""
|
||||
|
@ -258,10 +266,40 @@ class VIEW3D_OT_transform_gizmo_set(Operator):
|
|||
return self.execute(context)
|
||||
|
||||
|
||||
class VIEW3D_FH_empty_image(FileHandler):
|
||||
bl_idname = "VIEW3D_FH_empty_image"
|
||||
bl_label = "Add empty image"
|
||||
bl_import_operator = "OBJECT_OT_empty_image_add"
|
||||
bl_file_extensions = bl_file_extensions_image_and_movie
|
||||
|
||||
@classmethod
|
||||
def poll_drop(cls, context):
|
||||
if not context.space_data or context.space_data.type != 'VIEW_3D':
|
||||
return False
|
||||
rv3d = context.space_data.region_3d
|
||||
return rv3d.view_perspective == 'PERSP' or rv3d.view_perspective == 'ORTHO'
|
||||
|
||||
|
||||
class VIEW3D_FH_camera_background_image(FileHandler):
|
||||
bl_idname = "VIEW3D_FH_camera_background_image"
|
||||
bl_label = "Add camera background image"
|
||||
bl_import_operator = "VIEW3D_OT_camera_background_image_add"
|
||||
bl_file_extensions = bl_file_extensions_image_and_movie
|
||||
|
||||
@classmethod
|
||||
def poll_drop(cls, context):
|
||||
if not context.space_data or context.space_data.type != 'VIEW_3D':
|
||||
return False
|
||||
rv3d = context.space_data.region_3d
|
||||
return rv3d.view_perspective == 'CAMERA'
|
||||
|
||||
|
||||
classes = (
|
||||
VIEW3D_OT_edit_mesh_extrude_individual_move,
|
||||
VIEW3D_OT_edit_mesh_extrude_move,
|
||||
VIEW3D_OT_edit_mesh_extrude_shrink_fatten,
|
||||
VIEW3D_OT_edit_mesh_extrude_manifold_normal,
|
||||
VIEW3D_OT_transform_gizmo_set,
|
||||
VIEW3D_FH_camera_background_image,
|
||||
VIEW3D_FH_empty_image,
|
||||
)
|
||||
|
|
|
@ -89,7 +89,7 @@ class GREASE_PENCIL_MT_grease_pencil_add_layer_extra(Menu):
|
|||
layout.operator("grease_pencil.layer_group_add", text="Add Group")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("grease_pencil.layer_duplicate", text="Duplicate", icon='DUPLICATE')
|
||||
layout.operator("grease_pencil.layer_duplicate", text="Duplicate", icon='DUPLICATE').empty_keyframes = False
|
||||
layout.operator("grease_pencil.layer_duplicate", text="Duplicate Empty Keyframes").empty_keyframes = True
|
||||
|
||||
layout.separator()
|
||||
|
@ -97,7 +97,7 @@ class GREASE_PENCIL_MT_grease_pencil_add_layer_extra(Menu):
|
|||
layout.operator("grease_pencil.layer_hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
|
||||
|
||||
layout.separator()
|
||||
layout.operator("grease_pencil.layer_lock_all", icon='LOCKED', text="Lock All")
|
||||
layout.operator("grease_pencil.layer_lock_all", icon='LOCKED', text="Lock All").lock = True
|
||||
layout.operator("grease_pencil.layer_lock_all", icon='UNLOCKED', text="Unlock All").lock = False
|
||||
|
||||
layout.separator()
|
||||
|
|
|
@ -1488,6 +1488,7 @@ class _defs_sculpt:
|
|||
def trim_box():
|
||||
def draw_settings(_context, layout, tool):
|
||||
props = tool.operator_properties("sculpt.trim_box_gesture")
|
||||
layout.prop(props, "trim_solver", expand=False)
|
||||
layout.prop(props, "trim_mode", expand=False)
|
||||
layout.prop(props, "trim_orientation", expand=False)
|
||||
layout.prop(props, "trim_extrude_mode", expand=False)
|
||||
|
@ -1505,6 +1506,7 @@ class _defs_sculpt:
|
|||
def trim_lasso():
|
||||
def draw_settings(_context, layout, tool):
|
||||
props = tool.operator_properties("sculpt.trim_lasso_gesture")
|
||||
layout.prop(props, "trim_solver", expand=False)
|
||||
layout.prop(props, "trim_mode", expand=False)
|
||||
layout.prop(props, "trim_orientation", expand=False)
|
||||
layout.prop(props, "trim_extrude_mode", expand=False)
|
||||
|
|
|
@ -877,6 +877,7 @@ class USERPREF_PT_theme(ThemePanel, Panel):
|
|||
row.menu("USERPREF_MT_interface_theme_presets", text=USERPREF_MT_interface_theme_presets.bl_label)
|
||||
row.operator("wm.interface_theme_preset_add", text="", icon='ADD')
|
||||
row.operator("wm.interface_theme_preset_remove", text="", icon='REMOVE')
|
||||
row.operator("wm.interface_theme_preset_save", text="", icon='FILE_TICK')
|
||||
|
||||
row = split.row(align=True)
|
||||
row.operator("preferences.theme_install", text="Install...", icon='IMPORT')
|
||||
|
|
|
@ -7548,9 +7548,6 @@ class VIEW3D_PT_snapping(Panel):
|
|||
|
||||
col.separator()
|
||||
|
||||
if 'INCREMENT' in tool_settings.snap_elements:
|
||||
col.prop(tool_settings, "use_snap_grid_absolute")
|
||||
|
||||
if 'VOLUME' in tool_settings.snap_elements:
|
||||
col.prop(tool_settings, "use_snap_peel_object")
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_lib_override.hh"
|
||||
|
||||
|
|
|
@ -223,7 +223,7 @@ bool AssetCatalogDefinitionFile::write_to_disk_unsafe(const CatalogFilePath &des
|
|||
}
|
||||
|
||||
bool AssetCatalogDefinitionFile::ensure_directory_exists(
|
||||
const CatalogFilePath directory_path) const
|
||||
const CatalogFilePath &directory_path) const
|
||||
{
|
||||
/* TODO(@sybren): design a way to get such errors presented to users (or ensure that they never
|
||||
* occur). */
|
||||
|
|
|
@ -81,7 +81,7 @@ class AssetCatalogDefinitionFile {
|
|||
* Return true when the file was written correctly, false when there was a problem.
|
||||
*/
|
||||
bool write_to_disk_unsafe(const CatalogFilePath &dest_file_path) const;
|
||||
bool ensure_directory_exists(const CatalogFilePath directory_path) const;
|
||||
bool ensure_directory_exists(const CatalogFilePath &directory_path) const;
|
||||
};
|
||||
|
||||
} // namespace blender::asset_system
|
||||
|
|
|
@ -20,7 +20,8 @@ namespace blender::asset_system {
|
|||
|
||||
AssetIdentifier::AssetIdentifier(std::shared_ptr<std::string> library_root_path,
|
||||
std::string relative_asset_path)
|
||||
: library_root_path_(library_root_path), relative_asset_path_(relative_asset_path)
|
||||
: library_root_path_(std::move(library_root_path)),
|
||||
relative_asset_path_(std::move(relative_asset_path))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,
|
|||
const int id_type,
|
||||
std::unique_ptr<AssetMetaData> metadata,
|
||||
const AssetLibrary &owner_asset_library)
|
||||
: identifier_(identifier),
|
||||
: identifier_(std::move(identifier)),
|
||||
is_local_id_(false),
|
||||
owner_asset_library_(owner_asset_library),
|
||||
external_asset_()
|
||||
|
@ -35,7 +35,7 @@ AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,
|
|||
AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,
|
||||
ID &id,
|
||||
const AssetLibrary &owner_asset_library)
|
||||
: identifier_(identifier),
|
||||
: identifier_(std::move(identifier)),
|
||||
is_local_id_(true),
|
||||
owner_asset_library_(owner_asset_library),
|
||||
local_asset_id_(&id)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#define BLF_BLUR_ENABLE 0
|
||||
|
||||
struct ColorManagedDisplay;
|
||||
struct ListBase;
|
||||
struct ResultBLF;
|
||||
struct rcti;
|
||||
|
||||
|
@ -81,7 +82,7 @@ bool BLF_get_vfont_metrics(int fontid, float *ascend_ratio, float *em_ratio, flo
|
|||
*/
|
||||
float BLF_character_to_curves(int fontid,
|
||||
unsigned int unicode,
|
||||
struct ListBase *nurbsbase,
|
||||
ListBase *nurbsbase,
|
||||
const float scale);
|
||||
|
||||
/**
|
||||
|
@ -143,15 +144,14 @@ void BLF_batch_draw_end();
|
|||
/**
|
||||
* Draw the string using the current font.
|
||||
*/
|
||||
void BLF_draw_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info)
|
||||
void BLF_draw(int fontid, const char *str, size_t str_len, ResultBLF *r_info = nullptr)
|
||||
ATTR_NONNULL(2);
|
||||
void BLF_draw(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, int tab_columns)
|
||||
ATTR_NONNULL(2);
|
||||
|
||||
typedef bool (*BLF_GlyphBoundsFn)(const char *str,
|
||||
size_t str_step_ofs,
|
||||
const struct rcti *bounds,
|
||||
const rcti *bounds,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
|
@ -182,8 +182,7 @@ size_t BLF_str_offset_from_cursor_position(int fontid,
|
|||
bool BLF_str_offset_to_glyph_bounds(int fontid,
|
||||
const char *str,
|
||||
size_t str_offset,
|
||||
struct rcti *glyph_bounds) ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_NONNULL(2, 4);
|
||||
rcti *glyph_bounds) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2, 4);
|
||||
|
||||
/**
|
||||
* Get the string byte offset that fits within a given width.
|
||||
|
@ -206,26 +205,21 @@ size_t BLF_width_to_rstrlen(int fontid,
|
|||
* This function return the bounding box of the string
|
||||
* and are not multiplied by the aspect.
|
||||
*/
|
||||
void BLF_boundbox_ex(int fontid,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
struct rcti *box,
|
||||
struct ResultBLF *r_info) ATTR_NONNULL(2);
|
||||
void BLF_boundbox(int fontid, const char *str, size_t str_len, struct rcti *box) ATTR_NONNULL();
|
||||
void BLF_boundbox(int fontid,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
rcti *box,
|
||||
ResultBLF *r_info = nullptr) ATTR_NONNULL(2);
|
||||
|
||||
/**
|
||||
* The next both function return the width and height
|
||||
* of the string, using the current font and both value
|
||||
* are multiplied by the aspect of the font.
|
||||
*/
|
||||
float BLF_width_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info)
|
||||
float BLF_width(int fontid, const char *str, size_t str_len, ResultBLF *r_info = nullptr)
|
||||
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
|
||||
float BLF_width(int fontid, const char *str, size_t str_len) ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_NONNULL();
|
||||
float BLF_height_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info)
|
||||
float BLF_height(int fontid, const char *str, size_t str_len, ResultBLF *r_info = nullptr)
|
||||
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
|
||||
float BLF_height(int fontid, const char *str, size_t str_len) ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_NONNULL();
|
||||
|
||||
/**
|
||||
* Return dimensions of the font without any sample text.
|
||||
|
@ -299,7 +293,7 @@ void BLF_buffer(int fontid,
|
|||
int w,
|
||||
int h,
|
||||
int nch,
|
||||
struct ColorManagedDisplay *display);
|
||||
ColorManagedDisplay *display);
|
||||
|
||||
/**
|
||||
* Set the color to be used for text.
|
||||
|
@ -310,9 +304,8 @@ void BLF_buffer_col(int fontid, const float rgba[4]) ATTR_NONNULL(2);
|
|||
* Draw the string into the buffer, this function draw in both buffer,
|
||||
* float and unsigned char _BUT_ it's not necessary set both buffer, NULL is valid here.
|
||||
*/
|
||||
void BLF_draw_buffer_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info)
|
||||
void BLF_draw_buffer(int fontid, const char *str, size_t str_len, ResultBLF *r_info = nullptr)
|
||||
ATTR_NONNULL(2);
|
||||
void BLF_draw_buffer(int fontid, const char *str, size_t str_len) ATTR_NONNULL(2);
|
||||
|
||||
/* `blf_thumbs.cc` */
|
||||
|
||||
|
|
|
@ -567,13 +567,21 @@ static void blf_draw_gpu__end(const FontBLF *font)
|
|||
}
|
||||
}
|
||||
|
||||
void BLF_draw_ex(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
|
||||
void BLF_draw(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
|
||||
{
|
||||
FontBLF *font = blf_get(fontid);
|
||||
|
||||
BLF_RESULT_CHECK_INIT(r_info);
|
||||
|
||||
if (str_len == 0 || str[0] == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
FontBLF *font = blf_get(fontid);
|
||||
|
||||
if (font) {
|
||||
|
||||
/* Avoid bgl usage to corrupt BLF drawing. */
|
||||
GPU_bgl_end();
|
||||
|
||||
blf_draw_gpu__start(font);
|
||||
if (font->flags & BLF_WORD_WRAP) {
|
||||
blf_font_draw__wrap(font, str, str_len, r_info);
|
||||
|
@ -584,17 +592,6 @@ void BLF_draw_ex(int fontid, const char *str, const size_t str_len, ResultBLF *r
|
|||
blf_draw_gpu__end(font);
|
||||
}
|
||||
}
|
||||
void BLF_draw(int fontid, const char *str, const size_t str_len)
|
||||
{
|
||||
if (str_len == 0 || str[0] == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Avoid bgl usage to corrupt BLF drawing. */
|
||||
GPU_bgl_end();
|
||||
|
||||
BLF_draw_ex(fontid, str, str_len, nullptr);
|
||||
}
|
||||
|
||||
int BLF_draw_mono(int fontid, const char *str, const size_t str_len, int cwidth, int tab_columns)
|
||||
{
|
||||
|
@ -699,7 +696,7 @@ size_t BLF_width_to_rstrlen(
|
|||
return 0;
|
||||
}
|
||||
|
||||
void BLF_boundbox_ex(
|
||||
void BLF_boundbox(
|
||||
int fontid, const char *str, const size_t str_len, rcti *r_box, ResultBLF *r_info)
|
||||
{
|
||||
FontBLF *font = blf_get(fontid);
|
||||
|
@ -716,11 +713,6 @@ void BLF_boundbox_ex(
|
|||
}
|
||||
}
|
||||
|
||||
void BLF_boundbox(int fontid, const char *str, const size_t str_len, rcti *r_box)
|
||||
{
|
||||
BLF_boundbox_ex(fontid, str, str_len, r_box, nullptr);
|
||||
}
|
||||
|
||||
void BLF_width_and_height(
|
||||
int fontid, const char *str, const size_t str_len, float *r_width, float *r_height)
|
||||
{
|
||||
|
@ -734,7 +726,7 @@ void BLF_width_and_height(
|
|||
}
|
||||
}
|
||||
|
||||
float BLF_width_ex(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
|
||||
float BLF_width(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
|
||||
{
|
||||
FontBLF *font = blf_get(fontid);
|
||||
|
||||
|
@ -747,11 +739,6 @@ float BLF_width_ex(int fontid, const char *str, const size_t str_len, ResultBLF
|
|||
return 0.0f;
|
||||
}
|
||||
|
||||
float BLF_width(int fontid, const char *str, const size_t str_len)
|
||||
{
|
||||
return BLF_width_ex(fontid, str, str_len, nullptr);
|
||||
}
|
||||
|
||||
float BLF_fixed_width(int fontid)
|
||||
{
|
||||
FontBLF *font = blf_get(fontid);
|
||||
|
@ -763,7 +750,7 @@ float BLF_fixed_width(int fontid)
|
|||
return 0.0f;
|
||||
}
|
||||
|
||||
float BLF_height_ex(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
|
||||
float BLF_height(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
|
||||
{
|
||||
FontBLF *font = blf_get(fontid);
|
||||
|
||||
|
@ -776,11 +763,6 @@ float BLF_height_ex(int fontid, const char *str, const size_t str_len, ResultBLF
|
|||
return 0.0f;
|
||||
}
|
||||
|
||||
float BLF_height(int fontid, const char *str, const size_t str_len)
|
||||
{
|
||||
return BLF_height_ex(fontid, str, str_len, nullptr);
|
||||
}
|
||||
|
||||
int BLF_height_max(int fontid)
|
||||
{
|
||||
FontBLF *font = blf_get(fontid);
|
||||
|
@ -915,7 +897,7 @@ void blf_draw_buffer__start(FontBLF *font)
|
|||
}
|
||||
void blf_draw_buffer__end() {}
|
||||
|
||||
void BLF_draw_buffer_ex(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
|
||||
void BLF_draw_buffer(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
|
||||
{
|
||||
FontBLF *font = blf_get(fontid);
|
||||
|
||||
|
@ -930,10 +912,6 @@ void BLF_draw_buffer_ex(int fontid, const char *str, const size_t str_len, Resul
|
|||
blf_draw_buffer__end();
|
||||
}
|
||||
}
|
||||
void BLF_draw_buffer(int fontid, const char *str, const size_t str_len)
|
||||
{
|
||||
BLF_draw_buffer_ex(fontid, str, str_len, nullptr);
|
||||
}
|
||||
|
||||
blender::Vector<blender::StringRef> BLF_string_wrap(int fontid,
|
||||
blender::StringRef str,
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
struct FontBLF;
|
||||
struct GlyphBLF;
|
||||
struct GlyphCacheBLF;
|
||||
struct ListBase;
|
||||
struct ResultBLF;
|
||||
struct rcti;
|
||||
|
||||
|
@ -49,9 +50,9 @@ struct rcti;
|
|||
#define BLF_DPI 72
|
||||
|
||||
/** Font array. */
|
||||
extern struct FontBLF *global_font[BLF_MAX_FONT];
|
||||
extern FontBLF *global_font[BLF_MAX_FONT];
|
||||
|
||||
void blf_batch_draw_begin(struct FontBLF *font);
|
||||
void blf_batch_draw_begin(FontBLF *font);
|
||||
void blf_batch_draw();
|
||||
|
||||
/**
|
||||
|
@ -68,34 +69,28 @@ bool blf_font_id_is_valid(int fontid);
|
|||
/**
|
||||
* Return glyph id from char-code.
|
||||
*/
|
||||
uint blf_get_char_index(struct FontBLF *font, uint charcode);
|
||||
uint blf_get_char_index(FontBLF *font, uint charcode);
|
||||
|
||||
/**
|
||||
* Create an FT_Face for this font if not already existing.
|
||||
*/
|
||||
bool blf_ensure_face(struct FontBLF *font);
|
||||
void blf_ensure_size(struct FontBLF *font);
|
||||
bool blf_ensure_face(FontBLF *font);
|
||||
void blf_ensure_size(FontBLF *font);
|
||||
|
||||
void blf_draw_buffer__start(struct FontBLF *font);
|
||||
void blf_draw_buffer__start(FontBLF *font);
|
||||
void blf_draw_buffer__end();
|
||||
|
||||
struct FontBLF *blf_font_new_from_filepath(const char *filepath);
|
||||
struct FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, size_t mem_size);
|
||||
void blf_font_attach_from_mem(struct FontBLF *font, const unsigned char *mem, size_t mem_size);
|
||||
FontBLF *blf_font_new_from_filepath(const char *filepath);
|
||||
FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, size_t mem_size);
|
||||
void blf_font_attach_from_mem(FontBLF *font, const unsigned char *mem, size_t mem_size);
|
||||
|
||||
/**
|
||||
* Change font's output size. Returns true if successful in changing the size.
|
||||
*/
|
||||
bool blf_font_size(struct FontBLF *font, float size);
|
||||
bool blf_font_size(FontBLF *font, float size);
|
||||
|
||||
void blf_font_draw(struct FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
struct ResultBLF *r_info);
|
||||
void blf_font_draw__wrap(struct FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
struct ResultBLF *r_info);
|
||||
void blf_font_draw(FontBLF *font, const char *str, size_t str_len, ResultBLF *r_info);
|
||||
void blf_font_draw__wrap(FontBLF *font, const char *str, size_t str_len, ResultBLF *r_info);
|
||||
|
||||
blender::Vector<blender::StringRef> blf_font_string_wrap(FontBLF *font,
|
||||
blender::StringRef str,
|
||||
|
@ -105,89 +100,63 @@ blender::Vector<blender::StringRef> blf_font_string_wrap(FontBLF *font,
|
|||
* Use fixed column width, but an utf8 character may occupy multiple columns.
|
||||
*/
|
||||
int blf_font_draw_mono(
|
||||
struct FontBLF *font, const char *str, size_t str_len, int cwidth, int tab_columns);
|
||||
void blf_font_draw_buffer(struct FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
struct ResultBLF *r_info);
|
||||
void blf_font_draw_buffer__wrap(struct FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
struct ResultBLF *r_info);
|
||||
FontBLF *font, const char *str, size_t str_len, int cwidth, int tab_columns);
|
||||
void blf_font_draw_buffer(FontBLF *font, const char *str, size_t str_len, ResultBLF *r_info);
|
||||
void blf_font_draw_buffer__wrap(FontBLF *font, const char *str, size_t str_len, ResultBLF *r_info);
|
||||
size_t blf_font_width_to_strlen(
|
||||
struct FontBLF *font, const char *str, size_t str_len, int width, int *r_width);
|
||||
FontBLF *font, const char *str, size_t str_len, int width, int *r_width);
|
||||
size_t blf_font_width_to_rstrlen(
|
||||
struct FontBLF *font, const char *str, size_t str_len, int width, int *r_width);
|
||||
void blf_font_boundbox(struct FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
struct rcti *r_box,
|
||||
struct ResultBLF *r_info);
|
||||
void blf_font_boundbox__wrap(struct FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
struct rcti *r_box,
|
||||
struct ResultBLF *r_info);
|
||||
void blf_font_width_and_height(struct FontBLF *font,
|
||||
FontBLF *font, const char *str, size_t str_len, int width, int *r_width);
|
||||
void blf_font_boundbox(
|
||||
FontBLF *font, const char *str, size_t str_len, rcti *r_box, ResultBLF *r_info);
|
||||
void blf_font_boundbox__wrap(
|
||||
FontBLF *font, const char *str, size_t str_len, rcti *r_box, ResultBLF *r_info);
|
||||
void blf_font_width_and_height(FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
float *r_width,
|
||||
float *r_height,
|
||||
struct ResultBLF *r_info);
|
||||
float blf_font_width(struct FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
struct ResultBLF *r_info);
|
||||
float blf_font_height(struct FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
struct ResultBLF *r_info);
|
||||
float blf_font_fixed_width(struct FontBLF *font);
|
||||
int blf_font_height_max(struct FontBLF *font);
|
||||
int blf_font_width_max(struct FontBLF *font);
|
||||
int blf_font_descender(struct FontBLF *font);
|
||||
int blf_font_ascender(struct FontBLF *font);
|
||||
ResultBLF *r_info);
|
||||
float blf_font_width(FontBLF *font, const char *str, size_t str_len, ResultBLF *r_info);
|
||||
float blf_font_height(FontBLF *font, const char *str, size_t str_len, ResultBLF *r_info);
|
||||
float blf_font_fixed_width(FontBLF *font);
|
||||
int blf_font_height_max(FontBLF *font);
|
||||
int blf_font_width_max(FontBLF *font);
|
||||
int blf_font_descender(FontBLF *font);
|
||||
int blf_font_ascender(FontBLF *font);
|
||||
|
||||
char *blf_display_name(struct FontBLF *font);
|
||||
char *blf_display_name(FontBLF *font);
|
||||
|
||||
void blf_font_boundbox_foreach_glyph(struct FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
bool (*user_fn)(const char *str,
|
||||
size_t str_step_ofs,
|
||||
const struct rcti *bounds,
|
||||
void *user_data),
|
||||
void *user_data);
|
||||
void blf_font_boundbox_foreach_glyph(
|
||||
FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
bool (*user_fn)(const char *str, size_t str_step_ofs, const rcti *bounds, void *user_data),
|
||||
void *user_data);
|
||||
|
||||
size_t blf_str_offset_from_cursor_position(struct FontBLF *font,
|
||||
size_t blf_str_offset_from_cursor_position(FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
int location_x);
|
||||
|
||||
void blf_str_offset_to_glyph_bounds(struct FontBLF *font,
|
||||
void blf_str_offset_to_glyph_bounds(FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_offset,
|
||||
struct rcti *glyph_bounds);
|
||||
rcti *glyph_bounds);
|
||||
|
||||
void blf_font_free(struct FontBLF *font);
|
||||
void blf_font_free(FontBLF *font);
|
||||
|
||||
struct GlyphCacheBLF *blf_glyph_cache_acquire(struct FontBLF *font);
|
||||
void blf_glyph_cache_release(struct FontBLF *font);
|
||||
void blf_glyph_cache_clear(struct FontBLF *font);
|
||||
GlyphCacheBLF *blf_glyph_cache_acquire(FontBLF *font);
|
||||
void blf_glyph_cache_release(FontBLF *font);
|
||||
void blf_glyph_cache_clear(FontBLF *font);
|
||||
|
||||
/**
|
||||
* Create (or load from cache) a fully-rendered bitmap glyph.
|
||||
*/
|
||||
struct GlyphBLF *blf_glyph_ensure(struct FontBLF *font,
|
||||
struct GlyphCacheBLF *gc,
|
||||
uint charcode,
|
||||
uint8_t subpixel = 0);
|
||||
GlyphBLF *blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, uint charcode, uint8_t subpixel = 0);
|
||||
|
||||
#ifdef BLF_SUBPIXEL_AA
|
||||
struct GlyphBLF *blf_glyph_ensure_subpixel(struct FontBLF *font,
|
||||
struct GlyphCacheBLF *gc,
|
||||
struct GlyphBLF *g,
|
||||
int32_t pen_x);
|
||||
GlyphBLF *blf_glyph_ensure_subpixel(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, int32_t pen_x);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -195,11 +164,10 @@ struct GlyphBLF *blf_glyph_ensure_subpixel(struct FontBLF *font,
|
|||
*/
|
||||
float blf_character_to_curves(FontBLF *font,
|
||||
unsigned int unicode,
|
||||
struct ListBase *nurbsbase,
|
||||
ListBase *nurbsbase,
|
||||
const float scale);
|
||||
|
||||
void blf_glyph_draw(
|
||||
struct FontBLF *font, struct GlyphCacheBLF *gc, struct GlyphBLF *g, int x, int y);
|
||||
void blf_glyph_draw(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, int x, int y);
|
||||
|
||||
#ifdef WIN32
|
||||
/* `blf_font_win32_compat.cc` */
|
||||
|
|
|
@ -112,6 +112,7 @@ void BKE_id_attributes_active_color_set(struct ID *id, const char *name);
|
|||
void BKE_id_attributes_default_color_set(struct ID *id, const char *name);
|
||||
|
||||
const struct CustomDataLayer *BKE_id_attributes_color_find(const struct ID *id, const char *name);
|
||||
bool BKE_color_attribute_supported(const struct Mesh &mesh, const blender::StringRef name);
|
||||
|
||||
std::string BKE_id_attribute_calc_unique_name(const struct ID &id, const blender::StringRef name);
|
||||
|
||||
|
|
|
@ -252,8 +252,6 @@ void CTX_wm_operator_poll_msg_clear(bContext *C);
|
|||
|
||||
/* Data Context
|
||||
*
|
||||
* - #ListBase consists of #CollectionPointerLink items and must be
|
||||
* freed with #BLI_freelistN!
|
||||
* - The dir #ListBase consists of #LinkData items.
|
||||
*/
|
||||
|
||||
|
@ -269,7 +267,7 @@ PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, Stru
|
|||
PointerRNA CTX_data_pointer_get_type_silent(const bContext *C,
|
||||
const char *member,
|
||||
StructRNA *type);
|
||||
ListBase CTX_data_collection_get(const bContext *C, const char *member);
|
||||
blender::Vector<PointerRNA> CTX_data_collection_get(const bContext *C, const char *member);
|
||||
|
||||
/**
|
||||
* For each pointer in collection_pointers, remap it to point to `ptr->propname`.
|
||||
|
@ -278,11 +276,8 @@ ListBase CTX_data_collection_get(const bContext *C, const char *member);
|
|||
*
|
||||
* lb = CTX_data_collection_get(C, "selected_pose_bones"); // lb contains pose bones.
|
||||
* CTX_data_collection_remap_property(lb, "color"); // lb now contains bone colors.
|
||||
*
|
||||
* NOTE: this alters the items contained in the given listbase.
|
||||
* It does not change the listbase itself.
|
||||
*/
|
||||
void CTX_data_collection_remap_property(ListBase /*CollectionPointerLink*/ collection_pointers,
|
||||
void CTX_data_collection_remap_property(blender::MutableSpan<PointerRNA> collection_pointers,
|
||||
const char *propname);
|
||||
|
||||
/**
|
||||
|
@ -296,7 +291,7 @@ ListBase CTX_data_dir_get(const bContext *C);
|
|||
int /*eContextResult*/ CTX_data_get(const bContext *C,
|
||||
const char *member,
|
||||
PointerRNA *r_ptr,
|
||||
ListBase *r_lb,
|
||||
blender::Vector<PointerRNA> *r_lb,
|
||||
PropertyRNA **r_prop,
|
||||
int *r_index,
|
||||
short *r_type);
|
||||
|
@ -328,25 +323,22 @@ bool CTX_data_dir(const char *member);
|
|||
|
||||
#define CTX_DATA_BEGIN(C, Type, instance, member) \
|
||||
{ \
|
||||
ListBase ctx_data_list; \
|
||||
CollectionPointerLink *ctx_link; \
|
||||
blender::Vector<PointerRNA> ctx_data_list; \
|
||||
CTX_data_##member(C, &ctx_data_list); \
|
||||
for (ctx_link = (CollectionPointerLink *)ctx_data_list.first; ctx_link; \
|
||||
ctx_link = ctx_link->next) \
|
||||
{ \
|
||||
Type instance = (Type)ctx_link->ptr.data;
|
||||
for (PointerRNA & ctx_link : ctx_data_list) { \
|
||||
Type instance = (Type)ctx_link.data;
|
||||
|
||||
#define CTX_DATA_END \
|
||||
} \
|
||||
BLI_freelistN(&ctx_data_list); \
|
||||
} \
|
||||
(void)0
|
||||
|
||||
#define CTX_DATA_BEGIN_WITH_ID(C, Type, instance, member, Type_id, instance_id) \
|
||||
CTX_DATA_BEGIN (C, Type, instance, member) \
|
||||
Type_id instance_id = (Type_id)ctx_link->ptr.owner_id;
|
||||
Type_id instance_id = (Type_id)ctx_link.owner_id;
|
||||
|
||||
int ctx_data_list_count(const bContext *C, bool (*func)(const bContext *, ListBase *));
|
||||
int ctx_data_list_count(const bContext *C,
|
||||
bool (*func)(const bContext *, blender::Vector<PointerRNA> *));
|
||||
|
||||
#define CTX_DATA_COUNT(C, member) ctx_data_list_count(C, CTX_data_##member)
|
||||
|
||||
|
@ -377,22 +369,22 @@ void CTX_data_main_set(bContext *C, Main *bmain);
|
|||
void CTX_data_scene_set(bContext *C, Scene *scene);
|
||||
|
||||
/* Only Outliner currently! */
|
||||
bool CTX_data_selected_ids(const bContext *C, ListBase *list);
|
||||
bool CTX_data_selected_ids(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
|
||||
bool CTX_data_selected_editable_objects(const bContext *C, ListBase *list);
|
||||
bool CTX_data_selected_editable_bases(const bContext *C, ListBase *list);
|
||||
bool CTX_data_selected_editable_objects(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
bool CTX_data_selected_editable_bases(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
|
||||
bool CTX_data_editable_objects(const bContext *C, ListBase *list);
|
||||
bool CTX_data_editable_bases(const bContext *C, ListBase *list);
|
||||
bool CTX_data_editable_objects(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
bool CTX_data_editable_bases(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
|
||||
bool CTX_data_selected_objects(const bContext *C, ListBase *list);
|
||||
bool CTX_data_selected_bases(const bContext *C, ListBase *list);
|
||||
bool CTX_data_selected_objects(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
bool CTX_data_selected_bases(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
|
||||
bool CTX_data_visible_objects(const bContext *C, ListBase *list);
|
||||
bool CTX_data_visible_bases(const bContext *C, ListBase *list);
|
||||
bool CTX_data_visible_objects(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
bool CTX_data_visible_bases(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
|
||||
bool CTX_data_selectable_objects(const bContext *C, ListBase *list);
|
||||
bool CTX_data_selectable_bases(const bContext *C, ListBase *list);
|
||||
bool CTX_data_selectable_objects(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
bool CTX_data_selectable_bases(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
|
||||
Object *CTX_data_active_object(const bContext *C);
|
||||
Base *CTX_data_active_base(const bContext *C);
|
||||
|
@ -406,25 +398,26 @@ Mask *CTX_data_edit_mask(const bContext *C);
|
|||
|
||||
CacheFile *CTX_data_edit_cachefile(const bContext *C);
|
||||
|
||||
bool CTX_data_selected_nodes(const bContext *C, ListBase *list);
|
||||
bool CTX_data_selected_nodes(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
|
||||
EditBone *CTX_data_active_bone(const bContext *C);
|
||||
bool CTX_data_selected_bones(const bContext *C, ListBase *list);
|
||||
bool CTX_data_selected_editable_bones(const bContext *C, ListBase *list);
|
||||
bool CTX_data_visible_bones(const bContext *C, ListBase *list);
|
||||
bool CTX_data_editable_bones(const bContext *C, ListBase *list);
|
||||
bool CTX_data_selected_bones(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
bool CTX_data_selected_editable_bones(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
bool CTX_data_visible_bones(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
bool CTX_data_editable_bones(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
|
||||
bPoseChannel *CTX_data_active_pose_bone(const bContext *C);
|
||||
bool CTX_data_selected_pose_bones(const bContext *C, ListBase *list);
|
||||
bool CTX_data_selected_pose_bones_from_active_object(const bContext *C, ListBase *list);
|
||||
bool CTX_data_visible_pose_bones(const bContext *C, ListBase *list);
|
||||
bool CTX_data_selected_pose_bones(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
bool CTX_data_selected_pose_bones_from_active_object(const bContext *C,
|
||||
blender::Vector<PointerRNA> *list);
|
||||
bool CTX_data_visible_pose_bones(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
|
||||
bGPdata *CTX_data_gpencil_data(const bContext *C);
|
||||
bGPDlayer *CTX_data_active_gpencil_layer(const bContext *C);
|
||||
bGPDframe *CTX_data_active_gpencil_frame(const bContext *C);
|
||||
bool CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list);
|
||||
bool CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list);
|
||||
bool CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list);
|
||||
bool CTX_data_visible_gpencil_layers(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
bool CTX_data_editable_gpencil_layers(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
bool CTX_data_editable_gpencil_strokes(const bContext *C, blender::Vector<PointerRNA> *list);
|
||||
|
||||
const AssetLibraryReference *CTX_wm_asset_library_ref(const bContext *C);
|
||||
class blender::asset_system::AssetRepresentation *CTX_wm_asset(const bContext *C);
|
||||
|
|
|
@ -12,14 +12,14 @@
|
|||
#include "BLI_bounds_types.hh"
|
||||
#include "BLI_generic_virtual_array.hh"
|
||||
#include "BLI_implicit_sharing.hh"
|
||||
#include "BLI_index_mask.hh"
|
||||
#include "BLI_index_mask_fwd.hh"
|
||||
#include "BLI_math_matrix_types.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_offset_indices.hh"
|
||||
#include "BLI_shared_cache.hh"
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_vector.hh"
|
||||
#include "BLI_virtual_array.hh"
|
||||
#include "BLI_virtual_array_fwd.hh"
|
||||
|
||||
#include "BKE_attribute_math.hh"
|
||||
#include "BKE_curves.h"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_offset_indices.hh"
|
||||
#include "BLI_virtual_array.hh"
|
||||
#include "BLI_virtual_array_fwd.hh"
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
|
|
|
@ -16,6 +16,7 @@ extern "C" {
|
|||
struct Collection;
|
||||
struct Depsgraph;
|
||||
struct ListBase;
|
||||
struct RNG;
|
||||
struct Object;
|
||||
struct ParticleData;
|
||||
struct ParticleKey;
|
||||
|
@ -78,6 +79,9 @@ typedef struct EffectorCache {
|
|||
|
||||
struct PartDeflect *pd;
|
||||
|
||||
/** Random noise generator for e.g. wind. */
|
||||
struct RNG *rng;
|
||||
|
||||
/* precalculated for guides */
|
||||
struct GuideEffectorData *guide_data;
|
||||
float guide_loc[4], guide_dir[3], guide_radius;
|
||||
|
|
|
@ -1,378 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct BlendDataReader;
|
||||
struct BlendWriter;
|
||||
struct ID;
|
||||
struct IDProperty;
|
||||
struct IDPropertyUIData;
|
||||
struct IDPropertyUIDataEnumItem;
|
||||
|
||||
typedef union IDPropertyTemplate {
|
||||
int i;
|
||||
float f;
|
||||
double d;
|
||||
struct {
|
||||
const char *str;
|
||||
/** String length (including the null byte): `strlen(str) + 1`. */
|
||||
int len;
|
||||
/** #eIDPropertySubType */
|
||||
char subtype;
|
||||
} string;
|
||||
struct ID *id;
|
||||
struct {
|
||||
int len;
|
||||
/** #eIDPropertyType */
|
||||
char type;
|
||||
} array;
|
||||
} IDPropertyTemplate;
|
||||
|
||||
/* ----------- Property Array Type ---------- */
|
||||
|
||||
/**
|
||||
* \note as a start to move away from the stupid #IDP_New function,
|
||||
* this type has its own allocation function.
|
||||
*/
|
||||
struct IDProperty *IDP_NewIDPArray(const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
struct IDProperty *IDP_CopyIDPArray(const struct IDProperty *array,
|
||||
int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
|
||||
/**
|
||||
* Shallow copies item.
|
||||
*/
|
||||
void IDP_SetIndexArray(struct IDProperty *prop, int index, struct IDProperty *item) ATTR_NONNULL();
|
||||
struct IDProperty *IDP_GetIndexArray(struct IDProperty *prop, int index) ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_NONNULL();
|
||||
void IDP_AppendArray(struct IDProperty *prop, struct IDProperty *item);
|
||||
void IDP_ResizeIDPArray(struct IDProperty *prop, int len);
|
||||
|
||||
/* ----------- Numeric Array Type ----------- */
|
||||
|
||||
/**
|
||||
* This function works for strings too!
|
||||
*/
|
||||
void IDP_ResizeArray(struct IDProperty *prop, int newlen);
|
||||
void IDP_FreeArray(struct IDProperty *prop);
|
||||
|
||||
/* ---------- String Type ------------ */
|
||||
/**
|
||||
* \param st: The string to assign.
|
||||
* Doesn't need to be null terminated when clamped by `maxncpy`.
|
||||
* \param name: The property name.
|
||||
* \param maxncpy: The maximum size of the string (including the `\0` terminator).
|
||||
* When zero, this is the equivalent of passing in `strlen(st) + 1`
|
||||
* \return The new string property.
|
||||
*/
|
||||
struct IDProperty *IDP_NewStringMaxSize(const char *st,
|
||||
size_t st_maxncpy,
|
||||
const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(3);
|
||||
struct IDProperty *IDP_NewString(const char *st, const char *name) ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_NONNULL(2);
|
||||
/**
|
||||
* \param st: The string to assign.
|
||||
* Doesn't need to be null terminated when clamped by `maxncpy`.
|
||||
* \param maxncpy: The maximum size of the string (including the `\0` terminator).
|
||||
* When zero, this is the equivalent of passing in `strlen(st) + 1`
|
||||
*/
|
||||
void IDP_AssignStringMaxSize(struct IDProperty *prop, const char *st, size_t st_maxncpy)
|
||||
ATTR_NONNULL();
|
||||
void IDP_AssignString(struct IDProperty *prop, const char *st) ATTR_NONNULL();
|
||||
void IDP_FreeString(struct IDProperty *prop) ATTR_NONNULL();
|
||||
|
||||
/*-------- Enum Type -------*/
|
||||
|
||||
const struct IDPropertyUIDataEnumItem *IDP_EnumItemFind(const struct IDProperty *prop);
|
||||
|
||||
bool IDP_EnumItemsValidate(const struct IDPropertyUIDataEnumItem *items,
|
||||
int items_num,
|
||||
void (*error_fn)(const char *));
|
||||
|
||||
/*-------- ID Type -------*/
|
||||
|
||||
typedef void (*IDPWalkFunc)(void *user_data, struct IDProperty *idp);
|
||||
|
||||
void IDP_AssignID(struct IDProperty *prop, struct ID *id, int flag);
|
||||
|
||||
/*-------- Group Functions -------*/
|
||||
|
||||
/**
|
||||
* Sync values from one group to another when values name and types match,
|
||||
* copy the values, else ignore.
|
||||
*
|
||||
* \note Was used for syncing proxies.
|
||||
*/
|
||||
void IDP_SyncGroupValues(struct IDProperty *dest, const struct IDProperty *src) ATTR_NONNULL();
|
||||
void IDP_SyncGroupTypes(struct IDProperty *dest, const struct IDProperty *src, bool do_arraylen)
|
||||
ATTR_NONNULL();
|
||||
/**
|
||||
* Replaces all properties with the same name in a destination group from a source group.
|
||||
*/
|
||||
void IDP_ReplaceGroupInGroup(struct IDProperty *dest, const struct IDProperty *src) ATTR_NONNULL();
|
||||
void IDP_ReplaceInGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
|
||||
/**
|
||||
* Checks if a property with the same name as prop exists, and if so replaces it.
|
||||
* Use this to preserve order!
|
||||
*/
|
||||
void IDP_ReplaceInGroup_ex(struct IDProperty *group,
|
||||
struct IDProperty *prop,
|
||||
struct IDProperty *prop_exist);
|
||||
/**
|
||||
* If a property is missing in \a dest, add it.
|
||||
* Do it recursively.
|
||||
*/
|
||||
void IDP_MergeGroup(struct IDProperty *dest, const struct IDProperty *src, bool do_overwrite)
|
||||
ATTR_NONNULL();
|
||||
/**
|
||||
* If a property is missing in \a dest, add it.
|
||||
* Do it recursively.
|
||||
*/
|
||||
void IDP_MergeGroup_ex(struct IDProperty *dest,
|
||||
const struct IDProperty *src,
|
||||
bool do_overwrite,
|
||||
int flag) ATTR_NONNULL();
|
||||
/**
|
||||
* This function has a sanity check to make sure ID properties with the same name don't
|
||||
* get added to the group.
|
||||
*
|
||||
* The sanity check just means the property is not added to the group if another property
|
||||
* exists with the same name; the client code using ID properties then needs to detect this
|
||||
* (the function that adds new properties to groups, #IDP_AddToGroup,
|
||||
* returns false if a property can't be added to the group, and true if it can)
|
||||
* and free the property.
|
||||
*/
|
||||
bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
|
||||
/**
|
||||
* This is the same as IDP_AddToGroup, only you pass an item
|
||||
* in the group list to be inserted after.
|
||||
*/
|
||||
bool IDP_InsertToGroup(struct IDProperty *group,
|
||||
struct IDProperty *previous,
|
||||
struct IDProperty *pnew) ATTR_NONNULL(1 /*group*/, 3 /*pnew*/);
|
||||
/**
|
||||
* \note this does not free the property!
|
||||
*
|
||||
* To free the property, you have to do:
|
||||
* #IDP_FreeProperty(prop);
|
||||
*/
|
||||
void IDP_RemoveFromGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
|
||||
/**
|
||||
* Removes the property from the group and frees it.
|
||||
*/
|
||||
void IDP_FreeFromGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
|
||||
|
||||
struct IDProperty *IDP_GetPropertyFromGroup(const struct IDProperty *prop,
|
||||
const char *name) ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_NONNULL();
|
||||
/**
|
||||
* Same as above but ensure type match.
|
||||
*/
|
||||
struct IDProperty *IDP_GetPropertyTypeFromGroup(const struct IDProperty *prop,
|
||||
const char *name,
|
||||
char type) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
|
||||
/*-------- Main Functions --------*/
|
||||
/**
|
||||
* Get the Group property that contains the id properties for ID `id`.
|
||||
*/
|
||||
struct IDProperty *IDP_GetProperties(struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
|
||||
/**
|
||||
* Ensure the Group property that contains the id properties for ID `id` exists & return it.
|
||||
*/
|
||||
struct IDProperty *IDP_EnsureProperties(struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
|
||||
struct IDProperty *IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_NONNULL();
|
||||
struct IDProperty *IDP_CopyProperty_ex(const struct IDProperty *prop,
|
||||
int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
/**
|
||||
* Copy content from source #IDProperty into destination one,
|
||||
* freeing destination property's content first.
|
||||
*/
|
||||
void IDP_CopyPropertyContent(struct IDProperty *dst, const struct IDProperty *src) ATTR_NONNULL();
|
||||
|
||||
/**
|
||||
* \param is_strict: When false treat missing items as a match.
|
||||
*/
|
||||
bool IDP_EqualsProperties_ex(const struct IDProperty *prop1,
|
||||
const struct IDProperty *prop2,
|
||||
bool is_strict) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
bool IDP_EqualsProperties(const struct IDProperty *prop1,
|
||||
const struct IDProperty *prop2) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* Allocate a new ID.
|
||||
*
|
||||
* This function takes three arguments: the ID property type, a union which defines
|
||||
* its initial value, and a name.
|
||||
*
|
||||
* The union is simple to use; see the top of BKE_idprop.h for its definition.
|
||||
* An example of using this function:
|
||||
*
|
||||
* \code{.c}
|
||||
* IDPropertyTemplate val;
|
||||
* IDProperty *group, *idgroup, *color;
|
||||
* group = IDP_New(IDP_GROUP, val, "group1"); // groups don't need a template.
|
||||
*
|
||||
* val.array.len = 4
|
||||
* val.array.type = IDP_FLOAT;
|
||||
* color = IDP_New(IDP_ARRAY, val, "color1");
|
||||
*
|
||||
* idgroup = IDP_EnsureProperties(some_id);
|
||||
* IDP_AddToGroup(idgroup, color);
|
||||
* IDP_AddToGroup(idgroup, group);
|
||||
* \endcode
|
||||
*
|
||||
* Note that you MUST either attach the id property to an id property group with
|
||||
* IDP_AddToGroup or MEM_freeN the property, doing anything else might result in
|
||||
* a memory leak.
|
||||
*/
|
||||
struct IDProperty *IDP_New(char type,
|
||||
const IDPropertyTemplate *val,
|
||||
const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
|
||||
/**
|
||||
* \note This will free allocated data, all child properties of arrays and groups, and unlink IDs!
|
||||
* But it does not free the actual #IDProperty struct itself.
|
||||
*/
|
||||
void IDP_FreePropertyContent_ex(struct IDProperty *prop, bool do_id_user);
|
||||
void IDP_FreePropertyContent(struct IDProperty *prop);
|
||||
void IDP_FreeProperty_ex(struct IDProperty *prop, bool do_id_user);
|
||||
void IDP_FreeProperty(struct IDProperty *prop);
|
||||
|
||||
void IDP_ClearProperty(struct IDProperty *prop);
|
||||
|
||||
void IDP_Reset(struct IDProperty *prop, const struct IDProperty *reference);
|
||||
|
||||
#define IDP_Int(prop) ((prop)->data.val)
|
||||
#define IDP_Bool(prop) ((prop)->data.val)
|
||||
#define IDP_Array(prop) ((prop)->data.pointer)
|
||||
/* C11 const correctness for casts */
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
|
||||
# define IDP_Float(prop) \
|
||||
_Generic((prop), \
|
||||
struct IDProperty *: (*(float *)&(prop)->data.val), \
|
||||
const struct IDProperty *: (*(const float *)&(prop)->data.val))
|
||||
# define IDP_Double(prop) \
|
||||
_Generic((prop), \
|
||||
struct IDProperty *: (*(double *)&(prop)->data.val), \
|
||||
const struct IDProperty *: (*(const double *)&(prop)->data.val))
|
||||
# define IDP_String(prop) \
|
||||
_Generic((prop), \
|
||||
struct IDProperty *: ((char *)(prop)->data.pointer), \
|
||||
const struct IDProperty *: ((const char *)(prop)->data.pointer))
|
||||
# define IDP_IDPArray(prop) \
|
||||
_Generic((prop), \
|
||||
struct IDProperty *: ((struct IDProperty *)(prop)->data.pointer), \
|
||||
const struct IDProperty *: ((const struct IDProperty *)(prop)->data.pointer))
|
||||
# define IDP_Id(prop) \
|
||||
_Generic((prop), \
|
||||
struct IDProperty *: ((ID *)(prop)->data.pointer), \
|
||||
const struct IDProperty *: ((const ID *)(prop)->data.pointer))
|
||||
#else
|
||||
# define IDP_Float(prop) (*(float *)&(prop)->data.val)
|
||||
# define IDP_Double(prop) (*(double *)&(prop)->data.val)
|
||||
# define IDP_String(prop) ((char *)(prop)->data.pointer)
|
||||
# define IDP_IDPArray(prop) ((struct IDProperty *)(prop)->data.pointer)
|
||||
# define IDP_Id(prop) ((ID *)(prop)->data.pointer)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Return an int from an #IDProperty with a compatible type. This should be avoided, but
|
||||
* it's sometimes necessary, for example when legacy files have incorrect property types.
|
||||
*/
|
||||
int IDP_coerce_to_int_or_zero(const struct IDProperty *prop);
|
||||
/**
|
||||
* Return a float from an #IDProperty with a compatible type. This should be avoided, but
|
||||
* it's sometimes necessary, for example when legacy files have incorrect property types.
|
||||
*/
|
||||
float IDP_coerce_to_float_or_zero(const struct IDProperty *prop);
|
||||
/**
|
||||
* Return a double from an #IDProperty with a compatible type. This should be avoided, but
|
||||
* it's sometimes necessary, for example when legacy files have incorrect property types.
|
||||
*/
|
||||
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).
|
||||
*/
|
||||
typedef void (*IDPForeachPropertyCallback)(struct IDProperty *id_property, void *user_data);
|
||||
|
||||
/**
|
||||
* Loop through all ID properties in hierarchy of given \a id_property_root included.
|
||||
*
|
||||
* \note Container types (groups and arrays) are processed after applying the callback on them.
|
||||
*
|
||||
* \param type_filter: If not 0, only apply callback on properties of matching types, see
|
||||
* IDP_TYPE_FILTER_ enum in DNA_ID.h.
|
||||
*/
|
||||
void IDP_foreach_property(struct IDProperty *id_property_root,
|
||||
int type_filter,
|
||||
IDPForeachPropertyCallback callback,
|
||||
void *user_data);
|
||||
|
||||
/* Format IDProperty as strings */
|
||||
char *IDP_reprN(const struct IDProperty *prop, uint *r_len);
|
||||
void IDP_repr_fn(const struct IDProperty *prop,
|
||||
void (*str_append_fn)(void *user_data, const char *str, uint str_len),
|
||||
void *user_data);
|
||||
void IDP_print(const struct IDProperty *prop);
|
||||
|
||||
void IDP_BlendWrite(struct BlendWriter *writer, const struct IDProperty *prop);
|
||||
void IDP_BlendReadData_impl(struct BlendDataReader *reader,
|
||||
struct IDProperty **prop,
|
||||
const char *caller_func_id);
|
||||
#define IDP_BlendDataRead(reader, prop) IDP_BlendReadData_impl(reader, prop, __func__)
|
||||
|
||||
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 sub-types. */
|
||||
IDP_UI_DATA_TYPE_FLOAT = 1,
|
||||
/** IDP_STRING properties. */
|
||||
IDP_UI_DATA_TYPE_STRING = 2,
|
||||
/** IDP_ID. */
|
||||
IDP_UI_DATA_TYPE_ID = 3,
|
||||
/** IDP_BOOLEAN or IDP_ARRAY with subtype IDP_BOOLEAN. */
|
||||
IDP_UI_DATA_TYPE_BOOLEAN = 4,
|
||||
} 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);
|
||||
/**
|
||||
* Free allocated pointers in the UI data that isn't shared with the UI data in the `other`
|
||||
* argument. Useful for returning early on failure when updating UI data in place, or when
|
||||
* replacing a subset of the UI data's allocated pointers.
|
||||
*/
|
||||
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);
|
||||
/**
|
||||
* Convert UI data like default arrays from the old type to the new type as possible.
|
||||
* Takes ownership of the input data; it can return it directly if the types match.
|
||||
*/
|
||||
struct IDPropertyUIData *IDP_TryConvertUIData(struct IDPropertyUIData *src,
|
||||
eIDPropertyUIDataType src_type,
|
||||
eIDPropertyUIDataType dst_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -4,10 +4,362 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BKE_idprop.h"
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "BLI_serialize.hh"
|
||||
#include <memory>
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
struct BlendDataReader;
|
||||
struct BlendWriter;
|
||||
struct ID;
|
||||
struct IDProperty;
|
||||
struct IDPropertyUIData;
|
||||
struct IDPropertyUIDataEnumItem;
|
||||
namespace blender::io::serialize {
|
||||
class ArrayValue;
|
||||
class Value;
|
||||
} // namespace blender::io::serialize
|
||||
|
||||
union IDPropertyTemplate {
|
||||
int i;
|
||||
float f;
|
||||
double d;
|
||||
struct {
|
||||
const char *str;
|
||||
/** String length (including the null byte): `strlen(str) + 1`. */
|
||||
int len;
|
||||
/** #eIDPropertySubType */
|
||||
char subtype;
|
||||
} string;
|
||||
ID *id;
|
||||
struct {
|
||||
int len;
|
||||
/** #eIDPropertyType */
|
||||
char type;
|
||||
} array;
|
||||
};
|
||||
|
||||
/* ----------- Property Array Type ---------- */
|
||||
|
||||
/**
|
||||
* \note as a start to move away from the stupid #IDP_New function,
|
||||
* this type has its own allocation function.
|
||||
*/
|
||||
IDProperty *IDP_NewIDPArray(const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
IDProperty *IDP_CopyIDPArray(const IDProperty *array, int flag) ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_NONNULL();
|
||||
|
||||
/**
|
||||
* Shallow copies item.
|
||||
*/
|
||||
void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item) ATTR_NONNULL();
|
||||
IDProperty *IDP_GetIndexArray(IDProperty *prop, int index) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
void IDP_AppendArray(IDProperty *prop, IDProperty *item);
|
||||
void IDP_ResizeIDPArray(IDProperty *prop, int len);
|
||||
|
||||
/* ----------- Numeric Array Type ----------- */
|
||||
|
||||
/**
|
||||
* This function works for strings too!
|
||||
*/
|
||||
void IDP_ResizeArray(IDProperty *prop, int newlen);
|
||||
void IDP_FreeArray(IDProperty *prop);
|
||||
|
||||
/* ---------- String Type ------------ */
|
||||
/**
|
||||
* \param st: The string to assign.
|
||||
* Doesn't need to be null terminated when clamped by `maxncpy`.
|
||||
* \param name: The property name.
|
||||
* \param maxncpy: The maximum size of the string (including the `\0` terminator).
|
||||
* When zero, this is the equivalent of passing in `strlen(st) + 1`
|
||||
* \return The new string property.
|
||||
*/
|
||||
IDProperty *IDP_NewStringMaxSize(const char *st,
|
||||
size_t st_maxncpy,
|
||||
const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(3);
|
||||
IDProperty *IDP_NewString(const char *st, const char *name) ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_NONNULL(2);
|
||||
/**
|
||||
* \param st: The string to assign.
|
||||
* Doesn't need to be null terminated when clamped by `maxncpy`.
|
||||
* \param maxncpy: The maximum size of the string (including the `\0` terminator).
|
||||
* When zero, this is the equivalent of passing in `strlen(st) + 1`
|
||||
*/
|
||||
void IDP_AssignStringMaxSize(IDProperty *prop, const char *st, size_t st_maxncpy) ATTR_NONNULL();
|
||||
void IDP_AssignString(IDProperty *prop, const char *st) ATTR_NONNULL();
|
||||
void IDP_FreeString(IDProperty *prop) ATTR_NONNULL();
|
||||
|
||||
/*-------- Enum Type -------*/
|
||||
|
||||
const IDPropertyUIDataEnumItem *IDP_EnumItemFind(const IDProperty *prop);
|
||||
|
||||
bool IDP_EnumItemsValidate(const IDPropertyUIDataEnumItem *items,
|
||||
int items_num,
|
||||
void (*error_fn)(const char *));
|
||||
|
||||
/*-------- ID Type -------*/
|
||||
|
||||
using IDPWalkFunc = void (*)(void *user_data, IDProperty *idp);
|
||||
|
||||
void IDP_AssignID(IDProperty *prop, ID *id, int flag);
|
||||
|
||||
/*-------- Group Functions -------*/
|
||||
|
||||
/**
|
||||
* Sync values from one group to another when values name and types match,
|
||||
* copy the values, else ignore.
|
||||
*
|
||||
* \note Was used for syncing proxies.
|
||||
*/
|
||||
void IDP_SyncGroupValues(IDProperty *dest, const IDProperty *src) ATTR_NONNULL();
|
||||
void IDP_SyncGroupTypes(IDProperty *dest, const IDProperty *src, bool do_arraylen) ATTR_NONNULL();
|
||||
/**
|
||||
* Replaces all properties with the same name in a destination group from a source group.
|
||||
*/
|
||||
void IDP_ReplaceGroupInGroup(IDProperty *dest, const IDProperty *src) ATTR_NONNULL();
|
||||
void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL();
|
||||
/**
|
||||
* Checks if a property with the same name as prop exists, and if so replaces it.
|
||||
* Use this to preserve order!
|
||||
*/
|
||||
void IDP_ReplaceInGroup_ex(IDProperty *group, IDProperty *prop, IDProperty *prop_exist);
|
||||
/**
|
||||
* If a property is missing in \a dest, add it.
|
||||
* Do it recursively.
|
||||
*/
|
||||
void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, bool do_overwrite) ATTR_NONNULL();
|
||||
/**
|
||||
* If a property is missing in \a dest, add it.
|
||||
* Do it recursively.
|
||||
*/
|
||||
void IDP_MergeGroup_ex(IDProperty *dest, const IDProperty *src, bool do_overwrite, int flag)
|
||||
ATTR_NONNULL();
|
||||
/**
|
||||
* This function has a sanity check to make sure ID properties with the same name don't
|
||||
* get added to the group.
|
||||
*
|
||||
* The sanity check just means the property is not added to the group if another property
|
||||
* exists with the same name; the client code using ID properties then needs to detect this
|
||||
* (the function that adds new properties to groups, #IDP_AddToGroup,
|
||||
* returns false if a property can't be added to the group, and true if it can)
|
||||
* and free the property.
|
||||
*/
|
||||
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL();
|
||||
/**
|
||||
* This is the same as IDP_AddToGroup, only you pass an item
|
||||
* in the group list to be inserted after.
|
||||
*/
|
||||
bool IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew)
|
||||
ATTR_NONNULL(1 /*group*/, 3 /*pnew*/);
|
||||
/**
|
||||
* \note this does not free the property!
|
||||
*
|
||||
* To free the property, you have to do:
|
||||
* #IDP_FreeProperty(prop);
|
||||
*/
|
||||
void IDP_RemoveFromGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL();
|
||||
/**
|
||||
* Removes the property from the group and frees it.
|
||||
*/
|
||||
void IDP_FreeFromGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL();
|
||||
|
||||
IDProperty *IDP_GetPropertyFromGroup(const IDProperty *prop,
|
||||
const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
/**
|
||||
* Same as above but ensure type match.
|
||||
*/
|
||||
IDProperty *IDP_GetPropertyTypeFromGroup(const IDProperty *prop,
|
||||
const char *name,
|
||||
char type) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
|
||||
/*-------- Main Functions --------*/
|
||||
/**
|
||||
* Get the Group property that contains the id properties for ID `id`.
|
||||
*/
|
||||
IDProperty *IDP_GetProperties(ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
|
||||
/**
|
||||
* Ensure the Group property that contains the id properties for ID `id` exists & return it.
|
||||
*/
|
||||
IDProperty *IDP_EnsureProperties(ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
|
||||
IDProperty *IDP_CopyProperty(const IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
IDProperty *IDP_CopyProperty_ex(const IDProperty *prop, int flag) ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_NONNULL();
|
||||
/**
|
||||
* Copy content from source #IDProperty into destination one,
|
||||
* freeing destination property's content first.
|
||||
*/
|
||||
void IDP_CopyPropertyContent(IDProperty *dst, const IDProperty *src) ATTR_NONNULL();
|
||||
|
||||
/**
|
||||
* \param is_strict: When false treat missing items as a match.
|
||||
*/
|
||||
bool IDP_EqualsProperties_ex(const IDProperty *prop1,
|
||||
const IDProperty *prop2,
|
||||
bool is_strict) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
bool IDP_EqualsProperties(const IDProperty *prop1,
|
||||
const IDProperty *prop2) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* Allocate a new ID.
|
||||
*
|
||||
* This function takes three arguments: the ID property type, a union which defines
|
||||
* its initial value, and a name.
|
||||
*
|
||||
* The union is simple to use; see the top of BKE_idprop.h for its definition.
|
||||
* An example of using this function:
|
||||
*
|
||||
* \code{.c}
|
||||
* IDPropertyTemplate val;
|
||||
* IDProperty *group, *idgroup, *color;
|
||||
* group = IDP_New(IDP_GROUP, val, "group1"); // groups don't need a template.
|
||||
*
|
||||
* val.array.len = 4
|
||||
* val.array.type = IDP_FLOAT;
|
||||
* color = IDP_New(IDP_ARRAY, val, "color1");
|
||||
*
|
||||
* idgroup = IDP_EnsureProperties(some_id);
|
||||
* IDP_AddToGroup(idgroup, color);
|
||||
* IDP_AddToGroup(idgroup, group);
|
||||
* \endcode
|
||||
*
|
||||
* Note that you MUST either attach the id property to an id property group with
|
||||
* IDP_AddToGroup or MEM_freeN the property, doing anything else might result in
|
||||
* a memory leak.
|
||||
*/
|
||||
IDProperty *IDP_New(char type,
|
||||
const IDPropertyTemplate *val,
|
||||
const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
|
||||
/**
|
||||
* \note This will free allocated data, all child properties of arrays and groups, and unlink IDs!
|
||||
* But it does not free the actual #IDProperty struct itself.
|
||||
*/
|
||||
void IDP_FreePropertyContent_ex(IDProperty *prop, bool do_id_user);
|
||||
void IDP_FreePropertyContent(IDProperty *prop);
|
||||
void IDP_FreeProperty_ex(IDProperty *prop, bool do_id_user);
|
||||
void IDP_FreeProperty(IDProperty *prop);
|
||||
|
||||
void IDP_ClearProperty(IDProperty *prop);
|
||||
|
||||
void IDP_Reset(IDProperty *prop, const IDProperty *reference);
|
||||
|
||||
#define IDP_Int(prop) ((prop)->data.val)
|
||||
#define IDP_Bool(prop) ((prop)->data.val)
|
||||
#define IDP_Array(prop) ((prop)->data.pointer)
|
||||
/* C11 const correctness for casts */
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
|
||||
# define IDP_Float(prop) \
|
||||
_Generic((prop), \
|
||||
IDProperty *: (*(float *)&(prop)->data.val), \
|
||||
const IDProperty *: (*(const float *)&(prop)->data.val))
|
||||
# define IDP_Double(prop) \
|
||||
_Generic((prop), \
|
||||
IDProperty *: (*(double *)&(prop)->data.val), \
|
||||
const IDProperty *: (*(const double *)&(prop)->data.val))
|
||||
# define IDP_String(prop) \
|
||||
_Generic((prop), \
|
||||
IDProperty *: ((char *)(prop)->data.pointer), \
|
||||
const IDProperty *: ((const char *)(prop)->data.pointer))
|
||||
# define IDP_IDPArray(prop) \
|
||||
_Generic((prop), \
|
||||
IDProperty *: ((IDProperty *)(prop)->data.pointer), \
|
||||
const IDProperty *: ((const IDProperty *)(prop)->data.pointer))
|
||||
# define IDP_Id(prop) \
|
||||
_Generic((prop), \
|
||||
IDProperty *: ((ID *)(prop)->data.pointer), \
|
||||
const IDProperty *: ((const ID *)(prop)->data.pointer))
|
||||
#else
|
||||
# define IDP_Float(prop) (*(float *)&(prop)->data.val)
|
||||
# define IDP_Double(prop) (*(double *)&(prop)->data.val)
|
||||
# define IDP_String(prop) ((char *)(prop)->data.pointer)
|
||||
# define IDP_IDPArray(prop) ((IDProperty *)(prop)->data.pointer)
|
||||
# define IDP_Id(prop) ((ID *)(prop)->data.pointer)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Return an int from an #IDProperty with a compatible type. This should be avoided, but
|
||||
* it's sometimes necessary, for example when legacy files have incorrect property types.
|
||||
*/
|
||||
int IDP_coerce_to_int_or_zero(const IDProperty *prop);
|
||||
/**
|
||||
* Return a float from an #IDProperty with a compatible type. This should be avoided, but
|
||||
* it's sometimes necessary, for example when legacy files have incorrect property types.
|
||||
*/
|
||||
float IDP_coerce_to_float_or_zero(const IDProperty *prop);
|
||||
/**
|
||||
* Return a double from an #IDProperty with a compatible type. This should be avoided, but
|
||||
* it's sometimes necessary, for example when legacy files have incorrect property types.
|
||||
*/
|
||||
double IDP_coerce_to_double_or_zero(const IDProperty *prop);
|
||||
|
||||
/**
|
||||
* Loop through all ID properties in hierarchy of given \a id_property_root included.
|
||||
*
|
||||
* \note Container types (groups and arrays) are processed after applying the callback on them.
|
||||
*
|
||||
* \param type_filter: If not 0, only apply callback on properties of matching types, see
|
||||
* IDP_TYPE_FILTER_ enum in DNA_ID.h.
|
||||
*/
|
||||
void IDP_foreach_property(IDProperty *id_property_root,
|
||||
int type_filter,
|
||||
blender::FunctionRef<void(IDProperty *id_property)> callback);
|
||||
|
||||
/* Format IDProperty as strings */
|
||||
char *IDP_reprN(const IDProperty *prop, uint *r_len);
|
||||
void IDP_repr_fn(const IDProperty *prop,
|
||||
void (*str_append_fn)(void *user_data, const char *str, uint str_len),
|
||||
void *user_data);
|
||||
void IDP_print(const IDProperty *prop);
|
||||
|
||||
void IDP_BlendWrite(BlendWriter *writer, const IDProperty *prop);
|
||||
void IDP_BlendReadData_impl(BlendDataReader *reader,
|
||||
IDProperty **prop,
|
||||
const char *caller_func_id);
|
||||
#define IDP_BlendDataRead(reader, prop) IDP_BlendReadData_impl(reader, prop, __func__)
|
||||
|
||||
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 sub-types. */
|
||||
IDP_UI_DATA_TYPE_FLOAT = 1,
|
||||
/** IDP_STRING properties. */
|
||||
IDP_UI_DATA_TYPE_STRING = 2,
|
||||
/** IDP_ID. */
|
||||
IDP_UI_DATA_TYPE_ID = 3,
|
||||
/** IDP_BOOLEAN or IDP_ARRAY with subtype IDP_BOOLEAN. */
|
||||
IDP_UI_DATA_TYPE_BOOLEAN = 4,
|
||||
};
|
||||
|
||||
bool IDP_ui_data_supported(const IDProperty *prop);
|
||||
eIDPropertyUIDataType IDP_ui_data_type(const IDProperty *prop);
|
||||
void IDP_ui_data_free(IDProperty *prop);
|
||||
/**
|
||||
* Free allocated pointers in the UI data that isn't shared with the UI data in the `other`
|
||||
* argument. Useful for returning early on failure when updating UI data in place, or when
|
||||
* replacing a subset of the UI data's allocated pointers.
|
||||
*/
|
||||
void IDP_ui_data_free_unique_contents(IDPropertyUIData *ui_data,
|
||||
eIDPropertyUIDataType type,
|
||||
const IDPropertyUIData *other);
|
||||
IDPropertyUIData *IDP_ui_data_ensure(IDProperty *prop);
|
||||
IDPropertyUIData *IDP_ui_data_copy(const IDProperty *prop);
|
||||
/**
|
||||
* Convert UI data like default arrays from the old type to the new type as possible.
|
||||
* Takes ownership of the input data; it can return it directly if the types match.
|
||||
*/
|
||||
IDPropertyUIData *IDP_TryConvertUIData(IDPropertyUIData *src,
|
||||
eIDPropertyUIDataType src_type,
|
||||
eIDPropertyUIDataType dst_type);
|
||||
|
||||
namespace blender::bke::idprop {
|
||||
|
||||
|
@ -18,7 +370,7 @@ namespace blender::bke::idprop {
|
|||
*
|
||||
* UI data such as max/min will not be serialized.
|
||||
*/
|
||||
std::unique_ptr<io::serialize::ArrayValue> convert_to_serialize_values(
|
||||
std::unique_ptr<blender::io::serialize::ArrayValue> convert_to_serialize_values(
|
||||
const IDProperty *properties);
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,31 +33,31 @@ struct Object;
|
|||
struct Scene;
|
||||
|
||||
/* TODO: Move to `BKE_mesh_types.hh` when possible. */
|
||||
typedef enum eMeshBatchDirtyMode {
|
||||
enum eMeshBatchDirtyMode {
|
||||
BKE_MESH_BATCH_DIRTY_ALL = 0,
|
||||
BKE_MESH_BATCH_DIRTY_SELECT,
|
||||
BKE_MESH_BATCH_DIRTY_SELECT_PAINT,
|
||||
BKE_MESH_BATCH_DIRTY_SHADING,
|
||||
BKE_MESH_BATCH_DIRTY_UVEDIT_ALL,
|
||||
BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT,
|
||||
} eMeshBatchDirtyMode;
|
||||
};
|
||||
|
||||
/* `mesh.cc` */
|
||||
|
||||
struct BMesh *BKE_mesh_to_bmesh_ex(const struct Mesh *mesh,
|
||||
const struct BMeshCreateParams *create_params,
|
||||
const struct BMeshFromMeshParams *convert_params);
|
||||
struct BMesh *BKE_mesh_to_bmesh(struct Mesh *mesh,
|
||||
struct Object *ob,
|
||||
bool add_key_index,
|
||||
const struct BMeshCreateParams *params);
|
||||
BMesh *BKE_mesh_to_bmesh_ex(const Mesh *mesh,
|
||||
const BMeshCreateParams *create_params,
|
||||
const BMeshFromMeshParams *convert_params);
|
||||
BMesh *BKE_mesh_to_bmesh(Mesh *mesh,
|
||||
Object *ob,
|
||||
bool add_key_index,
|
||||
const BMeshCreateParams *params);
|
||||
|
||||
struct Mesh *BKE_mesh_from_bmesh_nomain(struct BMesh *bm,
|
||||
const struct BMeshToMeshParams *params,
|
||||
const struct Mesh *me_settings);
|
||||
struct Mesh *BKE_mesh_from_bmesh_for_eval_nomain(struct BMesh *bm,
|
||||
const struct CustomData_MeshMasks *cd_mask_extra,
|
||||
const struct Mesh *me_settings);
|
||||
Mesh *BKE_mesh_from_bmesh_nomain(BMesh *bm,
|
||||
const BMeshToMeshParams *params,
|
||||
const Mesh *me_settings);
|
||||
Mesh *BKE_mesh_from_bmesh_for_eval_nomain(BMesh *bm,
|
||||
const CustomData_MeshMasks *cd_mask_extra,
|
||||
const Mesh *me_settings);
|
||||
|
||||
/**
|
||||
* Add original index (#CD_ORIGINDEX) layers if they don't already exist. This is meant to be used
|
||||
|
@ -66,34 +66,34 @@ struct Mesh *BKE_mesh_from_bmesh_for_eval_nomain(struct BMesh *bm,
|
|||
*
|
||||
* The mesh is expected to of a `ME_WRAPPER_TYPE_MDATA` wrapper type. This is asserted.
|
||||
*/
|
||||
void BKE_mesh_ensure_default_orig_index_customdata(struct Mesh *mesh);
|
||||
void BKE_mesh_ensure_default_orig_index_customdata(Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Same as #BKE_mesh_ensure_default_orig_index_customdata but does not perform any checks: they
|
||||
* must be done by the caller.
|
||||
*/
|
||||
void BKE_mesh_ensure_default_orig_index_customdata_no_check(struct Mesh *mesh);
|
||||
void BKE_mesh_ensure_default_orig_index_customdata_no_check(Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Free (or release) any data used by this mesh (does not free the mesh itself).
|
||||
* Only use for undo, in most cases `BKE_id_free(nullptr, me)` should be used.
|
||||
*/
|
||||
void BKE_mesh_free_data_for_undo(struct Mesh *mesh);
|
||||
void BKE_mesh_free_data_for_undo(Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Remove all geometry and derived data like caches from the mesh.
|
||||
*/
|
||||
void BKE_mesh_clear_geometry(struct Mesh *mesh);
|
||||
void BKE_mesh_clear_geometry(Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Same as #BKE_mesh_clear_geometry, but also clears attribute meta-data like active attribute
|
||||
* names and vertex group names. Used when the geometry is *entirely* replaced.
|
||||
*/
|
||||
void BKE_mesh_clear_geometry_and_metadata(struct Mesh *mesh);
|
||||
void BKE_mesh_clear_geometry_and_metadata(Mesh *mesh);
|
||||
|
||||
struct Mesh *BKE_mesh_add(struct Main *bmain, const char *name);
|
||||
Mesh *BKE_mesh_add(Main *bmain, const char *name);
|
||||
|
||||
void BKE_mesh_free_editmesh(struct Mesh *mesh);
|
||||
void BKE_mesh_free_editmesh(Mesh *mesh);
|
||||
|
||||
/**
|
||||
* A version of #BKE_mesh_copy_parameters that is intended for evaluated output
|
||||
|
@ -101,82 +101,68 @@ void BKE_mesh_free_editmesh(struct Mesh *mesh);
|
|||
*
|
||||
* \warning User counts are not handled for ID's.
|
||||
*/
|
||||
void BKE_mesh_copy_parameters_for_eval(struct Mesh *me_dst, const struct Mesh *me_src);
|
||||
void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src);
|
||||
/**
|
||||
* Copy user editable settings that we want to preserve
|
||||
* when a new mesh is based on an existing mesh.
|
||||
*/
|
||||
void BKE_mesh_copy_parameters(struct Mesh *me_dst, const struct Mesh *me_src);
|
||||
void BKE_mesh_ensure_skin_customdata(struct Mesh *mesh);
|
||||
void BKE_mesh_copy_parameters(Mesh *me_dst, const Mesh *me_src);
|
||||
void BKE_mesh_ensure_skin_customdata(Mesh *mesh);
|
||||
|
||||
/** Add face offsets to describe faces to a new mesh. */
|
||||
void BKE_mesh_face_offsets_ensure_alloc(struct Mesh *mesh);
|
||||
void BKE_mesh_face_offsets_ensure_alloc(Mesh *mesh);
|
||||
|
||||
struct Mesh *BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num);
|
||||
struct Mesh *BKE_mesh_new_nomain_from_template(
|
||||
const struct Mesh *me_src, int verts_num, int edges_num, int faces_num, int corners_num);
|
||||
struct Mesh *BKE_mesh_new_nomain_from_template_ex(const struct Mesh *me_src,
|
||||
int verts_num,
|
||||
int edges_num,
|
||||
int tessface_num,
|
||||
int faces_num,
|
||||
int corners_num,
|
||||
struct CustomData_MeshMasks mask);
|
||||
Mesh *BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num);
|
||||
Mesh *BKE_mesh_new_nomain_from_template(
|
||||
const Mesh *me_src, int verts_num, int edges_num, int faces_num, int corners_num);
|
||||
Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
|
||||
int verts_num,
|
||||
int edges_num,
|
||||
int tessface_num,
|
||||
int faces_num,
|
||||
int corners_num,
|
||||
CustomData_MeshMasks mask);
|
||||
|
||||
void BKE_mesh_eval_delete(struct Mesh *mesh_eval);
|
||||
void BKE_mesh_eval_delete(Mesh *mesh_eval);
|
||||
|
||||
/**
|
||||
* Performs copy for use during evaluation,
|
||||
* optional referencing original arrays to reduce memory.
|
||||
*/
|
||||
struct Mesh *BKE_mesh_copy_for_eval(const struct Mesh *source);
|
||||
Mesh *BKE_mesh_copy_for_eval(const Mesh *source);
|
||||
|
||||
/**
|
||||
* These functions construct a new Mesh,
|
||||
* contrary to #BKE_mesh_to_curve_nurblist which modifies ob itself.
|
||||
*/
|
||||
struct Mesh *BKE_mesh_new_nomain_from_curve(const struct Object *ob);
|
||||
struct Mesh *BKE_mesh_new_nomain_from_curve_displist(const struct Object *ob,
|
||||
const struct ListBase *dispbase);
|
||||
Mesh *BKE_mesh_new_nomain_from_curve(const Object *ob);
|
||||
Mesh *BKE_mesh_new_nomain_from_curve_displist(const Object *ob, const ListBase *dispbase);
|
||||
|
||||
bool BKE_mesh_attribute_required(const char *name);
|
||||
|
||||
float (*BKE_mesh_orco_verts_get(struct Object *ob))[3];
|
||||
void BKE_mesh_orco_verts_transform(struct Mesh *mesh, float (*orco)[3], int totvert, bool invert);
|
||||
float (*BKE_mesh_orco_verts_get(const Object *ob))[3];
|
||||
void BKE_mesh_orco_verts_transform(Mesh *mesh, float (*orco)[3], int totvert, bool invert);
|
||||
|
||||
/**
|
||||
* Add a #CD_ORCO layer to the Mesh if there is none already.
|
||||
*/
|
||||
void BKE_mesh_orco_ensure(struct Object *ob, struct Mesh *mesh);
|
||||
void BKE_mesh_orco_ensure(Object *ob, Mesh *mesh);
|
||||
|
||||
struct Mesh *BKE_mesh_from_object(struct Object *ob);
|
||||
void BKE_mesh_assign_object(struct Main *bmain, struct Object *ob, struct Mesh *mesh);
|
||||
void BKE_mesh_to_curve_nurblist(const struct Mesh *mesh,
|
||||
struct ListBase *nurblist,
|
||||
int edge_users_test);
|
||||
void BKE_mesh_to_curve(struct Main *bmain,
|
||||
struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Object *ob);
|
||||
void BKE_mesh_to_pointcloud(struct Main *bmain,
|
||||
struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Object *ob);
|
||||
void BKE_pointcloud_to_mesh(struct Main *bmain,
|
||||
struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Object *ob);
|
||||
void BKE_mesh_material_index_remove(struct Mesh *mesh, short index);
|
||||
bool BKE_mesh_material_index_used(struct Mesh *mesh, short index);
|
||||
void BKE_mesh_material_index_clear(struct Mesh *mesh);
|
||||
void BKE_mesh_material_remap(struct Mesh *mesh, const unsigned int *remap, unsigned int remap_len);
|
||||
Mesh *BKE_mesh_from_object(Object *ob);
|
||||
void BKE_mesh_assign_object(Main *bmain, Object *ob, Mesh *mesh);
|
||||
void BKE_mesh_to_curve_nurblist(const Mesh *mesh, ListBase *nurblist, int edge_users_test);
|
||||
void BKE_mesh_to_curve(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob);
|
||||
void BKE_mesh_to_pointcloud(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob);
|
||||
void BKE_pointcloud_to_mesh(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob);
|
||||
void BKE_mesh_material_index_remove(Mesh *mesh, short index);
|
||||
bool BKE_mesh_material_index_used(Mesh *mesh, short index);
|
||||
void BKE_mesh_material_index_clear(Mesh *mesh);
|
||||
void BKE_mesh_material_remap(Mesh *mesh, const unsigned int *remap, unsigned int remap_len);
|
||||
|
||||
void BKE_mesh_texspace_calc(struct Mesh *mesh);
|
||||
void BKE_mesh_texspace_ensure(struct Mesh *mesh);
|
||||
void BKE_mesh_texspace_get(struct Mesh *mesh,
|
||||
float r_texspace_location[3],
|
||||
float r_texspace_size[3]);
|
||||
void BKE_mesh_texspace_get_reference(struct Mesh *mesh,
|
||||
void BKE_mesh_texspace_calc(Mesh *mesh);
|
||||
void BKE_mesh_texspace_ensure(Mesh *mesh);
|
||||
void BKE_mesh_texspace_get(Mesh *mesh, float r_texspace_location[3], float r_texspace_size[3]);
|
||||
void BKE_mesh_texspace_get_reference(Mesh *mesh,
|
||||
char **r_texspace_flag,
|
||||
float **r_texspace_location,
|
||||
float **r_texspace_size);
|
||||
|
@ -191,62 +177,62 @@ void BKE_mesh_texspace_get_reference(struct Mesh *mesh,
|
|||
* \note Dependency graph argument is required when preserve_all_data_layers is true, and is
|
||||
* ignored otherwise.
|
||||
*/
|
||||
struct Mesh *BKE_mesh_new_from_object(struct Depsgraph *depsgraph,
|
||||
struct Object *object,
|
||||
bool preserve_all_data_layers,
|
||||
bool preserve_origindex);
|
||||
Mesh *BKE_mesh_new_from_object(Depsgraph *depsgraph,
|
||||
Object *object,
|
||||
bool preserve_all_data_layers,
|
||||
bool preserve_origindex);
|
||||
|
||||
/**
|
||||
* This is a version of BKE_mesh_new_from_object() which stores mesh in the given main database.
|
||||
* However, that function enforces object type to be a geometry one, and ensures a mesh is always
|
||||
* generated, be it empty.
|
||||
*/
|
||||
struct Mesh *BKE_mesh_new_from_object_to_bmain(struct Main *bmain,
|
||||
struct Depsgraph *depsgraph,
|
||||
struct Object *object,
|
||||
bool preserve_all_data_layers);
|
||||
Mesh *BKE_mesh_new_from_object_to_bmain(Main *bmain,
|
||||
Depsgraph *depsgraph,
|
||||
Object *object,
|
||||
bool preserve_all_data_layers);
|
||||
|
||||
/**
|
||||
* Move data from a mesh outside of the main data-base into a mesh in the data-base.
|
||||
* Takes ownership of the source mesh.
|
||||
*/
|
||||
void BKE_mesh_nomain_to_mesh(struct Mesh *mesh_src, struct Mesh *mesh_dst, struct Object *ob);
|
||||
void BKE_mesh_nomain_to_meshkey(struct Mesh *mesh_src, struct Mesh *mesh_dst, struct KeyBlock *kb);
|
||||
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob);
|
||||
void BKE_mesh_nomain_to_meshkey(Mesh *mesh_src, Mesh *mesh_dst, KeyBlock *kb);
|
||||
|
||||
/* vertex level transformations & checks (no derived mesh) */
|
||||
|
||||
/* basic vertex data functions */
|
||||
void BKE_mesh_transform(struct Mesh *mesh, const float mat[4][4], bool do_keys);
|
||||
void BKE_mesh_translate(struct Mesh *mesh, const float offset[3], bool do_keys);
|
||||
void BKE_mesh_transform(Mesh *mesh, const float mat[4][4], bool do_keys);
|
||||
void BKE_mesh_translate(Mesh *mesh, const float offset[3], bool do_keys);
|
||||
|
||||
void BKE_mesh_tessface_clear(struct Mesh *mesh);
|
||||
void BKE_mesh_tessface_clear(Mesh *mesh);
|
||||
|
||||
void BKE_mesh_mselect_clear(struct Mesh *mesh);
|
||||
void BKE_mesh_mselect_validate(struct Mesh *mesh);
|
||||
void BKE_mesh_mselect_clear(Mesh *mesh);
|
||||
void BKE_mesh_mselect_validate(Mesh *mesh);
|
||||
/**
|
||||
* \return the index within `me->mselect`, or -1
|
||||
*/
|
||||
int BKE_mesh_mselect_find(struct Mesh *mesh, int index, int type);
|
||||
int BKE_mesh_mselect_find(Mesh *mesh, int index, int type);
|
||||
/**
|
||||
* \return The index of the active element.
|
||||
*/
|
||||
int BKE_mesh_mselect_active_get(struct Mesh *mesh, int type);
|
||||
void BKE_mesh_mselect_active_set(struct Mesh *mesh, int index, int type);
|
||||
int BKE_mesh_mselect_active_get(Mesh *mesh, int type);
|
||||
void BKE_mesh_mselect_active_set(Mesh *mesh, int index, int type);
|
||||
|
||||
void BKE_mesh_count_selected_items(const struct Mesh *mesh, int r_count[3]);
|
||||
void BKE_mesh_count_selected_items(const Mesh *mesh, int r_count[3]);
|
||||
|
||||
/* *** mesh_normals.cc *** */
|
||||
|
||||
/** Return true if the mesh vertex normals either are not stored or are dirty. */
|
||||
bool BKE_mesh_vert_normals_are_dirty(const struct Mesh *mesh);
|
||||
bool BKE_mesh_vert_normals_are_dirty(const Mesh *mesh);
|
||||
|
||||
/** Return true if the mesh face normals either are not stored or are dirty. */
|
||||
bool BKE_mesh_face_normals_are_dirty(const struct Mesh *mesh);
|
||||
bool BKE_mesh_face_normals_are_dirty(const Mesh *mesh);
|
||||
|
||||
/**
|
||||
* References a contiguous loop-fan with normal offset vars.
|
||||
*/
|
||||
typedef struct MLoopNorSpace {
|
||||
struct MLoopNorSpace {
|
||||
/** Automatically computed loop normal. */
|
||||
float vec_lnor[3];
|
||||
/** Reference vector, orthogonal to vec_lnor. */
|
||||
|
@ -263,7 +249,7 @@ typedef struct MLoopNorSpace {
|
|||
* - BMLoop pointers. */
|
||||
struct LinkNode *loops;
|
||||
char flags;
|
||||
} MLoopNorSpace;
|
||||
};
|
||||
/**
|
||||
* MLoopNorSpace.flags
|
||||
*/
|
||||
|
@ -274,14 +260,14 @@ enum {
|
|||
/**
|
||||
* Collection of #MLoopNorSpace basic storage & pre-allocation.
|
||||
*/
|
||||
typedef struct MLoopNorSpaceArray {
|
||||
struct MLoopNorSpaceArray {
|
||||
MLoopNorSpace **lspacearr; /* Face corner aligned array */
|
||||
struct LinkNode
|
||||
*loops_pool; /* Allocated once, avoids to call BLI_linklist_prepend_arena() for each loop! */
|
||||
char data_type; /* Whether we store loop indices, or pointers to BMLoop. */
|
||||
int spaces_num; /* Number of clnors spaces defined in this array. */
|
||||
struct MemArena *mem;
|
||||
} MLoopNorSpaceArray;
|
||||
};
|
||||
/**
|
||||
* MLoopNorSpaceArray.data_type
|
||||
*/
|
||||
|
@ -360,7 +346,7 @@ void BKE_mesh_normals_loop_to_vertex(int numVerts,
|
|||
/**
|
||||
* High-level custom normals functions.
|
||||
*/
|
||||
bool BKE_mesh_has_custom_loop_normals(struct Mesh *mesh);
|
||||
bool BKE_mesh_has_custom_loop_normals(Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Higher level functions hiding most of the code needed around call to
|
||||
|
@ -369,7 +355,7 @@ bool BKE_mesh_has_custom_loop_normals(struct Mesh *mesh);
|
|||
* \param r_custom_loop_normals: is not const, since code will replace zero_v3 normals there
|
||||
* with automatically computed vectors.
|
||||
*/
|
||||
void BKE_mesh_set_custom_normals(struct Mesh *mesh, float (*r_custom_loop_normals)[3]);
|
||||
void BKE_mesh_set_custom_normals(Mesh *mesh, float (*r_custom_loop_normals)[3]);
|
||||
/**
|
||||
* Higher level functions hiding most of the code needed around call to
|
||||
* #normals_corner_custom_set_from_verts().
|
||||
|
@ -377,24 +363,24 @@ void BKE_mesh_set_custom_normals(struct Mesh *mesh, float (*r_custom_loop_normal
|
|||
* \param r_custom_vert_normals: is not const, since code will replace zero_v3 normals there
|
||||
* with automatically computed vectors.
|
||||
*/
|
||||
void BKE_mesh_set_custom_normals_from_verts(struct Mesh *mesh, float (*r_custom_vert_normals)[3]);
|
||||
void BKE_mesh_set_custom_normals_from_verts(Mesh *mesh, float (*r_custom_vert_normals)[3]);
|
||||
|
||||
/* *** mesh_evaluate.cc *** */
|
||||
|
||||
float BKE_mesh_calc_area(const struct Mesh *mesh);
|
||||
float BKE_mesh_calc_area(const Mesh *mesh);
|
||||
|
||||
bool BKE_mesh_center_median(const struct Mesh *mesh, float r_cent[3]);
|
||||
bool BKE_mesh_center_median(const Mesh *mesh, float r_cent[3]);
|
||||
/**
|
||||
* Calculate the center from faces,
|
||||
* use when we want to ignore vertex locations that don't have connected faces.
|
||||
*/
|
||||
bool BKE_mesh_center_median_from_faces(const struct Mesh *mesh, float r_cent[3]);
|
||||
bool BKE_mesh_center_of_surface(const struct Mesh *mesh, float r_cent[3]);
|
||||
bool BKE_mesh_center_median_from_faces(const Mesh *mesh, float r_cent[3]);
|
||||
bool BKE_mesh_center_of_surface(const Mesh *mesh, float r_cent[3]);
|
||||
/**
|
||||
* \note Mesh must be manifold with consistent face-winding,
|
||||
* see #mesh_calc_face_volume_centroid for details.
|
||||
*/
|
||||
bool BKE_mesh_center_of_volume(const struct Mesh *mesh, float r_cent[3]);
|
||||
bool BKE_mesh_center_of_volume(const Mesh *mesh, float r_cent[3]);
|
||||
|
||||
/**
|
||||
* Calculate the volume and center.
|
||||
|
@ -414,7 +400,7 @@ void BKE_mesh_calc_volume(const float (*vert_positions)[3],
|
|||
* Flip a single corner's #MDisps structure,
|
||||
* low level function to be called from face-flipping code which re-arranged the mdisps themselves.
|
||||
*/
|
||||
void BKE_mesh_mdisp_flip(struct MDisps *md, bool use_loop_mdisp_flip);
|
||||
void BKE_mesh_mdisp_flip(MDisps *md, bool use_loop_mdisp_flip);
|
||||
|
||||
/**
|
||||
* Account for custom-data such as UVs becoming detached because of imprecision
|
||||
|
@ -422,7 +408,7 @@ void BKE_mesh_mdisp_flip(struct MDisps *md, bool use_loop_mdisp_flip);
|
|||
* Without running this operation subdivision surface can cause UVs to be disconnected,
|
||||
* see: #81065.
|
||||
*/
|
||||
void BKE_mesh_merge_customdata_for_apply_modifier(struct Mesh *mesh);
|
||||
void BKE_mesh_merge_customdata_for_apply_modifier(Mesh *mesh);
|
||||
|
||||
/* Flush flags. */
|
||||
|
||||
|
@ -456,80 +442,75 @@ void BKE_mesh_calc_relative_deform(const int *face_offsets,
|
|||
*
|
||||
* \returns true if a change is made.
|
||||
*/
|
||||
bool BKE_mesh_validate(struct Mesh *mesh, bool do_verbose, bool cddata_check_mask);
|
||||
bool BKE_mesh_validate(Mesh *mesh, bool do_verbose, bool cddata_check_mask);
|
||||
/**
|
||||
* Checks if a Mesh is valid without any modification. This is always verbose.
|
||||
* \returns True if the mesh is valid.
|
||||
*/
|
||||
bool BKE_mesh_is_valid(struct Mesh *mesh);
|
||||
bool BKE_mesh_is_valid(Mesh *mesh);
|
||||
/**
|
||||
* Check all material indices of faces are valid, invalid ones are set to 0.
|
||||
* \returns True if the material indices are valid.
|
||||
*/
|
||||
bool BKE_mesh_validate_material_indices(struct Mesh *mesh);
|
||||
|
||||
#ifdef __cplusplus
|
||||
bool BKE_mesh_validate_material_indices(Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Validate the mesh, \a do_fixes requires \a mesh to be non-null.
|
||||
*
|
||||
* \return false if no changes needed to be made.
|
||||
*/
|
||||
bool BKE_mesh_validate_arrays(struct Mesh *mesh,
|
||||
bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
float (*vert_positions)[3],
|
||||
unsigned int verts_num,
|
||||
blender::int2 *edges,
|
||||
unsigned int edges_num,
|
||||
struct MFace *legacy_faces,
|
||||
MFace *legacy_faces,
|
||||
unsigned int legacy_faces_num,
|
||||
int *corner_verts,
|
||||
int *corner_edges,
|
||||
unsigned int corners_num,
|
||||
const int *face_offsets,
|
||||
unsigned int faces_num,
|
||||
struct MDeformVert *dverts, /* assume totvert length */
|
||||
MDeformVert *dverts, /* assume totvert length */
|
||||
bool do_verbose,
|
||||
bool do_fixes,
|
||||
bool *r_change);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \returns is_valid.
|
||||
*/
|
||||
bool BKE_mesh_validate_all_customdata(struct CustomData *vert_data,
|
||||
bool BKE_mesh_validate_all_customdata(CustomData *vert_data,
|
||||
uint verts_num,
|
||||
struct CustomData *edge_data,
|
||||
CustomData *edge_data,
|
||||
uint edges_num,
|
||||
struct CustomData *corner_data,
|
||||
CustomData *corner_data,
|
||||
uint corners_num,
|
||||
struct CustomData *face_data,
|
||||
CustomData *face_data,
|
||||
uint faces_num,
|
||||
bool check_meshmask,
|
||||
bool do_verbose,
|
||||
bool do_fixes,
|
||||
bool *r_change);
|
||||
|
||||
void BKE_mesh_strip_loose_faces(struct Mesh *mesh);
|
||||
void BKE_mesh_strip_loose_faces(Mesh *mesh);
|
||||
|
||||
/* In DerivedMesh.cc */
|
||||
void BKE_mesh_wrapper_deferred_finalize_mdata(struct Mesh *mesh_eval);
|
||||
void BKE_mesh_wrapper_deferred_finalize_mdata(Mesh *mesh_eval);
|
||||
|
||||
/* **** Depsgraph evaluation **** */
|
||||
|
||||
void BKE_mesh_eval_geometry(struct Depsgraph *depsgraph, struct Mesh *mesh);
|
||||
void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh);
|
||||
|
||||
/* Draw Cache */
|
||||
void BKE_mesh_batch_cache_dirty_tag(struct Mesh *mesh, eMeshBatchDirtyMode mode);
|
||||
void BKE_mesh_batch_cache_dirty_tag(Mesh *mesh, eMeshBatchDirtyMode mode);
|
||||
void BKE_mesh_batch_cache_free(void *batch_cache);
|
||||
|
||||
extern void (*BKE_mesh_batch_cache_dirty_tag_cb)(struct Mesh *mesh, eMeshBatchDirtyMode mode);
|
||||
extern void (*BKE_mesh_batch_cache_dirty_tag_cb)(Mesh *mesh, eMeshBatchDirtyMode mode);
|
||||
extern void (*BKE_mesh_batch_cache_free_cb)(void *batch_cache);
|
||||
|
||||
/* `mesh_debug.cc` */
|
||||
|
||||
#ifndef NDEBUG
|
||||
char *BKE_mesh_debug_info(const struct Mesh *mesh)
|
||||
ATTR_NONNULL(1) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
|
||||
void BKE_mesh_debug_print(const struct Mesh *mesh) ATTR_NONNULL(1);
|
||||
char *BKE_mesh_debug_info(const Mesh *mesh) ATTR_NONNULL(1) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
|
||||
void BKE_mesh_debug_print(const Mesh *mesh) ATTR_NONNULL(1);
|
||||
#endif
|
||||
|
|
|
@ -140,9 +140,6 @@ struct MeshRuntime {
|
|||
/** Cache for BVH trees generated for the mesh. Defined in 'BKE_bvhutil.c' */
|
||||
BVHCache *bvh_cache = nullptr;
|
||||
|
||||
/** Cache of non-manifold boundary data for Shrink-wrap Target Project. */
|
||||
std::unique_ptr<ShrinkwrapBoundaryData> shrinkwrap_data;
|
||||
|
||||
/** Needed in case we need to lazily initialize the mesh. */
|
||||
CustomData_MeshMasks cd_mask_extra = {};
|
||||
|
||||
|
@ -204,6 +201,9 @@ struct MeshRuntime {
|
|||
/** Cache of data about vertices not used by faces. See #Mesh::verts_no_face(). */
|
||||
SharedCache<LooseVertCache> verts_no_face_cache;
|
||||
|
||||
/** Cache of non-manifold boundary data for shrinkwrap target Project. */
|
||||
SharedCache<ShrinkwrapBoundaryData> shrinkwrap_boundary_cache;
|
||||
|
||||
/**
|
||||
* A bit vector the size of the number of vertices, set to true for the center vertices of
|
||||
* subdivided faces. The values are set by the subdivision surface modifier and used by
|
||||
|
|
|
@ -70,7 +70,7 @@ struct uiLayout;
|
|||
* static struct lists. These are converted to the new template collections
|
||||
* in RNA types automatically.
|
||||
*/
|
||||
typedef struct bNodeSocketTemplate {
|
||||
struct bNodeSocketTemplate {
|
||||
int type;
|
||||
char name[64]; /* MAX_NAME */
|
||||
float val1, val2, val3, val4; /* default alloc value for inputs */
|
||||
|
@ -79,9 +79,9 @@ typedef struct bNodeSocketTemplate {
|
|||
int flag;
|
||||
|
||||
/* after this line is used internal only */
|
||||
struct bNodeSocket *sock; /* used to hold verified socket */
|
||||
char identifier[64]; /* generated from name */
|
||||
} bNodeSocketTemplate;
|
||||
bNodeSocket *sock; /* used to hold verified socket */
|
||||
char identifier[64]; /* generated from name */
|
||||
};
|
||||
|
||||
/* Use `void *` for callbacks that require C++. This is rather ugly, but works well for now. This
|
||||
* would not be necessary if we would use bNodeSocketType and bNodeType only in C++ code.
|
||||
|
@ -133,7 +133,7 @@ using NodeExtraInfoFunction = void (*)(blender::nodes::NodeExtraInfoParams ¶
|
|||
*
|
||||
* Defines the appearance and behavior of a socket in the UI.
|
||||
*/
|
||||
typedef struct bNodeSocketType {
|
||||
struct bNodeSocketType {
|
||||
/** Identifier name. */
|
||||
char idname[64];
|
||||
/** Type label. */
|
||||
|
@ -141,30 +141,21 @@ typedef struct bNodeSocketType {
|
|||
/** Sub-type label. */
|
||||
char subtype_label[64];
|
||||
|
||||
void (*draw)(struct bContext *C,
|
||||
struct uiLayout *layout,
|
||||
struct PointerRNA *ptr,
|
||||
struct PointerRNA *node_ptr,
|
||||
const char *text);
|
||||
void (*draw_color)(struct bContext *C,
|
||||
struct PointerRNA *ptr,
|
||||
struct PointerRNA *node_ptr,
|
||||
float *r_color);
|
||||
void (*draw)(
|
||||
bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, const char *text);
|
||||
void (*draw_color)(bContext *C, PointerRNA *ptr, PointerRNA *node_ptr, float *r_color);
|
||||
void (*draw_color_simple)(const bNodeSocketType *socket_type, float *r_color);
|
||||
|
||||
void (*interface_draw)(struct ID *id,
|
||||
struct bNodeTreeInterfaceSocket *socket,
|
||||
struct bContext *C,
|
||||
struct uiLayout *layout);
|
||||
void (*interface_init_socket)(struct ID *id,
|
||||
const struct bNodeTreeInterfaceSocket *interface_socket,
|
||||
struct bNode *node,
|
||||
struct bNodeSocket *socket,
|
||||
void (*interface_draw)(ID *id, bNodeTreeInterfaceSocket *socket, bContext *C, uiLayout *layout);
|
||||
void (*interface_init_socket)(ID *id,
|
||||
const bNodeTreeInterfaceSocket *interface_socket,
|
||||
bNode *node,
|
||||
bNodeSocket *socket,
|
||||
const char *data_path);
|
||||
void (*interface_from_socket)(struct ID *id,
|
||||
struct bNodeTreeInterfaceSocket *interface_socket,
|
||||
const struct bNode *node,
|
||||
const struct bNodeSocket *socket);
|
||||
void (*interface_from_socket)(ID *id,
|
||||
bNodeTreeInterfaceSocket *interface_socket,
|
||||
const bNode *node,
|
||||
const bNodeSocket *socket);
|
||||
|
||||
/* RNA integration */
|
||||
ExtensionRNA ext_socket;
|
||||
|
@ -179,7 +170,7 @@ typedef struct bNodeSocketType {
|
|||
int output_link_limit;
|
||||
|
||||
/* Callback to free the socket type. */
|
||||
void (*free_self)(struct bNodeSocketType *stype);
|
||||
void (*free_self)(bNodeSocketType *stype);
|
||||
|
||||
/* Return the CPPType of this socket. */
|
||||
const blender::CPPType *base_cpp_type;
|
||||
|
@ -191,24 +182,17 @@ typedef struct bNodeSocketType {
|
|||
SocketGetGeometryNodesCPPValueFunction get_geometry_nodes_cpp_value;
|
||||
/* Default value for this socket type. */
|
||||
const void *geometry_nodes_default_cpp_value;
|
||||
} bNodeSocketType;
|
||||
};
|
||||
|
||||
typedef void *(*NodeInitExecFunction)(struct bNodeExecContext *context,
|
||||
struct bNode *node,
|
||||
bNodeInstanceKey key);
|
||||
typedef void (*NodeFreeExecFunction)(void *nodedata);
|
||||
typedef void (*NodeExecFunction)(void *data,
|
||||
int thread,
|
||||
struct bNode *,
|
||||
struct bNodeExecData *execdata,
|
||||
struct bNodeStack **in,
|
||||
struct bNodeStack **out);
|
||||
typedef int (*NodeGPUExecFunction)(struct GPUMaterial *mat,
|
||||
struct bNode *node,
|
||||
struct bNodeExecData *execdata,
|
||||
struct GPUNodeStack *in,
|
||||
struct GPUNodeStack *out);
|
||||
typedef void (*NodeMaterialXFunction)(void *data, struct bNode *node, struct bNodeSocket *out);
|
||||
using NodeInitExecFunction = void *(*)(bNodeExecContext *context,
|
||||
bNode *node,
|
||||
bNodeInstanceKey key);
|
||||
using NodeFreeExecFunction = void (*)(void *nodedata);
|
||||
using NodeExecFunction = void (*)(
|
||||
void *data, int thread, bNode *, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out);
|
||||
using NodeGPUExecFunction = int (*)(
|
||||
GPUMaterial *mat, bNode *node, bNodeExecData *execdata, GPUNodeStack *in, GPUNodeStack *out);
|
||||
using NodeMaterialXFunction = void (*)(void *data, bNode *node, bNodeSocket *out);
|
||||
|
||||
/**
|
||||
* \brief Defines a node type.
|
||||
|
@ -216,7 +200,7 @@ typedef void (*NodeMaterialXFunction)(void *data, struct bNode *node, struct bNo
|
|||
* Initial attributes and constants for a node as well as callback functions
|
||||
* implementing the node behavior.
|
||||
*/
|
||||
typedef struct bNodeType {
|
||||
struct bNodeType {
|
||||
char idname[64]; /* identifier name */
|
||||
int type;
|
||||
|
||||
|
@ -236,30 +220,26 @@ typedef struct bNodeType {
|
|||
char storagename[64]; /* struct name for DNA */
|
||||
|
||||
/* Draw the option buttons on the node */
|
||||
void (*draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr);
|
||||
void (*draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr);
|
||||
/* Additional parameters in the side panel */
|
||||
void (*draw_buttons_ex)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr);
|
||||
void (*draw_buttons_ex)(uiLayout *, bContext *C, PointerRNA *ptr);
|
||||
|
||||
/* Additional drawing on backdrop */
|
||||
void (*draw_backdrop)(
|
||||
struct SpaceNode *snode, struct ImBuf *backdrop, struct bNode *node, int x, int y);
|
||||
void (*draw_backdrop)(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y);
|
||||
|
||||
/**
|
||||
* Optional custom label function for the node header.
|
||||
* \note Used as a fallback when #bNode.label isn't set.
|
||||
*/
|
||||
void (*labelfunc)(const struct bNodeTree *ntree,
|
||||
const struct bNode *node,
|
||||
char *label,
|
||||
int label_maxncpy);
|
||||
void (*labelfunc)(const bNodeTree *ntree, const bNode *node, char *label, int label_maxncpy);
|
||||
|
||||
/** Optional override for node class, used for drawing node header. */
|
||||
int (*ui_class)(const struct bNode *node);
|
||||
int (*ui_class)(const bNode *node);
|
||||
|
||||
/** Called when the node is updated in the editor. */
|
||||
void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node);
|
||||
void (*updatefunc)(bNodeTree *ntree, bNode *node);
|
||||
/** Check and update if internal ID data has changed. */
|
||||
void (*group_update_func)(struct bNodeTree *ntree, struct bNode *node);
|
||||
void (*group_update_func)(bNodeTree *ntree, bNode *node);
|
||||
|
||||
/**
|
||||
* Initialize a new node instance of this type after creation.
|
||||
|
@ -267,7 +247,7 @@ typedef struct bNodeType {
|
|||
* \note Assignments to `node->id` must not increment the user of the ID.
|
||||
* This is handled by the caller of this callback.
|
||||
*/
|
||||
void (*initfunc)(struct bNodeTree *ntree, struct bNode *node);
|
||||
void (*initfunc)(bNodeTree *ntree, bNode *node);
|
||||
/**
|
||||
* Free the node instance.
|
||||
*
|
||||
|
@ -275,22 +255,20 @@ typedef struct bNodeType {
|
|||
* while freeing #Main, the state of this ID is undefined.
|
||||
* Higher level logic to remove the node handles the user-count.
|
||||
*/
|
||||
void (*freefunc)(struct bNode *node);
|
||||
void (*freefunc)(bNode *node);
|
||||
/** Make a copy of the node instance. */
|
||||
void (*copyfunc)(struct bNodeTree *dest_ntree,
|
||||
struct bNode *dest_node,
|
||||
const struct bNode *src_node);
|
||||
void (*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node);
|
||||
|
||||
/* Registerable API callback versions, called in addition to C callbacks */
|
||||
void (*initfunc_api)(const struct bContext *C, struct PointerRNA *ptr);
|
||||
void (*freefunc_api)(struct PointerRNA *ptr);
|
||||
void (*copyfunc_api)(struct PointerRNA *ptr, const struct bNode *src_node);
|
||||
void (*initfunc_api)(const bContext *C, PointerRNA *ptr);
|
||||
void (*freefunc_api)(PointerRNA *ptr);
|
||||
void (*copyfunc_api)(PointerRNA *ptr, const bNode *src_node);
|
||||
|
||||
/**
|
||||
* An additional poll test for deciding whether nodes should be an option in search menus.
|
||||
* Potentially more strict poll than #poll(), but doesn't have to check the same things.
|
||||
*/
|
||||
bool (*add_ui_poll)(const struct bContext *C);
|
||||
bool (*add_ui_poll)(const bContext *C);
|
||||
|
||||
/**
|
||||
* Can this node type be added to a node tree?
|
||||
|
@ -301,21 +279,19 @@ typedef struct bNodeType {
|
|||
* when it's not just a dummy, that is, if it actually wants to access
|
||||
* the returned disabled-hint (null-check needed!).
|
||||
*/
|
||||
bool (*poll)(const struct bNodeType *ntype,
|
||||
const struct bNodeTree *nodetree,
|
||||
const char **r_disabled_hint);
|
||||
bool (*poll)(const bNodeType *ntype, const bNodeTree *nodetree, const char **r_disabled_hint);
|
||||
/**
|
||||
* Can this node be added to a node tree?
|
||||
* \param r_disabled_hint: See `poll()`.
|
||||
*/
|
||||
bool (*poll_instance)(const struct bNode *node,
|
||||
const struct bNodeTree *nodetree,
|
||||
bool (*poll_instance)(const bNode *node,
|
||||
const bNodeTree *nodetree,
|
||||
const char **r_disabled_hint);
|
||||
|
||||
/* Optional handling of link insertion. Returns false if the link shouldn't be created. */
|
||||
bool (*insert_link)(struct bNodeTree *ntree, struct bNode *node, struct bNodeLink *link);
|
||||
bool (*insert_link)(bNodeTree *ntree, bNode *node, bNodeLink *link);
|
||||
|
||||
void (*free_self)(struct bNodeType *ntype);
|
||||
void (*free_self)(bNodeType *ntype);
|
||||
|
||||
/* **** execution callbacks **** */
|
||||
NodeInitExecFunction init_exec_fn;
|
||||
|
@ -379,7 +355,7 @@ typedef struct bNodeType {
|
|||
|
||||
/* RNA integration */
|
||||
ExtensionRNA rna_ext;
|
||||
} bNodeType;
|
||||
};
|
||||
|
||||
/** #bNodeType.nclass (for add-menu and themes). */
|
||||
#define NODE_CLASS_INPUT 0
|
||||
|
@ -402,8 +378,8 @@ typedef struct bNodeType {
|
|||
|
||||
struct bNodeTreeExec;
|
||||
|
||||
typedef void (*bNodeClassCallback)(void *calldata, int nclass, const char *name);
|
||||
typedef struct bNodeTreeType {
|
||||
using bNodeClassCallback = void (*)(void *calldata, int nclass, const char *name);
|
||||
struct bNodeTreeType {
|
||||
int type; /* type identifier */
|
||||
char idname[64]; /* identifier name */
|
||||
|
||||
|
@ -416,33 +392,30 @@ typedef struct bNodeTreeType {
|
|||
|
||||
/* callbacks */
|
||||
/* Iteration over all node classes. */
|
||||
void (*foreach_nodeclass)(struct Scene *scene, void *calldata, bNodeClassCallback func);
|
||||
void (*foreach_nodeclass)(Scene *scene, void *calldata, bNodeClassCallback func);
|
||||
/* Check visibility in the node editor */
|
||||
bool (*poll)(const struct bContext *C, struct bNodeTreeType *ntreetype);
|
||||
bool (*poll)(const bContext *C, bNodeTreeType *ntreetype);
|
||||
/* Select a node tree from the context */
|
||||
void (*get_from_context)(const struct bContext *C,
|
||||
struct bNodeTreeType *ntreetype,
|
||||
struct bNodeTree **r_ntree,
|
||||
struct ID **r_id,
|
||||
struct ID **r_from);
|
||||
void (*get_from_context)(
|
||||
const bContext *C, bNodeTreeType *ntreetype, bNodeTree **r_ntree, ID **r_id, ID **r_from);
|
||||
|
||||
/* calls allowing threaded composite */
|
||||
void (*localize)(struct bNodeTree *localtree, struct bNodeTree *ntree);
|
||||
void (*local_merge)(struct Main *bmain, struct bNodeTree *localtree, struct bNodeTree *ntree);
|
||||
void (*localize)(bNodeTree *localtree, bNodeTree *ntree);
|
||||
void (*local_merge)(Main *bmain, bNodeTree *localtree, bNodeTree *ntree);
|
||||
|
||||
/* Tree update. Overrides `nodetype->updatetreefunc`. */
|
||||
void (*update)(struct bNodeTree *ntree);
|
||||
void (*update)(bNodeTree *ntree);
|
||||
|
||||
bool (*validate_link)(eNodeSocketDatatype from, eNodeSocketDatatype to);
|
||||
|
||||
void (*node_add_init)(struct bNodeTree *ntree, struct bNode *bnode);
|
||||
void (*node_add_init)(bNodeTree *ntree, bNode *bnode);
|
||||
|
||||
/* Check if the socket type is valid for this tree type. */
|
||||
bool (*valid_socket_type)(struct bNodeTreeType *ntreetype, struct bNodeSocketType *socket_type);
|
||||
bool (*valid_socket_type)(bNodeTreeType *ntreetype, bNodeSocketType *socket_type);
|
||||
|
||||
/* RNA integration */
|
||||
ExtensionRNA rna_ext;
|
||||
} bNodeTreeType;
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@ -450,11 +423,11 @@ typedef struct bNodeTreeType {
|
|||
/** \name Generic API, Trees
|
||||
* \{ */
|
||||
|
||||
struct bNodeTreeType *ntreeTypeFind(const char *idname);
|
||||
void ntreeTypeAdd(struct bNodeTreeType *nt);
|
||||
void ntreeTypeFreeLink(const struct bNodeTreeType *nt);
|
||||
bool ntreeIsRegistered(const struct bNodeTree *ntree);
|
||||
struct GHashIterator *ntreeTypeGetIterator();
|
||||
bNodeTreeType *ntreeTypeFind(const char *idname);
|
||||
void ntreeTypeAdd(bNodeTreeType *nt);
|
||||
void ntreeTypeFreeLink(const bNodeTreeType *nt);
|
||||
bool ntreeIsRegistered(const bNodeTree *ntree);
|
||||
GHashIterator *ntreeTypeGetIterator();
|
||||
|
||||
/* Helper macros for iterating over tree types. */
|
||||
#define NODE_TREE_TYPES_BEGIN(ntype) \
|
||||
|
@ -479,14 +452,14 @@ struct GHashIterator *ntreeTypeGetIterator();
|
|||
* In that case the update_typeinfo function will set type-info on registration
|
||||
* and do necessary updates.
|
||||
*/
|
||||
void ntreeSetTypes(const struct bContext *C, struct bNodeTree *ntree);
|
||||
void ntreeSetTypes(const bContext *C, bNodeTree *ntree);
|
||||
|
||||
struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char *idname);
|
||||
bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname);
|
||||
|
||||
/**
|
||||
* Free tree which is embedded into another data-block.
|
||||
*/
|
||||
void ntreeFreeEmbeddedTree(struct bNodeTree *ntree);
|
||||
void ntreeFreeEmbeddedTree(bNodeTree *ntree);
|
||||
|
||||
/**
|
||||
* Get address of potential node-tree pointer of given ID.
|
||||
|
@ -494,39 +467,38 @@ void ntreeFreeEmbeddedTree(struct bNodeTree *ntree);
|
|||
* \warning Using this function directly is potentially dangerous, if you don't know or are not
|
||||
* sure, please use `ntreeFromID()` instead.
|
||||
*/
|
||||
struct bNodeTree **BKE_ntree_ptr_from_id(struct ID *id);
|
||||
bNodeTree **BKE_ntree_ptr_from_id(ID *id);
|
||||
|
||||
/**
|
||||
* Returns the private NodeTree object of the data-block, if it has one.
|
||||
*/
|
||||
struct bNodeTree *ntreeFromID(struct ID *id);
|
||||
bNodeTree *ntreeFromID(ID *id);
|
||||
|
||||
void ntreeFreeLocalTree(struct bNodeTree *ntree);
|
||||
void ntreeFreeLocalTree(bNodeTree *ntree);
|
||||
|
||||
/**
|
||||
* Check recursively if a node tree contains another.
|
||||
*/
|
||||
bool ntreeContainsTree(const struct bNodeTree *tree_to_search_in,
|
||||
const struct bNodeTree *tree_to_search_for);
|
||||
bool ntreeContainsTree(const bNodeTree *tree_to_search_in, const bNodeTree *tree_to_search_for);
|
||||
|
||||
void ntreeUpdateAllUsers(struct Main *main, struct ID *id);
|
||||
void ntreeUpdateAllUsers(Main *main, ID *id);
|
||||
|
||||
/**
|
||||
* XXX: old trees handle output flags automatically based on special output
|
||||
* node types and last active selection.
|
||||
* New tree types have a per-output socket flag to indicate the final output to use explicitly.
|
||||
*/
|
||||
void ntreeSetOutput(struct bNodeTree *ntree);
|
||||
void ntreeSetOutput(bNodeTree *ntree);
|
||||
|
||||
/**
|
||||
* Returns localized tree for execution in threads.
|
||||
*/
|
||||
struct bNodeTree *ntreeLocalize(struct bNodeTree *ntree);
|
||||
bNodeTree *ntreeLocalize(bNodeTree *ntree);
|
||||
|
||||
/**
|
||||
* This is only direct data, tree itself should have been written.
|
||||
*/
|
||||
void ntreeBlendWrite(struct BlendWriter *writer, struct bNodeTree *ntree);
|
||||
void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree);
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@ -534,12 +506,12 @@ void ntreeBlendWrite(struct BlendWriter *writer, struct bNodeTree *ntree);
|
|||
/** \name Generic API, Nodes
|
||||
* \{ */
|
||||
|
||||
struct bNodeType *nodeTypeFind(const char *idname);
|
||||
bNodeType *nodeTypeFind(const char *idname);
|
||||
const char *nodeTypeFindAlias(const char *idname);
|
||||
void nodeRegisterType(struct bNodeType *ntype);
|
||||
void nodeUnregisterType(struct bNodeType *ntype);
|
||||
void nodeRegisterAlias(struct bNodeType *nt, const char *alias);
|
||||
struct GHashIterator *nodeTypeGetIterator();
|
||||
void nodeRegisterType(bNodeType *ntype);
|
||||
void nodeUnregisterType(bNodeType *ntype);
|
||||
void nodeRegisterAlias(bNodeType *nt, const char *alias);
|
||||
GHashIterator *nodeTypeGetIterator();
|
||||
|
||||
/* Helper macros for iterating over node types. */
|
||||
#define NODE_TYPES_BEGIN(ntype) \
|
||||
|
@ -555,11 +527,11 @@ struct GHashIterator *nodeTypeGetIterator();
|
|||
} \
|
||||
((void)0)
|
||||
|
||||
struct bNodeSocketType *nodeSocketTypeFind(const char *idname);
|
||||
void nodeRegisterSocketType(struct bNodeSocketType *stype);
|
||||
void nodeUnregisterSocketType(struct bNodeSocketType *stype);
|
||||
bool nodeSocketIsRegistered(const struct bNodeSocket *sock);
|
||||
struct GHashIterator *nodeSocketTypeGetIterator();
|
||||
bNodeSocketType *nodeSocketTypeFind(const char *idname);
|
||||
void nodeRegisterSocketType(bNodeSocketType *stype);
|
||||
void nodeUnregisterSocketType(bNodeSocketType *stype);
|
||||
bool nodeSocketIsRegistered(const bNodeSocket *sock);
|
||||
GHashIterator *nodeSocketTypeGetIterator();
|
||||
const char *nodeSocketTypeLabel(const bNodeSocketType *stype);
|
||||
|
||||
const char *nodeStaticSocketType(int type, int subtype);
|
||||
|
@ -582,114 +554,100 @@ const char *nodeStaticSocketLabel(int type, int subtype);
|
|||
} \
|
||||
((void)0)
|
||||
|
||||
struct bNodeSocket *nodeFindSocket(const struct bNode *node,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *identifier);
|
||||
struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree,
|
||||
struct bNode *node,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *idname,
|
||||
const char *identifier,
|
||||
const char *name);
|
||||
struct bNodeSocket *nodeAddStaticSocket(struct bNodeTree *ntree,
|
||||
struct bNode *node,
|
||||
eNodeSocketInOut in_out,
|
||||
int type,
|
||||
int subtype,
|
||||
const char *identifier,
|
||||
const char *name);
|
||||
void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
|
||||
bNodeSocket *nodeFindSocket(const bNode *node, eNodeSocketInOut in_out, const char *identifier);
|
||||
bNodeSocket *nodeAddSocket(bNodeTree *ntree,
|
||||
bNode *node,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *idname,
|
||||
const char *identifier,
|
||||
const char *name);
|
||||
bNodeSocket *nodeAddStaticSocket(bNodeTree *ntree,
|
||||
bNode *node,
|
||||
eNodeSocketInOut in_out,
|
||||
int type,
|
||||
int subtype,
|
||||
const char *identifier,
|
||||
const char *name);
|
||||
void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock);
|
||||
|
||||
void nodeModifySocketTypeStatic(
|
||||
struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, int type, int subtype);
|
||||
bNodeTree *ntree, bNode *node, bNodeSocket *sock, int type, int subtype);
|
||||
|
||||
struct bNode *nodeAddNode(const struct bContext *C, struct bNodeTree *ntree, const char *idname);
|
||||
struct bNode *nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type);
|
||||
bNode *nodeAddNode(const bContext *C, bNodeTree *ntree, const char *idname);
|
||||
bNode *nodeAddStaticNode(const bContext *C, bNodeTree *ntree, int type);
|
||||
|
||||
/**
|
||||
* Find the first available, non-duplicate name for a given node.
|
||||
*/
|
||||
void nodeUniqueName(struct bNodeTree *ntree, struct bNode *node);
|
||||
void nodeUniqueName(bNodeTree *ntree, bNode *node);
|
||||
/**
|
||||
* Create a new unique integer identifier for the node. Also set the node's
|
||||
* index in the tree, which is an eagerly maintained cache.
|
||||
*/
|
||||
void nodeUniqueID(struct bNodeTree *ntree, struct bNode *node);
|
||||
void nodeUniqueID(bNodeTree *ntree, bNode *node);
|
||||
|
||||
/**
|
||||
* Delete node, associated animation data and ID user count.
|
||||
*/
|
||||
void nodeRemoveNode(struct Main *bmain,
|
||||
struct bNodeTree *ntree,
|
||||
struct bNode *node,
|
||||
bool do_id_user);
|
||||
void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user);
|
||||
|
||||
void nodeDimensionsGet(const struct bNode *node, float *r_width, float *r_height);
|
||||
void nodeTagUpdateID(struct bNode *node);
|
||||
void nodeInternalLinks(struct bNode *node, struct bNodeLink **r_links, int *r_len);
|
||||
void nodeDimensionsGet(const bNode *node, float *r_width, float *r_height);
|
||||
void nodeTagUpdateID(bNode *node);
|
||||
void nodeInternalLinks(bNode *node, bNodeLink **r_links, int *r_len);
|
||||
|
||||
/**
|
||||
* Also used via RNA API, so we check for proper input output direction.
|
||||
*/
|
||||
struct bNodeLink *nodeAddLink(struct bNodeTree *ntree,
|
||||
struct bNode *fromnode,
|
||||
struct bNodeSocket *fromsock,
|
||||
struct bNode *tonode,
|
||||
struct bNodeSocket *tosock);
|
||||
void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link);
|
||||
void nodeRemSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
|
||||
bNodeLink *nodeAddLink(
|
||||
bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock);
|
||||
void nodeRemLink(bNodeTree *ntree, bNodeLink *link);
|
||||
void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock);
|
||||
|
||||
bool nodeLinkIsHidden(const struct bNodeLink *link);
|
||||
bool nodeLinkIsHidden(const bNodeLink *link);
|
||||
|
||||
void nodeAttachNode(struct bNodeTree *ntree, struct bNode *node, struct bNode *parent);
|
||||
void nodeDetachNode(struct bNodeTree *ntree, struct bNode *node);
|
||||
void nodeAttachNode(bNodeTree *ntree, bNode *node, bNode *parent);
|
||||
void nodeDetachNode(bNodeTree *ntree, bNode *node);
|
||||
|
||||
/**
|
||||
* Same as above but expects that the socket definitely is in the node tree.
|
||||
*/
|
||||
void nodeFindNode(struct bNodeTree *ntree,
|
||||
struct bNodeSocket *sock,
|
||||
struct bNode **r_node,
|
||||
int *r_sockindex);
|
||||
void nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_sockindex);
|
||||
/**
|
||||
* Finds a node based on its name.
|
||||
*/
|
||||
struct bNode *nodeFindNodebyName(struct bNodeTree *ntree, const char *name);
|
||||
bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name);
|
||||
/**
|
||||
* Finds a node based on given socket and returns true on success.
|
||||
*/
|
||||
bool nodeFindNodeTry(struct bNodeTree *ntree,
|
||||
struct bNodeSocket *sock,
|
||||
struct bNode **r_node,
|
||||
int *r_sockindex);
|
||||
bool nodeFindNodeTry(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_sockindex);
|
||||
|
||||
bool nodeIsParentAndChild(const bNode *parent, const bNode *child);
|
||||
|
||||
int nodeCountSocketLinks(const struct bNodeTree *ntree, const struct bNodeSocket *sock);
|
||||
int nodeCountSocketLinks(const bNodeTree *ntree, const bNodeSocket *sock);
|
||||
|
||||
void nodeSetSelected(struct bNode *node, bool select);
|
||||
void nodeSetSelected(bNode *node, bool select);
|
||||
/**
|
||||
* Two active flags, ID nodes have special flag for buttons display.
|
||||
*/
|
||||
void nodeSetActive(struct bNodeTree *ntree, struct bNode *node);
|
||||
struct bNode *nodeGetActive(struct bNodeTree *ntree);
|
||||
void nodeClearActive(struct bNodeTree *ntree);
|
||||
void nodeSetActive(bNodeTree *ntree, bNode *node);
|
||||
bNode *nodeGetActive(bNodeTree *ntree);
|
||||
void nodeClearActive(bNodeTree *ntree);
|
||||
/**
|
||||
* Two active flags, ID nodes have special flag for buttons display.
|
||||
*/
|
||||
struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree);
|
||||
bNode *nodeGetActiveTexture(bNodeTree *ntree);
|
||||
|
||||
int nodeSocketLinkLimit(const struct bNodeSocket *sock);
|
||||
int nodeSocketLinkLimit(const bNodeSocket *sock);
|
||||
|
||||
/**
|
||||
* Node Instance Hash.
|
||||
*/
|
||||
typedef struct bNodeInstanceHash {
|
||||
struct bNodeInstanceHash {
|
||||
/** XXX should be made a direct member, #GHash allocation needs to support it */
|
||||
GHash *ghash;
|
||||
} bNodeInstanceHash;
|
||||
};
|
||||
|
||||
typedef void (*bNodeInstanceValueFP)(void *value);
|
||||
using bNodeInstanceValueFP = void (*)(void *value);
|
||||
|
||||
/**
|
||||
* Magic number for initial hash key.
|
||||
|
@ -698,8 +656,8 @@ extern const bNodeInstanceKey NODE_INSTANCE_KEY_BASE;
|
|||
extern const bNodeInstanceKey NODE_INSTANCE_KEY_NONE;
|
||||
|
||||
bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key,
|
||||
const struct bNodeTree *ntree,
|
||||
const struct bNode *node);
|
||||
const bNodeTree *ntree,
|
||||
const bNode *node);
|
||||
|
||||
bNodeInstanceHash *BKE_node_instance_hash_new(const char *info);
|
||||
void BKE_node_instance_hash_free(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp);
|
||||
|
@ -725,26 +683,23 @@ void BKE_node_instance_hash_remove_untagged(bNodeInstanceHash *hash,
|
|||
/** \name Node Type Access
|
||||
* \{ */
|
||||
|
||||
bool nodeGroupPoll(const struct bNodeTree *nodetree,
|
||||
const struct bNodeTree *grouptree,
|
||||
bool nodeGroupPoll(const bNodeTree *nodetree,
|
||||
const bNodeTree *grouptree,
|
||||
const char **r_disabled_hint);
|
||||
|
||||
void node_type_base_custom(struct bNodeType *ntype,
|
||||
const char *idname,
|
||||
const char *name,
|
||||
const char *enum_name,
|
||||
short nclass);
|
||||
void node_type_base_custom(
|
||||
bNodeType *ntype, const char *idname, const char *name, const char *enum_name, short nclass);
|
||||
|
||||
/**
|
||||
* \warning Nodes defining a storage type _must_ allocate this for new nodes.
|
||||
* Otherwise nodes will reload as undefined (#46619).
|
||||
*/
|
||||
void node_type_storage(struct bNodeType *ntype,
|
||||
void node_type_storage(bNodeType *ntype,
|
||||
const char *storagename,
|
||||
void (*freefunc)(struct bNode *node),
|
||||
void (*copyfunc)(struct bNodeTree *dest_ntree,
|
||||
struct bNode *dest_node,
|
||||
const struct bNode *src_node));
|
||||
void (*freefunc)(bNode *node),
|
||||
void (*copyfunc)(bNodeTree *dest_ntree,
|
||||
bNode *dest_node,
|
||||
const bNode *src_node));
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@ -805,21 +760,19 @@ void node_type_storage(struct bNodeType *ntype,
|
|||
struct NodeTreeIterStore {
|
||||
bNodeTree *ngroup;
|
||||
Scene *scene;
|
||||
struct Material *mat;
|
||||
Material *mat;
|
||||
Tex *tex;
|
||||
struct Light *light;
|
||||
struct World *world;
|
||||
struct FreestyleLineStyle *linestyle;
|
||||
Light *light;
|
||||
World *world;
|
||||
FreestyleLineStyle *linestyle;
|
||||
};
|
||||
|
||||
void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *bmain);
|
||||
bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
|
||||
struct bNodeTree **r_nodetree,
|
||||
struct ID **r_id);
|
||||
void BKE_node_tree_iter_init(NodeTreeIterStore *ntreeiter, Main *bmain);
|
||||
bool BKE_node_tree_iter_step(NodeTreeIterStore *ntreeiter, bNodeTree **r_nodetree, ID **r_id);
|
||||
|
||||
#define FOREACH_NODETREE_BEGIN(bmain, _nodetree, _id) \
|
||||
{ \
|
||||
struct NodeTreeIterStore _nstore; \
|
||||
NodeTreeIterStore _nstore; \
|
||||
bNodeTree *_nodetree; \
|
||||
ID *_id; \
|
||||
/* avoid compiler warning about unused variables */ \
|
||||
|
@ -839,7 +792,7 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
|
|||
/** \name Node Tree
|
||||
*/
|
||||
|
||||
void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, int layer_index);
|
||||
void BKE_nodetree_remove_layer_n(bNodeTree *ntree, Scene *scene, int layer_index);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Shader Nodes
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "BLI_bounds_types.hh"
|
||||
#include "BLI_compiler_compat.h"
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_index_mask.hh"
|
||||
#include "BLI_index_mask_fwd.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_offset_indices.hh"
|
||||
#include "BLI_span.hh"
|
||||
|
|
|
@ -60,10 +60,11 @@ struct ShrinkwrapBoundaryData {
|
|||
blender::Array<ShrinkwrapBoundaryVertData> boundary_verts;
|
||||
};
|
||||
|
||||
/**
|
||||
* Free boundary data for target project.
|
||||
*/
|
||||
void BKE_shrinkwrap_compute_boundary_data(Mesh *mesh);
|
||||
namespace blender::bke::shrinkwrap {
|
||||
|
||||
const ShrinkwrapBoundaryData &boundary_cache_ensure(const Mesh &mesh);
|
||||
|
||||
} // namespace blender::bke::shrinkwrap
|
||||
|
||||
/* Information about a mesh and BVH tree. */
|
||||
struct ShrinkwrapTreeData {
|
||||
|
@ -79,7 +80,7 @@ struct ShrinkwrapTreeData {
|
|||
blender::Span<blender::float3> vert_normals;
|
||||
blender::Span<blender::float3> corner_normals;
|
||||
const bool *sharp_faces;
|
||||
ShrinkwrapBoundaryData *boundary;
|
||||
const ShrinkwrapBoundaryData *boundary;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -412,7 +412,6 @@ set(SRC
|
|||
BKE_grease_pencil_legacy_convert.hh
|
||||
BKE_grease_pencil_vertex_groups.hh
|
||||
BKE_icons.h
|
||||
BKE_idprop.h
|
||||
BKE_idprop.hh
|
||||
BKE_idtype.hh
|
||||
BKE_image.h
|
||||
|
|
|
@ -318,7 +318,7 @@ void DM_interp_vert_data(const DerivedMesh *source,
|
|||
&source->vertData, &dest->vertData, src_indices, weights, nullptr, count, dest_index);
|
||||
}
|
||||
|
||||
static float (*get_editbmesh_orco_verts(BMEditMesh *em))[3]
|
||||
static float (*get_editbmesh_orco_verts(const BMEditMesh *em))[3]
|
||||
{
|
||||
BMIter iter;
|
||||
BMVert *eve;
|
||||
|
@ -338,7 +338,7 @@ static float (*get_editbmesh_orco_verts(BMEditMesh *em))[3]
|
|||
}
|
||||
|
||||
/* orco custom data layer */
|
||||
static float (*get_orco_coords(Object *ob, BMEditMesh *em, int layer, int *free))[3]
|
||||
static float (*get_orco_coords(const Object *ob, const BMEditMesh *em, int layer, int *free))[3]
|
||||
{
|
||||
*free = 0;
|
||||
|
||||
|
@ -355,11 +355,11 @@ static float (*get_orco_coords(Object *ob, BMEditMesh *em, int layer, int *free)
|
|||
/* apply shape key for cloth, this should really be solved
|
||||
* by a more flexible customdata system, but not simple */
|
||||
if (!em) {
|
||||
ClothModifierData *clmd = (ClothModifierData *)BKE_modifiers_findby_type(
|
||||
const ClothModifierData *clmd = (const ClothModifierData *)BKE_modifiers_findby_type(
|
||||
ob, eModifierType_Cloth);
|
||||
if (clmd && clmd->sim_parms->shapekey_rest) {
|
||||
KeyBlock *kb = BKE_keyblock_find_by_index(BKE_key_from_object(ob),
|
||||
clmd->sim_parms->shapekey_rest);
|
||||
const KeyBlock *kb = BKE_keyblock_find_by_index(
|
||||
BKE_key_from_object(const_cast<Object *>(ob)), clmd->sim_parms->shapekey_rest);
|
||||
|
||||
if (kb && kb->data) {
|
||||
return (float(*)[3])kb->data;
|
||||
|
@ -373,7 +373,7 @@ static float (*get_orco_coords(Object *ob, BMEditMesh *em, int layer, int *free)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static Mesh *create_orco_mesh(Object *ob, Mesh *mesh, BMEditMesh *em, int layer)
|
||||
static Mesh *create_orco_mesh(const Object *ob, const Mesh *mesh, const BMEditMesh *em, int layer)
|
||||
{
|
||||
Mesh *orco_mesh;
|
||||
float(*orco)[3];
|
||||
|
@ -410,8 +410,11 @@ static MutableSpan<float3> orco_coord_layer_ensure(Mesh *mesh, const eCustomData
|
|||
return MutableSpan(reinterpret_cast<float3 *>(data), mesh->verts_num);
|
||||
}
|
||||
|
||||
static void add_orco_mesh(
|
||||
Object *ob, BMEditMesh *em, Mesh *mesh, Mesh *mesh_orco, const eCustomDataType layer)
|
||||
static void add_orco_mesh(Object *ob,
|
||||
const BMEditMesh *em,
|
||||
Mesh *mesh,
|
||||
const Mesh *mesh_orco,
|
||||
const eCustomDataType layer)
|
||||
{
|
||||
const int totvert = mesh->verts_num;
|
||||
|
||||
|
@ -1269,12 +1272,14 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
|
|||
}
|
||||
}
|
||||
|
||||
static void mesh_build_extra_data(Depsgraph *depsgraph, Object *ob, Mesh *mesh_eval)
|
||||
static void mesh_build_extra_data(const Depsgraph *depsgraph,
|
||||
const Object *ob,
|
||||
const Mesh *mesh_eval)
|
||||
{
|
||||
uint32_t eval_flags = DEG_get_eval_flags_for_id(depsgraph, &ob->id);
|
||||
|
||||
if (eval_flags & DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY) {
|
||||
BKE_shrinkwrap_compute_boundary_data(mesh_eval);
|
||||
blender::bke::shrinkwrap::boundary_cache_ensure(*mesh_eval);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
#include "BKE_constraint.h"
|
||||
#include "BKE_deform.hh"
|
||||
#include "BKE_fcurve.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_lib_query.hh"
|
||||
|
@ -247,13 +247,9 @@ static void action_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
|
||||
static IDProperty *action_asset_type_property(const bAction *action)
|
||||
{
|
||||
using namespace blender;
|
||||
const bool is_single_frame = BKE_action_has_single_frame(action);
|
||||
|
||||
IDPropertyTemplate idprop = {0};
|
||||
idprop.i = is_single_frame;
|
||||
|
||||
IDProperty *property = IDP_New(IDP_INT, &idprop, "is_single_frame");
|
||||
return property;
|
||||
return bke::idprop::create("is_single_frame", int(is_single_frame)).release();
|
||||
}
|
||||
|
||||
static void action_asset_metadata_ensure(void *asset_ptr, AssetMetaData *asset_data)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_addon.h" /* own include */
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
#include "BKE_armature.hh"
|
||||
#include "BKE_constraint.h"
|
||||
#include "BKE_curve.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_lib_query.hh"
|
||||
|
@ -227,9 +227,9 @@ static void armature_free_data(ID *id)
|
|||
static void armature_foreach_id_bone(Bone *bone, LibraryForeachIDData *data)
|
||||
{
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data,
|
||||
IDP_foreach_property(
|
||||
bone->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data));
|
||||
data, IDP_foreach_property(bone->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
|
||||
LISTBASE_FOREACH (Bone *, curbone, &bone->childbase) {
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, armature_foreach_id_bone(curbone, data));
|
||||
|
@ -239,21 +239,17 @@ static void armature_foreach_id_bone(Bone *bone, LibraryForeachIDData *data)
|
|||
static void armature_foreach_id_editbone(EditBone *edit_bone, LibraryForeachIDData *data)
|
||||
{
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data,
|
||||
IDP_foreach_property(edit_bone->prop,
|
||||
IDP_TYPE_FILTER_ID,
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback,
|
||||
data));
|
||||
data, IDP_foreach_property(edit_bone->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
}
|
||||
|
||||
static void armature_foreach_id_bone_collection(BoneCollection *bcoll, LibraryForeachIDData *data)
|
||||
{
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data,
|
||||
IDP_foreach_property(bcoll->prop,
|
||||
IDP_TYPE_FILTER_ID,
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback,
|
||||
data));
|
||||
data, IDP_foreach_property(bcoll->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
}
|
||||
|
||||
static void armature_foreach_id(ID *id, LibraryForeachIDData *data)
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "BLI_uuid.h"
|
||||
|
||||
#include "BKE_asset.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_preview_image.hh"
|
||||
|
||||
#include "BLO_read_write.hh"
|
||||
|
@ -155,9 +155,9 @@ void BKE_asset_metadata_catalog_id_set(AssetMetaData *asset_data,
|
|||
|
||||
void BKE_asset_metadata_idprop_ensure(AssetMetaData *asset_data, IDProperty *prop)
|
||||
{
|
||||
using namespace blender::bke;
|
||||
if (!asset_data->properties) {
|
||||
IDPropertyTemplate val = {0};
|
||||
asset_data->properties = IDP_New(IDP_GROUP, &val, "AssetMetaData.properties");
|
||||
asset_data->properties = idprop::create_group("AssetMetaData.properties").release();
|
||||
}
|
||||
/* Important: The property may already exist. For now just allow always allow a newly allocated
|
||||
* property, and replace the existing one as a way of updating. */
|
||||
|
|
|
@ -933,6 +933,22 @@ const CustomDataLayer *BKE_id_attributes_color_find(const ID *id, const char *na
|
|||
const_cast<ID *>(id), name, CD_MASK_COLOR_ALL, ATTR_DOMAIN_MASK_COLOR);
|
||||
}
|
||||
|
||||
bool BKE_color_attribute_supported(const Mesh &mesh, const blender::StringRef name)
|
||||
{
|
||||
std::optional<blender::bke::AttributeMetaData> meta_data = mesh.attributes().lookup_meta_data(
|
||||
name);
|
||||
|
||||
if (!meta_data) {
|
||||
return false;
|
||||
}
|
||||
if (!(ATTR_DOMAIN_AS_MASK(meta_data->domain) & ATTR_DOMAIN_MASK_COLOR) ||
|
||||
!(CD_TYPE_AS_MASK(meta_data->data_type) & CD_MASK_COLOR_ALL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *BKE_uv_map_vert_select_name_get(const char *uv_map_name, char *buffer)
|
||||
{
|
||||
BLI_assert(strlen(UV_VERTSEL_NAME) == 2);
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include "BKE_cachefile.hh"
|
||||
#include "BKE_callbacks.hh"
|
||||
#include "BKE_global.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_main.hh"
|
||||
#include "BKE_node.hh"
|
||||
#include "BKE_report.hh"
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "BKE_blender_user_menu.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Menu Type
|
||||
|
|
|
@ -1722,7 +1722,7 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context,
|
|||
const short idcode = id ? GS(id->name) : 0;
|
||||
|
||||
if (!id || !BKE_idtype_idcode_is_linkable(idcode)) {
|
||||
/* No need to reload non-linkable datatypes,
|
||||
/* No need to reload non-linkable data-types,
|
||||
* those will get relinked with their 'users ID'. */
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_camera.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_lib_query.hh"
|
||||
|
@ -124,33 +124,26 @@ static CameraCyclesCompatibilityData camera_write_cycles_compatibility_data_crea
|
|||
if (prop) {
|
||||
return prop;
|
||||
}
|
||||
IDPropertyTemplate val = {0};
|
||||
prop = IDP_New(IDP_GROUP, &val, "cycles");
|
||||
prop = blender::bke::idprop::create_group("cycles").release();
|
||||
IDP_AddToGroup(group, prop);
|
||||
return prop;
|
||||
};
|
||||
|
||||
auto cycles_property_int_set = [](IDProperty *idprop, const char *name, int value) {
|
||||
IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_INT);
|
||||
if (prop) {
|
||||
if (IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_INT)) {
|
||||
IDP_Int(prop) = value;
|
||||
}
|
||||
else {
|
||||
IDPropertyTemplate val = {0};
|
||||
val.i = value;
|
||||
IDP_AddToGroup(idprop, IDP_New(IDP_INT, &val, name));
|
||||
IDP_AddToGroup(idprop, blender::bke::idprop::create(name, value).release());
|
||||
}
|
||||
};
|
||||
|
||||
auto cycles_property_float_set = [](IDProperty *idprop, const char *name, float value) {
|
||||
IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_FLOAT);
|
||||
if (prop) {
|
||||
if (IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_FLOAT)) {
|
||||
IDP_Float(prop) = value;
|
||||
}
|
||||
else {
|
||||
IDPropertyTemplate val = {0};
|
||||
val.f = value;
|
||||
IDP_AddToGroup(idprop, IDP_New(IDP_FLOAT, &val, name));
|
||||
IDP_AddToGroup(idprop, blender::bke::idprop::create(name, value).release());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "BKE_anim_data.hh"
|
||||
#include "BKE_collection.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
#include "BKE_editmesh.hh"
|
||||
#include "BKE_fcurve_driver.h"
|
||||
#include "BKE_global.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_lib_query.hh"
|
||||
#include "BKE_mesh.hh"
|
||||
|
@ -210,9 +210,9 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob)
|
|||
|
||||
/* calculate delta of constraints evaluation */
|
||||
invert_m4_m4(imat, cob->startmat);
|
||||
/* XXX This would seem to be in wrong order. However, it does not work in 'right' order -
|
||||
* would be nice to understand why premul is needed here instead of usual postmul?
|
||||
* In any case, we **do not get a delta** here (e.g. startmat & matrix having same location,
|
||||
/* XXX This would seem to be in wrong order. However, it does not work in 'right' order - would
|
||||
* be nice to understand why pre-multiply is needed here instead of usual post-multiply?
|
||||
* In any case, we *do not get a delta* here (e.g. startmat & matrix having same location,
|
||||
* still gives a 'delta' with non-null translation component :/ ). */
|
||||
mul_m4_m4m4(delta, cob->matrix, imat);
|
||||
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
# include "BPY_extern.h"
|
||||
#endif
|
||||
|
||||
using blender::Vector;
|
||||
|
||||
static CLG_LogRef LOG = {"bke.context"};
|
||||
|
||||
/* struct */
|
||||
|
@ -129,7 +131,7 @@ void CTX_free(bContext *C)
|
|||
|
||||
/* store */
|
||||
|
||||
bContextStore *CTX_store_add(blender::Vector<std::unique_ptr<bContextStore>> &contexts,
|
||||
bContextStore *CTX_store_add(Vector<std::unique_ptr<bContextStore>> &contexts,
|
||||
const blender::StringRefNull name,
|
||||
const PointerRNA *ptr)
|
||||
{
|
||||
|
@ -148,7 +150,7 @@ bContextStore *CTX_store_add(blender::Vector<std::unique_ptr<bContextStore>> &co
|
|||
return ctx;
|
||||
}
|
||||
|
||||
bContextStore *CTX_store_add_all(blender::Vector<std::unique_ptr<bContextStore>> &contexts,
|
||||
bContextStore *CTX_store_add_all(Vector<std::unique_ptr<bContextStore>> &contexts,
|
||||
const bContextStore *context)
|
||||
{
|
||||
/* ensure we have a context to put the entry in, if it was already used
|
||||
|
@ -230,7 +232,7 @@ void CTX_py_state_pop(bContext *C, bContext_PyState *pystate)
|
|||
|
||||
struct bContextDataResult {
|
||||
PointerRNA ptr;
|
||||
ListBase list;
|
||||
Vector<PointerRNA> list;
|
||||
PropertyRNA *prop;
|
||||
int index;
|
||||
const char **dir;
|
||||
|
@ -244,8 +246,7 @@ static void *ctx_wm_python_context_get(const bContext *C,
|
|||
{
|
||||
#ifdef WITH_PYTHON
|
||||
if (UNLIKELY(C && CTX_py_dict_get(C))) {
|
||||
bContextDataResult result;
|
||||
memset(&result, 0, sizeof(bContextDataResult));
|
||||
bContextDataResult result{};
|
||||
BPY_context_member_get((bContext *)C, member, &result);
|
||||
|
||||
if (result.ptr.data) {
|
||||
|
@ -280,7 +281,7 @@ static eContextResult ctx_data_get(bContext *C, const char *member, bContextData
|
|||
int done = 0, recursion = C->data.recursion;
|
||||
int ret = 0;
|
||||
|
||||
memset(result, 0, sizeof(bContextDataResult));
|
||||
*result = {};
|
||||
#ifdef WITH_PYTHON
|
||||
if (CTX_py_dict_get(C)) {
|
||||
if (BPY_context_member_get(C, member, result)) {
|
||||
|
@ -378,32 +379,34 @@ static bool ctx_data_pointer_verify(const bContext *C, const char *member, void
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool ctx_data_collection_get(const bContext *C, const char *member, ListBase *list)
|
||||
static bool ctx_data_collection_get(const bContext *C,
|
||||
const char *member,
|
||||
Vector<PointerRNA> *list)
|
||||
{
|
||||
bContextDataResult result;
|
||||
if (ctx_data_get((bContext *)C, member, &result) == CTX_RESULT_OK) {
|
||||
BLI_assert(result.type == CTX_DATA_TYPE_COLLECTION);
|
||||
*list = result.list;
|
||||
*list = std::move(result.list);
|
||||
return true;
|
||||
}
|
||||
|
||||
BLI_listbase_clear(list);
|
||||
|
||||
list->clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ctx_data_base_collection_get(const bContext *C, const char *member, ListBase *list)
|
||||
static bool ctx_data_base_collection_get(const bContext *C,
|
||||
const char *member,
|
||||
Vector<PointerRNA> *list)
|
||||
{
|
||||
ListBase ctx_object_list;
|
||||
Vector<PointerRNA> ctx_object_list;
|
||||
if ((ctx_data_collection_get(C, member, &ctx_object_list) == false) ||
|
||||
BLI_listbase_is_empty(&ctx_object_list))
|
||||
ctx_object_list.is_empty())
|
||||
{
|
||||
BLI_listbase_clear(list);
|
||||
return 0;
|
||||
list->clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
bContextDataResult result;
|
||||
memset(&result, 0, sizeof(bContextDataResult));
|
||||
bContextDataResult result{};
|
||||
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
|
@ -411,11 +414,8 @@ static int ctx_data_base_collection_get(const bContext *C, const char *member, L
|
|||
|
||||
bool ok = false;
|
||||
|
||||
CollectionPointerLink *ctx_object;
|
||||
for (ctx_object = static_cast<CollectionPointerLink *>(ctx_object_list.first); ctx_object;
|
||||
ctx_object = ctx_object->next)
|
||||
{
|
||||
Object *ob = static_cast<Object *>(ctx_object->ptr.data);
|
||||
for (PointerRNA &ctx_object : ctx_object_list) {
|
||||
Object *ob = static_cast<Object *>(ctx_object.data);
|
||||
Base *base = BKE_view_layer_base_find(view_layer, ob);
|
||||
if (base != nullptr) {
|
||||
CTX_data_list_add(&result, &scene->id, &RNA_ObjectBase, base);
|
||||
|
@ -423,9 +423,8 @@ static int ctx_data_base_collection_get(const bContext *C, const char *member, L
|
|||
}
|
||||
}
|
||||
CTX_data_type_set(&result, CTX_DATA_TYPE_COLLECTION);
|
||||
BLI_freelistN(&ctx_object_list);
|
||||
|
||||
*list = result.list;
|
||||
*list = std::move(result.list);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -470,32 +469,28 @@ PointerRNA CTX_data_pointer_get_type_silent(const bContext *C, const char *membe
|
|||
return PointerRNA_NULL;
|
||||
}
|
||||
|
||||
ListBase CTX_data_collection_get(const bContext *C, const char *member)
|
||||
Vector<PointerRNA> CTX_data_collection_get(const bContext *C, const char *member)
|
||||
{
|
||||
bContextDataResult result;
|
||||
if (ctx_data_get((bContext *)C, member, &result) == CTX_RESULT_OK) {
|
||||
BLI_assert(result.type == CTX_DATA_TYPE_COLLECTION);
|
||||
return result.list;
|
||||
}
|
||||
|
||||
ListBase list = {nullptr, nullptr};
|
||||
return list;
|
||||
return {};
|
||||
}
|
||||
|
||||
void CTX_data_collection_remap_property(ListBase /*CollectionPointerLink*/ collection_pointers,
|
||||
void CTX_data_collection_remap_property(blender::MutableSpan<PointerRNA> collection_pointers,
|
||||
const char *propname)
|
||||
{
|
||||
LISTBASE_FOREACH (CollectionPointerLink *, link, &collection_pointers) {
|
||||
PointerRNA original_ptr = link->ptr;
|
||||
PointerRNA remapped_ptr = RNA_pointer_get(&original_ptr, propname);
|
||||
link->ptr = remapped_ptr;
|
||||
for (PointerRNA &ptr : collection_pointers) {
|
||||
ptr = RNA_pointer_get(&ptr, propname);
|
||||
}
|
||||
}
|
||||
|
||||
int /*eContextResult*/ CTX_data_get(const bContext *C,
|
||||
const char *member,
|
||||
PointerRNA *r_ptr,
|
||||
ListBase *r_lb,
|
||||
Vector<PointerRNA> *r_lb,
|
||||
PropertyRNA **r_prop,
|
||||
int *r_index,
|
||||
short *r_type)
|
||||
|
@ -512,7 +507,7 @@ int /*eContextResult*/ CTX_data_get(const bContext *C,
|
|||
}
|
||||
else {
|
||||
memset(r_ptr, 0, sizeof(*r_ptr));
|
||||
memset(r_lb, 0, sizeof(*r_lb));
|
||||
r_lb->clear();
|
||||
*r_type = 0;
|
||||
}
|
||||
|
||||
|
@ -541,7 +536,7 @@ ListBase CTX_data_dir_get_ex(const bContext *C,
|
|||
const bool use_rna,
|
||||
const bool use_all)
|
||||
{
|
||||
bContextDataResult result;
|
||||
bContextDataResult result{};
|
||||
ListBase lb;
|
||||
bScreen *screen;
|
||||
ScrArea *area;
|
||||
|
@ -576,7 +571,6 @@ ListBase CTX_data_dir_get_ex(const bContext *C,
|
|||
}
|
||||
}
|
||||
if ((region = CTX_wm_region(C)) && region->type && region->type->context) {
|
||||
memset(&result, 0, sizeof(result));
|
||||
region->type->context(C, "", &result);
|
||||
|
||||
if (result.dir) {
|
||||
|
@ -586,7 +580,6 @@ ListBase CTX_data_dir_get_ex(const bContext *C,
|
|||
}
|
||||
}
|
||||
if ((area = CTX_wm_area(C)) && area->type && area->type->context) {
|
||||
memset(&result, 0, sizeof(result));
|
||||
area->type->context(C, "", &result);
|
||||
|
||||
if (result.dir) {
|
||||
|
@ -597,7 +590,6 @@ ListBase CTX_data_dir_get_ex(const bContext *C,
|
|||
}
|
||||
if ((screen = CTX_wm_screen(C)) && screen->context) {
|
||||
bContextDataCallback cb = reinterpret_cast<bContextDataCallback>(screen->context);
|
||||
memset(&result, 0, sizeof(result));
|
||||
cb(C, "", &result);
|
||||
|
||||
if (result.dir) {
|
||||
|
@ -642,38 +634,26 @@ void CTX_data_pointer_set_ptr(bContextDataResult *result, const PointerRNA *ptr)
|
|||
|
||||
void CTX_data_id_list_add(bContextDataResult *result, ID *id)
|
||||
{
|
||||
CollectionPointerLink *link = MEM_cnew<CollectionPointerLink>(__func__);
|
||||
link->ptr = RNA_id_pointer_create(id);
|
||||
|
||||
BLI_addtail(&result->list, link);
|
||||
result->list.append(RNA_id_pointer_create(id));
|
||||
}
|
||||
|
||||
void CTX_data_list_add(bContextDataResult *result, ID *id, StructRNA *type, void *data)
|
||||
{
|
||||
CollectionPointerLink *link = MEM_cnew<CollectionPointerLink>(__func__);
|
||||
link->ptr = RNA_pointer_create(id, type, data);
|
||||
|
||||
BLI_addtail(&result->list, link);
|
||||
result->list.append(RNA_pointer_create(id, type, data));
|
||||
}
|
||||
|
||||
void CTX_data_list_add_ptr(bContextDataResult *result, const PointerRNA *ptr)
|
||||
{
|
||||
CollectionPointerLink *link = MEM_cnew<CollectionPointerLink>(__func__);
|
||||
link->ptr = *ptr;
|
||||
|
||||
BLI_addtail(&result->list, link);
|
||||
result->list.append(*ptr);
|
||||
}
|
||||
|
||||
int ctx_data_list_count(const bContext *C, bool (*func)(const bContext *, ListBase *))
|
||||
int ctx_data_list_count(const bContext *C,
|
||||
bool (*func)(const bContext *, blender::Vector<PointerRNA> *))
|
||||
{
|
||||
ListBase list;
|
||||
|
||||
blender::Vector<PointerRNA> list;
|
||||
if (func(C, &list)) {
|
||||
int tot = BLI_listbase_count(&list);
|
||||
BLI_freelistN(&list);
|
||||
return tot;
|
||||
return list.size();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1300,62 +1280,62 @@ ToolSettings *CTX_data_tool_settings(const bContext *C)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool CTX_data_selected_ids(const bContext *C, ListBase *list)
|
||||
bool CTX_data_selected_ids(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "selected_ids", list);
|
||||
}
|
||||
|
||||
bool CTX_data_selected_nodes(const bContext *C, ListBase *list)
|
||||
bool CTX_data_selected_nodes(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "selected_nodes", list);
|
||||
}
|
||||
|
||||
bool CTX_data_selected_editable_objects(const bContext *C, ListBase *list)
|
||||
bool CTX_data_selected_editable_objects(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "selected_editable_objects", list);
|
||||
}
|
||||
|
||||
bool CTX_data_selected_editable_bases(const bContext *C, ListBase *list)
|
||||
bool CTX_data_selected_editable_bases(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_base_collection_get(C, "selected_editable_objects", list);
|
||||
}
|
||||
|
||||
bool CTX_data_editable_objects(const bContext *C, ListBase *list)
|
||||
bool CTX_data_editable_objects(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "editable_objects", list);
|
||||
}
|
||||
|
||||
bool CTX_data_editable_bases(const bContext *C, ListBase *list)
|
||||
bool CTX_data_editable_bases(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_base_collection_get(C, "editable_objects", list);
|
||||
}
|
||||
|
||||
bool CTX_data_selected_objects(const bContext *C, ListBase *list)
|
||||
bool CTX_data_selected_objects(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "selected_objects", list);
|
||||
}
|
||||
|
||||
bool CTX_data_selected_bases(const bContext *C, ListBase *list)
|
||||
bool CTX_data_selected_bases(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_base_collection_get(C, "selected_objects", list);
|
||||
}
|
||||
|
||||
bool CTX_data_visible_objects(const bContext *C, ListBase *list)
|
||||
bool CTX_data_visible_objects(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "visible_objects", list);
|
||||
}
|
||||
|
||||
bool CTX_data_visible_bases(const bContext *C, ListBase *list)
|
||||
bool CTX_data_visible_bases(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_base_collection_get(C, "visible_objects", list);
|
||||
}
|
||||
|
||||
bool CTX_data_selectable_objects(const bContext *C, ListBase *list)
|
||||
bool CTX_data_selectable_objects(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "selectable_objects", list);
|
||||
}
|
||||
|
||||
bool CTX_data_selectable_bases(const bContext *C, ListBase *list)
|
||||
bool CTX_data_selectable_bases(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_base_collection_get(C, "selectable_objects", list);
|
||||
}
|
||||
|
@ -1413,22 +1393,22 @@ CacheFile *CTX_data_edit_cachefile(const bContext *C)
|
|||
return static_cast<CacheFile *>(ctx_data_pointer_get(C, "edit_cachefile"));
|
||||
}
|
||||
|
||||
bool CTX_data_selected_bones(const bContext *C, ListBase *list)
|
||||
bool CTX_data_selected_bones(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "selected_bones", list);
|
||||
}
|
||||
|
||||
bool CTX_data_selected_editable_bones(const bContext *C, ListBase *list)
|
||||
bool CTX_data_selected_editable_bones(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "selected_editable_bones", list);
|
||||
}
|
||||
|
||||
bool CTX_data_visible_bones(const bContext *C, ListBase *list)
|
||||
bool CTX_data_visible_bones(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "visible_bones", list);
|
||||
}
|
||||
|
||||
bool CTX_data_editable_bones(const bContext *C, ListBase *list)
|
||||
bool CTX_data_editable_bones(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "editable_bones", list);
|
||||
}
|
||||
|
@ -1438,17 +1418,18 @@ bPoseChannel *CTX_data_active_pose_bone(const bContext *C)
|
|||
return static_cast<bPoseChannel *>(ctx_data_pointer_get(C, "active_pose_bone"));
|
||||
}
|
||||
|
||||
bool CTX_data_selected_pose_bones(const bContext *C, ListBase *list)
|
||||
bool CTX_data_selected_pose_bones(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "selected_pose_bones", list);
|
||||
}
|
||||
|
||||
bool CTX_data_selected_pose_bones_from_active_object(const bContext *C, ListBase *list)
|
||||
bool CTX_data_selected_pose_bones_from_active_object(const bContext *C,
|
||||
blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "selected_pose_bones_from_active_object", list);
|
||||
}
|
||||
|
||||
bool CTX_data_visible_pose_bones(const bContext *C, ListBase *list)
|
||||
bool CTX_data_visible_pose_bones(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "visible_pose_bones", list);
|
||||
}
|
||||
|
@ -1468,17 +1449,17 @@ bGPDframe *CTX_data_active_gpencil_frame(const bContext *C)
|
|||
return static_cast<bGPDframe *>(ctx_data_pointer_get(C, "active_gpencil_frame"));
|
||||
}
|
||||
|
||||
bool CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list)
|
||||
bool CTX_data_visible_gpencil_layers(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "visible_gpencil_layers", list);
|
||||
}
|
||||
|
||||
bool CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list)
|
||||
bool CTX_data_editable_gpencil_layers(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "editable_gpencil_layers", list);
|
||||
}
|
||||
|
||||
bool CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list)
|
||||
bool CTX_data_editable_gpencil_strokes(const bContext *C, blender::Vector<PointerRNA> *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "editable_gpencil_strokes", list);
|
||||
}
|
||||
|
|
|
@ -189,7 +189,7 @@ BVHTree *BKE_bmbvh_tree_get(BMBVHTree *bmtree)
|
|||
* Return the coords from a triangle.
|
||||
*/
|
||||
static void bmbvh_tri_from_face(const float *cos[3],
|
||||
const std::array<BMLoop *, 3> ltri,
|
||||
const std::array<BMLoop *, 3> <ri,
|
||||
const float (*cos_cage)[3])
|
||||
{
|
||||
if (cos_cage == nullptr) {
|
||||
|
@ -227,7 +227,7 @@ static BMFace *bmbvh_ray_cast_handle_hit(BMBVHTree *bmtree,
|
|||
{
|
||||
if (r_hitout) {
|
||||
if (bmtree->flag & BMBVH_RETURN_ORIG) {
|
||||
std::array<BMLoop *, 3> ltri = bmtree->looptris[hit->index];
|
||||
const std::array<BMLoop *, 3> <ri = bmtree->looptris[hit->index];
|
||||
interp_v3_v3v3v3_uv(r_hitout, ltri[0]->v->co, ltri[1]->v->co, ltri[2]->v->co, bmcb_data->uv);
|
||||
}
|
||||
else {
|
||||
|
@ -249,7 +249,7 @@ static BMFace *bmbvh_ray_cast_handle_hit(BMBVHTree *bmtree,
|
|||
static void bmbvh_ray_cast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
|
||||
{
|
||||
RayCastUserData *bmcb_data = static_cast<RayCastUserData *>(userdata);
|
||||
const std::array<BMLoop *, 3> ltri = bmcb_data->looptris[index];
|
||||
const std::array<BMLoop *, 3> <ri = bmcb_data->looptris[index];
|
||||
float dist, uv[2];
|
||||
const float *tri_cos[3];
|
||||
bool isect;
|
||||
|
@ -338,7 +338,7 @@ static void bmbvh_ray_cast_cb_filter(void *userdata,
|
|||
{
|
||||
RayCastUserData_Filter *bmcb_data_filter = static_cast<RayCastUserData_Filter *>(userdata);
|
||||
RayCastUserData *bmcb_data = &bmcb_data_filter->bmcb_data;
|
||||
const std::array<BMLoop *, 3> ltri = bmcb_data->looptris[index];
|
||||
const std::array<BMLoop *, 3> <ri = bmcb_data->looptris[index];
|
||||
if (bmcb_data_filter->filter_cb(ltri[0]->f, bmcb_data_filter->filter_userdata)) {
|
||||
bmbvh_ray_cast_cb(bmcb_data, index, ray, hit);
|
||||
}
|
||||
|
@ -402,7 +402,7 @@ static void bmbvh_find_vert_closest_cb(void *userdata,
|
|||
BVHTreeNearest *hit)
|
||||
{
|
||||
VertSearchUserData *bmcb_data = static_cast<VertSearchUserData *>(userdata);
|
||||
const std::array<BMLoop *, 3> ltri = bmcb_data->looptris[index];
|
||||
const std::array<BMLoop *, 3> <ri = bmcb_data->looptris[index];
|
||||
const float dist_max_sq = bmcb_data->dist_max_sq;
|
||||
|
||||
const float *tri_cos[3];
|
||||
|
@ -440,7 +440,7 @@ BMVert *BKE_bmbvh_find_vert_closest(BMBVHTree *bmtree, const float co[3], const
|
|||
|
||||
BLI_bvhtree_find_nearest(bmtree->tree, co, &hit, bmbvh_find_vert_closest_cb, &bmcb_data);
|
||||
if (hit.index != -1) {
|
||||
const std::array<BMLoop *, 3> ltri = bmtree->looptris[hit.index];
|
||||
const std::array<BMLoop *, 3> <ri = bmtree->looptris[hit.index];
|
||||
return ltri[bmcb_data.index_tri]->v;
|
||||
}
|
||||
|
||||
|
@ -462,7 +462,7 @@ static void bmbvh_find_face_closest_cb(void *userdata,
|
|||
BVHTreeNearest *hit)
|
||||
{
|
||||
FaceSearchUserData *bmcb_data = static_cast<FaceSearchUserData *>(userdata);
|
||||
const std::array<BMLoop *, 3> ltri = bmcb_data->looptris[index];
|
||||
const std::array<BMLoop *, 3> <ri = bmcb_data->looptris[index];
|
||||
const float dist_max_sq = bmcb_data->dist_max_sq;
|
||||
|
||||
const float *tri_cos[3];
|
||||
|
@ -499,7 +499,7 @@ BMFace *BKE_bmbvh_find_face_closest(BMBVHTree *bmtree, const float co[3], const
|
|||
|
||||
BLI_bvhtree_find_nearest(bmtree->tree, co, &hit, bmbvh_find_face_closest_cb, &bmcb_data);
|
||||
if (hit.index != -1) {
|
||||
const std::array<BMLoop *, 3> ltri = bmtree->looptris[hit.index];
|
||||
const std::array<BMLoop *, 3> <ri = bmtree->looptris[hit.index];
|
||||
return ltri[0]->f;
|
||||
}
|
||||
|
||||
|
@ -520,15 +520,15 @@ static bool bmbvh_overlap_cb(void *userdata, int index_a, int index_b, int /*thr
|
|||
const BMBVHTree *bmtree_a = data->tree_pair[0];
|
||||
const BMBVHTree *bmtree_b = data->tree_pair[1];
|
||||
|
||||
const std::array<BMLoop *, 3> tri_a = bmtree_a->looptris[index_a];
|
||||
const std::array<BMLoop *, 3> tri_b = bmtree_b->looptris[index_b];
|
||||
const float *tri_a_co[3] = {tri_a[0]->v->co, tri_a[1]->v->co, tri_a[2]->v->co};
|
||||
const float *tri_b_co[3] = {tri_b[0]->v->co, tri_b[1]->v->co, tri_b[2]->v->co};
|
||||
const std::array<BMLoop *, 3> <ri_a = bmtree_a->looptris[index_a];
|
||||
const std::array<BMLoop *, 3> <ri_b = bmtree_b->looptris[index_b];
|
||||
const float *tri_a_co[3] = {ltri_a[0]->v->co, ltri_a[1]->v->co, ltri_a[2]->v->co};
|
||||
const float *tri_b_co[3] = {ltri_b[0]->v->co, ltri_b[1]->v->co, ltri_b[2]->v->co};
|
||||
float ix_pair[2][3];
|
||||
int verts_shared = 0;
|
||||
|
||||
if (bmtree_a->looptris == bmtree_b->looptris) {
|
||||
if (UNLIKELY(tri_a[0]->f == tri_b[0]->f)) {
|
||||
if (UNLIKELY(ltri_a[0]->f == ltri_b[0]->f)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,14 +59,14 @@ struct SGLSLEditMeshToTangent {
|
|||
const BMLoop *GetLoop(const uint face_num, uint vert_index)
|
||||
{
|
||||
// BLI_assert(vert_index >= 0 && vert_index < 4);
|
||||
std::array<BMLoop *, 3> lt;
|
||||
BMLoop *const *ltri;
|
||||
const BMLoop *l;
|
||||
|
||||
#ifdef USE_LOOPTRI_DETECT_QUADS
|
||||
if (face_as_quad_map) {
|
||||
lt = looptris[face_as_quad_map[face_num]];
|
||||
if (lt[0]->f->len == 4) {
|
||||
l = BM_FACE_FIRST_LOOP(lt[0]->f);
|
||||
ltri = looptris[face_as_quad_map[face_num]].data();
|
||||
if (ltri[0]->f->len == 4) {
|
||||
l = BM_FACE_FIRST_LOOP(ltri[0]->f);
|
||||
while (vert_index--) {
|
||||
l = l->next;
|
||||
}
|
||||
|
@ -75,12 +75,12 @@ struct SGLSLEditMeshToTangent {
|
|||
/* fall through to regular triangle */
|
||||
}
|
||||
else {
|
||||
lt = looptris[face_num];
|
||||
ltri = looptris[face_num].data();
|
||||
}
|
||||
#else
|
||||
lt = looptris[face_num];
|
||||
ltri = looptris[face_num].data();
|
||||
#endif
|
||||
return lt[vert_index];
|
||||
return ltri[vert_index];
|
||||
}
|
||||
|
||||
mikk::float3 GetPosition(const uint face_num, const uint vert_index)
|
||||
|
|
|
@ -113,9 +113,6 @@ PartDeflect *BKE_partdeflect_copy(const PartDeflect *pd_src)
|
|||
return nullptr;
|
||||
}
|
||||
PartDeflect *pd_dst = static_cast<PartDeflect *>(MEM_dupallocN(pd_src));
|
||||
if (pd_dst->rng != nullptr) {
|
||||
pd_dst->rng = BLI_rng_copy(pd_dst->rng);
|
||||
}
|
||||
return pd_dst;
|
||||
}
|
||||
|
||||
|
@ -124,9 +121,6 @@ void BKE_partdeflect_free(PartDeflect *pd)
|
|||
if (!pd) {
|
||||
return;
|
||||
}
|
||||
if (pd->rng) {
|
||||
BLI_rng_free(pd->rng);
|
||||
}
|
||||
MEM_freeN(pd);
|
||||
}
|
||||
|
||||
|
@ -136,12 +130,8 @@ static void precalculate_effector(Depsgraph *depsgraph, EffectorCache *eff)
|
|||
{
|
||||
float ctime = DEG_get_ctime(depsgraph);
|
||||
uint cfra = uint(ctime >= 0 ? ctime : -ctime);
|
||||
if (!eff->pd->rng) {
|
||||
eff->pd->rng = BLI_rng_new(eff->pd->seed + cfra);
|
||||
}
|
||||
else {
|
||||
BLI_rng_srandom(eff->pd->rng, eff->pd->seed + cfra);
|
||||
}
|
||||
|
||||
eff->rng = BLI_rng_new(eff->pd->seed + cfra);
|
||||
|
||||
if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type == OB_CURVES_LEGACY) {
|
||||
Curve *cu = static_cast<Curve *>(eff->ob->data);
|
||||
|
@ -375,6 +365,9 @@ void BKE_effectors_free(ListBase *lb)
|
|||
{
|
||||
if (lb) {
|
||||
LISTBASE_FOREACH (EffectorCache *, eff, lb) {
|
||||
if (eff->rng) {
|
||||
BLI_rng_free(eff->rng);
|
||||
}
|
||||
if (eff->guide_data) {
|
||||
MEM_freeN(eff->guide_data);
|
||||
}
|
||||
|
@ -960,7 +953,7 @@ static void do_physical_effector(EffectorCache *eff,
|
|||
float *total_force)
|
||||
{
|
||||
PartDeflect *pd = eff->pd;
|
||||
RNG *rng = pd->rng;
|
||||
RNG *rng = eff->rng;
|
||||
float force[3] = {0, 0, 0};
|
||||
float temp[3];
|
||||
float fac;
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include "BKE_fcurve.hh"
|
||||
#include "BKE_fcurve_driver.h"
|
||||
#include "BKE_global.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_lib_query.hh"
|
||||
#include "BKE_nla.h"
|
||||
|
||||
|
@ -184,11 +184,9 @@ void BKE_fmodifiers_foreach_id(ListBase *fmodifiers, LibraryForeachIDData *data)
|
|||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, fcm_py->script, IDWALK_CB_NOP);
|
||||
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data,
|
||||
IDP_foreach_property(fcm_py->prop,
|
||||
IDP_TYPE_FILTER_ID,
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback,
|
||||
data));
|
||||
data, IDP_foreach_property(fcm_py->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_fcurve.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
|
||||
static CLG_LogRef LOG = {"bke.fmodifier"};
|
||||
|
||||
|
|
|
@ -766,7 +766,7 @@ TreeNode::TreeNode()
|
|||
this->parent = nullptr;
|
||||
|
||||
this->GreasePencilLayerTreeNode::name = nullptr;
|
||||
this->flag = 0;
|
||||
this->flag = GP_LAYER_TREE_NODE_HIDE_MASKS;
|
||||
this->color[0] = this->color[1] = this->color[2] = 0;
|
||||
}
|
||||
|
||||
|
@ -880,6 +880,7 @@ Layer::Layer()
|
|||
this->frames_storage.values = nullptr;
|
||||
this->frames_storage.flag = 0;
|
||||
|
||||
this->blend_mode = GP_LAYER_BLEND_NONE;
|
||||
this->opacity = 1.0f;
|
||||
|
||||
this->parent = nullptr;
|
||||
|
|
|
@ -805,7 +805,7 @@ static ModifierData &legacy_object_modifier_common(Object &object,
|
|||
const ModifierType type,
|
||||
GpencilModifierData &legacy_md)
|
||||
{
|
||||
/* TODO: Copy of most of #ED_object_modifier_add, this should be a BKE_modifiers function
|
||||
/* TODO: Copy of most of #ed::object::modifier_add, this should be a BKE_modifiers function
|
||||
* actually. */
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info(type);
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_global.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
@ -198,11 +198,8 @@ static void idp_resize_group_array(IDProperty *prop, int newlen, void *newarr)
|
|||
if (newlen >= prop->len) {
|
||||
/* bigger */
|
||||
IDProperty **array = static_cast<IDProperty **>(newarr);
|
||||
IDPropertyTemplate val;
|
||||
|
||||
for (int a = prop->len; a < newlen; a++) {
|
||||
val.i = 0; /* silence MSVC warning about uninitialized var when debugging */
|
||||
array[a] = IDP_New(IDP_GROUP, &val, "IDP_ResizeArray group");
|
||||
array[a] = blender::bke::idprop::create_group("IDP_ResizeArray group").release();
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1235,29 +1232,28 @@ void IDP_Reset(IDProperty *prop, const IDProperty *reference)
|
|||
|
||||
void IDP_foreach_property(IDProperty *id_property_root,
|
||||
const int type_filter,
|
||||
IDPForeachPropertyCallback callback,
|
||||
void *user_data)
|
||||
const blender::FunctionRef<void(IDProperty *id_property)> callback)
|
||||
{
|
||||
if (!id_property_root) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (type_filter == 0 || (1 << id_property_root->type) & type_filter) {
|
||||
callback(id_property_root, user_data);
|
||||
callback(id_property_root);
|
||||
}
|
||||
|
||||
/* Recursive call into container types of ID properties. */
|
||||
switch (id_property_root->type) {
|
||||
case IDP_GROUP: {
|
||||
LISTBASE_FOREACH (IDProperty *, loop, &id_property_root->data.group) {
|
||||
IDP_foreach_property(loop, type_filter, callback, user_data);
|
||||
IDP_foreach_property(loop, type_filter, callback);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IDP_IDPARRAY: {
|
||||
IDProperty *loop = static_cast<IDProperty *>(IDP_Array(id_property_root));
|
||||
for (int i = 0; i < id_property_root->len; i++) {
|
||||
IDP_foreach_property(&loop[i], type_filter, callback, user_data);
|
||||
IDP_foreach_property(&loop[i], type_filter, callback);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "BKE_idprop.hh"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_serialize.hh"
|
||||
|
||||
namespace blender::bke::idprop {
|
||||
using namespace blender::io::serialize;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "testing/testing.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_serialize.hh"
|
||||
|
||||
#include "DNA_ID.h"
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#include "DNA_ID.h"
|
||||
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
|
|
@ -2003,7 +2003,7 @@ void BKE_image_stamp_buf(Scene *scene,
|
|||
|
||||
/* must enable BLF_WORD_WRAP before using */
|
||||
#define TEXT_SIZE_CHECK_WORD_WRAP(str, w, h) \
|
||||
((str[0]) && (BLF_boundbox_ex(mono, str, sizeof(str), &wrap.rect, &wrap.info), \
|
||||
((str[0]) && (BLF_boundbox(mono, str, sizeof(str), &wrap.rect, &wrap.info), \
|
||||
(void)(h = h_fixed * wrap.info.lines), \
|
||||
(w = BLI_rcti_size_x(&wrap.rect))))
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "DNA_userdef_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_keyconfig.h" /* own include */
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
@ -42,8 +42,8 @@ wmKeyConfigPref *BKE_keyconfig_pref_ensure(UserDef *userdef, const char *kc_idna
|
|||
BLI_addtail(&userdef->user_keyconfig_prefs, kpt);
|
||||
}
|
||||
if (kpt->prop == nullptr) {
|
||||
IDPropertyTemplate val = {0};
|
||||
kpt->prop = IDP_New(IDP_GROUP, &val, kc_idname); /* name is unimportant. */
|
||||
/* name is unimportant. */
|
||||
kpt->prop = blender::bke::idprop::create_group(kc_idname).release();
|
||||
}
|
||||
return kpt;
|
||||
}
|
||||
|
@ -115,9 +115,7 @@ void BKE_keyconfig_pref_set_select_mouse(UserDef *userdef, int value, bool overr
|
|||
wmKeyConfigPref *kpt = BKE_keyconfig_pref_ensure(userdef, WM_KEYCONFIG_STR_DEFAULT);
|
||||
IDProperty *idprop = IDP_GetPropertyFromGroup(kpt->prop, "select_mouse");
|
||||
if (!idprop) {
|
||||
IDPropertyTemplate tmp{};
|
||||
tmp.i = value;
|
||||
IDP_AddToGroup(kpt->prop, IDP_New(IDP_INT, &tmp, "select_mouse"));
|
||||
IDP_AddToGroup(kpt->prop, blender::bke::idprop::create("select_mouse", value).release());
|
||||
}
|
||||
else if (override) {
|
||||
IDP_Int(idprop) = value;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "BKE_animsys.h"
|
||||
#include "BKE_collection.hh"
|
||||
#include "BKE_freestyle.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_main.hh"
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
#include "BKE_context.hh"
|
||||
#include "BKE_global.hh"
|
||||
#include "BKE_gpencil_legacy.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
#include "BKE_key.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include "BKE_anim_data.hh"
|
||||
#include "BKE_asset.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
#include "BKE_key.hh"
|
||||
#include "BKE_layer.hh"
|
||||
|
|
|
@ -4228,9 +4228,48 @@ bool BKE_lib_override_library_property_operation_operands_validate(
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool override_library_is_valid(const ID &id,
|
||||
const IDOverrideLibrary &liboverride,
|
||||
ReportList *reports)
|
||||
{
|
||||
if (liboverride.reference == nullptr) {
|
||||
/* This (probably) used to be a template ID, could be linked or local, not an override. */
|
||||
BKE_reportf(reports,
|
||||
RPT_WARNING,
|
||||
"Library override templates have been removed: removing all override data from "
|
||||
"the data-block '%s'",
|
||||
id.name);
|
||||
return false;
|
||||
}
|
||||
if (liboverride.reference == &id) {
|
||||
/* Very serious data corruption, cannot do much about it besides removing the liboverride data.
|
||||
*/
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
"Data corruption: data-block '%s' is using itself as library override reference, "
|
||||
"removing all override data",
|
||||
id.name);
|
||||
return false;
|
||||
}
|
||||
if (!ID_IS_LINKED(liboverride.reference)) {
|
||||
/* Very serious data corruption, cannot do much about it besides removing the liboverride data.
|
||||
*/
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
"Data corruption: data-block '%s' is using another local data-block ('%s') as "
|
||||
"library override reference, removing all override data",
|
||||
id.name,
|
||||
liboverride.reference->name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void BKE_lib_override_library_validate(Main *bmain, ID *id, ReportList *reports)
|
||||
{
|
||||
if (!ID_IS_OVERRIDE_LIBRARY(id)) {
|
||||
/* Do NOT use `ID_IS_OVERRIDE_LIBRARY` here, since this code also needs to fix broken cases (like
|
||||
* null reference pointer), which would be skipped by that macro. */
|
||||
if (id->override_library == nullptr && !ID_IS_OVERRIDE_LIBRARY_VIRTUAL(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4238,7 +4277,7 @@ void BKE_lib_override_library_validate(Main *bmain, ID *id, ReportList *reports)
|
|||
IDOverrideLibrary *liboverride = id->override_library;
|
||||
if (ID_IS_OVERRIDE_LIBRARY_VIRTUAL(id)) {
|
||||
liboverride = BKE_lib_override_library_get(bmain, id, nullptr, &liboverride_id);
|
||||
if (!liboverride) {
|
||||
if (!liboverride || !override_library_is_valid(*liboverride_id, *liboverride, reports)) {
|
||||
/* Happens in case the given ID is a liboverride-embedded one (actual embedded ID like
|
||||
* NodeTree or master collection, or shape-keys), used by a totally not-liboverride owner ID.
|
||||
* Just clear the relevant ID flag.
|
||||
|
@ -4252,39 +4291,8 @@ void BKE_lib_override_library_validate(Main *bmain, ID *id, ReportList *reports)
|
|||
/* NOTE: In code deleting liboverride data below, #BKE_lib_override_library_make_local is used
|
||||
* instead of directly calling #BKE_lib_override_library_free, because the former also handles
|
||||
* properly 'liboverride embedded' IDs, like root node-trees, or shape-keys. */
|
||||
|
||||
if (liboverride->reference == nullptr) {
|
||||
/* This (probably) used to be a template ID, could be linked or local, not an override. */
|
||||
BKE_reportf(reports,
|
||||
RPT_WARNING,
|
||||
"Library override templates have been removed: removing all override data from "
|
||||
"the data-block '%s'",
|
||||
liboverride_id->name);
|
||||
if (!override_library_is_valid(*liboverride_id, *liboverride, reports)) {
|
||||
BKE_lib_override_library_make_local(nullptr, liboverride_id);
|
||||
return;
|
||||
}
|
||||
if (liboverride->reference == liboverride_id) {
|
||||
/* Very serious data corruption, cannot do much about it besides removing the liboverride data.
|
||||
*/
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
"Data corruption: data-block '%s' is using itself as library override reference, "
|
||||
"removing all override data",
|
||||
liboverride_id->name);
|
||||
BKE_lib_override_library_make_local(nullptr, liboverride_id);
|
||||
return;
|
||||
}
|
||||
if (!ID_IS_LINKED(liboverride->reference)) {
|
||||
/* Very serious data corruption, cannot do much about it besides removing the liboverride data.
|
||||
*/
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
"Data corruption: data-block '%s' is using another local data-block ('%s') as "
|
||||
"library override reference, removing all override data",
|
||||
liboverride_id->name,
|
||||
liboverride->reference->name);
|
||||
BKE_lib_override_library_make_local(nullptr, liboverride_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4293,9 +4301,7 @@ void BKE_lib_override_library_main_validate(Main *bmain, ReportList *reports)
|
|||
ID *id;
|
||||
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
||||
if (ID_IS_OVERRIDE_LIBRARY(id)) {
|
||||
BKE_lib_override_library_validate(bmain, id, reports);
|
||||
}
|
||||
BKE_lib_override_library_validate(bmain, id, reports);
|
||||
}
|
||||
FOREACH_MAIN_ID_END;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_anim_data.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_lib_query.hh"
|
||||
|
@ -344,10 +344,9 @@ static bool library_foreach_ID_link(Main *bmain,
|
|||
}
|
||||
}
|
||||
|
||||
IDP_foreach_property(id->properties,
|
||||
IDP_TYPE_FILTER_ID,
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback,
|
||||
&data);
|
||||
IDP_foreach_property(id->properties, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, &data);
|
||||
});
|
||||
if (BKE_lib_query_foreachid_iter_stop(&data)) {
|
||||
library_foreach_ID_data_cleanup(&data);
|
||||
return false;
|
||||
|
|
|
@ -1005,10 +1005,10 @@ void BKE_mesh_texspace_get_reference(Mesh *mesh,
|
|||
}
|
||||
}
|
||||
|
||||
float (*BKE_mesh_orco_verts_get(Object *ob))[3]
|
||||
float (*BKE_mesh_orco_verts_get(const Object *ob))[3]
|
||||
{
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
Mesh *tme = mesh->texcomesh ? mesh->texcomesh : mesh;
|
||||
const Mesh *mesh = static_cast<const Mesh *>(ob->data);
|
||||
const Mesh *tme = mesh->texcomesh ? mesh->texcomesh : mesh;
|
||||
|
||||
/* Get appropriate vertex coordinates */
|
||||
float(*vcos)[3] = (float(*)[3])MEM_calloc_arrayN(mesh->verts_num, sizeof(*vcos), "orco mesh");
|
||||
|
|
|
@ -299,9 +299,9 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
|
|||
mesh->runtime->verts_no_face_cache.tag_dirty();
|
||||
mesh->runtime->corner_tris_cache.tag_dirty();
|
||||
mesh->runtime->corner_tri_faces_cache.tag_dirty();
|
||||
mesh->runtime->shrinkwrap_boundary_cache.tag_dirty();
|
||||
mesh->runtime->subsurf_face_dot_tags.clear_and_shrink();
|
||||
mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink();
|
||||
mesh->runtime->shrinkwrap_data.reset();
|
||||
mesh->flag &= ~ME_NO_OVERLAPPING_TOPOLOGY;
|
||||
}
|
||||
|
||||
|
@ -331,7 +331,7 @@ void Mesh::tag_edges_split()
|
|||
}
|
||||
this->runtime->subsurf_face_dot_tags.clear_and_shrink();
|
||||
this->runtime->subsurf_optimal_display_edges.clear_and_shrink();
|
||||
this->runtime->shrinkwrap_data.reset();
|
||||
this->runtime->shrinkwrap_boundary_cache.tag_dirty();
|
||||
}
|
||||
|
||||
void Mesh::tag_sharpness_changed()
|
||||
|
@ -350,6 +350,7 @@ void Mesh::tag_face_winding_changed()
|
|||
this->runtime->face_normals_cache.tag_dirty();
|
||||
this->runtime->corner_normals_cache.tag_dirty();
|
||||
this->runtime->vert_to_corner_map_cache.tag_dirty();
|
||||
this->runtime->shrinkwrap_boundary_cache.tag_dirty();
|
||||
}
|
||||
|
||||
void Mesh::tag_positions_changed()
|
||||
|
@ -357,6 +358,7 @@ void Mesh::tag_positions_changed()
|
|||
this->runtime->vert_normals_cache.tag_dirty();
|
||||
this->runtime->face_normals_cache.tag_dirty();
|
||||
this->runtime->corner_normals_cache.tag_dirty();
|
||||
this->runtime->shrinkwrap_boundary_cache.tag_dirty();
|
||||
this->tag_positions_changed_no_normals();
|
||||
}
|
||||
|
||||
|
@ -365,6 +367,7 @@ void Mesh::tag_positions_changed_no_normals()
|
|||
free_bvh_cache(*this->runtime);
|
||||
this->runtime->corner_tris_cache.tag_dirty();
|
||||
this->runtime->bounds_cache.tag_dirty();
|
||||
this->runtime->shrinkwrap_boundary_cache.tag_dirty();
|
||||
}
|
||||
|
||||
void Mesh::tag_positions_changed_uniformly()
|
||||
|
|
|
@ -60,7 +60,6 @@
|
|||
#include "BKE_context.hh"
|
||||
#include "BKE_cryptomatte.h"
|
||||
#include "BKE_global.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
#include "BKE_image_format.h"
|
||||
|
@ -320,9 +319,9 @@ static void ntree_free_data(ID *id)
|
|||
static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket *sock)
|
||||
{
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data,
|
||||
IDP_foreach_property(
|
||||
sock->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data));
|
||||
data, IDP_foreach_property(sock->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
|
||||
switch (eNodeSocketDatatype(sock->type)) {
|
||||
case SOCK_OBJECT: {
|
||||
|
@ -384,11 +383,9 @@ static void node_foreach_id(ID *id, LibraryForeachIDData *data)
|
|||
BKE_LIB_FOREACHID_PROCESS_ID(data, node->id, IDWALK_CB_USER);
|
||||
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data,
|
||||
IDP_foreach_property(node->prop,
|
||||
IDP_TYPE_FILTER_ID,
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback,
|
||||
data));
|
||||
data, IDP_foreach_property(node->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, library_foreach_node_socket(data, sock));
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_lib_query.hh"
|
||||
#include "BKE_node.hh"
|
||||
|
@ -607,11 +607,9 @@ static void item_foreach_id(LibraryForeachIDData *data, bNodeTreeInterfaceItem &
|
|||
bNodeTreeInterfaceSocket &socket = reinterpret_cast<bNodeTreeInterfaceSocket &>(item);
|
||||
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data,
|
||||
IDP_foreach_property(socket.properties,
|
||||
IDP_TYPE_FILTER_ID,
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback,
|
||||
data));
|
||||
data, IDP_foreach_property(socket.properties, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
|
||||
socket_types::socket_data_foreach_id(data, socket);
|
||||
break;
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
#include "BKE_gpencil_legacy.h"
|
||||
#include "BKE_gpencil_modifier_legacy.h"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_key.hh"
|
||||
|
@ -245,9 +245,6 @@ static void object_copy_data(Main *bmain,
|
|||
|
||||
if (ob_src->pd) {
|
||||
ob_dst->pd = (PartDeflect *)MEM_dupallocN(ob_src->pd);
|
||||
if (ob_dst->pd->rng) {
|
||||
ob_dst->pd->rng = (RNG *)MEM_dupallocN(ob_src->pd->rng);
|
||||
}
|
||||
}
|
||||
BKE_rigidbody_object_copy(bmain, ob_dst, ob_src, flag_subdata);
|
||||
|
||||
|
@ -436,11 +433,9 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data)
|
|||
if (object->pose) {
|
||||
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data,
|
||||
IDP_foreach_property(pchan->prop,
|
||||
IDP_TYPE_FILTER_ID,
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback,
|
||||
data));
|
||||
data, IDP_foreach_property(pchan->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, pchan->custom, IDWALK_CB_USER);
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
|
@ -1046,20 +1041,13 @@ static void object_lib_override_apply_post(ID *id_dst, ID *id_src)
|
|||
|
||||
static IDProperty *object_asset_dimensions_property(Object *ob)
|
||||
{
|
||||
using namespace blender::bke;
|
||||
float3 dimensions;
|
||||
BKE_object_dimensions_get(ob, dimensions);
|
||||
if (is_zero_v3(dimensions)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IDPropertyTemplate idprop{};
|
||||
idprop.array.len = 3;
|
||||
idprop.array.type = IDP_FLOAT;
|
||||
|
||||
IDProperty *property = IDP_New(IDP_ARRAY, &idprop, "dimensions");
|
||||
memcpy(IDP_Array(property), dimensions, sizeof(dimensions));
|
||||
|
||||
return property;
|
||||
return idprop::create("dimensions", Span(&dimensions.x, 3)).release();
|
||||
}
|
||||
|
||||
static void object_asset_metadata_ensure(void *asset_ptr, AssetMetaData *asset_data)
|
||||
|
@ -1068,8 +1056,7 @@ static void object_asset_metadata_ensure(void *asset_ptr, AssetMetaData *asset_d
|
|||
BLI_assert(GS(ob->id.name) == ID_OB);
|
||||
|
||||
/* Update dimensions hint for the asset. */
|
||||
IDProperty *dimensions_prop = object_asset_dimensions_property(ob);
|
||||
if (dimensions_prop) {
|
||||
if (IDProperty *dimensions_prop = object_asset_dimensions_property(ob)) {
|
||||
BKE_asset_metadata_idprop_ensure(asset_data, dimensions_prop);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include "BKE_geometry_set.hh"
|
||||
#include "BKE_geometry_set_instances.hh"
|
||||
#include "BKE_global.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_instances.hh"
|
||||
#include "BKE_main.hh"
|
||||
#include "BKE_mesh.hh"
|
||||
|
|
|
@ -1909,7 +1909,7 @@ void BKE_sculpt_color_layer_create_if_needed(Object *object)
|
|||
using namespace blender::bke;
|
||||
Mesh *orig_me = BKE_object_get_original_mesh(object);
|
||||
|
||||
if (orig_me->attributes().contains(orig_me->active_color_attribute)) {
|
||||
if (BKE_color_attribute_supported(*orig_me, orig_me->active_color_attribute)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -313,11 +313,8 @@ static void particle_settings_blend_write(BlendWriter *writer, ID *id, const voi
|
|||
}
|
||||
}
|
||||
|
||||
void BKE_particle_partdeflect_blend_read_data(BlendDataReader * /*reader*/, PartDeflect *pd)
|
||||
void BKE_particle_partdeflect_blend_read_data(BlendDataReader * /*reader*/, PartDeflect * /*pd*/)
|
||||
{
|
||||
if (pd) {
|
||||
pd->rng = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static void particle_settings_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "BKE_action.h"
|
||||
#include "BKE_action.hh"
|
||||
#include "BKE_armature.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_object_types.hh"
|
||||
|
||||
using namespace blender::bke;
|
||||
|
|
|
@ -320,7 +320,8 @@ void BKE_reports_print(ReportList *reports, eReportType level)
|
|||
return;
|
||||
}
|
||||
|
||||
puts(cstring);
|
||||
/* A trailing newline is already part of `cstring`. */
|
||||
fputs(cstring, stdout);
|
||||
fflush(stdout);
|
||||
MEM_freeN(cstring);
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
#include "BKE_editmesh.hh"
|
||||
#include "BKE_effect.h"
|
||||
#include "BKE_fcurve.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_image_format.h"
|
||||
|
@ -829,8 +829,9 @@ static bool seq_foreach_member_id_cb(Sequence *seq, void *user_data)
|
|||
FOREACHID_PROCESS_IDSUPER(data, seq->clip, IDWALK_CB_USER);
|
||||
FOREACHID_PROCESS_IDSUPER(data, seq->mask, IDWALK_CB_USER);
|
||||
FOREACHID_PROCESS_IDSUPER(data, seq->sound, IDWALK_CB_USER);
|
||||
IDP_foreach_property(
|
||||
seq->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data);
|
||||
IDP_foreach_property(seq->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
});
|
||||
LISTBASE_FOREACH (SequenceModifierData *, smd, &seq->modifiers) {
|
||||
FOREACHID_PROCESS_IDSUPER(data, smd->mask_id, IDWALK_CB_USER);
|
||||
}
|
||||
|
@ -885,10 +886,9 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data)
|
|||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, view_layer->world_override, IDWALK_CB_USER);
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data,
|
||||
IDP_foreach_property(view_layer->id_properties,
|
||||
IDP_TYPE_FILTER_ID,
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback,
|
||||
data));
|
||||
IDP_foreach_property(view_layer->id_properties, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
|
||||
BKE_view_layer_synced_ensure(scene, view_layer);
|
||||
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
|
||||
|
@ -914,11 +914,9 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data)
|
|||
LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) {
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, marker->camera, IDWALK_CB_NOP);
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data,
|
||||
IDP_foreach_property(marker->prop,
|
||||
IDP_TYPE_FILTER_ID,
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback,
|
||||
data));
|
||||
data, IDP_foreach_property(marker->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
}
|
||||
|
||||
ToolSettings *toolsett = scene->toolsettings;
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
#include "BLT_translation.hh"
|
||||
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_lib_query.hh"
|
||||
|
|
|
@ -142,7 +142,7 @@ bool BKE_shrinkwrap_init_tree(
|
|||
}
|
||||
|
||||
if (shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) {
|
||||
data->boundary = mesh->runtime->shrinkwrap_data.get();
|
||||
data->boundary = &blender::bke::shrinkwrap::boundary_cache_ensure(*mesh);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -153,9 +153,11 @@ void BKE_shrinkwrap_free_tree(ShrinkwrapTreeData *data)
|
|||
free_bvhtree_from_mesh(&data->treeData);
|
||||
}
|
||||
|
||||
namespace blender::bke::shrinkwrap {
|
||||
|
||||
/* Accumulate edge for average boundary edge direction. */
|
||||
static void merge_vert_dir(ShrinkwrapBoundaryVertData *vdata,
|
||||
signed char *status,
|
||||
MutableSpan<int8_t> status,
|
||||
int index,
|
||||
const float edge_dir[3],
|
||||
signed char side)
|
||||
|
@ -177,34 +179,28 @@ static void merge_vert_dir(ShrinkwrapBoundaryVertData *vdata,
|
|||
status[index] = (status[index] == 0) ? side : -1;
|
||||
}
|
||||
|
||||
static std::unique_ptr<ShrinkwrapBoundaryData> shrinkwrap_build_boundary_data(Mesh *mesh)
|
||||
static ShrinkwrapBoundaryData shrinkwrap_build_boundary_data(const Mesh &mesh)
|
||||
{
|
||||
using namespace blender;
|
||||
const blender::Span<float3> positions = mesh->vert_positions();
|
||||
const blender::Span<int2> edges = mesh->edges();
|
||||
const Span<int> corner_verts = mesh->corner_verts();
|
||||
const Span<int> corner_edges = mesh->corner_edges();
|
||||
const Span<float3> positions = mesh.vert_positions();
|
||||
const Span<int2> edges = mesh.edges();
|
||||
const Span<int> corner_verts = mesh.corner_verts();
|
||||
const Span<int> corner_edges = mesh.corner_edges();
|
||||
|
||||
/* Count faces per edge (up to 2). */
|
||||
char *edge_mode = static_cast<char *>(
|
||||
MEM_calloc_arrayN(size_t(mesh->edges_num), sizeof(char), __func__));
|
||||
Array<int8_t> edge_mode(edges.size(), 0);
|
||||
|
||||
for (int i = 0; i < mesh->corners_num; i++) {
|
||||
const int eidx = corner_edges[i];
|
||||
|
||||
if (edge_mode[eidx] < 2) {
|
||||
edge_mode[eidx]++;
|
||||
for (const int edge : corner_edges) {
|
||||
if (edge_mode[edge] < 2) {
|
||||
edge_mode[edge]++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Build the boundary edge bitmask. */
|
||||
blender::BitVector<> edge_is_boundary(mesh->edges_num, false);
|
||||
uint num_boundary_edges = 0;
|
||||
BitVector<> edge_is_boundary(mesh.edges_num, false);
|
||||
|
||||
for (int i = 0; i < mesh->edges_num; i++) {
|
||||
edge_mode[i] = (edge_mode[i] == 1);
|
||||
|
||||
if (edge_mode[i]) {
|
||||
int num_boundary_edges = 0;
|
||||
for (const int64_t i : edges.index_range()) {
|
||||
if (edge_mode[i] == 1) {
|
||||
edge_is_boundary[i].set();
|
||||
num_boundary_edges++;
|
||||
}
|
||||
|
@ -212,63 +208,52 @@ static std::unique_ptr<ShrinkwrapBoundaryData> shrinkwrap_build_boundary_data(Me
|
|||
|
||||
/* If no boundary, return nullptr. */
|
||||
if (num_boundary_edges == 0) {
|
||||
MEM_freeN(edge_mode);
|
||||
return {};
|
||||
}
|
||||
|
||||
/* Allocate the data object. */
|
||||
std::unique_ptr<ShrinkwrapBoundaryData> data = std::make_unique<ShrinkwrapBoundaryData>();
|
||||
|
||||
data->edge_is_boundary = std::move(edge_is_boundary);
|
||||
ShrinkwrapBoundaryData data;
|
||||
|
||||
/* Build the boundary corner_tris bit-mask. */
|
||||
const blender::Span<int3> corner_tris = mesh->corner_tris();
|
||||
const Span<int3> corner_tris = mesh.corner_tris();
|
||||
|
||||
blender::BitVector<> tri_has_boundary(corner_tris.size(), false);
|
||||
BitVector<> tri_has_boundary(corner_tris.size(), false);
|
||||
|
||||
for (const int64_t i : corner_tris.index_range()) {
|
||||
const int3 real_edges = bke::mesh::corner_tri_get_real_edges(
|
||||
edges, corner_verts, corner_edges, corner_tris[i]);
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
if (real_edges[j] >= 0 && edge_mode[real_edges[j]]) {
|
||||
if (real_edges[j] >= 0 && edge_is_boundary[real_edges[j]]) {
|
||||
tri_has_boundary[i].set();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data->tri_has_boundary = std::move(tri_has_boundary);
|
||||
|
||||
/* Find boundary vertices and build a mapping table for compact storage of data. */
|
||||
Array<int> vert_boundary_id(mesh->verts_num, 0);
|
||||
|
||||
for (int i = 0; i < mesh->edges_num; i++) {
|
||||
if (edge_mode[i]) {
|
||||
const blender::int2 &edge = edges[i];
|
||||
Array<int> vert_boundary_id(mesh.verts_num, 0);
|
||||
|
||||
for (const int64_t i : edges.index_range()) {
|
||||
if (edge_is_boundary[i]) {
|
||||
const int2 &edge = edges[i];
|
||||
vert_boundary_id[edge[0]] = 1;
|
||||
vert_boundary_id[edge[1]] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint num_boundary_verts = 0;
|
||||
|
||||
for (int i = 0; i < mesh->verts_num; i++) {
|
||||
vert_boundary_id[i] = (vert_boundary_id[i] != 0) ? int(num_boundary_verts++) : -1;
|
||||
int boundary_verts_num = 0;
|
||||
for (const int64_t i : positions.index_range()) {
|
||||
vert_boundary_id[i] = (vert_boundary_id[i] != 0) ? boundary_verts_num++ : -1;
|
||||
}
|
||||
|
||||
data->vert_boundary_id = vert_boundary_id;
|
||||
|
||||
/* Compute average directions. */
|
||||
Array<ShrinkwrapBoundaryVertData> boundary_verts(num_boundary_verts);
|
||||
Array<ShrinkwrapBoundaryVertData> boundary_verts(boundary_verts_num);
|
||||
|
||||
signed char *vert_status = static_cast<signed char *>(
|
||||
MEM_calloc_arrayN(num_boundary_verts, sizeof(char), __func__));
|
||||
|
||||
for (int i = 0; i < mesh->edges_num; i++) {
|
||||
if (edge_mode[i]) {
|
||||
const blender::int2 &edge = edges[i];
|
||||
Array<int8_t> vert_status(boundary_verts_num);
|
||||
for (const int64_t i : edges.index_range()) {
|
||||
if (edge_is_boundary[i]) {
|
||||
const int2 &edge = edges[i];
|
||||
|
||||
float dir[3];
|
||||
sub_v3_v3v3(dir, positions[edge[1]], positions[edge[0]]);
|
||||
|
@ -279,11 +264,9 @@ static std::unique_ptr<ShrinkwrapBoundaryData> shrinkwrap_build_boundary_data(Me
|
|||
}
|
||||
}
|
||||
|
||||
MEM_freeN(vert_status);
|
||||
|
||||
/* Finalize average direction and compute normal. */
|
||||
const blender::Span<blender::float3> vert_normals = mesh->vert_normals();
|
||||
for (int i = 0; i < mesh->verts_num; i++) {
|
||||
const Span<float3> vert_normals = mesh.vert_normals();
|
||||
for (const int64_t i : positions.index_range()) {
|
||||
int bidx = vert_boundary_id[i];
|
||||
|
||||
if (bidx >= 0) {
|
||||
|
@ -298,17 +281,23 @@ static std::unique_ptr<ShrinkwrapBoundaryData> shrinkwrap_build_boundary_data(Me
|
|||
}
|
||||
}
|
||||
|
||||
data->boundary_verts = std::move(boundary_verts);
|
||||
data.edge_is_boundary = std::move(edge_is_boundary);
|
||||
data.tri_has_boundary = std::move(tri_has_boundary);
|
||||
data.vert_boundary_id = std::move(vert_boundary_id);
|
||||
data.boundary_verts = std::move(boundary_verts);
|
||||
|
||||
MEM_freeN(edge_mode);
|
||||
return data;
|
||||
}
|
||||
|
||||
void BKE_shrinkwrap_compute_boundary_data(Mesh *mesh)
|
||||
const ShrinkwrapBoundaryData &boundary_cache_ensure(const Mesh &mesh)
|
||||
{
|
||||
mesh->runtime->shrinkwrap_data = shrinkwrap_build_boundary_data(mesh);
|
||||
mesh.runtime->shrinkwrap_boundary_cache.ensure(
|
||||
[&](ShrinkwrapBoundaryData &r_data) { r_data = shrinkwrap_build_boundary_data(mesh); });
|
||||
return mesh.runtime->shrinkwrap_boundary_cache.data();
|
||||
}
|
||||
|
||||
} // namespace blender::bke::shrinkwrap
|
||||
|
||||
/**
|
||||
* Shrink-wrap to the nearest vertex
|
||||
*
|
||||
|
|
|
@ -383,8 +383,8 @@ VolumeGridType get_type(const VolumeGridData &volume_grid)
|
|||
return volume_grid.grid_type();
|
||||
#else
|
||||
UNUSED_VARS(volume_grid);
|
||||
#endif
|
||||
return VOLUME_GRID_UNKNOWN;
|
||||
#endif
|
||||
}
|
||||
|
||||
int get_channels_num(const VolumeGridType type)
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "BKE_asset.hh"
|
||||
#include "BKE_global.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_lib_query.hh"
|
||||
|
|
|
@ -63,7 +63,7 @@ template<typename T, int S> inline std::string UIntF<T, S>::to_string(const int
|
|||
template<typename T, int S> inline std::string IntF<T, S>::to_string(const int base) const
|
||||
{
|
||||
if (is_negative(*this)) {
|
||||
std::string str = UIntF<T, S>(-*this);
|
||||
std::string str = UIntF<T, S>(-*this).to_string(base);
|
||||
str.insert(str.begin(), '-');
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -191,8 +191,7 @@ void BLI_memarena_merge(MemArena *ma_dst, MemArena *ma_src)
|
|||
/* Loop over `ma_src` instead of `ma_dst` since it's likely the destination is larger
|
||||
* when used for accumulating from multiple sources. */
|
||||
struct MemBuf *mb_src = ma_src->bufs;
|
||||
mb_src = ma_src->bufs;
|
||||
while (mb_src && mb_src->next) {
|
||||
while (mb_src->next) {
|
||||
mb_src = mb_src->next;
|
||||
}
|
||||
mb_src->next = ma_dst->bufs->next;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
* with only very minor edits, see:
|
||||
* http://github.com/freebsd/freebsd/blob/master/sys/libkern/qsort.c
|
||||
*
|
||||
* \note modified to use glibc arg order for callbacks.
|
||||
* \note modified to use GLIBC argument order for callbacks.
|
||||
*/
|
||||
BLI_INLINE char *med3(char *a, char *b, char *c, BLI_sort_cmp_t cmp, void *thunk);
|
||||
BLI_INLINE void swapfunc(char *a, char *b, int n, int swaptype);
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "BLI_fixed_width_int.hh"
|
||||
#include "BLI_fixed_width_int_str.hh"
|
||||
|
@ -27,6 +29,30 @@ TEST(fixed_width_int, IsZero)
|
|||
EXPECT_FALSE(is_zero(Int256(-10)));
|
||||
}
|
||||
|
||||
TEST(fixed_width_int, ToString)
|
||||
{
|
||||
{
|
||||
const std::string str = "4875677549274093345634534";
|
||||
EXPECT_EQ(UInt256(str).to_string(), str);
|
||||
}
|
||||
{
|
||||
const std::string str = "0";
|
||||
EXPECT_EQ(UInt256(str).to_string(), str);
|
||||
}
|
||||
{
|
||||
const std::string str = "4875677549274093345634534";
|
||||
EXPECT_EQ(Int256(str).to_string(), str);
|
||||
}
|
||||
{
|
||||
const std::string str = "-4875677549274093345634534";
|
||||
EXPECT_EQ(Int256(str).to_string(), str);
|
||||
}
|
||||
{
|
||||
const std::string str = "0";
|
||||
EXPECT_EQ(Int256(str).to_string(), str);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(fixed_width_int, Add256)
|
||||
{
|
||||
EXPECT_EQ(UInt256("290213998554153310989149424513459608072") +
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
#include "BKE_blender_version.h"
|
||||
#include "BKE_collection.hh"
|
||||
#include "BKE_global.hh" /* for G */
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* \ingroup blenloader
|
||||
*/
|
||||
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
/* allow readfile to use deprecated functionality */
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
#include "BKE_fcurve_driver.h"
|
||||
#include "BKE_freestyle.h"
|
||||
#include "BKE_gpencil_geom_legacy.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_key.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
#include "BKE_deform.hh"
|
||||
#include "BKE_fcurve.hh"
|
||||
#include "BKE_fcurve_driver.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_lib_override.hh"
|
||||
|
@ -1561,6 +1561,7 @@ static void do_version_subsurface_methods(bNode *node)
|
|||
|
||||
static void version_geometry_nodes_add_attribute_input_settings(NodesModifierData *nmd)
|
||||
{
|
||||
using namespace blender;
|
||||
if (nmd->settings.properties == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
@ -1583,14 +1584,13 @@ static void version_geometry_nodes_add_attribute_input_settings(NodesModifierDat
|
|||
char use_attribute_prop_name[MAX_IDPROP_NAME];
|
||||
SNPRINTF(use_attribute_prop_name, "%s%s", property->name, "_use_attribute");
|
||||
|
||||
IDPropertyTemplate idprop = {0};
|
||||
IDProperty *use_attribute_prop = IDP_New(IDP_INT, &idprop, use_attribute_prop_name);
|
||||
IDProperty *use_attribute_prop = bke::idprop::create(use_attribute_prop_name, 0).release();
|
||||
IDP_AddToGroup(nmd->settings.properties, use_attribute_prop);
|
||||
|
||||
char attribute_name_prop_name[MAX_IDPROP_NAME];
|
||||
SNPRINTF(attribute_name_prop_name, "%s%s", property->name, "_attribute_name");
|
||||
|
||||
IDProperty *attribute_prop = IDP_New(IDP_STRING, &idprop, attribute_name_prop_name);
|
||||
IDProperty *attribute_prop = bke::idprop::create(attribute_name_prop_name, "").release();
|
||||
IDP_AddToGroup(nmd->settings.properties, attribute_prop);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_grease_pencil_legacy_convert.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_ipo.h"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_lib_override.hh"
|
||||
|
@ -389,14 +389,11 @@ int version_cycles_property_int(IDProperty *idprop, const char *name, int defaul
|
|||
|
||||
void version_cycles_property_int_set(IDProperty *idprop, const char *name, int value)
|
||||
{
|
||||
IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_INT);
|
||||
if (prop) {
|
||||
if (IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_INT)) {
|
||||
IDP_Int(prop) = value;
|
||||
}
|
||||
else {
|
||||
IDPropertyTemplate val = {0};
|
||||
val.i = value;
|
||||
IDP_AddToGroup(idprop, IDP_New(IDP_INT, &val, name));
|
||||
IDP_AddToGroup(idprop, blender::bke::idprop::create(name, value).release());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
#include "BKE_curveprofile.h"
|
||||
#include "BKE_customdata.hh"
|
||||
#include "BKE_gpencil_legacy.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_main.hh"
|
||||
|
@ -200,6 +200,44 @@ static void blo_update_defaults_screen(bScreen *screen,
|
|||
/* Disable Curve Normals. */
|
||||
v3d->overlay.edit_flag &= ~V3D_OVERLAY_EDIT_CU_NORMALS;
|
||||
v3d->overlay.normals_constant_screen_size = 7.0f;
|
||||
|
||||
/* Level out the 3D Viewport camera rotation, see: #113751. */
|
||||
constexpr float viewports_to_level[][4] = {
|
||||
/* Animation, Modeling, Scripting, Texture Paint, UV Editing. */
|
||||
{0x1.6e7cb8p-1, -0x1.c1747p-2, -0x1.2997dap-2, -0x1.d5d806p-2},
|
||||
/* Layout. */
|
||||
{0x1.6e7cb8p-1, -0x1.c17478p-2, -0x1.2997dcp-2, -0x1.d5d80cp-2},
|
||||
/* Geometry Nodes. */
|
||||
{0x1.6e7cb6p-1, -0x1.c17476p-2, -0x1.2997dep-2, -0x1.d5d80cp-2},
|
||||
};
|
||||
|
||||
constexpr float viewports_to_clear_ofs[][4] = {
|
||||
/* Geometry Nodes. */
|
||||
{0x1.6e7cb6p-1, -0x1.c17476p-2, -0x1.2997dep-2, -0x1.d5d80cp-2},
|
||||
/* Sculpting. */
|
||||
{0x1.885b28p-1, -0x1.2d10cp-1, -0x1.42ae54p-3, -0x1.a486a2p-3},
|
||||
};
|
||||
|
||||
constexpr float unified_viewquat[4] = {
|
||||
0x1.6cbc88p-1, -0x1.c3a5c8p-2, -0x1.26413ep-2, -0x1.db430ap-2};
|
||||
|
||||
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
|
||||
if (region->regiontype == RGN_TYPE_WINDOW) {
|
||||
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(viewports_to_clear_ofs); i++) {
|
||||
if (equals_v4v4(rv3d->viewquat, viewports_to_clear_ofs[i])) {
|
||||
zero_v3(rv3d->ofs);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(viewports_to_level); i++) {
|
||||
if (equals_v4v4(rv3d->viewquat, viewports_to_level[i])) {
|
||||
copy_qt_qt(rv3d->viewquat, unified_viewquat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (area->spacetype == SPACE_CLIP) {
|
||||
SpaceClip *sclip = static_cast<SpaceClip *>(area->spacedata.first);
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include "BKE_addon.h"
|
||||
#include "BKE_blender_version.h"
|
||||
#include "BKE_colorband.hh"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_keyconfig.h"
|
||||
#include "BKE_main.hh"
|
||||
#include "BKE_preferences.h"
|
||||
|
|
|
@ -103,7 +103,7 @@
|
|||
#include "BKE_blender_version.h"
|
||||
#include "BKE_bpath.hh"
|
||||
#include "BKE_global.hh" /* For #Global `G`. */
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_idtype.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue