Fix #119909: Unkeyable custom properties receive keyframes #119914

Merged
Christoph Lendenfeld merged 13 commits from ChrisLend/blender:fix_more_selective_when_keying_custom_props into main 2024-04-12 14:48:20 +02:00
624 changed files with 9159 additions and 8262 deletions
Showing only changes of commit 52bb9629a8 - Show all commits

119
doc/python_api/conf.py Normal file
View File

@ -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)

View File

@ -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

View File

@ -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:

View File

@ -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)]

View File

@ -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;
}
};

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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,

View File

@ -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;

View File

@ -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 +

View File

@ -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"};

View File

@ -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. */

View File

@ -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)
*/

View File

@ -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,

View File

@ -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,
)

View File

@ -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()

View File

@ -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)

View File

@ -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')

View File

@ -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")

View File

@ -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"

View File

@ -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). */

View File

@ -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

View File

@ -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))
{
}

View File

@ -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)

View File

@ -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` */

View File

@ -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,

View File

@ -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` */

View File

@ -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);

View File

@ -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);

View File

@ -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"

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);
/**

View File

@ -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

View File

@ -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

View File

@ -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 &para
*
* 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

View File

@ -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"

View File

@ -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;
};
/**

View File

@ -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

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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"

View File

@ -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)

View File

@ -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. */

View File

@ -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);

View File

@ -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"

View File

@ -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

View File

@ -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;
}

View File

@ -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());
}
};

View File

@ -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"

View File

@ -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);

View File

@ -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);
}

View File

@ -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> &ltri,
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> &ltri = 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> &ltri = 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> &ltri = 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> &ltri = 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> &ltri = 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> &ltri = 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> &ltri = 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> &ltri_a = bmtree_a->looptris[index_a];
const std::array<BMLoop *, 3> &ltri_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;
}

View File

@ -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)

View File

@ -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;

View File

@ -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:

View File

@ -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"};

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -5,6 +5,7 @@
#include "testing/testing.h"
#include "BLI_listbase.h"
#include "BLI_serialize.hh"
#include "DNA_ID.h"

View File

@ -17,7 +17,7 @@
#include "DNA_ID.h"
#include "BKE_idprop.h"
#include "BKE_idprop.hh"
#include "BKE_idtype.hh"
#include "MEM_guardedalloc.h"

View File

@ -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))))

View File

@ -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;

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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;
}

View File

@ -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;

View File

@ -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");

View File

@ -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()

View File

@ -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));
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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"

View File

@ -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;
}

View File

@ -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)

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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"

View File

@ -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
*

View File

@ -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)

View File

@ -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"

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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") +

View File

@ -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"

View File

@ -6,7 +6,7 @@
* \ingroup blenloader
*/
#include "BKE_idprop.h"
#include "BKE_idprop.hh"
#include "BLI_utildefines.h"
/* allow readfile to use deprecated functionality */

View File

@ -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"

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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);

View File

@ -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"

View File

@ -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