GPv3: Cyclical set operator #111904

Merged
Falk David merged 16 commits from casey-bianco-davis/blender:GPv3-cyclical-set-operator into main 2023-10-20 10:12:34 +02:00
191 changed files with 3579 additions and 1587 deletions
Showing only changes of commit 051bad9e88 - Show all commits

View File

@ -513,6 +513,8 @@ endif()
# Misc
if(WIN32 OR APPLE)
option(WITH_INPUT_IME "Enable Input Method Editor (IME) for complex Asian character input" ON)
else()
set(WITH_INPUT_IME OFF)
endif()
option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON)
if(UNIX AND NOT APPLE)
@ -1138,7 +1140,7 @@ if(UNIX AND NOT (APPLE OR HAIKU))
endif()
set_and_warn_incompatible(WITH_HEADLESS WITH_GHOST_SDL OFF)
if(WIN32 OR APPLE)
if(WITH_INPUT_IME)
set_and_warn_incompatible(WITH_HEADLESS WITH_INPUT_IME OFF)
set_and_warn_incompatible(WITH_GHOST_SDL WITH_INPUT_IME OFF)
endif()

View File

@ -59,6 +59,13 @@ macro(path_ensure_trailing_slash
unset(_path_sep)
endmacro()
macro(path_strip_trailing_slash
path_new path_input
)
file(TO_NATIVE_PATH "/" _path_sep)
string(REGEX REPLACE "[${_path_sep}]+$" "" ${path_new} ${path_input})
endmacro()
# Our own version of `cmake_path(IS_PREFIX ..)`.
# This can be removed when 3.20 or greater is the minimum supported version.
macro(path_is_prefix
@ -1404,6 +1411,67 @@ Path to python site-packages or dist-packages containing '${package}' module hea
endif()
endfunction()
# Find a file in Python's module path and cache it.
# Re-generating cache upon changes to the Python installation.
# `out_var_abs`: absolute path (cached).
# `out_var_rel`: `PYTHON_ROOT` relative path (not cached).
macro(find_python_module_file
module_file
out_var_abs
out_var_rel
)
# Reset if the file isn't found.
if(DEFINED ${out_var_abs})
if(NOT EXISTS ${${out_var_abs}})
unset(${out_var_abs} CACHE)
endif()
endif()
# Reset if the version number or Python path changes.
set(_python_mod_file_deps_test "${PYTHON_LIBPATH};${PYTHON_VERSION}")
if(DEFINED _${out_var_abs}_DEPS)
if(NOT (_${out_var_abs}_DEPS STREQUAL _python_mod_file_deps_test))
unset(${out_var_abs} CACHE)
endif()
else()
unset(${out_var_abs} CACHE)
endif()
path_strip_trailing_slash(_python_root "${PYTHON_LIBPATH}")
set(_python_base "${_python_root}/python${PYTHON_VERSION}")
# This always moves up one level (even if there is a trailing slash).
get_filename_component(_python_root "${_python_root}" DIRECTORY)
path_ensure_trailing_slash(_python_root "${_python_root}")
if(NOT (DEFINED ${out_var_abs}))
message(STATUS "Finding Python Module File: ${module_file}")
find_file(${out_var_abs}
NAMES
"${module_file}"
PATHS
"${_python_base}"
PATH_SUFFIXES
"site-packages"
"dist-packages"
"vendor-packages"
""
NO_DEFAULT_PATH
)
if(${out_var_abs})
set(_${out_var_abs}_DEPS "${_python_mod_file_deps_test}" CACHE STRING "")
string(LENGTH "${_python_root}" _python_root_len)
string(SUBSTRING ${${out_var_abs}} ${_python_root_len} -1 ${out_var_rel})
unset(_python_root_len)
endif()
endif()
unset(_python_mod_file_deps_test)
unset(_python_base)
unset(_python_root)
endmacro()
# like Python's 'print(dir())'
function(print_all_vars)
get_cmake_property(_vars VARIABLES)

View File

@ -37,6 +37,14 @@ template<> struct AttributeConverter<int> {
return float(value);
}
};
template<> struct AttributeConverter<blender::float2> {
using CyclesT = float2;
static constexpr auto type_desc = TypeFloat2;
static CyclesT convert(const blender::float2 &value)
{
return make_float2(value[0], value[1]);
}
};
template<> struct AttributeConverter<blender::float3> {
using CyclesT = float3;
static constexpr auto type_desc = TypeVector;

View File

@ -345,6 +345,12 @@ string MetalDevice::preprocess_source(MetalPipelineType pso_type,
break;
case METAL_GPU_AMD:
global_defines += "#define __KERNEL_METAL_AMD__\n";
/* The increased amount of BSDF code leads to a big performance regression
* on AMD. There is currently no workaround to fix this general. Instead
* disable Principled Hair. */
if (kernel_features & KERNEL_FEATURE_NODE_PRINCIPLED_HAIR) {
global_defines += "#define WITH_PRINCIPLED_HAIR\n";
}
break;
case METAL_GPU_APPLE:
global_defines += "#define __KERNEL_METAL_APPLE__\n";

View File

@ -66,13 +66,14 @@ struct SocketType {
LINK_TEXTURE_GENERATED = (1 << 4),
LINK_TEXTURE_NORMAL = (1 << 5),
LINK_TEXTURE_UV = (1 << 6),
LINK_INCOMING = (1 << 7),
LINK_NORMAL = (1 << 8),
LINK_POSITION = (1 << 9),
LINK_TANGENT = (1 << 10),
LINK_OSL_INITIALIZER = (1 << 11),
LINK_TEXTURE_INCOMING = (1 << 7),
LINK_INCOMING = (1 << 8),
LINK_NORMAL = (1 << 9),
LINK_POSITION = (1 << 10),
LINK_TANGENT = (1 << 11),
LINK_OSL_INITIALIZER = (1 << 12),
DEFAULT_LINK_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) |
(1 << 10) | (1 << 11)
(1 << 10) | (1 << 11) | (1 << 12)
};
ustring name;

View File

@ -195,6 +195,7 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
sc, Ng, sd->wi, rand_xy, eval, wo, pdf, sampled_roughness);
*eta = 1.0f;
break;
# ifdef __PRINCIPLED_HAIR__
case CLOSURE_BSDF_HAIR_CHIANG_ID:
label = bsdf_hair_chiang_sample(kg, sc, sd, rand, eval, wo, pdf, sampled_roughness);
*eta = 1.0f;
@ -203,6 +204,7 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
label = bsdf_hair_huang_sample(kg, sc, sd, rand, eval, wo, pdf, sampled_roughness);
*eta = 1.0f;
break;
# endif
case CLOSURE_BSDF_SHEEN_ID:
label = bsdf_sheen_sample(sc, Ng, sd->wi, rand_xy, eval, wo, pdf);
*sampled_roughness = one_float2();
@ -325,6 +327,7 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
((ccl_private HairBsdf *)sc)->roughness2);
*eta = 1.0f;
break;
# ifdef __PRINCIPLED_HAIR__
case CLOSURE_BSDF_HAIR_CHIANG_ID:
alpha = ((ccl_private ChiangHairBSDF *)sc)->m0_roughness;
*roughness = make_float2(alpha, alpha);
@ -335,6 +338,7 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
*roughness = make_float2(alpha, alpha);
*eta = 1.0f;
break;
# endif
case CLOSURE_BSDF_SHEEN_ID:
alpha = ((ccl_private SheenBsdf *)sc)->roughness;
*roughness = make_float2(alpha, alpha);
@ -409,6 +413,7 @@ ccl_device_inline int bsdf_label(const KernelGlobals kg,
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
label = LABEL_TRANSMIT | LABEL_GLOSSY;
break;
# ifdef __PRINCIPLED_HAIR__
case CLOSURE_BSDF_HAIR_CHIANG_ID:
if (bsdf_is_transmission(sc, wo))
label = LABEL_TRANSMIT | LABEL_GLOSSY;
@ -418,6 +423,7 @@ ccl_device_inline int bsdf_label(const KernelGlobals kg,
case CLOSURE_BSDF_HAIR_HUANG_ID:
label = LABEL_REFLECT | LABEL_GLOSSY;
break;
# endif
case CLOSURE_BSDF_SHEEN_ID:
label = LABEL_REFLECT | LABEL_DIFFUSE;
break;
@ -500,12 +506,14 @@ ccl_device_inline
case CLOSURE_BSDF_GLOSSY_TOON_ID:
eval = bsdf_glossy_toon_eval(sc, sd->wi, wo, pdf);
break;
# ifdef __PRINCIPLED_HAIR__
case CLOSURE_BSDF_HAIR_CHIANG_ID:
eval = bsdf_hair_chiang_eval(kg, sd, sc, wo, pdf);
break;
case CLOSURE_BSDF_HAIR_HUANG_ID:
eval = bsdf_hair_huang_eval(kg, sd, sc, wo, pdf);
break;
# endif
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
eval = bsdf_hair_reflection_eval(sc, sd->wi, wo, pdf);
break;
@ -560,12 +568,14 @@ ccl_device void bsdf_blur(KernelGlobals kg, ccl_private ShaderClosure *sc, float
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
bsdf_ashikhmin_shirley_blur(sc, roughness);
break;
# ifdef __PRINCIPLED_HAIR__
case CLOSURE_BSDF_HAIR_CHIANG_ID:
bsdf_hair_chiang_blur(sc, roughness);
break;
case CLOSURE_BSDF_HAIR_HUANG_ID:
bsdf_hair_huang_blur(sc, roughness);
break;
# endif
default:
break;
}
@ -593,6 +603,7 @@ ccl_device_inline Spectrum bsdf_albedo(KernelGlobals kg,
albedo *= bsdf_microfacet_estimate_albedo(
kg, sd, (ccl_private const MicrofacetBsdf *)sc, reflection, transmission);
}
# ifdef __PRINCIPLED_HAIR__
else if (sc->type == CLOSURE_BSDF_HAIR_CHIANG_ID) {
/* TODO(lukas): Principled Hair could also be split into a glossy and a transmission component,
* similar to Glass BSDFs. */
@ -601,6 +612,7 @@ ccl_device_inline Spectrum bsdf_albedo(KernelGlobals kg,
else if (sc->type == CLOSURE_BSDF_HAIR_HUANG_ID) {
albedo *= bsdf_hair_huang_albedo(sd, sc);
}
# endif
#endif
return albedo;
}

View File

@ -638,6 +638,7 @@ ccl_device
break;
}
#ifdef __HAIR__
# ifdef __PRINCIPLED_HAIR__
case CLOSURE_BSDF_HAIR_CHIANG_ID:
case CLOSURE_BSDF_HAIR_HUANG_ID: {
uint4 data_node2 = read_node(kg, &offset);
@ -790,6 +791,7 @@ ccl_device
}
break;
}
# endif /* __PRINCIPLED_HAIR__ */
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: {
Spectrum weight = closure_weight * mix_weight;

View File

@ -75,6 +75,7 @@ CCL_NAMESPACE_BEGIN
#define __PASSES__
#define __PATCH_EVAL__
#define __POINTCLOUD__
#define __PRINCIPLED_HAIR__
#define __RAY_DIFFERENTIALS__
#define __SHADER_RAYTRACE__
#define __SHADOW_CATCHER__
@ -111,6 +112,10 @@ CCL_NAMESPACE_BEGIN
# undef __LIGHT_TREE__
/* Disabled due to compiler crash on Metal/AMD. */
# undef __MNEE__
/* Disable due to performance regression on Metal/AMD. */
# ifndef WITH_PRINCIPLED_HAIR
# undef __PRINCIPLED_HAIR__
# endif
#endif
/* Scene-based selective features compilation. */
@ -1681,9 +1686,7 @@ enum KernelFeatureFlag : uint32_t {
KERNEL_FEATURE_NODE_RAYTRACE = (1U << 6U),
KERNEL_FEATURE_NODE_AOV = (1U << 7U),
KERNEL_FEATURE_NODE_LIGHT_PATH = (1U << 8U),
/* Use denoising kernels and output denoising passes. */
KERNEL_FEATURE_DENOISING = (1U << 9U),
KERNEL_FEATURE_NODE_PRINCIPLED_HAIR = (1U << 9U),
/* Use path tracing kernels. */
KERNEL_FEATURE_PATH_TRACING = (1U << 10U),
@ -1732,6 +1735,9 @@ enum KernelFeatureFlag : uint32_t {
/* Light and shadow linking. */
KERNEL_FEATURE_LIGHT_LINKING = (1U << 27U),
KERNEL_FEATURE_SHADOW_LINKING = (1U << 28U),
/* Use denoising kernels and output denoising passes. */
KERNEL_FEATURE_DENOISING = (1U << 29U),
};
/* Shader node feature mask, to specialize shader evaluation for kernels. */
@ -1744,7 +1750,7 @@ enum KernelFeatureFlag : uint32_t {
#define KERNEL_FEATURE_NODE_MASK_SURFACE_SHADOW \
(KERNEL_FEATURE_NODE_BSDF | KERNEL_FEATURE_NODE_EMISSION | KERNEL_FEATURE_NODE_BUMP | \
KERNEL_FEATURE_NODE_BUMP_STATE | KERNEL_FEATURE_NODE_VORONOI_EXTRA | \
KERNEL_FEATURE_NODE_LIGHT_PATH)
KERNEL_FEATURE_NODE_LIGHT_PATH | KERNEL_FEATURE_NODE_PRINCIPLED_HAIR)
#define KERNEL_FEATURE_NODE_MASK_SURFACE \
(KERNEL_FEATURE_NODE_MASK_SURFACE_SHADOW | KERNEL_FEATURE_NODE_RAYTRACE | \
KERNEL_FEATURE_NODE_AOV | KERNEL_FEATURE_NODE_LIGHT_PATH)

View File

@ -349,13 +349,22 @@ void Shader::tag_update(Scene *scene)
has_displacement = has_displacement || output->input("Displacement")->link;
if (!has_surface) {
/* If we need to output surface AOVs, add a Transparent BSDF so that the
* surface shader runs. */
foreach (ShaderNode *node, graph->nodes) {
if (node->special_type == SHADER_SPECIAL_TYPE_OUTPUT_AOV) {
foreach (const ShaderInput *in, node->inputs) {
if (in->link) {
TransparentBsdfNode *transparent = graph->create_node<TransparentBsdfNode>();
graph->add(transparent);
graph->connect(transparent->output("BSDF"), output->input("Surface"));
has_surface = true;
break;
}
}
if (has_surface) {
break;
}
}
}
}

View File

@ -847,8 +847,9 @@ void ShaderGraph::default_inputs(bool do_osl)
/* nodes can specify default texture coordinates, for now we give
* everything the position by default, except for the sky texture */
ShaderNode *geom = NULL;
ShaderNode *texco = NULL;
GeometryNode *geom = NULL;
TextureCoordinateNode *texco = NULL;
VectorTransformNode *normal_transform = NULL;
foreach (ShaderNode *node, nodes) {
foreach (ShaderInput *input, node->inputs) {
@ -874,6 +875,20 @@ void ShaderGraph::default_inputs(bool do_osl)
connect(texco->output("UV"), input);
}
else if (input->flags() & SocketType::LINK_TEXTURE_INCOMING) {
if (!geom) {
geom = create_node<GeometryNode>();
}
if (!normal_transform) {
normal_transform = create_node<VectorTransformNode>();
normal_transform->set_transform_type(NODE_VECTOR_TRANSFORM_TYPE_NORMAL);
normal_transform->set_convert_from(NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD);
normal_transform->set_convert_to(NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT);
connect(geom->output("Incoming"), normal_transform->input("Vector"));
}
connect(normal_transform->output("Vector"), input);
}
else if (input->flags() & SocketType::LINK_INCOMING) {
if (!geom) {
geom = create_node<GeometryNode>();
@ -912,6 +927,9 @@ void ShaderGraph::default_inputs(bool do_osl)
if (texco) {
add(texco);
}
if (normal_transform) {
add(normal_transform);
}
}
void ShaderGraph::refine_bump_nodes()

View File

@ -1336,7 +1336,7 @@ NODE_DEFINE(IESLightNode)
SOCKET_STRING(filename, "File Name", ustring());
SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
SOCKET_IN_POINT(vector, "Vector", zero_float3(), SocketType::LINK_TEXTURE_NORMAL);
SOCKET_IN_POINT(vector, "Vector", zero_float3(), SocketType::LINK_TEXTURE_INCOMING);
SOCKET_OUT_FLOAT(fac, "Fac");

View File

@ -859,6 +859,11 @@ class PrincipledHairBsdfNode : public BsdfBaseNode {
NODE_SOCKET_API(NodePrincipledHairParametrization, parametrization)
/* Selected scattering model (near-/far-field). */
NODE_SOCKET_API(NodePrincipledHairModel, model)
virtual int get_feature()
{
return ShaderNode::get_feature() | KERNEL_FEATURE_NODE_PRINCIPLED_HAIR;
}
};
class HairBsdfNode : public BsdfNode {

View File

@ -52,18 +52,6 @@
/* Logging, use `ghost.wl.*` prefix. */
#include "CLG_log.h"
/**
* NOTE(@ideasman42): Workaround a bug with fractional scaling with LIBDECOR.
* When fractional scaling is used the GHOST window uses a buffer-scale of 1
* with the actual scale compensated for by a #wp_viewport.
*
* This causes various glitches between the GHOST window and LIBDECOR.
* While this hack doesn't resolve all of them it does fix the problem where a new windows
* decorations don't match the window, sometimes causing a delayed decrease in the windows size.
* See #109194 for related issues.
*/
#define USE_LIBDECOR_FRACTIONAL_SCALE_HACK
static const xdg_activation_token_v1_listener *xdg_activation_listener_get();
static constexpr size_t base_dpi = 96;
@ -77,6 +65,12 @@ static constexpr size_t base_dpi = 96;
struct WGL_LibDecor_Window {
libdecor_frame *frame = nullptr;
/**
* Used at startup to set the initial window size
* (before fractional scale information is available).
*/
int scale_fractional_from_output = 0;
/** The window has been configured (see #xdg_surface_ack_configure). */
bool initial_configure_seen = false;
};
@ -119,6 +113,25 @@ static void gwl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor)
delete decor;
}
/* -------------------------------------------------------------------- */
/** \name Rounding Utilities
* \{ */
static void gwl_round_int_by(int *value_p, const int round_value)
{
GHOST_ASSERT(round_value > 0, "Invalid rounding value!");
*value_p = (*value_p / round_value) * round_value;
}
static void gwl_round_int2_by(int value_p[2], const int round_value)
{
GHOST_ASSERT(round_value > 0, "Invalid rounding value!");
value_p[0] = (value_p[0] / round_value) * round_value;
value_p[1] = (value_p[1] / round_value) * round_value;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Window-Viewport/Wayland to/from Scale Conversion
* \{ */
@ -531,20 +544,6 @@ static bool gwl_window_viewport_set(GWL_Window *win,
else {
wl_surface_commit(win->wl.surface);
}
#if defined(WITH_GHOST_WAYLAND_LIBDECOR) && defined(USE_LIBDECOR_FRACTIONAL_SCALE_HACK)
/* NOTE(@ideasman42): it's important this only runs when enabling the viewport
* since there is a bug with LIBDECOR not supporting the switch from non-fractional
* to fractional scaled surfaces. */
if (use_libdecor) {
WGL_LibDecor_Window &decor = *win->libdecor;
libdecor_state *state = libdecor_state_new(
gwl_window_fractional_from_viewport_round(win->frame, win->frame.size[0]),
gwl_window_fractional_from_viewport_round(win->frame, win->frame.size[1]));
libdecor_frame_commit(decor.frame, state, nullptr);
libdecor_state_free(state);
}
#endif
}
return true;
@ -1150,25 +1149,65 @@ static void libdecor_frame_handle_configure(libdecor_frame *frame,
GWL_WindowFrame *frame_pending = &static_cast<GWL_Window *>(data)->frame_pending;
/* Set the size. */
int size_next[2];
int size_decor[2]{
libdecor_frame_get_content_width(frame),
libdecor_frame_get_content_height(frame),
};
int size_next[2] = {0, 0};
bool has_size = false;
{
GWL_Window *win = static_cast<GWL_Window *>(data);
const int scale = win->frame.buffer_scale;
if (!libdecor_configuration_get_content_size(
const int fractional_scale = win->frame.fractional_scale ?
win->frame.fractional_scale :
win->libdecor->scale_fractional_from_output;
/* The size from LIBDECOR wont use the GHOST windows buffer size.
* so it's important to calculate the buffer size that would have been used
* if fractional scaling wasn't supported. */
const int scale = fractional_scale ? (fractional_scale / FRACTIONAL_DENOMINATOR) + 1 :
win->frame.buffer_scale;
const int scale_as_fractional = scale * FRACTIONAL_DENOMINATOR;
if (libdecor_configuration_get_content_size(
configuration, frame, &size_next[0], &size_next[1])) {
size_next[0] = win->frame.size[0] / scale;
size_next[1] = win->frame.size[1] / scale;
}
if (win->frame.fractional_scale) {
win->frame_pending.size[0] = gwl_window_fractional_to_viewport_round(win->frame,
size_next[0]);
win->frame_pending.size[1] = gwl_window_fractional_to_viewport_round(win->frame,
size_next[1]);
}
else if (fractional_scale && (fractional_scale != (scale * FRACTIONAL_DENOMINATOR))) {
/* The windows `preferred_scale` is not yet available,
* set the size as if fractional scale is available. */
frame_pending->size[0] = ((size_next[0] * scale) * fractional_scale) / scale_as_fractional;
frame_pending->size[1] = ((size_next[1] * scale) * fractional_scale) / scale_as_fractional;
}
else {
frame_pending->size[0] = size_next[0] * scale;
frame_pending->size[1] = size_next[1] * scale;
}
if (win->frame.fractional_scale) {
win->frame_pending.size[0] = gwl_window_fractional_to_viewport_round(win->frame,
size_next[0]);
win->frame_pending.size[1] = gwl_window_fractional_to_viewport_round(win->frame,
size_next[1]);
/* Account for buffer rounding requirement, once fractional scaling is enabled
* the buffer scale will be 1, rounding is a requirement until then. */
gwl_round_int2_by(frame_pending->size, win->frame.buffer_scale);
has_size = true;
}
else {
frame_pending->size[0] = size_next[0] * scale;
frame_pending->size[1] = size_next[1] * scale;
/* The window decorations may be zero on startup. */
if (UNLIKELY(size_decor[0] == 0 || size_decor[1] == 0)) {
if (fractional_scale != 0 && (scale_as_fractional != fractional_scale)) {
/* Invert the fractional part: (1.25 -> 1.75), (2.75 -> 2.25), (1.5 -> 1.5).
* Needed to properly set the initial window size. */
const int scale_fractional_part_inv = scale_as_fractional -
(FRACTIONAL_DENOMINATOR -
(scale_as_fractional - fractional_scale));
size_decor[0] = ((win->frame.size[0] / scale_as_fractional) * scale_fractional_part_inv);
size_decor[1] = ((win->frame.size[1] / scale_as_fractional) * scale_fractional_part_inv);
}
else {
size_decor[0] = win->frame.size[0] / scale;
size_decor[1] = win->frame.size[1] / scale;
}
}
}
# ifdef USE_EVENT_BACKGROUND_THREAD
@ -1177,8 +1216,7 @@ static void libdecor_frame_handle_configure(libdecor_frame *frame,
* (which uses a deferred update) and the window get noticeably out of sync.
* Rely on the new `frame_pending->size` to resize the window later. */
if (is_main_thread == false) {
size_next[0] = win->frame.size[0] / scale;
size_next[1] = win->frame.size[1] / scale;
has_size = false;
}
# endif
}
@ -1211,6 +1249,10 @@ static void libdecor_frame_handle_configure(libdecor_frame *frame,
{
GWL_Window *win = static_cast<GWL_Window *>(data);
WGL_LibDecor_Window &decor = *win->libdecor;
if (has_size == false) {
size_next[0] = size_decor[0];
size_next[1] = size_decor[1];
}
libdecor_state *state = libdecor_state_new(UNPACK2(size_next));
libdecor_frame_commit(frame, state, configuration);
libdecor_state_free(state);
@ -1424,10 +1466,10 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
* is detected and enabled. Unfortunately, it doesn't seem possible to receive the
* #wp_fractional_scale_v1_listener::preferred_scale information before the window is created
* So leave the buffer scaled up because there is no *guarantee* the fractional scaling support
* will run which could result in an incorrect buffer scale.
* Leaving the buffer scale is necessary for #USE_LIBDECOR_FRACTIONAL_SCALE_HACK to work too. */
* will run which could result in an incorrect buffer scale. */
int scale_fractional_from_output;
window_->frame.buffer_scale = outputs_uniform_scale_or_default(
system_->outputs_get(), 1, nullptr);
system_->outputs_get(), 1, &scale_fractional_from_output);
window_->frame_pending.buffer_scale = window_->frame.buffer_scale;
window_->frame.size[0] = int32_t(width);
@ -1435,10 +1477,7 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
/* The window surface must be rounded to the scale,
* failing to do so causes the WAYLAND-server to close the window immediately. */
window_->frame.size[0] = (window_->frame.size[0] / window_->frame.buffer_scale) *
window_->frame.buffer_scale;
window_->frame.size[1] = (window_->frame.size[1] / window_->frame.buffer_scale) *
window_->frame.buffer_scale;
gwl_round_int2_by(window_->frame.size, window_->frame.buffer_scale);
window_->is_dialog = is_dialog;
@ -1539,12 +1578,16 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
/* Causes a glitch with `libdecor` for some reason. */
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
if (use_libdecor) {
WGL_LibDecor_Window &decor = *window_->libdecor;
if (fractional_scale_manager) {
decor.scale_fractional_from_output = scale_fractional_from_output;
}
/* Additional round-trip is needed to ensure `xdg_toplevel` is set. */
wl_display_roundtrip(system_->wl_display_get());
/* NOTE: LIBDECOR requires the window to be created & configured before the state can be set.
* Workaround this by using the underlying `xdg_toplevel` */
WGL_LibDecor_Window &decor = *window_->libdecor;
while (!decor.initial_configure_seen) {
wl_display_flush(system->wl_display_get());
wl_display_dispatch(system->wl_display_get());
@ -1709,8 +1752,11 @@ GHOST_TSuccess GHOST_WindowWayland::setClientSize(const uint32_t width, const ui
std::lock_guard lock_frame_guard{window_->frame_pending_mutex};
#endif
window_->frame_pending.size[0] = width;
window_->frame_pending.size[1] = height;
GWL_WindowFrame &frame_pending = window_->frame_pending;
frame_pending.size[0] = width;
frame_pending.size[1] = height;
gwl_round_int2_by(frame_pending.size, frame_pending.buffer_scale);
gwl_window_frame_pending_size_set(window_, nullptr, nullptr, nullptr);
@ -2219,9 +2265,7 @@ bool GHOST_WindowWayland::outputs_changed_update_scale()
window_->frame_pending.size[i] = (value * scale_next) / scale_prev;
}
if (window_->frame_pending.buffer_scale > 1) {
window_->frame_pending.size[i] = (window_->frame_pending.size[i] /
window_->frame_pending.buffer_scale) *
window_->frame_pending.buffer_scale;
gwl_round_int_by(&window_->frame_pending.size[i], window_->frame_pending.buffer_scale);
}
}

View File

@ -21,6 +21,8 @@ WAYLAND_DYNLOAD_FN(libdecor_configuration_get_window_state)
WAYLAND_DYNLOAD_FN(libdecor_decorate)
WAYLAND_DYNLOAD_FN(libdecor_dispatch)
WAYLAND_DYNLOAD_FN(libdecor_frame_commit)
WAYLAND_DYNLOAD_FN(libdecor_frame_get_content_height)
WAYLAND_DYNLOAD_FN(libdecor_frame_get_content_width)
WAYLAND_DYNLOAD_FN(libdecor_frame_get_xdg_toplevel)
WAYLAND_DYNLOAD_FN(libdecor_frame_map)
WAYLAND_DYNLOAD_FN(libdecor_frame_set_app_id)
@ -76,6 +78,8 @@ struct WaylandDynload_Libdecor {
void WL_DYN_FN(libdecor_frame_commit)(struct libdecor_frame *frame,
struct libdecor_state *state,
struct libdecor_configuration *configuration);
int WL_DYN_FN(libdecor_frame_get_content_width)(struct libdecor_frame *frame);
int WL_DYN_FN(libdecor_frame_get_content_height)(struct libdecor_frame *frame);
struct xdg_toplevel *WL_DYN_FN(libdecor_frame_get_xdg_toplevel)(struct libdecor_frame *frame);
void WL_DYN_FN(libdecor_frame_map)(struct libdecor_frame *frame);
void WL_DYN_FN(libdecor_frame_set_app_id)(struct libdecor_frame *frame, const char *app_id);
@ -112,6 +116,10 @@ struct WaylandDynload_Libdecor {
# define libdecor_dispatch(...) (*wayland_dynload_libdecor.libdecor_dispatch)(__VA_ARGS__)
# define libdecor_frame_commit(...) \
(*wayland_dynload_libdecor.libdecor_frame_commit)(__VA_ARGS__)
# define libdecor_frame_get_content_height(...) \
(*wayland_dynload_libdecor.libdecor_frame_get_content_height)(__VA_ARGS__)
# define libdecor_frame_get_content_width(...) \
(*wayland_dynload_libdecor.libdecor_frame_get_content_width)(__VA_ARGS__)
# define libdecor_frame_get_xdg_toplevel(...) \
(*wayland_dynload_libdecor.libdecor_frame_get_xdg_toplevel)(__VA_ARGS__)
# define libdecor_frame_map(...) (*wayland_dynload_libdecor.libdecor_frame_map)(__VA_ARGS__)

View File

@ -217,6 +217,7 @@ class NODE_MT_geometry_node_GEO_GEOMETRY_OPERATIONS(Menu):
layout.separator()
node_add_menu.add_node_type(layout, "GeometryNodeSeparateComponents")
node_add_menu.add_node_type(layout, "GeometryNodeSeparateGeometry")
node_add_menu.add_node_type(layout, "GeometryNodeSplitToInstances")
node_add_menu.draw_assets_for_catalog(layout, "Geometry/Operations")

View File

@ -554,7 +554,10 @@ class GreasePencilMaterialsPanel:
icon_link = 'MESH_DATA' if slot.link == 'DATA' else 'OBJECT_DATA'
row.prop(slot, "link", icon=icon_link, icon_only=True)
if not is_grease_pencil_version3 and ob.data.use_stroke_edit_mode:
if is_grease_pencil_version3 and ob.mode == 'EDIT':
row = layout.row(align=True)
row.operator("grease_pencil.stroke_change_color", text="Assign")
elif not is_grease_pencil_version3 and ob.data.use_stroke_edit_mode:
row = layout.row(align=True)
row.operator("gpencil.stroke_change_color", text="Assign")
row.operator("gpencil.material_select", text="Select").deselect = False

View File

@ -270,7 +270,7 @@ class EEVEE_NEXT_MATERIAL_PT_settings(MaterialButtonsPanel, Panel):
row.prop(mat, "alpha_threshold")
if mat.blend_method not in {'OPAQUE', 'CLIP', 'HASHED'}:
col.prop(mat, "show_transparent_back", text="Transparency")
layout.prop(mat, "show_transparent_back")
layout.prop(mat, "use_screen_refraction")
layout.prop(mat, "pass_index")

View File

@ -1902,6 +1902,10 @@ class VIEW3D_MT_select_edit_mesh(Menu):
layout.operator("mesh.select_axis", text="Side of Active")
layout.operator("mesh.select_mirror")
layout.separator()
layout.operator("mesh.select_by_attribute", text="By Attribute")
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
@ -5823,6 +5827,7 @@ class VIEW3D_MT_edit_curves(Menu):
layout.menu("VIEW3D_MT_transform")
layout.separator()
layout.operator("curves.attribute_set")
layout.operator("curves.delete")
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)

View File

@ -50,7 +50,6 @@ int insert_keyframe(Main *bmain,
int array_index,
const AnimationEvalContext *anim_eval_context,
eBezTriple_KeyframeType keytype,
ListBase *nla_cache,
eInsertKeyFlags flag);
/**

View File

@ -616,7 +616,6 @@ int insert_keyframe(Main *bmain,
int array_index,
const AnimationEvalContext *anim_eval_context,
eBezTriple_KeyframeType keytype,
ListBase *nla_cache,
eInsertKeyFlags flag)
{
/* validate pointer first - exit if failure */
@ -661,10 +660,10 @@ int insert_keyframe(Main *bmain,
/* apply NLA-mapping to frame to use (if applicable) */
NlaKeyframingContext *nla_context = nullptr;
ListBase tmp_nla_cache = {nullptr, nullptr};
ListBase nla_cache = {nullptr, nullptr};
AnimData *adt = BKE_animdata_from_id(id);
const AnimationEvalContext remapped_context = nla_time_remap(
anim_eval_context, &id_ptr, adt, act, nla_cache ? nla_cache : &tmp_nla_cache, &nla_context);
anim_eval_context, &id_ptr, adt, act, &nla_cache, &nla_context);
/* Obtain values to insert. */
float value_buffer[RNA_MAX_ARRAY_LENGTH];
@ -788,7 +787,7 @@ int insert_keyframe(Main *bmain,
}
MEM_freeN(successful_remaps);
BKE_animsys_free_nla_keyframing_context_cache(&tmp_nla_cache);
BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
if (key_count > 0) {
if (act != nullptr) {

View File

@ -128,7 +128,6 @@ void autokeyframe_object(
/* only key on available channels */
if (adt && adt->action) {
ListBase nla_cache = {nullptr, nullptr};
LISTBASE_FOREACH (FCurve *, fcu, &adt->action->curves) {
insert_keyframe(bmain,
reports,
@ -139,11 +138,8 @@ void autokeyframe_object(
fcu->array_index,
&anim_eval_context,
eBezTriple_KeyframeType(ts->keyframe_type),
&nla_cache,
flag);
}
BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
}
}
else if (is_autokey_flag(scene, AUTOKEY_FLAG_INSERTNEEDED)) {
@ -333,7 +329,6 @@ bool autokeyframe_property(bContext *C,
rnaindex,
&anim_eval_context,
eBezTriple_KeyframeType(ts->keyframe_type),
nullptr,
flag) != 0;
if (path) {
MEM_freeN(path);

View File

@ -122,7 +122,7 @@ AssetLibrary *AssetLibraryService::get_asset_library_on_disk(eAssetLibraryType l
std::string normalized_root_path = utils::normalize_directory_path(root_path);
std::unique_ptr<AssetLibrary> *lib_uptr_ptr = on_disk_libraries_.lookup_ptr(
normalized_root_path);
{library_type, normalized_root_path});
if (lib_uptr_ptr != nullptr) {
CLOG_INFO(&LOG, 2, "get \"%s\" (cached)", normalized_root_path.c_str());
AssetLibrary *lib = lib_uptr_ptr->get();
@ -139,7 +139,7 @@ AssetLibrary *AssetLibraryService::get_asset_library_on_disk(eAssetLibraryType l
/* Reload catalogs on refresh. */
lib->on_refresh_ = [](AssetLibrary &self) { self.catalog_service->reload_catalogs(); };
on_disk_libraries_.add_new(normalized_root_path, std::move(lib_uptr));
on_disk_libraries_.add_new({library_type, normalized_root_path}, std::move(lib_uptr));
CLOG_INFO(&LOG, 2, "get \"%s\" (loaded)", normalized_root_path.c_str());
return lib;
}

View File

@ -9,6 +9,7 @@
#pragma once
#include <optional>
#include <utility>
#include "AS_asset_library.hh"
@ -38,9 +39,12 @@ namespace blender::asset_system {
class AssetLibraryService {
static std::unique_ptr<AssetLibraryService> instance_;
/* Mapping absolute path of the library's root path (normalize with #normalize_directory_path()!)
* the AssetLibrary instance. */
Map<std::string, std::unique_ptr<AssetLibrary>> on_disk_libraries_;
/** Identify libraries with the library type, and the absolute path of the library's root path
* (normalize with #normalize_directory_path()!). The type is relevant since the current file
* library may point to the same path as a custom library. */
using OnDiskLibraryIdentifier = std::pair<eAssetLibraryType, std::string>;
/* Mapping of a (type, root path) pair to the AssetLibrary instance. */
Map<OnDiskLibraryIdentifier, std::unique_ptr<AssetLibrary>> on_disk_libraries_;
/** Library without a known path, i.e. the "Current File" library if the file isn't saved yet. If
* the file was saved, a valid path for the library can be determined and #on_disk_libraries_
* above should be used. */

View File

@ -113,8 +113,6 @@ TEST_F(AssetLibraryServiceTest, library_from_reference)
{
AssetLibraryService *service = AssetLibraryService::get();
AssetLibrary *const lib = service->get_asset_library_on_disk_custom(__func__,
asset_library_root_);
AssetLibrary *const curfile_lib = service->get_asset_library_current_file();
AssetLibraryReference ref{};
@ -123,12 +121,24 @@ TEST_F(AssetLibraryServiceTest, library_from_reference)
<< "Getting the local (current file) reference without a main saved on disk should return "
"the current file library";
Main dummy_main{};
std::string dummy_filepath = asset_library_root_ + SEP + "dummy.blend";
STRNCPY(dummy_main.filepath, dummy_filepath.c_str());
EXPECT_EQ(lib, service->get_asset_library(&dummy_main, ref))
<< "Getting the local (current file) reference with a main saved on disk should return "
"the an asset library for this directory";
{
Main dummy_main{};
std::string dummy_filepath = asset_library_root_ + SEP + "dummy.blend";
STRNCPY(dummy_main.filepath, dummy_filepath.c_str());
AssetLibrary *custom_lib = service->get_asset_library_on_disk_custom(__func__,
asset_library_root_);
AssetLibrary *tmp_curfile_lib = service->get_asset_library(&dummy_main, ref);
/* Requested a current file library with a (fake) file saved in the same directory as a custom
* asset library. The resulting library should never match the custom asset library, even
* though the paths match. */
EXPECT_NE(custom_lib, tmp_curfile_lib)
<< "Getting an asset library from a local (current file) library reference should never "
"match any custom asset library";
EXPECT_EQ(custom_lib->root_path(), tmp_curfile_lib->root_path());
}
}
TEST_F(AssetLibraryServiceTest, library_path_trailing_slashes)

View File

@ -29,7 +29,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 0
#define BLENDER_FILE_SUBVERSION 1
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to

View File

@ -75,6 +75,19 @@ class PointCloudFieldContext : public fn::FieldContext {
}
};
class GreasePencilFieldContext : public fn::FieldContext {
private:
const GreasePencil &grease_pencil_;
public:
GreasePencilFieldContext(const GreasePencil &grease_pencil) : grease_pencil_(grease_pencil) {}
const GreasePencil &grease_pencil() const
{
return grease_pencil_;
}
};
class GreasePencilLayerFieldContext : public fn::FieldContext {
private:
const GreasePencil &grease_pencil_;
@ -153,6 +166,7 @@ class GeometryFieldContext : public fn::FieldContext {
int grease_pencil_layer_index);
GeometryFieldContext(const Mesh &mesh, eAttrDomain domain);
GeometryFieldContext(const CurvesGeometry &curves, eAttrDomain domain);
GeometryFieldContext(const GreasePencil &grease_pencil);
GeometryFieldContext(const GreasePencil &grease_pencil, eAttrDomain domain, int layer_index);
GeometryFieldContext(const PointCloud &points);
GeometryFieldContext(const Instances &instances);

View File

@ -110,6 +110,24 @@ class Drawing : public ::GreasePencilDrawing {
bool has_users() const;
};
class DrawingReference : public ::GreasePencilDrawingReference {
public:
DrawingReference();
DrawingReference(const DrawingReference &other);
~DrawingReference();
};
const Drawing *get_eval_grease_pencil_layer_drawing(const GreasePencil &grease_pencil,
int layer_index);
Drawing *get_eval_grease_pencil_layer_drawing_for_write(GreasePencil &grease_pencil,
int layer_index);
/**
* Copies the drawings from one array to another. Assumes that \a dst_drawings is allocated but not
* initialized, e.g. it will allocate new drawings and store the pointers.
*/
void copy_drawing_array(Span<const GreasePencilDrawingBase *> src_drawings,
MutableSpan<GreasePencilDrawingBase *> dst_drawings);
class LayerGroup;
class Layer;
@ -503,6 +521,7 @@ class LayerGroup : public ::GreasePencilLayerTreeGroup {
* Adds a new layer named \a name at the end of this group and returns it.
*/
Layer &add_layer(StringRefNull name);
Layer &add_layer(const Layer &duplicate_layer);
/**
* Adds a new group named \a name at the end of this group and returns it.
*/
@ -645,11 +664,6 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
void legacy_gpencil_to_grease_pencil(Main &main, GreasePencil &grease_pencil, bGPdata &gpd);
} // namespace convert
const Drawing *get_eval_grease_pencil_layer_drawing(const GreasePencil &grease_pencil,
int layer_index);
Drawing *get_eval_grease_pencil_layer_drawing_for_write(GreasePencil &grease_pencil,
int layer_index);
} // namespace greasepencil
class GreasePencilRuntime {
@ -704,6 +718,16 @@ inline const blender::bke::greasepencil::Drawing &GreasePencilDrawing::wrap() co
return *reinterpret_cast<const blender::bke::greasepencil::Drawing *>(this);
}
inline blender::bke::greasepencil::DrawingReference &GreasePencilDrawingReference::wrap()
{
return *reinterpret_cast<blender::bke::greasepencil::DrawingReference *>(this);
}
inline const blender::bke::greasepencil::DrawingReference &GreasePencilDrawingReference::wrap()
const
{
return *reinterpret_cast<const blender::bke::greasepencil::DrawingReference *>(this);
}
inline GreasePencilFrame GreasePencilFrame::null()
{
return GreasePencilFrame{-1, 0, 0};
@ -779,6 +803,8 @@ GreasePencil *BKE_grease_pencil_new_nomain();
GreasePencil *BKE_grease_pencil_copy_for_eval(const GreasePencil *grease_pencil_src);
BoundBox *BKE_grease_pencil_boundbox_get(Object *ob);
void BKE_grease_pencil_data_update(Depsgraph *depsgraph, Scene *scene, Object *object);
void BKE_grease_pencil_duplicate_drawing_array(const GreasePencil *grease_pencil_src,
GreasePencil *grease_pencil_dst);
int BKE_grease_pencil_object_material_index_get(Object *ob, Material *ma);
int BKE_grease_pencil_object_material_index_get_by_name(Object *ob, const char *name);

View File

@ -63,6 +63,7 @@ class InstanceReference {
InstanceReference(Object &object);
InstanceReference(Collection &collection);
InstanceReference(GeometrySet geometry_set);
InstanceReference(std::unique_ptr<GeometrySet> geometry_set);
InstanceReference(const InstanceReference &other);
InstanceReference(InstanceReference &&other);
@ -187,6 +188,11 @@ class Instances {
/** \name #InstanceReference Inline Methods
* \{ */
inline InstanceReference::InstanceReference(std::unique_ptr<GeometrySet> geometry_set)
: type_(Type::GeometrySet), data_(nullptr), geometry_set_(std::move(geometry_set))
{
}
inline InstanceReference::InstanceReference(Object &object) : type_(Type::Object), data_(&object)
{
}

View File

@ -539,6 +539,7 @@ void BKE_mesh_flush_hidden_from_faces(struct Mesh *me);
void BKE_mesh_flush_select_from_faces(struct Mesh *me);
void BKE_mesh_flush_select_from_verts(struct Mesh *me);
void BKE_mesh_flush_select_from_edges(struct Mesh *me);
/* spatial evaluation */
/**

View File

@ -72,7 +72,7 @@ void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh);
void BKE_mesh_legacy_convert_loops_to_corners(Mesh *mesh);
void BKE_mesh_legacy_face_map_to_generic(Mesh *mesh);
void BKE_mesh_legacy_face_map_to_generic(Main *bmain);
/**
* Recreate #MFace Tessellation.

View File

@ -1314,6 +1314,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define GEO_NODE_TOOL_SET_FACE_SET 2113
#define GEO_NODE_POINTS_TO_CURVES 2114
#define GEO_NODE_INPUT_EDGE_SMOOTH 2115
#define GEO_NODE_SPLIT_TO_INSTANCES 2116
/** \} */

View File

@ -1230,8 +1230,8 @@ CurvesGeometry curves_copy_curve_selection(
gather_attributes(
src_attributes, ATTR_DOMAIN_CURVE, propagation_info, {}, curves_to_copy, dst_attributes);
dst_curves.remove_attributes_based_on_types();
dst_curves.update_curve_types();
dst_curves.remove_attributes_based_on_types();
return dst_curves;
}

View File

@ -98,7 +98,7 @@ static void remember_deformed_grease_pencil_if_necessary(const GreasePencil *gre
if (drawing->strokes().points_num() != orig_drawing->strokes().points_num()) {
continue;
}
drawing_hints.positions->as_mutable_span().copy_from(drawing->strokes().positions());
drawing_hints.positions.emplace(drawing->strokes().positions());
}
}

View File

@ -137,6 +137,12 @@ GeometryFieldContext::GeometryFieldContext(const PointCloud &points)
: geometry_(&points), type_(GeometryComponent::Type::PointCloud), domain_(ATTR_DOMAIN_POINT)
{
}
GeometryFieldContext::GeometryFieldContext(const GreasePencil &grease_pencil)
: geometry_(&grease_pencil),
type_(GeometryComponent::Type::GreasePencil),
domain_(ATTR_DOMAIN_LAYER)
{
}
GeometryFieldContext::GeometryFieldContext(const GreasePencil &grease_pencil,
const eAttrDomain domain,
const int layer_index)
@ -252,6 +258,11 @@ GVArray GeometryFieldInput::get_varray_for_context(const fn::FieldContext &conte
{
return this->get_varray_for_context({point_context->pointcloud()}, mask);
}
if (const GreasePencilFieldContext *grease_pencil_context =
dynamic_cast<const GreasePencilFieldContext *>(&context))
{
return this->get_varray_for_context({grease_pencil_context->grease_pencil()}, mask);
}
if (const GreasePencilLayerFieldContext *grease_pencil_context =
dynamic_cast<const GreasePencilLayerFieldContext *>(&context))
{

View File

@ -21,6 +21,7 @@
#include "BLI_bounds.hh"
#include "BLI_map.hh"
#include "BLI_math_base.hh"
#include "BLI_math_geom.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector_types.hh"
@ -94,29 +95,7 @@ static void grease_pencil_copy_data(Main * /*bmain*/,
grease_pencil_dst->material_array = static_cast<Material **>(
MEM_dupallocN(grease_pencil_src->material_array));
/* Duplicate drawing array. */
grease_pencil_dst->drawing_array_num = grease_pencil_src->drawing_array_num;
grease_pencil_dst->drawing_array = MEM_cnew_array<GreasePencilDrawingBase *>(
grease_pencil_src->drawing_array_num, __func__);
for (int i = 0; i < grease_pencil_src->drawing_array_num; i++) {
const GreasePencilDrawingBase *src_drawing_base = grease_pencil_src->drawing_array[i];
switch (src_drawing_base->type) {
case GP_DRAWING: {
const GreasePencilDrawing *src_drawing = reinterpret_cast<const GreasePencilDrawing *>(
src_drawing_base);
grease_pencil_dst->drawing_array[i] = reinterpret_cast<GreasePencilDrawingBase *>(
MEM_new<bke::greasepencil::Drawing>(__func__, src_drawing->wrap()));
break;
}
case GP_DRAWING_REFERENCE: {
const GreasePencilDrawingReference *src_drawing_reference =
reinterpret_cast<const GreasePencilDrawingReference *>(src_drawing_base);
grease_pencil_dst->drawing_array[i] = reinterpret_cast<GreasePencilDrawingBase *>(
MEM_dupallocN(src_drawing_reference));
break;
}
}
}
BKE_grease_pencil_duplicate_drawing_array(grease_pencil_src, grease_pencil_dst);
/* Duplicate layer tree. */
grease_pencil_dst->root_group_ptr = MEM_new<bke::greasepencil::LayerGroup>(
@ -431,6 +410,24 @@ void Drawing::tag_topology_changed()
this->tag_positions_changed();
}
DrawingReference::DrawingReference()
{
this->base.type = GP_DRAWING_REFERENCE;
this->base.flag = 0;
this->id_reference = nullptr;
}
DrawingReference::DrawingReference(const DrawingReference &other)
{
this->base.type = GP_DRAWING_REFERENCE;
this->base.flag = other.base.flag;
this->id_reference = other.id_reference;
}
DrawingReference::~DrawingReference() {}
const Drawing *get_eval_grease_pencil_layer_drawing(const GreasePencil &grease_pencil,
const int layer_index)
{
@ -454,6 +451,31 @@ Drawing *get_eval_grease_pencil_layer_drawing_for_write(GreasePencil &grease_pen
return const_cast<Drawing *>(get_eval_grease_pencil_layer_drawing(grease_pencil, layer));
}
void copy_drawing_array(Span<const GreasePencilDrawingBase *> src_drawings,
MutableSpan<GreasePencilDrawingBase *> dst_drawings)
{
BLI_assert(src_drawings.size() == dst_drawings.size());
for (const int i : src_drawings.index_range()) {
const GreasePencilDrawingBase *src_drawing_base = src_drawings[i];
switch (src_drawing_base->type) {
case GP_DRAWING: {
const GreasePencilDrawing *src_drawing = reinterpret_cast<const GreasePencilDrawing *>(
src_drawing_base);
dst_drawings[i] = reinterpret_cast<GreasePencilDrawingBase *>(
MEM_new<bke::greasepencil::Drawing>(__func__, src_drawing->wrap()));
break;
}
case GP_DRAWING_REFERENCE: {
const GreasePencilDrawingReference *src_drawing_reference =
reinterpret_cast<const GreasePencilDrawingReference *>(src_drawing_base);
dst_drawings[i] = reinterpret_cast<GreasePencilDrawingBase *>(
MEM_new<bke::greasepencil::DrawingReference>(__func__, src_drawing_reference->wrap()));
break;
}
}
}
}
TreeNode::TreeNode()
{
this->next = this->prev = nullptr;
@ -489,6 +511,7 @@ TreeNode::~TreeNode()
void TreeNode::set_name(StringRefNull name)
{
MEM_SAFE_FREE(this->GreasePencilLayerTreeNode::name);
this->GreasePencilLayerTreeNode::name = BLI_strdup(name.c_str());
}
@ -869,6 +892,12 @@ Layer &LayerGroup::add_layer(StringRefNull name)
return this->add_node(new_layer->as_node()).as_layer();
}
Layer &LayerGroup::add_layer(const Layer &duplicate_layer)
{
Layer *new_layer = MEM_new<Layer>(__func__, duplicate_layer);
return this->add_node(new_layer->as_node()).as_layer();
}
LayerGroup &LayerGroup::add_group(StringRefNull name)
{
LayerGroup *new_group = MEM_new<LayerGroup>(__func__, name);
@ -1206,6 +1235,17 @@ void BKE_grease_pencil_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
object->runtime.geometry_set_eval = new GeometrySet(std::move(geometry_set));
}
void BKE_grease_pencil_duplicate_drawing_array(const GreasePencil *grease_pencil_src,
GreasePencil *grease_pencil_dst)
{
using namespace blender;
grease_pencil_dst->drawing_array_num = grease_pencil_src->drawing_array_num;
grease_pencil_dst->drawing_array = MEM_cnew_array<GreasePencilDrawingBase *>(
grease_pencil_src->drawing_array_num, __func__);
bke::greasepencil::copy_drawing_array(grease_pencil_src->drawings(),
grease_pencil_dst->drawings());
}
/** \} */
/* ------------------------------------------------------------------- */
@ -1636,7 +1676,7 @@ static void remove_drawings_unchecked(GreasePencil &grease_pencil,
case GP_DRAWING_REFERENCE: {
GreasePencilDrawingReference *drawing_reference_to_remove =
reinterpret_cast<GreasePencilDrawingReference *>(drawing_base_to_remove);
MEM_freeN(drawing_reference_to_remove);
MEM_delete(&drawing_reference_to_remove->wrap());
break;
}
}
@ -1664,6 +1704,24 @@ void GreasePencil::remove_drawings_with_no_users()
remove_drawings_unchecked(*this, drawings_to_be_removed.as_span());
}
void GreasePencil::update_drawing_users_for_layer(const blender::bke::greasepencil::Layer &layer)
{
using namespace blender;
for (auto [key, value] : layer.frames().items()) {
if (value.drawing_index > 0 && value.drawing_index < this->drawings().size()) {
GreasePencilDrawingBase *drawing_base = this->drawing(value.drawing_index);
if (drawing_base->type != GP_DRAWING) {
continue;
}
bke::greasepencil::Drawing &drawing =
reinterpret_cast<GreasePencilDrawing *>(drawing_base)->wrap();
if (!drawing.has_users()) {
drawing.add_user();
}
}
}
}
void GreasePencil::move_frames(blender::bke::greasepencil::Layer &layer,
const blender::Map<int, int> &frame_number_destinations)
{
@ -1956,9 +2014,10 @@ static std::string unique_node_name(const GreasePencil &grease_pencil,
blender::StringRefNull name)
{
using namespace blender;
std::string unique_name(name.c_str());
char unique_name[MAX_NAME];
BLI_strncpy(unique_name, name.c_str(), MAX_NAME);
VectorSet<StringRefNull> names = get_node_names(grease_pencil);
unique_node_name_ex(names, default_name, unique_name.data());
unique_node_name_ex(names, default_name, unique_name);
return unique_name;
}
@ -2015,7 +2074,7 @@ static int find_layer_insertion_index(
bke::greasepencil::LayerGroup &parent_group = *group.as_node().parent_group();
const Span<const bke::greasepencil::TreeNode *> nodes = parent_group.nodes();
int index = nodes.first_index(&group.as_node());
while (index > 0 && index < nodes.size()) {
while (index > 0 && index < nodes.size() - 1) {
if (nodes[index]->is_layer()) {
break;
}
@ -2026,26 +2085,46 @@ static int find_layer_insertion_index(
index--;
}
}
index = math::clamp(index, 0, int(layers.size() - 1));
return index;
}
static void grow_or_init_customdata(GreasePencil *grease_pencil,
const blender::bke::greasepencil::LayerGroup &parent_group)
{
using namespace blender;
const Span<const bke::greasepencil::Layer *> layers = grease_pencil->layers();
if (layers.is_empty()) {
CustomData_realloc(&grease_pencil->layers_data, 0, 1);
}
else {
int insertion_index = find_layer_insertion_index(layers, parent_group, false);
grow_customdata(grease_pencil->layers_data, insertion_index, layers.size());
}
}
blender::bke::greasepencil::Layer &GreasePencil::add_layer(
blender::bke::greasepencil::LayerGroup &parent_group, const blender::StringRefNull name)
{
using namespace blender;
std::string unique_name = unique_layer_name(*this, name);
const Span<const bke::greasepencil::Layer *> layers = this->layers();
if (layers.is_empty()) {
CustomData_realloc(&this->layers_data, 0, 1);
return parent_group.add_layer(unique_name);
}
int insertion_index = find_layer_insertion_index(layers, parent_group, false);
grow_customdata(this->layers_data, insertion_index, layers.size());
grow_or_init_customdata(this, parent_group);
return parent_group.add_layer(unique_name);
}
blender::bke::greasepencil::Layer &GreasePencil::add_layer(
blender::bke::greasepencil::LayerGroup &parent_group,
const blender::bke::greasepencil::Layer &duplicate_layer)
{
using namespace blender;
std::string unique_name = unique_layer_name(*this, duplicate_layer.name());
grow_or_init_customdata(this, parent_group);
bke::greasepencil::Layer &new_layer = parent_group.add_layer(duplicate_layer);
this->update_drawing_users_for_layer(new_layer);
new_layer.set_name(unique_name);
return new_layer;
}
blender::bke::greasepencil::LayerGroup &GreasePencil::add_layer_group(
blender::bke::greasepencil::LayerGroup &parent_group, const blender::StringRefNull name)
{
@ -2284,10 +2363,6 @@ void GreasePencil::move_node_into(blender::bke::greasepencil::TreeNode &node,
const Span<const bke::greasepencil::Layer *> layers = this->layers();
const int from_index = layers.first_index(&node.as_layer());
int to_index = find_layer_insertion_index(layers, parent_group, true);
if (from_index > to_index) {
to_index++;
}
reorder_layer_data(*this, from_index, to_index);
}
if (node.is_group()) {
@ -2477,7 +2552,7 @@ static void free_drawing_array(GreasePencil &grease_pencil)
case GP_DRAWING_REFERENCE: {
GreasePencilDrawingReference *drawing_reference =
reinterpret_cast<GreasePencilDrawingReference *>(drawing_base);
MEM_freeN(drawing_reference);
MEM_delete(&drawing_reference->wrap());
break;
}
}

View File

@ -129,8 +129,14 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
/* Do first point. */
const bGPDspoint &first_pt = stroke_points.first();
stroke_positions.first() = float3(first_pt.x, first_pt.y, first_pt.z);
/* Store the actual radius of the stroke (without layer adjustment). */
stroke_radii.first() = gps->thickness * first_pt.pressure;
/* Previously, Grease Pencil used a radius convention where 1 "px" = 0.001 units. This "px" was
* the brush size which would be stored in the stroke thickness and then scaled by the point
* pressure factor. Finally, the render engine would divide this thickness value by 2000 (we're
* going from a thickness to a radius, hence the factor of two) to convert back into blender
* units.
* Store the radius now directly in blender units. This makes it consistent with how hair
* curves handle the radius. */
stroke_radii.first() = gps->thickness * first_pt.pressure / 2000.0f;
stroke_opacities.first() = first_pt.strength;
stroke_deltatimes.first() = 0;
stroke_rotations.first() = first_pt.uv_rot;
@ -143,8 +149,7 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
const bGPDspoint &pt_prev = stroke_points[point_i - 1];
const bGPDspoint &pt = stroke_points[point_i];
stroke_positions[point_i] = float3(pt.x, pt.y, pt.z);
/* Store the actual radius of the stroke (without layer adjustment). */
stroke_radii[point_i] = gps->thickness * pt.pressure;
stroke_radii[point_i] = gps->thickness * pt.pressure / 2000.0f;
stroke_opacities[point_i] = pt.strength;
stroke_deltatimes[point_i] = pt.time - pt_prev.time;
stroke_rotations[point_i] = pt.uv_rot;

View File

@ -683,6 +683,44 @@ void BKE_mesh_flush_select_from_verts(Mesh *me)
select_poly.finish();
}
void BKE_mesh_flush_select_from_edges(Mesh *me)
{
using namespace blender;
using namespace blender::bke;
MutableAttributeAccessor attributes = me->attributes_for_write();
const VArray<bool> select_edge = *attributes.lookup_or_default<bool>(
".select_edge", ATTR_DOMAIN_POINT, false);
if (select_edge.is_single() && !select_edge.get_internal_single()) {
attributes.remove(".select_vert");
attributes.remove(".select_poly");
return;
}
SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_only_span<bool>(
".select_vert", ATTR_DOMAIN_POINT);
SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_only_span<bool>(
".select_poly", ATTR_DOMAIN_FACE);
{
IndexMaskMemory memory;
const VArray<bool> hide_vert = *attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
array_utils::copy(
*attributes.lookup_or_default<bool>(".select_vert", ATTR_DOMAIN_POINT, false),
IndexMask::from_bools(hide_vert, memory).complement(hide_vert.index_range(), memory),
select_vert.span);
}
{
IndexMaskMemory memory;
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
array_utils::copy(
*attributes.lookup_or_default<bool>(".select_vert", ATTR_DOMAIN_FACE, false),
IndexMask::from_bools(hide_poly, memory).complement(hide_poly.index_range(), memory),
select_poly.span);
}
select_vert.finish();
select_poly.finish();
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@ -17,11 +17,13 @@
#include "DNA_object_types.h"
#include "BLI_array_utils.hh"
#include "BLI_listbase.h"
#include "BLI_map.hh"
#include "BLI_math_geom.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector_types.hh"
#include "BLI_memarena.h"
#include "BLI_multi_value_map.hh"
#include "BLI_polyfill_2d.h"
#include "BLI_resource_scope.hh"
#include "BLI_string.h"
@ -31,6 +33,7 @@
#include "BKE_attribute.hh"
#include "BKE_customdata.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_mesh.hh"
#include "BKE_mesh_legacy_convert.hh"
#include "BKE_multires.hh"
@ -1346,18 +1349,18 @@ void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
/** \name Face Map Conversion
* \{ */
void BKE_mesh_legacy_face_map_to_generic(Mesh *mesh)
static void move_face_map_data_to_attributes(Mesh *mesh)
{
using namespace blender;
if (mesh->attributes().contains("face_maps")) {
return;
}
void *data = nullptr;
int *data = nullptr;
const ImplicitSharingInfo *sharing_info = nullptr;
for (const int i : IndexRange(mesh->face_data.totlayer)) {
CustomDataLayer &layer = mesh->face_data.layers[i];
if (layer.type == CD_FACEMAP) {
data = layer.data;
data = static_cast<int *>(layer.data);
sharing_info = layer.sharing_info;
layer.data = nullptr;
layer.sharing_info = nullptr;
@ -1365,13 +1368,53 @@ void BKE_mesh_legacy_face_map_to_generic(Mesh *mesh)
break;
}
}
if (data != nullptr) {
CustomData_add_layer_named_with_data(
&mesh->face_data, CD_PROP_INT32, data, mesh->faces_num, "face_maps", sharing_info);
if (!data) {
return;
}
CustomData_add_layer_named_with_data(
&mesh->face_data, CD_PROP_INT32, data, mesh->faces_num, "face_maps", sharing_info);
if (sharing_info != nullptr) {
sharing_info->remove_user_and_delete_if_last();
}
MultiValueMap<int, int> groups;
for (const int i : IndexRange(mesh->faces_num)) {
if (data[i] == -1) {
/* -1 values "didn't have" a face map. */
continue;
}
groups.add(data[i], i);
}
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
for (const auto item : groups.items()) {
bke::SpanAttributeWriter<bool> attribute = attributes.lookup_or_add_for_write_span<bool>(
".temp_face_map_" + std::to_string(item.key), ATTR_DOMAIN_FACE);
if (attribute) {
attribute.span.fill_indices(item.value.as_span(), true);
attribute.finish();
}
}
}
void BKE_mesh_legacy_face_map_to_generic(Main *bmain)
{
LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
move_face_map_data_to_attributes(mesh);
}
LISTBASE_FOREACH (Object *, object, &bmain->objects) {
if (object->type != OB_MESH) {
continue;
}
Mesh *mesh = static_cast<Mesh *>(object->data);
int i;
LISTBASE_FOREACH_INDEX (bFaceMap *, face_map, &object->fmaps, i) {
mesh->attributes_for_write().rename(".temp_face_map_" + std::to_string(i), face_map->name);
}
BLI_freelistN(&object->fmaps);
}
}
/** \} */

View File

@ -707,6 +707,7 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id)
/* Only for versioning, vertex group names are now stored on object data. */
BLO_read_list(reader, &ob->defbase);
BLO_read_list(reader, &ob->fmaps);
/* XXX deprecated - old animation system <<< */
direct_link_nlastrips(reader, &ob->nlastrips);

File diff suppressed because it is too large Load Diff

View File

@ -181,6 +181,8 @@ void count_indices(Span<int> indices, MutableSpan<int> counts);
void invert_booleans(MutableSpan<bool> span);
void invert_booleans(MutableSpan<bool> span, const IndexMask &mask);
int64_t count_booleans(const VArray<bool> &varray);
enum class BooleanMix {
None,
AllFalse,

View File

@ -141,4 +141,40 @@ BooleanMix booleans_mix_calc(const VArray<bool> &varray, const IndexRange range_
[&](BooleanMix a, BooleanMix b) { return (a == b) ? a : BooleanMix::Mixed; });
}
int64_t count_booleans(const VArray<bool> &varray)
{
if (varray.is_empty()) {
return 0;
}
const CommonVArrayInfo info = varray.common_info();
if (info.type == CommonVArrayInfo::Type::Single) {
return *static_cast<const bool *>(info.data) ? varray.size() : 0;
}
if (info.type == CommonVArrayInfo::Type::Span) {
const Span<bool> span(static_cast<const bool *>(info.data), varray.size());
return threading::parallel_reduce(
varray.index_range(),
4096,
0,
[&](const IndexRange range, const int64_t init) {
const Span<bool> slice = span.slice(range);
return init + std::count(slice.begin(), slice.end(), true);
},
std::plus<int64_t>());
}
return threading::parallel_reduce(
varray.index_range(),
2048,
0,
[&](const IndexRange range, const int64_t init) {
int64_t value = init;
/* Alternatively, this could use #materialize to retrieve many values at once. */
for (const int64_t i : range) {
value += int64_t(varray[i]);
}
return value;
},
std::plus<int64_t>());
}
} // namespace blender::array_utils

View File

@ -311,6 +311,10 @@ void do_versions_after_linking_400(FileData *fd, Main *bmain)
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 34)) {
BKE_mesh_legacy_face_map_to_generic(bmain);
}
/**
* Versioning code until next subversion bump goes here.
*
@ -1055,6 +1059,30 @@ static void enable_geometry_nodes_is_modifier(Main &bmain)
}
}
static void versioning_grease_pencil_stroke_radii_scaling(GreasePencil *grease_pencil)
{
using namespace blender;
/* Previously, Grease Pencil used a radius convention where 1 "px" = 0.001 units. This "px" was
* the brush size which would be stored in the stroke thickness and then scaled by the point
* pressure factor. Finally, the render engine would divide this thickness value by 2000 (we're
* going from a thickness to a radius, hence the factor of two) to convert back into blender
* units.
* Store the radius now directly in blender units. This makes it consistent with how hair curves
* handle the radius. */
for (GreasePencilDrawingBase *base : grease_pencil->drawings()) {
if (base->type != GP_DRAWING) {
continue;
}
bke::greasepencil::Drawing &drawing = reinterpret_cast<GreasePencilDrawing *>(base)->wrap();
MutableSpan<float> radii = drawing.radii_for_write();
threading::parallel_for(radii.index_range(), 8192, [&](const IndexRange range) {
for (const int i : range) {
radii[i] /= 2000.0f;
}
});
}
}
void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
{
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 1)) {
@ -1089,17 +1117,14 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
#define SCE_SNAP_PROJECT (1 << 3)
if (ts->snap_flag & SCE_SNAP_PROJECT) {
ts->snap_mode &= ~SCE_SNAP_TO_FACE;
ts->snap_mode |= SCE_SNAP_INDIVIDUAL_PROJECT;
ts->snap_mode &= ~(1 << 2); /* SCE_SNAP_TO_FACE */
ts->snap_mode |= (1 << 8); /* SCE_SNAP_INDIVIDUAL_PROJECT */
}
#undef SCE_SNAP_PROJECT
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 6)) {
LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
BKE_mesh_legacy_face_map_to_generic(mesh);
}
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
versioning_replace_legacy_glossy_node(ntree);
versioning_remove_microfacet_sharp_distribution(ntree);
@ -1382,7 +1407,7 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
scene->toolsettings->snap_flag_anim |= SCE_SNAP;
scene->toolsettings->snap_anim_mode |= SCE_SNAP_TO_FRAME;
scene->toolsettings->snap_anim_mode |= (1 << 10); /* SCE_SNAP_TO_FRAME */
}
}
@ -1634,10 +1659,10 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
snap_to_new |= SCE_SNAP_TO_GRID;
}
if (type == IS_DEFAULT && snap_to_old & (1 << 8)) {
snap_to_new |= SCE_SNAP_INDIVIDUAL_PROJECT;
snap_to_new |= SCE_SNAP_INDIVIDUAL_NEAREST;
}
if (type == IS_DEFAULT && snap_to_old & (1 << 9)) {
snap_to_new |= SCE_SNAP_INDIVIDUAL_NEAREST;
snap_to_new |= SCE_SNAP_INDIVIDUAL_PROJECT;
}
if (snap_to_old & (1 << 10)) {
snap_to_new |= SCE_SNAP_TO_FRAME;
@ -1685,6 +1710,12 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 1)) {
LISTBASE_FOREACH (GreasePencil *, grease_pencil, &bmain->grease_pencils) {
versioning_grease_pencil_stroke_radii_scaling(grease_pencil);
}
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -149,11 +149,6 @@ static CLG_LogRef LOG = {"blo.writefile"};
/** \name Internal Write Wrapper's (Abstracts Compression)
* \{ */
enum eWriteWrapType {
WW_WRAP_NONE = 1,
WW_WRAP_ZSTD,
};
struct ZstdFrame {
ZstdFrame *next, *prev;
@ -161,70 +156,94 @@ struct ZstdFrame {
uint32_t uncompressed_size;
};
struct WriteWrap {
/* callbacks */
bool (*open)(WriteWrap *ww, const char *filepath);
bool (*close)(WriteWrap *ww);
size_t (*write)(WriteWrap *ww, const char *data, size_t data_len);
class WriteWrap {
public:
virtual bool open(const char *filepath) = 0;
virtual bool close() = 0;
virtual bool write(const void *data, size_t data_len) = 0;
/* Buffer output (we only want when output isn't already buffered). */
bool use_buf;
/* internal */
int file_handle;
struct {
ListBase threadpool;
ListBase tasks;
ThreadMutex mutex;
ThreadCondition condition;
int next_frame;
int num_frames;
int level;
ListBase frames;
bool write_error;
} zstd;
/* Buffer output (we only want when output isn't already buffered). */
bool use_buf = true;
};
/* none */
static bool ww_open_none(WriteWrap *ww, const char *filepath)
class RawWriteWrap : public WriteWrap {
public:
bool open(const char *filepath) override;
bool close() override;
bool write(const void *data, size_t data_len) override;
private:
int file_handle = 0;
};
bool RawWriteWrap::open(const char *filepath)
{
int file;
file = BLI_open(filepath, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666);
if (file != -1) {
ww->file_handle = file;
file_handle = file;
return true;
}
return false;
}
static bool ww_close_none(WriteWrap *ww)
bool RawWriteWrap::close()
{
return (close(ww->file_handle) != -1);
return (::close(file_handle) != -1);
}
static size_t ww_write_none(WriteWrap *ww, const char *buf, size_t buf_len)
bool RawWriteWrap::write(const void *buf, size_t buf_len)
{
return write(ww->file_handle, buf, buf_len);
return ::write(file_handle, buf, buf_len) == buf_len;
}
/* zstd */
class ZstdWriteWrap : public WriteWrap {
WriteWrap &baseWrap;
struct ZstdWriteBlockTask {
ListBase threadpool = {};
ListBase tasks = {};
ThreadMutex mutex = {};
ThreadCondition condition = {};
int next_frame = 0;
int num_frames = 0;
int level = 0;
ListBase frames = {};
bool write_error = false;
public:
ZstdWriteWrap(WriteWrap &baseWrap) : baseWrap(baseWrap) {}
bool open(const char *filepath) override;
bool close() override;
bool write(const void *data, size_t data_len) override;
private:
struct ZstdWriteBlockTask;
void write_task(ZstdWriteBlockTask *task);
void write_u32_le(uint32_t val);
void write_seekable_frames();
};
struct ZstdWriteWrap::ZstdWriteBlockTask {
ZstdWriteBlockTask *next, *prev;
void *data;
size_t size;
int frame_number;
WriteWrap *ww;
ZstdWriteWrap *ww;
static void *write_task(void *userdata)
{
auto *task = static_cast<ZstdWriteBlockTask *>(userdata);
task->ww->write_task(task);
return nullptr;
}
};
static void *zstd_write_task(void *userdata)
void ZstdWriteWrap::write_task(ZstdWriteBlockTask *task)
{
ZstdWriteBlockTask *task = static_cast<ZstdWriteBlockTask *>(userdata);
WriteWrap *ww = task->ww;
size_t out_buf_len = ZSTD_compressBound(task->size);
void *out_buf = MEM_mallocN(out_buf_len, "Zstd out buffer");
size_t out_size = ZSTD_compress(
@ -232,58 +251,57 @@ static void *zstd_write_task(void *userdata)
MEM_freeN(task->data);
BLI_mutex_lock(&ww->zstd.mutex);
BLI_mutex_lock(&mutex);
while (ww->zstd.next_frame != task->frame_number) {
BLI_condition_wait(&ww->zstd.condition, &ww->zstd.mutex);
while (next_frame != task->frame_number) {
BLI_condition_wait(&condition, &mutex);
}
if (ZSTD_isError(out_size)) {
ww->zstd.write_error = true;
write_error = true;
}
else {
if (ww_write_none(ww, static_cast<const char *>(out_buf), out_size) == out_size) {
if (baseWrap.write(out_buf, out_size)) {
ZstdFrame *frameinfo = static_cast<ZstdFrame *>(
MEM_mallocN(sizeof(ZstdFrame), "zstd frameinfo"));
frameinfo->uncompressed_size = task->size;
frameinfo->compressed_size = out_size;
BLI_addtail(&ww->zstd.frames, frameinfo);
BLI_addtail(&frames, frameinfo);
}
else {
ww->zstd.write_error = true;
write_error = true;
}
}
ww->zstd.next_frame++;
next_frame++;
BLI_mutex_unlock(&ww->zstd.mutex);
BLI_condition_notify_all(&ww->zstd.condition);
BLI_mutex_unlock(&mutex);
BLI_condition_notify_all(&condition);
MEM_freeN(out_buf);
return nullptr;
}
static bool ww_open_zstd(WriteWrap *ww, const char *filepath)
bool ZstdWriteWrap::open(const char *filepath)
{
if (!ww_open_none(ww, filepath)) {
if (!baseWrap.open(filepath)) {
return false;
}
/* Leave one thread open for the main writing logic, unless we only have one HW thread. */
int num_threads = max_ii(1, BLI_system_thread_count() - 1);
BLI_threadpool_init(&ww->zstd.threadpool, zstd_write_task, num_threads);
BLI_mutex_init(&ww->zstd.mutex);
BLI_condition_init(&ww->zstd.condition);
BLI_threadpool_init(&threadpool, ZstdWriteBlockTask::write_task, num_threads);
BLI_mutex_init(&mutex);
BLI_condition_init(&condition);
return true;
}
static void zstd_write_u32_le(WriteWrap *ww, uint32_t val)
void ZstdWriteWrap::write_u32_le(uint32_t val)
{
#ifdef __BIG_ENDIAN__
BLI_endian_switch_uint32(&val);
#endif
ww_write_none(ww, (char *)&val, sizeof(uint32_t));
baseWrap.write(&val, sizeof(uint32_t));
}
/* In order to implement efficient seeking when reading the .blend, we append
@ -294,49 +312,49 @@ static void zstd_write_u32_le(WriteWrap *ww, uint32_t val)
* If this information is not present in a file (e.g. if it was compressed
* with external tools), it can still be opened in Blender, but seeking will
* not be supported, so more memory might be needed. */
static void zstd_write_seekable_frames(WriteWrap *ww)
void ZstdWriteWrap::write_seekable_frames()
{
/* Write seek table header (magic number and frame size). */
zstd_write_u32_le(ww, 0x184D2A5E);
write_u32_le(0x184D2A5E);
/* The actual frame number might not match ww->zstd.num_frames if there was a write error. */
const uint32_t num_frames = BLI_listbase_count(&ww->zstd.frames);
/* The actual frame number might not match num_frames if there was a write error. */
const uint32_t num_frames = BLI_listbase_count(&frames);
/* Each frame consists of two u32, so 8 bytes each.
* After the frames, a footer containing two u32 and one byte (9 bytes total) is written. */
const uint32_t frame_size = num_frames * 8 + 9;
zstd_write_u32_le(ww, frame_size);
write_u32_le(frame_size);
/* Write seek table entries. */
LISTBASE_FOREACH (ZstdFrame *, frame, &ww->zstd.frames) {
zstd_write_u32_le(ww, frame->compressed_size);
zstd_write_u32_le(ww, frame->uncompressed_size);
LISTBASE_FOREACH (ZstdFrame *, frame, &frames) {
write_u32_le(frame->compressed_size);
write_u32_le(frame->uncompressed_size);
}
/* Write seek table footer (number of frames, option flags and second magic number). */
zstd_write_u32_le(ww, num_frames);
write_u32_le(num_frames);
const char flags = 0; /* We don't store checksums for each frame. */
ww_write_none(ww, &flags, 1);
zstd_write_u32_le(ww, 0x8F92EAB1);
baseWrap.write(&flags, 1);
write_u32_le(0x8F92EAB1);
}
static bool ww_close_zstd(WriteWrap *ww)
bool ZstdWriteWrap::close()
{
BLI_threadpool_end(&ww->zstd.threadpool);
BLI_freelistN(&ww->zstd.tasks);
BLI_threadpool_end(&threadpool);
BLI_freelistN(&tasks);
BLI_mutex_end(&ww->zstd.mutex);
BLI_condition_end(&ww->zstd.condition);
BLI_mutex_end(&mutex);
BLI_condition_end(&condition);
zstd_write_seekable_frames(ww);
BLI_freelistN(&ww->zstd.frames);
write_seekable_frames();
BLI_freelistN(&frames);
return ww_close_none(ww) && !ww->zstd.write_error;
return baseWrap.close() && !write_error;
}
static size_t ww_write_zstd(WriteWrap *ww, const char *buf, size_t buf_len)
bool ZstdWriteWrap::write(const void *buf, size_t buf_len)
{
if (ww->zstd.write_error) {
return 0;
if (write_error) {
return false;
}
ZstdWriteBlockTask *task = static_cast<ZstdWriteBlockTask *>(
@ -344,54 +362,30 @@ static size_t ww_write_zstd(WriteWrap *ww, const char *buf, size_t buf_len)
task->data = MEM_mallocN(buf_len, __func__);
memcpy(task->data, buf, buf_len);
task->size = buf_len;
task->frame_number = ww->zstd.num_frames++;
task->ww = ww;
task->frame_number = num_frames++;
task->ww = this;
BLI_mutex_lock(&ww->zstd.mutex);
BLI_addtail(&ww->zstd.tasks, task);
BLI_mutex_lock(&mutex);
BLI_addtail(&tasks, task);
/* If there's a free worker thread, just push the block into that thread.
* Otherwise, we wait for the earliest thread to finish.
* We look up the earliest thread while holding the mutex, but release it
* before joining the thread to prevent a deadlock. */
ZstdWriteBlockTask *first_task = static_cast<ZstdWriteBlockTask *>(ww->zstd.tasks.first);
BLI_mutex_unlock(&ww->zstd.mutex);
if (!BLI_available_threads(&ww->zstd.threadpool)) {
BLI_threadpool_remove(&ww->zstd.threadpool, first_task);
ZstdWriteBlockTask *first_task = static_cast<ZstdWriteBlockTask *>(tasks.first);
BLI_mutex_unlock(&mutex);
if (!BLI_available_threads(&threadpool)) {
BLI_threadpool_remove(&threadpool, first_task);
/* If the task list was empty before we pushed our task, there should
* always be a free thread. */
BLI_assert(first_task != task);
BLI_remlink(&ww->zstd.tasks, first_task);
BLI_remlink(&tasks, first_task);
MEM_freeN(first_task);
}
BLI_threadpool_insert(&ww->zstd.threadpool, task);
BLI_threadpool_insert(&threadpool, task);
return buf_len;
}
/* --- end compression types --- */
static void ww_handle_init(eWriteWrapType ww_type, WriteWrap *r_ww)
{
memset(r_ww, 0, sizeof(*r_ww));
switch (ww_type) {
case WW_WRAP_ZSTD: {
r_ww->open = ww_open_zstd;
r_ww->close = ww_close_zstd;
r_ww->write = ww_write_zstd;
r_ww->use_buf = true;
break;
}
default: {
r_ww->open = ww_open_none;
r_ww->close = ww_close_none;
r_ww->write = ww_write_none;
r_ww->use_buf = true;
break;
}
}
return true;
}
/** \} */
@ -483,7 +477,7 @@ static void writedata_do_write(WriteData *wd, const void *mem, size_t memlen)
BLO_memfile_chunk_add(&wd->mem, static_cast<const char *>(mem), memlen);
}
else {
if (wd->ww->write(wd->ww, static_cast<const char *>(mem), memlen) != memlen) {
if (!wd->ww->write(mem, memlen)) {
wd->error = true;
}
}
@ -1463,23 +1457,17 @@ static void write_file_main_validate_post(Main *bmain, ReportList *reports)
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name File Writing (Public)
* \{ */
bool BLO_write_file(Main *mainvar,
const char *filepath,
const int write_flags,
const BlendFileWriteParams *params,
ReportList *reports)
static bool BLO_write_file_impl(Main *mainvar,
const char *filepath,
const int write_flags,
const BlendFileWriteParams *params,
ReportList *reports,
WriteWrap &ww)
{
BLI_assert(!BLI_path_is_rel(filepath));
BLI_assert(BLI_path_is_abs_from_cwd(filepath));
char tempname[FILE_MAX + 1];
WriteWrap ww;
eBLO_WritePathRemap remap_mode = params->remap_mode;
const bool use_save_versions = params->use_save_versions;
@ -1498,9 +1486,7 @@ bool BLO_write_file(Main *mainvar,
/* open temporary file, so we preserve the original in case we crash */
SNPRINTF(tempname, "%s@", filepath);
ww_handle_init((write_flags & G_FILE_COMPRESS) ? WW_WRAP_ZSTD : WW_WRAP_NONE, &ww);
if (ww.open(&ww, tempname) == false) {
if (ww.open(tempname) == false) {
BKE_reportf(
reports, RPT_ERROR, "Cannot open file %s for writing: %s", tempname, strerror(errno));
return false;
@ -1593,7 +1579,7 @@ bool BLO_write_file(Main *mainvar,
const bool err = write_file_handle(
mainvar, &ww, nullptr, nullptr, write_flags, use_userdef, thumb);
ww.close(&ww);
ww.close();
if (UNLIKELY(path_list_backup)) {
BKE_bpath_list_restore(mainvar, path_list_flag, path_list_backup);
@ -1626,6 +1612,26 @@ bool BLO_write_file(Main *mainvar,
return true;
}
/* -------------------------------------------------------------------- */
/** \name File Writing (Public)
* \{ */
bool BLO_write_file(Main *mainvar,
const char *filepath,
const int write_flags,
const BlendFileWriteParams *params,
ReportList *reports)
{
RawWriteWrap raw_wrap;
if (write_flags & G_FILE_COMPRESS) {
ZstdWriteWrap zstd_wrap(raw_wrap);
return BLO_write_file_impl(mainvar, filepath, write_flags, params, reports, zstd_wrap);
}
return BLO_write_file_impl(mainvar, filepath, write_flags, params, reports, raw_wrap);
}
bool BLO_write_file_mem(Main *mainvar, MemFile *compare, MemFile *current, int write_flags)
{
bool use_userdef = false;

View File

@ -42,10 +42,8 @@ if(WITH_PYTHON)
)
endif()
if(WIN32 OR APPLE)
if(WITH_INPUT_IME)
add_definitions(-DWITH_INPUT_IME)
endif()
if(WITH_INPUT_IME)
add_definitions(-DWITH_INPUT_IME)
endif()
blender_add_lib(bf_blentranslation "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@ -13,6 +13,7 @@
# include "BLI_map.hh"
# include "BLI_ordered_edge.hh"
# include "BLI_set.hh"
# include "BLI_utildefines.h"
# include "bmesh.h"
@ -36,6 +37,17 @@
(void)0
# endif
template<> struct blender::DefaultHash<blender::Set<const BMVert *>> {
uint64_t operator()(const blender::Set<const BMVert *> &value) const
{
uint64_t hash = 0;
for (const BMVert *vert : value) {
hash = get_default_hash_2(hash, vert);
}
return hash;
}
};
bool BM_mesh_validate(BMesh *bm)
{
blender::Map<blender::OrderedEdge, BMEdge *> edge_hash;
@ -119,6 +131,7 @@ bool BM_mesh_validate(BMesh *bm)
}
/* face structure */
blender::Map<blender::Set<const BMVert *>, int> face_map;
BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
BMLoop *l_iter;
BMLoop *l_first;
@ -138,6 +151,8 @@ bool BM_mesh_validate(BMesh *bm)
j = 0;
blender::Set<const BMVert *> face_verts;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
if (BM_elem_flag_test(l_iter, BM_ELEM_INTERNAL_TAG)) {
@ -175,9 +190,17 @@ bool BM_mesh_validate(BMesh *bm)
BM_elem_flag_enable(l_iter, BM_ELEM_INTERNAL_TAG);
BM_elem_flag_enable(l_iter->v, BM_ELEM_INTERNAL_TAG);
BM_elem_flag_enable(l_iter->e, BM_ELEM_INTERNAL_TAG);
face_verts.add(l_iter->v);
j++;
} while ((l_iter = l_iter->next) != l_first);
face_map.add_or_modify(
std::move(face_verts),
[&](int *value) { *value = i; },
[&](int *value) { ERRMSG("face %d: duplicate of %d", i, *value); });
if (j != f->len) {
ERRMSG("face %d: has length of %d but should be %d", i, f->len, j);
}

View File

@ -685,6 +685,7 @@ set(GLSL_SRC
intern/draw_shader_shared.h
engines/gpencil/shaders/gpencil_frag.glsl
engines/gpencil/shaders/grease_pencil_frag.glsl
engines/gpencil/shaders/gpencil_vert.glsl
engines/gpencil/shaders/grease_pencil_vert.glsl
engines/gpencil/shaders/gpencil_antialiasing_frag.glsl

View File

@ -610,12 +610,21 @@ void Instance::light_bake_irradiance(
capture_view.render_world();
irradiance_cache.bake.surfels_create(probe);
if (irradiance_cache.bake.should_break()) {
return;
}
irradiance_cache.bake.surfels_lights_eval();
irradiance_cache.bake.clusters_build();
irradiance_cache.bake.irradiance_offset();
});
if (irradiance_cache.bake.should_break()) {
return;
}
sampling.init(probe);
while (!sampling.finished()) {
context_wrapper([&]() {

View File

@ -863,13 +863,22 @@ void IrradianceBake::surfels_create(const Object &probe_object)
irradiance_L1_b_tx_.ensure_3d(GPU_RGBA32F, grid_resolution, texture_usage);
irradiance_L1_c_tx_.ensure_3d(GPU_RGBA32F, grid_resolution, texture_usage);
validity_tx_.ensure_3d(GPU_R32F, grid_resolution, texture_usage);
virtual_offset_tx_.ensure_3d(GPU_RGBA16F, grid_resolution, texture_usage);
if (!irradiance_L0_tx_.is_valid() || !irradiance_L1_a_tx_.is_valid() ||
!irradiance_L1_b_tx_.is_valid() || !irradiance_L1_c_tx_.is_valid() ||
!validity_tx_.is_valid() || !virtual_offset_tx_.is_valid())
{
inst_.info = "Error: Not enough memory to bake " + std::string(probe_object.id.name) + ".";
do_break_ = true;
return;
}
irradiance_L0_tx_.clear(float4(0.0f));
irradiance_L1_a_tx_.clear(float4(0.0f));
irradiance_L1_b_tx_.clear(float4(0.0f));
irradiance_L1_c_tx_.clear(float4(0.0f));
validity_tx_.clear(float4(0.0f));
virtual_offset_tx_.ensure_3d(GPU_RGBA16F, grid_resolution, texture_usage);
virtual_offset_tx_.clear(float4(0.0f));
DRW_stats_group_start("IrradianceBake.SceneBounds");
@ -950,10 +959,28 @@ void IrradianceBake::surfels_create(const Object &probe_object)
capture_info_buf_.read();
if (capture_info_buf_.surfel_len == 0) {
/* No surfel to allocated. */
do_break_ = true;
return;
}
/* TODO(fclem): Check for GL limit and abort if the surfel cache doesn't fit the GPU memory. */
if (capture_info_buf_.surfel_len > surfels_buf_.size()) {
size_t max_size = GPU_max_storage_buffer_size();
if (GPU_mem_stats_supported()) {
int total_mem_kb, free_mem_kb;
GPU_mem_stats_get(&total_mem_kb, &free_mem_kb);
max_size = min(max_size, size_t(free_mem_kb) * 1024);
}
size_t required_mem = sizeof(Surfel) * (capture_info_buf_.surfel_len - surfels_buf_.size());
if (required_mem > max_size) {
capture_info_buf_.surfel_len = 0u;
capture_info_buf_.push_update();
inst_.info = "Error: Not enough memory to bake " + std::string(probe_object.id.name) + ".";
do_break_ = true;
return;
}
}
surfels_buf_.resize(capture_info_buf_.surfel_len);
surfels_buf_.clear_to_zero();

View File

@ -130,12 +130,21 @@ class IrradianceBake {
/** True if emission is recorded during the light propagation. */
bool capture_emission_ = false;
/** True if the bake job should stop. */
bool do_break_ = false;
public:
IrradianceBake(Instance &inst) : inst_(inst){};
void init(const Object &probe_object);
void sync();
/** True if the bake job should stop. */
bool should_break()
{
return do_break_;
}
/** Create the views used to rasterize the scene into surfel representation. */
void surfel_raster_views_sync(float3 scene_min, float3 scene_max, float4x4 probe_to_world);
/** Create a surfel representation of the scene from the probe using the capture pipeline. */

View File

@ -179,6 +179,11 @@ class LightBake {
}
});
if (instance_->info != "") {
/** TODO: Print to the Status Bar UI. */
printf("%s\n", instance_->info.c_str());
}
if ((G.is_break == true) || (stop != nullptr && *stop == true)) {
break;
}

View File

@ -0,0 +1,142 @@
/* SPDX-FileCopyrightText: 2020-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma BLENDER_REQUIRE(common_grease_pencil_lib.glsl)
#pragma BLENDER_REQUIRE(common_colormanagement_lib.glsl)
float length_squared(vec2 v)
{
return dot(v, v);
}
float length_squared(vec3 v)
{
return dot(v, v);
}
vec3 gpencil_lighting(void)
{
vec3 light_accum = vec3(0.0);
for (int i = 0; i < GPENCIL_LIGHT_BUFFER_LEN; i++) {
if (gp_lights[i]._color.x == -1.0) {
break;
}
vec3 L = gp_lights[i]._position - gp_interp.pos;
float vis = 1.0;
gpLightType type = floatBitsToUint(gp_lights[i]._type);
/* Spot Attenuation. */
if (type == GP_LIGHT_TYPE_SPOT) {
mat3 rot_scale = mat3(gp_lights[i]._right, gp_lights[i]._up, gp_lights[i]._forward);
vec3 local_L = rot_scale * L;
local_L /= abs(local_L.z);
float ellipse = inversesqrt(length_squared(local_L));
vis *= smoothstep(0.0, 1.0, (ellipse - gp_lights[i]._spot_size) / gp_lights[i]._spot_blend);
/* Also mask +Z cone. */
vis *= step(0.0, local_L.z);
}
/* Inverse square decay. Skip for suns. */
float L_len_sqr = length_squared(L);
if (type < GP_LIGHT_TYPE_SUN) {
vis /= L_len_sqr;
}
else {
L = gp_lights[i]._forward;
L_len_sqr = 1.0;
}
/* Lambertian falloff */
if (type != GP_LIGHT_TYPE_AMBIENT) {
L /= sqrt(L_len_sqr);
vis *= clamp(dot(gpNormal, L), 0.0, 1.0);
}
light_accum += vis * gp_lights[i]._color;
}
/* Clamp to avoid NaNs. */
return clamp(light_accum, 0.0, 1e10);
}
void main()
{
vec4 col;
if (flag_test(gp_interp_flat.mat_flag, GP_STROKE_TEXTURE_USE)) {
bool premul = flag_test(gp_interp_flat.mat_flag, GP_STROKE_TEXTURE_PREMUL);
col = texture_read_as_linearrgb(gpStrokeTexture, premul, gp_interp.uv);
}
else if (flag_test(gp_interp_flat.mat_flag, GP_FILL_TEXTURE_USE)) {
bool use_clip = flag_test(gp_interp_flat.mat_flag, GP_FILL_TEXTURE_CLIP);
vec2 uvs = (use_clip) ? clamp(gp_interp.uv, 0.0, 1.0) : gp_interp.uv;
bool premul = flag_test(gp_interp_flat.mat_flag, GP_FILL_TEXTURE_PREMUL);
col = texture_read_as_linearrgb(gpFillTexture, premul, uvs);
}
else if (flag_test(gp_interp_flat.mat_flag, GP_FILL_GRADIENT_USE)) {
bool radial = flag_test(gp_interp_flat.mat_flag, GP_FILL_GRADIENT_RADIAL);
float fac = clamp(radial ? length(gp_interp.uv * 2.0 - 1.0) : gp_interp.uv.x, 0.0, 1.0);
uint matid = gp_interp_flat.mat_flag >> GPENCIl_MATID_SHIFT;
col = mix(gp_materials[matid].fill_color, gp_materials[matid].fill_mix_color, fac);
}
else /* SOLID */ {
col = vec4(1.0);
}
col.rgb *= col.a;
/* Composite all other colors on top of texture color.
* Everything is pre-multiply by `col.a` to have the stencil effect. */
fragColor = col * gp_interp.color_mul + col.a * gp_interp.color_add;
fragColor.rgb *= gpencil_lighting();
fragColor *= gpencil_stroke_round_cap_mask(gp_interp_flat.sspos.xy,
gp_interp_flat.sspos.zw,
gp_interp_flat.aspect,
gp_interp_noperspective.thickness.x,
gp_interp_noperspective.hardness);
/* To avoid aliasing artifacts, we reduce the opacity of small strokes. */
fragColor *= smoothstep(0.0, 1.0, gp_interp_noperspective.thickness.y);
/* Holdout materials. */
if (flag_test(gp_interp_flat.mat_flag, GP_STROKE_HOLDOUT | GP_FILL_HOLDOUT)) {
revealColor = fragColor.aaaa;
}
else {
/* NOT holdout materials.
* For compatibility with colored alpha buffer.
* Note that we are limited to mono-chromatic alpha blending here
* because of the blend equation and the limit of 1 color target
* when using custom color blending. */
revealColor = vec4(0.0, 0.0, 0.0, fragColor.a);
if (fragColor.a < 0.001) {
discard;
return;
}
}
vec2 fb_size = max(vec2(textureSize(gpSceneDepthTexture, 0).xy),
vec2(textureSize(gpMaskTexture, 0).xy));
vec2 uvs = gl_FragCoord.xy / fb_size;
/* Manual depth test */
float scene_depth = texture(gpSceneDepthTexture, uvs).r;
if (gl_FragCoord.z > scene_depth) {
discard;
return;
}
/* FIXME(fclem): Grrr. This is bad for performance but it's the easiest way to not get
* depth written where the mask obliterate the layer. */
float mask = texture(gpMaskTexture, uvs).r;
if (mask < 0.001) {
discard;
return;
}
/* We override the fragment depth using the fragment shader to ensure a constant value.
* This has a cost as the depth test cannot happen early.
* We could do this in the vertex shader but then perspective interpolation of uvs and
* fragment clipping gets really complicated. */
if (gp_interp_flat.depth >= 0.0) {
gl_FragDepth = gp_interp_flat.depth;
}
else {
gl_FragDepth = gl_FragCoord.z;
}
}

View File

@ -85,7 +85,7 @@ GPU_SHADER_CREATE_INFO(gpencil_geometry_next)
.vertex_out(gpencil_geometry_flat_iface)
.vertex_out(gpencil_geometry_noperspective_iface)
.vertex_source("grease_pencil_vert.glsl")
.fragment_source("gpencil_frag.glsl")
.fragment_source("grease_pencil_frag.glsl")
.additional_info("draw_gpencil_new")
.depth_write(DepthWrite::ANY);

View File

@ -515,10 +515,6 @@ class DofPass {
class AntiAliasingPass {
private:
bool enabled_ = false;
/* Current TAA sample index in [0..samples_len_] range. */
int sample_ = 0;
/* Total number of samples to after which TAA stops accumulating samples. */
int samples_len_ = 0;
/* Weight accumulated. */
float weight_accum_ = 0;
/* Samples weight for this iteration. */

View File

@ -64,6 +64,8 @@
#include "draw_manager.h"
#include "draw_texture_pool.h"
#include "BKE_global.h"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "BLI_utildefines.h"
@ -858,6 +860,25 @@ class Texture : NonCopyable {
GPU_texture_clear(tx_, GPU_DATA_INT, &values[0]);
}
/**
* Clear the texture to NaN for floats, or a to debug value for ints.
* (For debugging unitialized data issues)
*/
void debug_clear()
{
if (GPU_texture_has_float_format(this->tx_) || GPU_texture_has_normalized_format(this->tx_)) {
this->clear(float4(NAN_FLT));
}
else if (GPU_texture_has_integer_format(this->tx_)) {
if (GPU_texture_has_signed_format(this->tx_)) {
this->clear(int4(0xF0F0F0F0));
}
else {
this->clear(uint4(0xF0F0F0F0));
}
}
}
/**
* Returns a buffer containing the texture data for the specified miplvl.
* The memory block needs to be manually freed by MEM_freeN().
@ -923,6 +944,9 @@ class Texture : NonCopyable {
}
if (tx_ == nullptr) {
tx_ = create(w, h, d, mip_len, format, usage, data, layered, cubemap);
if (data == nullptr && (G.debug & G_DEBUG_GPU)) {
debug_clear();
}
return true;
}
return false;
@ -981,6 +1005,10 @@ class TextureFromPool : public Texture, NonMovable {
this->tx_ = DRW_texture_pool_texture_acquire(
DST.vmempool->texture_pool, UNPACK2(extent), format, usage);
if (G.debug & G_DEBUG_GPU) {
debug_clear();
}
}
void release()

View File

@ -201,25 +201,12 @@ static void grease_pencil_edit_lines_batch_ensure(
for (const Drawing *drawing : drawings) {
const bke::CurvesGeometry &curves = drawing->strokes();
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
const VArray<bool> cyclic = curves.cyclic();
/* Calculate the vertex and triangle offsets for all the curves. */
for (const int curve_i : curves.curves_range()) {
const IndexRange points = points_by_curve[curve_i];
const bool is_cyclic = cyclic[curve_i];
/* Add one id for the first point in the curve. */
total_line_ids_num++;
/* Add ids for the segments. */
total_line_ids_num += points.size() - 1;
/* Add one segment for the cycle line. */
if (points.size() > 2 && is_cyclic) {
total_line_ids_num++;
}
/* Add one id for the jump to the next curve. */
total_line_ids_num++;
}
/* Add one id for the restart after every curve. */
total_line_ids_num += curves.curves_num();
/* Add one id for every non-cyclic segment. */
total_line_ids_num += curves.points_num();
/* Add one id for the last segment of every cyclic curve. */
total_line_ids_num += array_utils::count_booleans(curves.cyclic());
}
GPUIndexBufBuilder elb;
@ -245,7 +232,7 @@ static void grease_pencil_edit_lines_batch_ensure(
GPU_indexbuf_add_generic_vert(&elb, point + drawing_start_offset);
}
if (points.size() > 2 && is_cyclic) {
if (is_cyclic) {
GPU_indexbuf_add_generic_vert(&elb, points.first() + drawing_start_offset);
}

View File

@ -66,18 +66,8 @@ vec2 gpencil_project_to_screenspace(vec4 v, vec4 viewport_size)
float gpencil_stroke_thickness_modulate(float thickness, vec4 ndc_pos, vec4 viewport_size)
{
/* Modify stroke thickness by object and layer factors. */
thickness = max(1.0, thickness * gpThicknessScale + gpThicknessOffset);
if (gpThicknessIsScreenSpace) {
/* Multiply offset by view Z so that offset is constant in screen-space.
* (e.i: does not change with the distance to camera) */
thickness *= ndc_pos.w;
}
else {
/* World space point size. */
thickness *= gpThicknessWorldScale * ProjectionMatrix[1][1] * viewport_size.y;
}
/* World space point size. */
thickness *= gpThicknessScale * ProjectionMatrix[1][1] * viewport_size.y;
return thickness;
}
@ -85,7 +75,7 @@ float gpencil_clamp_small_stroke_thickness(float thickness, vec4 ndc_pos)
{
/* To avoid aliasing artifacts, we clamp the line thickness and
* reduce its opacity in the fragment shader. */
float min_thickness = ndc_pos.w * 1.3;
float min_thickness = ndc_pos.w * 0.00065;
thickness = max(min_thickness, thickness);
return thickness;

View File

@ -171,11 +171,8 @@ GPU_SHADER_CREATE_INFO(draw_gpencil_new)
.sampler(0, ImageType::FLOAT_BUFFER, "gp_pos_tx")
.sampler(1, ImageType::FLOAT_BUFFER, "gp_col_tx")
/* Per Object */
.define("gpThicknessScale", "1.0") /* TODO(fclem): Replace with object info. */
.define("gpThicknessWorldScale", "1.0 / 2000.0") /* TODO(fclem): Same as above. */
.define("gpThicknessIsScreenSpace", "(gpThicknessWorldScale < 0.0)")
.define("gpThicknessScale", "1.0") /* TODO(fclem): Replace with object info. */
/* Per Layer */
.define("gpThicknessOffset", "0.0") /* TODO(fclem): Remove. */
.additional_info("draw_modelmat_new",
"draw_resource_id_varying",
"draw_view",

View File

@ -1336,7 +1336,6 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
index,
&anim_eval_context,
eBezTriple_KeyframeType(ts->keyframe_type),
nullptr,
flag) != 0);
MEM_freeN(path);

View File

@ -1051,7 +1051,6 @@ int ANIM_apply_keyingset(
Main *bmain = CTX_data_main(C);
ReportList *reports = CTX_wm_reports(C);
ListBase nla_cache = {nullptr, nullptr};
char keytype = scene->toolsettings->keyframe_type;
int num_channels = 0;
const char *groupname = nullptr;
@ -1130,7 +1129,6 @@ int ANIM_apply_keyingset(
i,
&anim_eval_context,
eBezTriple_KeyframeType(keytype),
&nla_cache,
kflag2);
}
else if (mode == MODIFYKEY_MODE_DELETE) {
@ -1158,8 +1156,6 @@ int ANIM_apply_keyingset(
WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_ADDED, nullptr);
}
BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
/* return the number of channels successfully affected */
BLI_assert(num_channels >= 0);
return num_channels;

View File

@ -316,12 +316,11 @@ static void *ed_armature_pick_bone_impl(
const bool is_editmode, bContext *C, const int xy[2], bool findunsel, Base **r_base)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
rcti rect;
GPUSelectResult buffer[MAXPICKELEMS];
short hits;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
BLI_assert((vc.obedit != nullptr) == is_editmode);
BLI_rcti_init_pt_radius(&rect, xy, 0);
@ -950,8 +949,7 @@ bool ED_armature_edit_deselect_all_visible_multi_ex(Base **bases, uint bases_len
bool ED_armature_edit_deselect_all_visible_multi(bContext *C)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
uint bases_len = 0;
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
vc.scene, vc.view_layer, vc.v3d, &bases_len);
@ -1143,12 +1141,11 @@ bool ED_armature_edit_select_pick(bContext *C, const int mval[2], const SelectPi
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
EditBone *nearBone = nullptr;
int selmask;
Base *basact = nullptr;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
vc.mval[0] = mval[0];
vc.mval[1] = mval[1];

View File

@ -411,8 +411,7 @@ bool ED_pose_deselect_all_multi_ex(Base **bases,
bool ED_pose_deselect_all_multi(bContext *C, int select_mode, const bool ignore_visibility)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
uint bases_len = 0;
Base **bases = BKE_object_pose_base_array_get_unique(

View File

@ -4792,7 +4792,6 @@ bool ED_curve_editnurb_select_pick(bContext *C,
const SelectPick_Params *params)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
Nurb *nu;
BezTriple *bezt = nullptr;
BPoint *bp = nullptr;
@ -4801,7 +4800,7 @@ bool ED_curve_editnurb_select_pick(bContext *C,
bool changed = false;
view3d_operator_needs_opengl(C);
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
copy_v2_v2_int(vc.mval, mval);
const bool use_handle_select = (vc.v3d->overlay.handle_display != CURVE_HANDLE_NONE);
@ -5616,9 +5615,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
if (vc.rv3d && !RNA_struct_property_is_set(op->ptr, "location")) {
Curve *cu;

View File

@ -574,7 +574,7 @@ static bool curve_draw_init(bContext *C, wmOperator *op, bool is_invoke)
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
if (is_invoke) {
ED_view3d_viewcontext_init(C, &cdd->vc, depsgraph);
cdd->vc = ED_view3d_viewcontext_init(C, depsgraph);
if (ELEM(nullptr, cdd->vc.region, cdd->vc.rv3d, cdd->vc.v3d, cdd->vc.win, cdd->vc.scene)) {
MEM_freeN(cdd);
BKE_report(op->reports, RPT_ERROR, "Unable to access 3D viewport");

View File

@ -1559,10 +1559,9 @@ wmKeyMap *curve_pen_modal_keymap(wmKeyConfig *keyconf)
static int curve_pen_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
Object *obedit = CTX_data_edit_object(C);
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
Curve *cu = static_cast<Curve *>(vc.obedit->data);
ListBase *nurbs = &cu->editnurb->nurbs;
const float threshold_dist_px = ED_view3d_select_dist_px() * SEL_DIST_FACTOR;
@ -1749,8 +1748,8 @@ static int curve_pen_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int curve_pen_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewContext vc;
ED_view3d_viewcontext_init(C, &vc, CTX_data_ensure_evaluated_depsgraph(C));
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
Curve *cu = static_cast<Curve *>(vc.obedit->data);
ListBase *nurbs = &cu->editnurb->nurbs;

View File

@ -256,8 +256,7 @@ bool ED_curve_deselect_all_multi_ex(Base **bases, int bases_len)
bool ED_curve_deselect_all_multi(bContext *C)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
uint bases_len = 0;
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
vc.scene, vc.view_layer, vc.v3d, &bases_len);
@ -702,7 +701,6 @@ void CURVE_OT_select_linked(wmOperatorType *ot)
static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
Nurb *nu;
BezTriple *bezt;
BPoint *bp;
@ -711,7 +709,7 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent
Base *basact = nullptr;
view3d_operator_needs_opengl(C);
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
copy_v2_v2_int(vc.mval, event->mval);
if (!ED_curve_pick_vert(&vc, 1, &nu, &bezt, &bp, nullptr, &basact)) {
@ -2028,7 +2026,6 @@ static void curve_select_shortest_path_surf(Nurb *nu, int vert_src, int vert_dst
static int edcu_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
Nurb *nu_dst;
BezTriple *bezt_dst;
BPoint *bp_dst;
@ -2037,7 +2034,7 @@ static int edcu_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE
Base *basact = nullptr;
view3d_operator_needs_opengl(C);
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
copy_v2_v2_int(vc.mval, event->mval);
if (!ED_curve_pick_vert(&vc, 1, &nu_dst, &bezt_dst, &bp_dst, nullptr, &basact)) {

View File

@ -2386,7 +2386,6 @@ bool ED_curve_editfont_select_pick(
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *obedit = CTX_data_edit_object(C);
Curve *cu = static_cast<Curve *>(obedit->data);
ViewContext vc;
/* bias against the active, in pixels, allows cycling */
const float active_bias_px = 4.0f;
const float mval_fl[2] = {float(mval[0]), float(mval[1])};
@ -2395,7 +2394,7 @@ bool ED_curve_editfont_select_pick(
const float dist = ED_view3d_select_dist_px();
float dist_sq_best = dist * dist;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);

View File

@ -23,6 +23,7 @@ set(INC_SYS
)
set(SRC
intern/attribute_set.cc
intern/curves_add.cc
intern/curves_data.cc
intern/curves_edit.cc

View File

@ -0,0 +1,227 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edmesh
*/
#include "BLI_generic_pointer.hh"
#include "BKE_attribute.h"
#include "BKE_attribute_math.hh"
#include "BKE_context.h"
#include "BKE_report.h"
#include "BKE_type_conversions.hh"
#include "WM_api.hh"
#include "WM_types.hh"
#include "ED_curves.hh"
#include "ED_geometry.hh"
#include "ED_object.hh"
#include "ED_screen.hh"
#include "ED_transform.hh"
#include "ED_view3d.hh"
#include "RNA_access.hh"
#include "BLT_translation.h"
#include "UI_interface.hh"
#include "UI_resources.hh"
#include "DNA_object_types.h"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"
/* -------------------------------------------------------------------- */
/** \name Delete Operator
* \{ */
namespace blender::ed::curves {
static bool active_attribute_poll(bContext *C)
{
if (!editable_curves_in_edit_mode_poll(C)) {
return false;
}
Object *object = CTX_data_active_object(C);
Curves &curves_id = *static_cast<Curves *>(object->data);
const CustomDataLayer *layer = BKE_id_attributes_active_get(&const_cast<ID &>(curves_id.id));
if (!layer) {
CTX_wm_operator_poll_msg_set(C, "No active attribute");
return false;
}
if (layer->type == CD_PROP_STRING) {
CTX_wm_operator_poll_msg_set(C, "Active string attribute not supported");
return false;
}
return true;
}
static IndexMask retrieve_selected_elements(const Curves &curves_id,
const eAttrDomain domain,
IndexMaskMemory &memory)
{
switch (domain) {
case ATTR_DOMAIN_POINT:
return retrieve_selected_points(curves_id, memory);
case ATTR_DOMAIN_CURVE:
return retrieve_selected_curves(curves_id, memory);
default:
BLI_assert_unreachable();
return {};
}
}
static void validate_value(const bke::AttributeAccessor attributes,
const StringRef name,
const CPPType &type,
void *buffer)
{
const bke::AttributeValidator validator = attributes.lookup_validator(name);
if (!validator) {
return;
}
BUFFER_FOR_CPP_TYPE_VALUE(type, validated_buffer);
BLI_SCOPED_DEFER([&]() { type.destruct(validated_buffer); });
const IndexMask single_mask(1);
mf::ParamsBuilder params(*validator.function, &single_mask);
params.add_readonly_single_input(GPointer(type, buffer));
params.add_uninitialized_single_output({type, validated_buffer, 1});
mf::ContextBuilder context;
validator.function->call(single_mask, params, context);
type.copy_assign(validated_buffer, buffer);
}
static int set_attribute_exec(bContext *C, wmOperator *op)
{
Object *active_object = CTX_data_active_object(C);
Curves &active_curves_id = *static_cast<Curves *>(active_object->data);
CustomDataLayer *active_attribute = BKE_id_attributes_active_get(&active_curves_id.id);
const eCustomDataType active_type = eCustomDataType(active_attribute->type);
const CPPType &type = *bke::custom_data_type_to_cpp_type(active_type);
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
BLI_SCOPED_DEFER([&]() { type.destruct(buffer); });
const GPointer value = geometry::rna_property_for_attribute_type_retrieve_value(
*op->ptr, active_type, buffer);
const bke::DataTypeConversions &conversions = bke::get_implicit_type_conversions();
for (Curves *curves_id : get_unique_editable_curves(*C)) {
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
CustomDataLayer *layer = BKE_id_attributes_active_get(&curves_id->id);
if (!layer) {
continue;
}
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
bke::GSpanAttributeWriter attribute = attributes.lookup_for_write_span(layer->name);
/* Use implicit conversions to try to handle the case where the active attribute has a
* different type on multiple objects. */
const CPPType &dst_type = attribute.span.type();
if (&type != &dst_type && !conversions.is_convertible(type, dst_type)) {
continue;
}
BUFFER_FOR_CPP_TYPE_VALUE(dst_type, dst_buffer);
BLI_SCOPED_DEFER([&]() { dst_type.destruct(dst_buffer); });
conversions.convert_to_uninitialized(type, dst_type, value.get(), dst_buffer);
validate_value(attributes, layer->name, dst_type, dst_buffer);
const GPointer dst_value(type, dst_buffer);
IndexMaskMemory memory;
const IndexMask selection = retrieve_selected_elements(*curves_id, attribute.domain, memory);
if (selection.is_empty()) {
attribute.finish();
continue;
}
dst_type.fill_assign_indices(dst_value.get(), attribute.span.data(), selection);
attribute.finish();
DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, curves_id);
}
return OPERATOR_FINISHED;
}
static int set_attribute_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Object *active_object = CTX_data_active_object(C);
Curves &active_curves_id = *static_cast<Curves *>(active_object->data);
CustomDataLayer *active_attribute = BKE_id_attributes_active_get(&active_curves_id.id);
const bke::CurvesGeometry &curves = active_curves_id.geometry.wrap();
const bke::AttributeAccessor attributes = curves.attributes();
const bke::GAttributeReader attribute = attributes.lookup(active_attribute->name);
const eAttrDomain domain = attribute.domain;
IndexMaskMemory memory;
const IndexMask selection = retrieve_selected_elements(active_curves_id, domain, memory);
const CPPType &type = attribute.varray.type();
PropertyRNA *prop = geometry::rna_property_for_type(*op->ptr,
bke::cpp_type_to_custom_data_type(type));
if (RNA_property_is_set(op->ptr, prop)) {
return WM_operator_props_popup(C, op, event);
}
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
BLI_SCOPED_DEFER([&]() { type.destruct(buffer); });
bke::attribute_math::convert_to_static_type(type, [&](auto dummy) {
using T = decltype(dummy);
const VArray<T> values_typed = attribute.varray.typed<T>();
bke::attribute_math::DefaultMixer<T> mixer{MutableSpan(static_cast<T *>(buffer), 1)};
selection.foreach_index([&](const int i) { mixer.mix_in(0, values_typed[i]); });
mixer.finalize();
});
geometry::rna_property_for_attribute_type_set_value(*op->ptr, *prop, GPointer(type, buffer));
return WM_operator_props_popup(C, op, event);
}
static void set_attribute_ui(bContext *C, wmOperator *op)
{
uiLayout *layout = uiLayoutColumn(op->layout, true);
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
Object *object = CTX_data_active_object(C);
Curves &curves_id = *static_cast<Curves *>(object->data);
CustomDataLayer *active_attribute = BKE_id_attributes_active_get(&curves_id.id);
const eCustomDataType active_type = eCustomDataType(active_attribute->type);
const StringRefNull prop_name = geometry::rna_property_name_for_type(active_type);
const char *name = active_attribute->name;
uiItemR(layout, op->ptr, prop_name.c_str(), UI_ITEM_NONE, name, ICON_NONE);
}
void CURVES_OT_attribute_set(wmOperatorType *ot)
{
using namespace blender::ed;
using namespace blender::ed::curves;
ot->name = "Set Attribute";
ot->description = "Set values of the active attribute for selected elements";
ot->idname = "CURVES_OT_attribute_set";
ot->exec = set_attribute_exec;
ot->invoke = set_attribute_invoke;
ot->poll = active_attribute_poll;
ot->ui = set_attribute_ui;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
geometry::register_rna_properties_for_attribute_types(*ot->srna);
}
} // namespace blender::ed::curves
/** \} */

View File

@ -793,6 +793,16 @@ static int curves_set_selection_domain_exec(bContext *C, wmOperator *op)
continue;
}
/* Adding and removing attributes with the C++ API doesn't affect the active attribute index.
* In order to make the active attribute consistent before and after the change, save the name
* and reset the active item afterwards.
*
* This would be unnecessary if the active attribute were stored as a string on the ID. */
std::string active_attribute;
if (const CustomDataLayer *layer = BKE_id_attributes_active_get(&curves_id->id)) {
active_attribute = layer->name;
}
if (const GVArray src = *attributes.lookup(".selection", domain)) {
const CPPType &type = src.type();
void *dst = MEM_malloc_arrayN(attributes.domain_size(domain), type.size(), __func__);
@ -808,6 +818,8 @@ static int curves_set_selection_domain_exec(bContext *C, wmOperator *op)
}
}
BKE_id_attributes_active_set(&curves_id->id, active_attribute.c_str());
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
* attribute for now. */
DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY);
@ -1236,6 +1248,7 @@ static void CURVES_OT_delete(wmOperatorType *ot)
void ED_operatortypes_curves()
{
using namespace blender::ed::curves;
WM_operatortype_append(CURVES_OT_attribute_set);
WM_operatortype_append(CURVES_OT_convert_to_particle_system);
WM_operatortype_append(CURVES_OT_convert_from_particle_system);
WM_operatortype_append(CURVES_OT_snap_curves_to_surface);

View File

@ -12,6 +12,8 @@
#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
#include "BLI_color.hh"
#include "BKE_attribute.h"
#include "BKE_context.h"
#include "BKE_deform.h"
@ -42,6 +44,137 @@
namespace blender::ed::geometry {
StringRefNull rna_property_name_for_type(const eCustomDataType type)
{
switch (type) {
case CD_PROP_FLOAT:
return "value_float";
case CD_PROP_FLOAT2:
return "value_float_vector_2d";
case CD_PROP_FLOAT3:
return "value_float_vector_3d";
case CD_PROP_COLOR:
case CD_PROP_BYTE_COLOR:
return "value_color";
case CD_PROP_BOOL:
return "value_bool";
case CD_PROP_INT8:
case CD_PROP_INT32:
return "value_int";
default:
BLI_assert_unreachable();
return "";
}
}
PropertyRNA *rna_property_for_type(PointerRNA &ptr, const eCustomDataType type)
{
return RNA_struct_find_property(&ptr, rna_property_name_for_type(type).c_str());
}
void register_rna_properties_for_attribute_types(StructRNA &srna)
{
static blender::float4 color_default(1);
RNA_def_float(&srna, "value_float", 0.0f, -FLT_MAX, FLT_MAX, "Value", "", -FLT_MAX, FLT_MAX);
RNA_def_float_array(&srna,
"value_float_vector_2d",
2,
nullptr,
-FLT_MAX,
FLT_MAX,
"Value",
"",
-FLT_MAX,
FLT_MAX);
RNA_def_float_array(&srna,
"value_float_vector_3d",
3,
nullptr,
-FLT_MAX,
FLT_MAX,
"Value",
"",
-FLT_MAX,
FLT_MAX);
RNA_def_int(&srna, "value_int", 0, INT_MIN, INT_MAX, "Value", "", INT_MIN, INT_MAX);
RNA_def_float_color(
&srna, "value_color", 4, color_default, -FLT_MAX, FLT_MAX, "Value", "", 0.0f, 1.0f);
RNA_def_boolean(&srna, "value_bool", false, "Value", "");
}
GPointer rna_property_for_attribute_type_retrieve_value(PointerRNA &ptr,
const eCustomDataType type,
void *buffer)
{
const StringRefNull prop_name = rna_property_name_for_type(type);
switch (type) {
case CD_PROP_FLOAT:
*static_cast<float *>(buffer) = RNA_float_get(&ptr, prop_name.c_str());
break;
case CD_PROP_FLOAT2:
RNA_float_get_array(&ptr, prop_name.c_str(), static_cast<float *>(buffer));
break;
case CD_PROP_FLOAT3:
RNA_float_get_array(&ptr, prop_name.c_str(), static_cast<float *>(buffer));
break;
case CD_PROP_COLOR:
RNA_float_get_array(&ptr, prop_name.c_str(), static_cast<float *>(buffer));
break;
case CD_PROP_BYTE_COLOR:
ColorGeometry4f value;
RNA_float_get_array(&ptr, prop_name.c_str(), value);
*static_cast<ColorGeometry4b *>(buffer) = value.encode();
break;
case CD_PROP_BOOL:
*static_cast<bool *>(buffer) = RNA_boolean_get(&ptr, prop_name.c_str());
break;
case CD_PROP_INT8:
*static_cast<int8_t *>(buffer) = RNA_int_get(&ptr, prop_name.c_str());
break;
case CD_PROP_INT32:
*static_cast<int32_t *>(buffer) = RNA_int_get(&ptr, prop_name.c_str());
break;
default:
BLI_assert_unreachable();
}
return GPointer(bke::custom_data_type_to_cpp_type(type), buffer);
}
void rna_property_for_attribute_type_set_value(PointerRNA &ptr,
PropertyRNA &prop,
const GPointer value)
{
switch (bke::cpp_type_to_custom_data_type(*value.type())) {
case CD_PROP_FLOAT:
RNA_property_float_set(&ptr, &prop, *value.get<float>());
break;
case CD_PROP_FLOAT2:
RNA_property_float_set_array(&ptr, &prop, *value.get<float2>());
break;
case CD_PROP_FLOAT3:
RNA_property_float_set_array(&ptr, &prop, *value.get<float3>());
break;
case CD_PROP_BYTE_COLOR:
RNA_property_float_set_array(&ptr, &prop, value.get<ColorGeometry4b>()->decode());
break;
case CD_PROP_COLOR:
RNA_property_float_set_array(&ptr, &prop, *value.get<ColorGeometry4f>());
break;
case CD_PROP_BOOL:
RNA_property_boolean_set(&ptr, &prop, *value.get<bool>());
break;
case CD_PROP_INT8:
RNA_property_int_set(&ptr, &prop, *value.get<int8_t>());
break;
case CD_PROP_INT32:
RNA_property_int_set(&ptr, &prop, *value.get<int32_t>());
break;
default:
BLI_assert_unreachable();
}
}
/*********************** Attribute Operators ************************/
static bool geometry_attributes_poll(bContext *C)

View File

@ -7,6 +7,7 @@
*/
#include <array>
#include <iomanip>
#include "BKE_curves.hh"
#include "BKE_grease_pencil.hh"
@ -189,21 +190,24 @@ static std::array<float3, 175> stroke_positions({
});
static constexpr std::array<float, 175> stroke_radii({
0.038f, 0.069f, 0.089f, 0.112f, 0.134f, 0.155f, 0.175f, 0.194f, 0.211f, 0.227f, 0.242f, 0.256f,
0.268f, 0.28f, 0.29f, 0.299f, 0.307f, 0.315f, 0.322f, 0.329f, 0.335f, 0.341f, 0.346f, 0.351f,
0.355f, 0.36f, 0.364f, 0.368f, 0.371f, 0.373f, 0.376f, 0.377f, 0.378f, 0.379f, 0.379f, 0.379f,
0.38f, 0.38f, 0.381f, 0.382f, 0.384f, 0.386f, 0.388f, 0.39f, 0.393f, 0.396f, 0.399f, 0.403f,
0.407f, 0.411f, 0.415f, 0.42f, 0.425f, 0.431f, 0.437f, 0.443f, 0.45f, 0.457f, 0.464f, 0.471f,
0.479f, 0.487f, 0.495f, 0.503f, 0.512f, 0.52f, 0.528f, 0.537f, 0.545f, 0.553f, 0.562f, 0.57f,
0.579f, 0.588f, 0.597f, 0.606f, 0.615f, 0.625f, 0.635f, 0.644f, 0.654f, 0.664f, 0.675f, 0.685f,
0.696f, 0.707f, 0.718f, 0.729f, 0.74f, 0.751f, 0.761f, 0.772f, 0.782f, 0.793f, 0.804f, 0.815f,
0.828f, 0.843f, 0.86f, 0.879f, 0.897f, 0.915f, 0.932f, 0.947f, 0.962f, 0.974f, 0.985f, 0.995f,
1.004f, 1.011f, 1.018f, 1.024f, 1.029f, 1.033f, 1.036f, 1.037f, 1.037f, 1.035f, 1.032f, 1.029f,
1.026f, 1.023f, 1.021f, 1.019f, 1.017f, 1.016f, 1.016f, 1.016f, 1.016f, 1.017f, 1.017f, 1.018f,
1.017f, 1.017f, 1.016f, 1.015f, 1.013f, 1.009f, 1.005f, 0.998f, 0.99f, 0.98f, 0.968f, 0.955f,
0.939f, 0.923f, 0.908f, 0.895f, 0.882f, 0.87f, 0.858f, 0.844f, 0.828f, 0.81f, 0.79f, 0.769f,
0.747f, 0.724f, 0.7f, 0.676f, 0.651f, 0.625f, 0.599f, 0.573f, 0.546f, 0.516f, 0.483f, 0.446f,
0.407f, 0.365f, 0.322f, 0.28f, 0.236f, 0.202f, 0.155f,
0.00143, 0.00259, 0.00334, 0.00420, 0.00503, 0.00581, 0.00656, 0.00728, 0.00791, 0.00851,
0.00907, 0.00960, 0.01005, 0.01050, 0.01087, 0.01121, 0.01151, 0.01181, 0.01208, 0.01234,
0.01256, 0.01279, 0.01297, 0.01316, 0.01331, 0.01350, 0.01365, 0.01380, 0.01391, 0.01399,
0.01410, 0.01414, 0.01418, 0.01421, 0.01421, 0.01421, 0.01425, 0.01425, 0.01429, 0.01433,
0.01440, 0.01448, 0.01455, 0.01462, 0.01474, 0.01485, 0.01496, 0.01511, 0.01526, 0.01541,
0.01556, 0.01575, 0.01594, 0.01616, 0.01639, 0.01661, 0.01688, 0.01714, 0.01740, 0.01766,
0.01796, 0.01826, 0.01856, 0.01886, 0.01920, 0.01950, 0.01980, 0.02014, 0.02044, 0.02074,
0.02107, 0.02138, 0.02171, 0.02205, 0.02239, 0.02273, 0.02306, 0.02344, 0.02381, 0.02415,
0.02452, 0.02490, 0.02531, 0.02569, 0.02610, 0.02651, 0.02693, 0.02734, 0.02775, 0.02816,
0.02854, 0.02895, 0.02933, 0.02974, 0.03015, 0.03056, 0.03105, 0.03161, 0.03225, 0.03296,
0.03364, 0.03431, 0.03495, 0.03551, 0.03608, 0.03652, 0.03694, 0.03731, 0.03765, 0.03791,
0.03818, 0.03840, 0.03859, 0.03874, 0.03885, 0.03889, 0.03889, 0.03881, 0.03870, 0.03859,
0.03848, 0.03836, 0.03829, 0.03821, 0.03814, 0.03810, 0.03810, 0.03810, 0.03810, 0.03814,
0.03814, 0.03818, 0.03814, 0.03814, 0.03810, 0.03806, 0.03799, 0.03784, 0.03769, 0.03743,
0.03713, 0.03675, 0.03630, 0.03581, 0.03521, 0.03461, 0.03405, 0.03356, 0.03308, 0.03263,
0.03218, 0.03165, 0.03105, 0.03038, 0.02963, 0.02884, 0.02801, 0.02715, 0.02625, 0.02535,
0.02441, 0.02344, 0.02246, 0.02149, 0.02048, 0.01935, 0.01811, 0.01673, 0.01526, 0.01369,
0.01208, 0.01050, 0.00885, 0.00758, 0.00581,
});
static constexpr std::array<float, 175> stroke_opacities({
@ -636,65 +640,76 @@ static constexpr std::array<float, 700> monkey_fill_opacities({
});
static constexpr std::array<float, 700> monkey_fill_radii({
0.2670, 0.3100, 0.3800, 0.4330, 0.4710, 0.4960, 0.5110, 0.5210, 0.5270, 0.5310, 0.5340, 0.5350,
0.5360, 0.5360, 0.5360, 0.5350, 0.5340, 0.5340, 0.5330, 0.5330, 0.5320, 0.5310, 0.5310, 0.5320,
0.5350, 0.5400, 0.5420, 0.5430, 0.5430, 0.5460, 0.5490, 0.5490, 0.5490, 0.5490, 0.5510, 0.5530,
0.5540, 0.5540, 0.5550, 0.5560, 0.5570, 0.5570, 0.5570, 0.5570, 0.5580, 0.5580, 0.5570, 0.5560,
0.5540, 0.5520, 0.5510, 0.5500, 0.5490, 0.5490, 0.5490, 0.5500, 0.5520, 0.5560, 0.5630, 0.5720,
0.5820, 0.5910, 0.5970, 0.6020, 0.6050, 0.6070, 0.6090, 0.6120, 0.6160, 0.6190, 0.6230, 0.6260,
0.6300, 0.6370, 0.6460, 0.6540, 0.6590, 0.6640, 0.6670, 0.6710, 0.6740, 0.6770, 0.6780, 0.6800,
0.6800, 0.6810, 0.6820, 0.6830, 0.6850, 0.6870, 0.6900, 0.6930, 0.6970, 0.7000, 0.7040, 0.7070,
0.7090, 0.7110, 0.7120, 0.7140, 0.7150, 0.7150, 0.7160, 0.7170, 0.7180, 0.7180, 0.7180, 0.7190,
0.7190, 0.7190, 0.7190, 0.7190, 0.7180, 0.7170, 0.7170, 0.7180, 0.7170, 0.7150, 0.7130, 0.7180,
0.7320, 0.7530, 0.7740, 0.7910, 0.8020, 0.8090, 0.8120, 0.8140, 0.8140, 0.8120, 0.8100, 0.8060,
0.8000, 0.7940, 0.7880, 0.7830, 0.7810, 0.7790, 0.7780, 0.7770, 0.7770, 0.7760, 0.7750, 0.7740,
0.7740, 0.7730, 0.7720, 0.7710, 0.7700, 0.7680, 0.7670, 0.7660, 0.7650, 0.7640, 0.7610, 0.7560,
0.7510, 0.7450, 0.7390, 0.7330, 0.7280, 0.7230, 0.7180, 0.7130, 0.7090, 0.7040, 0.7000, 0.6950,
0.6910, 0.6860, 0.6810, 0.6760, 0.6710, 0.6660, 0.6630, 0.6610, 0.6600, 0.6590, 0.6580, 0.6580,
0.6580, 0.6570, 0.6560, 0.6530, 0.6460, 0.6370, 0.6280, 0.6200, 0.6140, 0.6100, 0.6080, 0.6070,
0.6060, 0.6050, 0.6030, 0.5980, 0.5910, 0.5830, 0.5740, 0.5640, 0.5550, 0.5470, 0.5410, 0.5360,
0.5320, 0.5290, 0.5250, 0.5210, 0.5160, 0.5100, 0.5050, 0.4990, 0.4950, 0.4930, 0.4910, 0.4910,
0.4910, 0.4920, 0.4920, 0.4920, 0.4930, 0.4930, 0.4930, 0.4920, 0.4910, 0.4910, 0.4900, 0.4900,
0.4890, 0.4890, 0.4890, 0.4890, 0.4890, 0.4900, 0.4900, 0.4910, 0.4920, 0.4940, 0.4970, 0.5010,
0.5050, 0.5100, 0.5150, 0.5200, 0.5250, 0.5300, 0.5350, 0.5390, 0.5420, 0.5460, 0.5480, 0.5500,
0.5510, 0.5520, 0.5530, 0.5540, 0.5540, 0.5550, 0.5560, 0.5560, 0.5570, 0.5580, 0.5580, 0.5580,
0.5590, 0.5590, 0.5590, 0.5580, 0.5580, 0.5550, 0.1000, 0.2199, 0.4615, 0.6019, 0.6981, 0.7689,
0.8236, 0.8660, 0.9003, 0.9272, 0.9485, 0.9653, 0.9781, 0.9876, 0.9942, 0.9983, 0.9997, 0.9990,
0.9963, 0.9912, 0.9834, 0.9724, 0.9576, 0.9385, 0.9143, 0.8841, 0.8461, 0.7979, 0.7359, 0.6541,
0.5396, 0.3600, 0.1000, 0.1000, 0.2199, 0.6019, 0.7689, 0.8660, 0.9272, 0.9653, 0.9876, 0.9983,
0.9990, 0.9912, 0.9724, 0.9385, 0.8841, 0.7979, 0.6541, 0.3600, 0.1000, 0.1000, 0.2199, 0.3600,
0.4615, 0.5396, 0.6019, 0.6541, 0.6981, 0.7359, 0.7689, 0.7979, 0.8236, 0.8461, 0.8660, 0.8841,
0.9003, 0.9143, 0.9272, 0.9385, 0.9485, 0.9576, 0.9653, 0.9724, 0.9781, 0.9834, 0.9876, 0.9912,
0.9942, 0.9963, 0.9983, 0.9990, 0.9997, 0.9997, 0.9990, 0.9983, 0.9963, 0.9942, 0.9912, 0.9876,
0.9834, 0.9781, 0.9724, 0.9653, 0.9576, 0.9485, 0.9385, 0.9272, 0.9143, 0.9003, 0.8841, 0.8660,
0.8461, 0.8236, 0.7979, 0.7689, 0.7359, 0.6981, 0.6541, 0.6019, 0.5396, 0.4615, 0.3600, 0.2199,
0.1000, 0.1000, 0.2199, 0.4615, 0.6019, 0.6981, 0.7689, 0.8236, 0.8660, 0.9003, 0.9272, 0.9485,
0.9653, 0.9781, 0.9876, 0.9942, 0.9983, 0.9997, 0.9990, 0.9963, 0.9912, 0.9834, 0.9724, 0.9576,
0.9385, 0.9143, 0.8841, 0.8461, 0.7979, 0.7359, 0.6541, 0.5396, 0.3600, 0.1000, 0.1000, 0.2199,
0.3600, 0.4615, 0.5396, 0.6019, 0.6541, 0.6981, 0.7359, 0.7689, 0.7979, 0.8236, 0.8461, 0.8660,
0.8841, 0.9003, 0.9143, 0.9272, 0.9385, 0.9485, 0.9576, 0.9653, 0.9724, 0.9781, 0.9834, 0.9876,
0.9912, 0.9942, 0.9963, 0.9983, 0.9990, 0.9997, 0.9997, 0.9990, 0.9983, 0.9963, 0.9942, 0.9912,
0.9876, 0.9834, 0.9781, 0.9724, 0.9653, 0.9576, 0.9485, 0.9385, 0.9272, 0.9143, 0.9003, 0.8841,
0.8660, 0.8461, 0.8236, 0.7979, 0.7689, 0.7359, 0.6981, 0.6541, 0.6019, 0.5396, 0.4615, 0.3600,
0.2199, 0.1000, 0.1000, 0.2199, 0.4615, 0.6019, 0.6981, 0.7689, 0.8236, 0.8660, 0.9003, 0.9272,
0.9485, 0.9653, 0.9781, 0.9876, 0.9942, 0.9983, 0.9997, 0.9990, 0.9963, 0.9912, 0.9834, 0.9724,
0.9576, 0.9385, 0.9143, 0.8841, 0.8461, 0.7979, 0.7359, 0.6541, 0.5396, 0.3600, 0.1000, 0.1000,
0.2199, 0.6019, 0.7689, 0.8660, 0.9272, 0.9653, 0.9876, 0.9983, 0.9990, 0.9912, 0.9724, 0.9385,
0.8841, 0.7979, 0.6541, 0.3600, 0.1000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 0.1000, 0.2199, 0.4615, 0.6019, 0.6981, 0.7689,
0.8236, 0.8660, 0.9003, 0.9272, 0.9485, 0.9653, 0.9781, 0.9876, 0.9942, 0.9983, 0.9997, 0.9990,
0.9963, 0.9912, 0.9834, 0.9724, 0.9576, 0.9385, 0.9143, 0.8841, 0.8461, 0.7979, 0.7359, 0.6541,
0.5396, 0.3600, 0.1000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
1.0000, 1.0000, 1.0000, 1.0000, 0.1000, 0.2199, 0.6019, 0.7689, 0.8660, 0.9272, 0.9653, 0.9876,
0.9983, 0.9990, 0.9912, 0.9724, 0.9385, 0.8841, 0.7979, 0.6541, 0.3600, 0.1000, 0.1000, 0.2199,
0.6019, 0.7689, 0.8660, 0.9272, 0.9653, 0.9876, 0.9983, 0.9990, 0.9912, 0.9724, 0.9385, 0.8841,
0.7979, 0.6541, 0.3600, 0.1000,
0.01001, 0.01163, 0.01425, 0.01624, 0.01766, 0.01860, 0.01916, 0.01954, 0.01976, 0.01991,
0.02002, 0.02006, 0.02010, 0.02010, 0.02010, 0.02006, 0.02002, 0.02002, 0.01999, 0.01999,
0.01995, 0.01991, 0.01991, 0.01995, 0.02006, 0.02025, 0.02033, 0.02036, 0.02036, 0.02048,
0.02059, 0.02059, 0.02059, 0.02059, 0.02066, 0.02074, 0.02078, 0.02078, 0.02081, 0.02085,
0.02089, 0.02089, 0.02089, 0.02089, 0.02093, 0.02093, 0.02089, 0.02085, 0.02078, 0.02070,
0.02066, 0.02063, 0.02059, 0.02059, 0.02059, 0.02063, 0.02070, 0.02085, 0.02111, 0.02145,
0.02183, 0.02216, 0.02239, 0.02258, 0.02269, 0.02276, 0.02284, 0.02295, 0.02310, 0.02321,
0.02336, 0.02348, 0.02363, 0.02389, 0.02423, 0.02452, 0.02471, 0.02490, 0.02501, 0.02516,
0.02528, 0.02539, 0.02543, 0.02550, 0.02550, 0.02554, 0.02558, 0.02561, 0.02569, 0.02576,
0.02588, 0.02599, 0.02614, 0.02625, 0.02640, 0.02651, 0.02659, 0.02666, 0.02670, 0.02678,
0.02681, 0.02681, 0.02685, 0.02689, 0.02693, 0.02693, 0.02693, 0.02696, 0.02696, 0.02696,
0.02696, 0.02696, 0.02693, 0.02689, 0.02689, 0.02693, 0.02689, 0.02681, 0.02674, 0.02693,
0.02745, 0.02824, 0.02903, 0.02966, 0.03008, 0.03034, 0.03045, 0.03053, 0.03053, 0.03045,
0.03038, 0.03023, 0.03000, 0.02978, 0.02955, 0.02936, 0.02929, 0.02921, 0.02918, 0.02914,
0.02914, 0.02910, 0.02906, 0.02903, 0.02903, 0.02899, 0.02895, 0.02891, 0.02888, 0.02880,
0.02876, 0.02873, 0.02869, 0.02865, 0.02854, 0.02835, 0.02816, 0.02794, 0.02771, 0.02749,
0.02730, 0.02711, 0.02693, 0.02674, 0.02659, 0.02640, 0.02625, 0.02606, 0.02591, 0.02573,
0.02554, 0.02535, 0.02516, 0.02498, 0.02486, 0.02479, 0.02475, 0.02471, 0.02468, 0.02468,
0.02468, 0.02464, 0.02460, 0.02449, 0.02423, 0.02389, 0.02355, 0.02325, 0.02303, 0.02288,
0.02280, 0.02276, 0.02273, 0.02269, 0.02261, 0.02242, 0.02216, 0.02186, 0.02153, 0.02115,
0.02081, 0.02051, 0.02029, 0.02010, 0.01995, 0.01984, 0.01969, 0.01954, 0.01935, 0.01912,
0.01894, 0.01871, 0.01856, 0.01849, 0.01841, 0.01841, 0.01841, 0.01845, 0.01845, 0.01845,
0.01849, 0.01849, 0.01849, 0.01845, 0.01841, 0.01841, 0.01838, 0.01838, 0.01834, 0.01834,
0.01834, 0.01834, 0.01834, 0.01838, 0.01838, 0.01841, 0.01845, 0.01853, 0.01864, 0.01879,
0.01894, 0.01912, 0.01931, 0.01950, 0.01969, 0.01987, 0.02006, 0.02021, 0.02033, 0.02048,
0.02055, 0.02063, 0.02066, 0.02070, 0.02074, 0.02078, 0.02078, 0.02081, 0.02085, 0.02085,
0.02089, 0.02093, 0.02093, 0.02093, 0.02096, 0.02096, 0.02096, 0.02093, 0.02093, 0.02081,
0.00300, 0.00660, 0.01384, 0.01806, 0.02094, 0.02307, 0.02471, 0.02598, 0.02701, 0.02782,
0.02845, 0.02896, 0.02934, 0.02963, 0.02983, 0.02995, 0.02999, 0.02997, 0.02989, 0.02974,
0.02950, 0.02917, 0.02873, 0.02815, 0.02743, 0.02652, 0.02538, 0.02394, 0.02208, 0.01962,
0.01619, 0.01080, 0.00300, 0.00300, 0.00660, 0.01806, 0.02307, 0.02598, 0.02782, 0.02896,
0.02963, 0.02995, 0.02997, 0.02974, 0.02917, 0.02815, 0.02652, 0.02394, 0.01962, 0.01080,
0.00300, 0.00300, 0.00660, 0.01080, 0.01384, 0.01619, 0.01806, 0.01962, 0.02094, 0.02208,
0.02307, 0.02394, 0.02471, 0.02538, 0.02598, 0.02652, 0.02701, 0.02743, 0.02782, 0.02815,
0.02845, 0.02873, 0.02896, 0.02917, 0.02934, 0.02950, 0.02963, 0.02974, 0.02983, 0.02989,
0.02995, 0.02997, 0.02999, 0.02999, 0.02997, 0.02995, 0.02989, 0.02983, 0.02974, 0.02963,
0.02950, 0.02934, 0.02917, 0.02896, 0.02873, 0.02845, 0.02815, 0.02782, 0.02743, 0.02701,
0.02652, 0.02598, 0.02538, 0.02471, 0.02394, 0.02307, 0.02208, 0.02094, 0.01962, 0.01806,
0.01619, 0.01384, 0.01080, 0.00660, 0.00300, 0.00300, 0.00660, 0.01384, 0.01806, 0.02094,
0.02307, 0.02471, 0.02598, 0.02701, 0.02782, 0.02845, 0.02896, 0.02934, 0.02963, 0.02983,
0.02995, 0.02999, 0.02997, 0.02989, 0.02974, 0.02950, 0.02917, 0.02873, 0.02815, 0.02743,
0.02652, 0.02538, 0.02394, 0.02208, 0.01962, 0.01619, 0.01080, 0.00300, 0.00300, 0.00660,
0.01080, 0.01384, 0.01619, 0.01806, 0.01962, 0.02094, 0.02208, 0.02307, 0.02394, 0.02471,
0.02538, 0.02598, 0.02652, 0.02701, 0.02743, 0.02782, 0.02815, 0.02845, 0.02873, 0.02896,
0.02917, 0.02934, 0.02950, 0.02963, 0.02974, 0.02983, 0.02989, 0.02995, 0.02997, 0.02999,
0.02999, 0.02997, 0.02995, 0.02989, 0.02983, 0.02974, 0.02963, 0.02950, 0.02934, 0.02917,
0.02896, 0.02873, 0.02845, 0.02815, 0.02782, 0.02743, 0.02701, 0.02652, 0.02598, 0.02538,
0.02471, 0.02394, 0.02307, 0.02208, 0.02094, 0.01962, 0.01806, 0.01619, 0.01384, 0.01080,
0.00660, 0.00300, 0.00300, 0.00660, 0.01384, 0.01806, 0.02094, 0.02307, 0.02471, 0.02598,
0.02701, 0.02782, 0.02845, 0.02896, 0.02934, 0.02963, 0.02983, 0.02995, 0.02999, 0.02997,
0.02989, 0.02974, 0.02950, 0.02917, 0.02873, 0.02815, 0.02743, 0.02652, 0.02538, 0.02394,
0.02208, 0.01962, 0.01619, 0.01080, 0.00300, 0.00200, 0.00440, 0.01204, 0.01538, 0.01732,
0.01854, 0.01931, 0.01975, 0.01997, 0.01998, 0.01982, 0.01945, 0.01877, 0.01768, 0.01596,
0.01308, 0.00720, 0.00200, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000,
0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000,
0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000,
0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000,
0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000,
0.03000, 0.03000, 0.00300, 0.00660, 0.01384, 0.01806, 0.02094, 0.02307, 0.02471, 0.02598,
0.02701, 0.02782, 0.02845, 0.02896, 0.02934, 0.02963, 0.02983, 0.02995, 0.02999, 0.02997,
0.02989, 0.02974, 0.02950, 0.02917, 0.02873, 0.02815, 0.02743, 0.02652, 0.02538, 0.02394,
0.02208, 0.01962, 0.01619, 0.01080, 0.00300, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000,
0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000,
0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000,
0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000,
0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000,
0.03000, 0.03000, 0.03000, 0.03000, 0.00200, 0.00440, 0.01204, 0.01538, 0.01732, 0.01854,
0.01931, 0.01975, 0.01997, 0.01998, 0.01982, 0.01945, 0.01877, 0.01768, 0.01596, 0.01308,
0.00720, 0.00200, 0.00200, 0.00440, 0.01204, 0.01538, 0.01732, 0.01854, 0.01931, 0.01975,
0.01997, 0.01998, 0.01982, 0.01945, 0.01877, 0.01768, 0.01596, 0.01308, 0.00720, 0.00200,
});
static constexpr std::array<int, 14> monkey_fill_offsets({
@ -1022,49 +1037,58 @@ static constexpr std::array<float, 516> monkey_line_opacities({
});
static constexpr std::array<float, 516> monkey_line_radii({
0.1000, 0.2199, 0.4615, 0.6019, 0.6981, 0.7689, 0.8236, 0.8660, 0.9003, 0.9272, 0.9485, 0.9653,
0.9781, 0.9876, 0.9942, 0.9983, 0.9997, 0.9990, 0.9963, 0.9912, 0.9834, 0.9724, 0.9576, 0.9385,
0.9143, 0.8841, 0.8461, 0.7979, 0.7359, 0.6541, 0.5396, 0.3600, 0.1000, 0.1000, 0.2199, 0.4615,
0.6019, 0.6981, 0.7689, 0.8236, 0.8660, 0.9003, 0.9272, 0.9485, 0.9653, 0.9781, 0.9876, 0.9942,
0.9983, 0.9997, 0.9990, 0.9963, 0.9912, 0.9834, 0.9724, 0.9576, 0.9385, 0.9143, 0.8841, 0.8461,
0.7979, 0.7359, 0.6541, 0.5396, 0.3600, 0.1000, 0.1000, 0.1288, 0.2962, 0.4147, 0.5028, 0.5723,
0.6291, 0.6768, 0.7177, 0.7530, 0.7838, 0.8109, 0.8349, 0.8564, 0.8756, 0.8922, 0.9074, 0.9211,
0.9329, 0.9440, 0.9531, 0.9617, 0.9688, 0.9755, 0.9808, 0.9858, 0.9894, 0.9930, 0.9952, 0.9973,
0.9987, 0.9993, 1.0000, 0.9993, 0.9987, 0.9973, 0.9952, 0.9930, 0.9894, 0.9858, 0.9808, 0.9755,
0.9688, 0.9617, 0.9531, 0.9440, 0.9329, 0.9211, 0.9074, 0.8922, 0.8756, 0.8564, 0.8349, 0.8109,
0.7838, 0.7530, 0.7177, 0.6768, 0.6291, 0.5723, 0.5028, 0.4147, 0.2962, 0.1288, 0.1000, 0.1000,
0.1288, 0.4147, 0.5723, 0.6768, 0.7530, 0.8109, 0.8564, 0.8922, 0.9211, 0.9440, 0.9617, 0.9755,
0.9858, 0.9930, 0.9973, 0.9993, 0.9993, 0.9973, 0.9930, 0.9858, 0.9755, 0.9617, 0.9440, 0.9211,
0.8922, 0.8564, 0.8109, 0.7530, 0.6768, 0.5723, 0.4147, 0.1288, 0.1000, 0.1000, 0.2199, 0.4615,
0.6019, 0.6981, 0.7689, 0.8236, 0.8660, 0.9003, 0.9272, 0.9485, 0.9653, 0.9781, 0.9876, 0.9942,
0.9983, 0.9997, 0.9990, 0.9963, 0.9912, 0.9834, 0.9724, 0.9576, 0.9385, 0.9143, 0.8841, 0.8461,
0.7979, 0.7359, 0.6541, 0.5396, 0.3600, 0.1000, 0.1000, 0.2199, 0.4615, 0.6019, 0.6981, 0.7689,
0.8236, 0.8660, 0.9003, 0.9272, 0.9485, 0.9653, 0.9781, 0.9876, 0.9942, 0.9983, 0.9997, 0.9990,
0.9963, 0.9912, 0.9834, 0.9724, 0.9576, 0.9385, 0.9143, 0.8841, 0.8461, 0.7979, 0.7359, 0.6541,
0.5396, 0.3600, 0.1000, 0.1000, 0.1288, 0.4147, 0.5723, 0.6768, 0.7530, 0.8109, 0.8564, 0.8922,
0.9211, 0.9440, 0.9617, 0.9755, 0.9858, 0.9930, 0.9973, 0.9993, 0.9993, 0.9973, 0.9930, 0.9858,
0.9755, 0.9617, 0.9440, 0.9211, 0.8922, 0.8564, 0.8109, 0.7530, 0.6768, 0.5723, 0.4147, 0.1288,
0.1000, 0.1000, 0.2199, 0.4615, 0.6019, 0.6981, 0.7689, 0.8236, 0.8660, 0.9003, 0.9272, 0.9485,
0.9653, 0.9781, 0.9876, 0.9942, 0.9983, 0.9997, 0.9990, 0.9963, 0.9912, 0.9834, 0.9724, 0.9576,
0.9385, 0.9143, 0.8841, 0.8461, 0.7979, 0.7359, 0.6541, 0.5396, 0.3600, 0.1000, 0.1000, 0.2199,
0.3600, 0.4615, 0.5396, 0.6019, 0.6541, 0.6981, 0.7359, 0.7689, 0.7979, 0.8236, 0.8461, 0.8660,
0.8841, 0.9003, 0.9143, 0.9272, 0.9385, 0.9485, 0.9576, 0.9653, 0.9724, 0.9781, 0.9834, 0.9876,
0.9912, 0.9942, 0.9963, 0.9983, 0.9990, 0.9997, 0.9997, 0.9990, 0.9983, 0.9963, 0.9942, 0.9912,
0.9876, 0.9834, 0.9781, 0.9724, 0.9653, 0.9576, 0.9485, 0.9385, 0.9272, 0.9143, 0.9003, 0.8841,
0.8660, 0.8461, 0.8236, 0.7979, 0.7689, 0.7359, 0.6981, 0.6541, 0.6019, 0.5396, 0.4615, 0.3600,
0.2199, 0.1000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 0.1000, 0.2199, 0.4615, 0.6019, 0.6981, 0.7689,
0.8236, 0.8660, 0.9003, 0.9272, 0.9485, 0.9653, 0.9781, 0.9876, 0.9942, 0.9983, 0.9997, 0.9990,
0.9963, 0.9912, 0.9834, 0.9724, 0.9576, 0.9385, 0.9143, 0.8841, 0.8461, 0.7979, 0.7359, 0.6541,
0.5396, 0.3600, 0.1000, 0.1000, 0.2199, 0.6019, 0.7689, 0.8660, 0.9272, 0.9653, 0.9876, 0.9983,
0.9990, 0.9912, 0.9724, 0.9385, 0.8841, 0.7979, 0.6541, 0.3600, 0.1000, 0.1000, 0.2199, 0.6019,
0.7689, 0.8660, 0.9272, 0.9653, 0.9876, 0.9983, 0.9990, 0.9912, 0.9724, 0.9385, 0.8841, 0.7979,
0.6541, 0.3600, 0.1000, 0.1000, 0.2199, 0.4615, 0.6019, 0.6981, 0.7689, 0.8236, 0.8660, 0.9003,
0.9272, 0.9485, 0.9653, 0.9781, 0.9876, 0.9942, 0.9983, 0.9997, 0.9990, 0.9963, 0.9912, 0.9834,
0.9724, 0.9576, 0.9385, 0.9143, 0.8841, 0.8461, 0.7979, 0.7359, 0.6541, 0.5396, 0.3600, 0.1000,
0.00300, 0.00660, 0.01384, 0.01806, 0.02094, 0.02307, 0.02471, 0.02598, 0.02701, 0.02782,
0.02845, 0.02896, 0.02934, 0.02963, 0.02983, 0.02995, 0.02999, 0.02997, 0.02989, 0.02974,
0.02950, 0.02917, 0.02873, 0.02815, 0.02743, 0.02652, 0.02538, 0.02394, 0.02208, 0.01962,
0.01619, 0.01080, 0.00300, 0.00300, 0.00660, 0.01384, 0.01806, 0.02094, 0.02307, 0.02471,
0.02598, 0.02701, 0.02782, 0.02845, 0.02896, 0.02934, 0.02963, 0.02983, 0.02995, 0.02999,
0.02997, 0.02989, 0.02974, 0.02950, 0.02917, 0.02873, 0.02815, 0.02743, 0.02652, 0.02538,
0.02394, 0.02208, 0.01962, 0.01619, 0.01080, 0.00300, 0.00300, 0.00386, 0.00889, 0.01244,
0.01508, 0.01717, 0.01887, 0.02030, 0.02153, 0.02259, 0.02351, 0.02433, 0.02505, 0.02569,
0.02627, 0.02677, 0.02722, 0.02763, 0.02799, 0.02832, 0.02859, 0.02885, 0.02906, 0.02926,
0.02942, 0.02957, 0.02968, 0.02979, 0.02986, 0.02992, 0.02996, 0.02998, 0.03000, 0.02998,
0.02996, 0.02992, 0.02986, 0.02979, 0.02968, 0.02957, 0.02942, 0.02926, 0.02906, 0.02885,
0.02859, 0.02832, 0.02799, 0.02763, 0.02722, 0.02677, 0.02627, 0.02569, 0.02505, 0.02433,
0.02351, 0.02259, 0.02153, 0.02030, 0.01887, 0.01717, 0.01508, 0.01244, 0.00889, 0.00386,
0.00300, 0.00300, 0.00386, 0.01244, 0.01717, 0.02030, 0.02259, 0.02433, 0.02569, 0.02677,
0.02763, 0.02832, 0.02885, 0.02926, 0.02957, 0.02979, 0.02992, 0.02998, 0.02998, 0.02992,
0.02979, 0.02957, 0.02926, 0.02885, 0.02832, 0.02763, 0.02677, 0.02569, 0.02433, 0.02259,
0.02030, 0.01717, 0.01244, 0.00386, 0.00300, 0.00300, 0.00660, 0.01384, 0.01806, 0.02094,
0.02307, 0.02471, 0.02598, 0.02701, 0.02782, 0.02845, 0.02896, 0.02934, 0.02963, 0.02983,
0.02995, 0.02999, 0.02997, 0.02989, 0.02974, 0.02950, 0.02917, 0.02873, 0.02815, 0.02743,
0.02652, 0.02538, 0.02394, 0.02208, 0.01962, 0.01619, 0.01080, 0.00300, 0.00200, 0.00440,
0.00923, 0.01204, 0.01396, 0.01538, 0.01647, 0.01732, 0.01801, 0.01854, 0.01897, 0.01931,
0.01956, 0.01975, 0.01988, 0.01997, 0.01999, 0.01998, 0.01993, 0.01982, 0.01967, 0.01945,
0.01915, 0.01877, 0.01829, 0.01768, 0.01692, 0.01596, 0.01472, 0.01308, 0.01079, 0.00720,
0.00200, 0.00200, 0.00258, 0.00829, 0.01145, 0.01354, 0.01506, 0.01622, 0.01713, 0.01784,
0.01842, 0.01888, 0.01923, 0.01951, 0.01972, 0.01986, 0.01995, 0.01999, 0.01999, 0.01995,
0.01986, 0.01972, 0.01951, 0.01923, 0.01888, 0.01842, 0.01784, 0.01713, 0.01622, 0.01506,
0.01354, 0.01145, 0.00829, 0.00258, 0.00200, 0.00300, 0.00660, 0.01384, 0.01806, 0.02094,
0.02307, 0.02471, 0.02598, 0.02701, 0.02782, 0.02845, 0.02896, 0.02934, 0.02963, 0.02983,
0.02995, 0.02999, 0.02997, 0.02989, 0.02974, 0.02950, 0.02917, 0.02873, 0.02815, 0.02743,
0.02652, 0.02538, 0.02394, 0.02208, 0.01962, 0.01619, 0.01080, 0.00300, 0.00300, 0.00660,
0.01080, 0.01384, 0.01619, 0.01806, 0.01962, 0.02094, 0.02208, 0.02307, 0.02394, 0.02471,
0.02538, 0.02598, 0.02652, 0.02701, 0.02743, 0.02782, 0.02815, 0.02845, 0.02873, 0.02896,
0.02917, 0.02934, 0.02950, 0.02963, 0.02974, 0.02983, 0.02989, 0.02995, 0.02997, 0.02999,
0.02999, 0.02997, 0.02995, 0.02989, 0.02983, 0.02974, 0.02963, 0.02950, 0.02934, 0.02917,
0.02896, 0.02873, 0.02845, 0.02815, 0.02782, 0.02743, 0.02701, 0.02652, 0.02598, 0.02538,
0.02471, 0.02394, 0.02307, 0.02208, 0.02094, 0.01962, 0.01806, 0.01619, 0.01384, 0.01080,
0.00660, 0.00300, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000,
0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000,
0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000,
0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000,
0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000, 0.03000,
0.03000, 0.03000, 0.03000, 0.03000, 0.00300, 0.00660, 0.01384, 0.01806, 0.02094, 0.02307,
0.02471, 0.02598, 0.02701, 0.02782, 0.02845, 0.02896, 0.02934, 0.02963, 0.02983, 0.02995,
0.02999, 0.02997, 0.02989, 0.02974, 0.02950, 0.02917, 0.02873, 0.02815, 0.02743, 0.02652,
0.02538, 0.02394, 0.02208, 0.01962, 0.01619, 0.01080, 0.00300, 0.00200, 0.00440, 0.01204,
0.01538, 0.01732, 0.01854, 0.01931, 0.01975, 0.01997, 0.01998, 0.01982, 0.01945, 0.01877,
0.01768, 0.01596, 0.01308, 0.00720, 0.00200, 0.00200, 0.00440, 0.01204, 0.01538, 0.01732,
0.01854, 0.01931, 0.01975, 0.01997, 0.01998, 0.01982, 0.01945, 0.01877, 0.01768, 0.01596,
0.01308, 0.00720, 0.00200, 0.00300, 0.00660, 0.01384, 0.01806, 0.02094, 0.02307, 0.02471,
0.02598, 0.02701, 0.02782, 0.02845, 0.02896, 0.02934, 0.02963, 0.02983, 0.02995, 0.02999,
0.02997, 0.02989, 0.02974, 0.02950, 0.02917, 0.02873, 0.02815, 0.02743, 0.02652, 0.02538,
0.02394, 0.02208, 0.01962, 0.01619, 0.01080, 0.00300,
});
static constexpr std::array<int, 16> monkey_line_offsets({
@ -1086,40 +1110,6 @@ static constexpr std::array<int, 16> monkey_line_offsets({
516,
});
static const std::array<int, 15> monkey_line_radii_factors({
60,
60,
60,
60,
60,
40,
40,
60,
60,
60,
60,
60,
40,
40,
60,
});
static const std::array<int, 13> monkey_fill_radii_factors({
75,
60,
60,
60,
60,
60,
60,
40,
60,
60,
60,
40,
40,
});
static int add_material_from_template(Main &bmain, Object &ob, const ColorTemplate &pct)
{
int index;
@ -1143,7 +1133,6 @@ static bke::CurvesGeometry create_drawing_data(const Span<float3> positions,
const Span<float> opacities,
const Span<int> offsets,
const Span<int> materials,
const Span<int> radii_factor,
const float4x4 &matrix)
{
using namespace blender::bke;
@ -1156,6 +1145,8 @@ static bke::CurvesGeometry create_drawing_data(const Span<float3> positions,
MutableSpan<float3> point_positions = curves.positions_for_write();
point_positions.copy_from(positions);
curves.transform(matrix);
SpanAttributeWriter<float> point_radii = attributes.lookup_or_add_for_write_only_span<float>(
"radius", ATTR_DOMAIN_POINT);
point_radii.span.copy_from(radii);
@ -1172,15 +1163,6 @@ static bke::CurvesGeometry create_drawing_data(const Span<float3> positions,
"material_index", ATTR_DOMAIN_CURVE);
stroke_materials.span.copy_from(materials);
const OffsetIndices points_by_curve = curves.points_by_curve();
for (const int curve_i : curves.curves_range()) {
const IndexRange points = points_by_curve[curve_i];
for (const int point_i : points) {
point_positions[point_i] = math::transform_point(matrix, point_positions[point_i]);
point_radii.span[point_i] *= radii_factor[curve_i];
}
}
point_radii.finish();
point_opacities.finish();
@ -1227,7 +1209,7 @@ void create_stroke(Main &bmain, Object &object, float4x4 matrix, const int frame
Drawing &drawing_lines =
reinterpret_cast<GreasePencilDrawing *>(grease_pencil.drawing(0))->wrap();
drawing_lines.strokes_for_write() = create_drawing_data(
stroke_positions, stroke_radii, stroke_opacities, {0, 175}, {material_index}, {75}, matrix);
stroke_positions, stroke_radii, stroke_opacities, {0, 175}, {material_index}, matrix);
drawing_lines.tag_topology_changed();
}
@ -1293,7 +1275,6 @@ void create_suzanne(Main &bmain, Object &object, float4x4 matrix, const int fram
monkey_line_opacities,
monkey_line_offsets,
monkey_line_materials,
monkey_line_radii_factors,
matrix);
drawing_lines.tag_topology_changed();
@ -1304,7 +1285,6 @@ void create_suzanne(Main &bmain, Object &object, float4x4 matrix, const int fram
monkey_fill_opacities,
monkey_fill_offsets,
monkey_fill_materials,
monkey_fill_radii_factors,
matrix);
drawing_fills.tag_topology_changed();
}

View File

@ -800,6 +800,56 @@ static void GREASE_PENCIL_OT_delete_frame(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static int grease_pencil_stroke_change_color_exec(bContext *C, wmOperator * /*op*/)
{
using namespace blender;
const Scene *scene = CTX_data_scene(C);
Object *object = CTX_data_active_object(C);
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
const int material_index = object->actcol - 1;
if (material_index == -1) {
return OPERATOR_CANCELLED;
}
grease_pencil.foreach_editable_drawing(
scene->r.cfra, [&](int /*drawing_index*/, bke::greasepencil::Drawing &drawing) {
bke::CurvesGeometry &curves = drawing.strokes_for_write();
if (curves.points_num() == 0) {
return;
}
bke::SpanAttributeWriter<int> materials =
curves.attributes_for_write().lookup_or_add_for_write_span<int>("material_index",
ATTR_DOMAIN_CURVE);
IndexMaskMemory memory;
casey-bianco-davis marked this conversation as resolved Outdated

We're already in the blender:: namespace, this shouldn't be necessary

We're already in the `blender::` namespace, this shouldn't be necessary
IndexMask selected_curves = ed::curves::retrieve_selected_curves(curves, memory);
selected_curves.foreach_index(
[&](const int curve_index) { materials.span[curve_index] = material_index; });
materials.finish();
});
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA | NA_EDITED, &grease_pencil);
return OPERATOR_FINISHED;
}
static void GREASE_PENCIL_OT_stroke_change_color(wmOperatorType *ot)
{
ot->name = "Change Stroke color";
ot->idname = "GREASE_PENCIL_OT_stroke_change_color";
ot->description = "Change Stroke color with selected material";
ot->exec = grease_pencil_stroke_change_color_exec;
ot->poll = editable_grease_pencil_poll;
casey-bianco-davis marked this conversation as resolved Outdated
switch (mode) {
  case CyclicalMode::CLOSE:
    index_mask::masked_fill(cyclic, true, curve_selection);
    break;
  case CyclicalMode::OPEN:
    index_mask::masked_fill(cyclic, false, curve_selection);
    break;
  case CyclicalMode::TOGGLE:
    array_utils::invert_booleans(cyclic, curve_selection);
    break;
}
``` switch (mode) { case CyclicalMode::CLOSE: index_mask::masked_fill(cyclic, true, curve_selection); break; case CyclicalMode::OPEN: index_mask::masked_fill(cyclic, false, curve_selection); break; case CyclicalMode::TOGGLE: array_utils::invert_booleans(cyclic, curve_selection); break; } ```
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
/* -------------------------------------------------------------------- */
@ -899,6 +949,7 @@ void ED_operatortypes_grease_pencil_edit()
WM_operatortype_append(GREASE_PENCIL_OT_stroke_simplify);
WM_operatortype_append(GREASE_PENCIL_OT_dissolve);
WM_operatortype_append(GREASE_PENCIL_OT_delete_frame);
WM_operatortype_append(GREASE_PENCIL_OT_stroke_change_color);
WM_operatortype_append(GREASE_PENCIL_OT_cyclical_set);
}

View File

@ -88,8 +88,8 @@ ImBuf *ED_space_clip_get_stable_buffer(const SpaceClip *sc,
bool ED_space_clip_get_position(const SpaceClip *sc,
const ARegion *region,
int mval[2],
float fpos[2]);
const int mval[2],
float r_fpos[2]);
/**
* Returns color in linear space, matching #ED_space_image_color_sample().
*/
@ -118,7 +118,10 @@ void ED_clip_point_stable_pos__reverse(const SpaceClip *sc,
/**
* Takes `event->mval`.
*/
void ED_clip_mouse_pos(const SpaceClip *sc, const ARegion *region, const int mval[2], float co[2]);
void ED_clip_mouse_pos(const SpaceClip *sc,
const ARegion *region,
const int mval[2],
float r_co[2]);
bool ED_space_clip_check_show_trackedit(const SpaceClip *sc);
bool ED_space_clip_check_show_maskedit(const SpaceClip *sc);

View File

@ -70,6 +70,14 @@ bool curves_poll(bContext *C);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Operators
* \{ */
void CURVES_OT_attribute_set(wmOperatorType *ot);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Mask Functions
* \{ */

View File

@ -18,6 +18,33 @@
struct Mesh;
struct ReportList;
#include "BLI_generic_pointer.hh"
#include "BLI_string_ref.hh"
struct PointerRNA;
struct PropertyRNA;
namespace blender::ed::geometry {
/* -------------------------------------------------------------------- */
/** \name Attribute Value RNA Property Helpers
*
* Functions to make it easier to register RNA properties for the various attribute types and
* retrieve/set their values.
* \{ */
StringRefNull rna_property_name_for_type(eCustomDataType type);
PropertyRNA *rna_property_for_type(PointerRNA &ptr, const eCustomDataType type);
void register_rna_properties_for_attribute_types(StructRNA &srna);
GPointer rna_property_for_attribute_type_retrieve_value(PointerRNA &ptr,
const eCustomDataType type,
void *buffer);
void rna_property_for_attribute_type_set_value(PointerRNA &ptr, PropertyRNA &prop, GPointer value);
/** \} */
} // namespace blender::ed::geometry
void ED_operatortypes_geometry();
/**

View File

@ -53,7 +53,10 @@ void ED_space_image_set_mask(bContext *C, SpaceImage *sima, Mask *mask);
/**
* Returns mouse position in image space.
*/
bool ED_space_image_get_position(SpaceImage *sima, ARegion *region, int mval[2], float fpos[2]);
bool ED_space_image_get_position(SpaceImage *sima,
ARegion *region,
const int mval[2],
float r_fpos[2]);
/**
* Returns color in linear space, matching #ED_space_node_color_sample().
*/

View File

@ -317,7 +317,7 @@ void EDBM_select_toggle_all(BMEditMesh *em);
void EDBM_select_swap(BMEditMesh *em); /* exported for UV */
bool EDBM_select_interior_faces(BMEditMesh *em);
void em_setup_viewcontext(bContext *C, ViewContext *vc); /* rename? */
ViewContext em_setup_viewcontext(bContext *C); /* rename? */
bool EDBM_mesh_deselect_all_multi_ex(Base **bases, uint bases_len);
bool EDBM_mesh_deselect_all_multi(bContext *C);

View File

@ -944,7 +944,7 @@ int view3d_opengl_select_with_id_filter(ViewContext *vc,
/* view3d_select.cc */
float ED_view3d_select_dist_px();
void ED_view3d_viewcontext_init(bContext *C, ViewContext *vc, Depsgraph *depsgraph);
ViewContext ED_view3d_viewcontext_init(bContext *C, Depsgraph *depsgraph);
/**
* Re-initialize `vc` with `obact` as if it's active object (with some differences).

View File

@ -117,10 +117,8 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
if(WIN32 OR APPLE)
if(WITH_INPUT_IME)
add_definitions(-DWITH_INPUT_IME)
endif()
if(WITH_INPUT_IME)
add_definitions(-DWITH_INPUT_IME)
endif()
if(WITH_EXPERIMENTAL_FEATURES)

View File

@ -69,7 +69,7 @@ struct Eyedropper {
int accum_tot;
wmWindow *cb_win;
int cb_win_mval[2];
int cb_win_event_xy[2];
void *draw_handle_sample_text;
char sample_text[MAX_NAME];
@ -80,7 +80,7 @@ struct Eyedropper {
static void eyedropper_draw_cb(const wmWindow * /*window*/, void *arg)
{
Eyedropper *eye = static_cast<Eyedropper *>(arg);
eyedropper_draw_cursor_text_region(eye->cb_win_mval, eye->sample_text);
eyedropper_draw_cursor_text_region(eye->cb_win_event_xy, eye->sample_text);
}
static bool eyedropper_init(bContext *C, wmOperator *op)
@ -258,15 +258,15 @@ static bool eyedropper_cryptomatte_sample_fl(bContext *C,
ScrArea *area = nullptr;
int mval[2];
wmWindow *win = WM_window_find_under_cursor(CTX_wm_window(C), event_xy, mval);
int event_xy_win[2];
wmWindow *win = WM_window_find_under_cursor(CTX_wm_window(C), event_xy, event_xy_win);
if (win) {
bScreen *screen = WM_window_get_active_screen(win);
area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mval);
area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event_xy_win);
}
eye->cb_win_mval[0] = mval[0];
eye->cb_win_mval[1] = mval[1];
eye->cb_win_event_xy[0] = event_xy_win[0];
eye->cb_win_event_xy[1] = event_xy_win[1];
if (win && win != eye->cb_win && eye->draw_handle_sample_text) {
WM_draw_cb_exit(eye->cb_win, eye->draw_handle_sample_text);
@ -279,29 +279,32 @@ static bool eyedropper_cryptomatte_sample_fl(bContext *C,
return false;
}
ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mval);
ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, event_xy_win);
if (!region) {
return false;
}
int region_mval[2] = {mval[0] - region->winrct.xmin, mval[1] - region->winrct.ymin};
const int mval[2] = {
event_xy_win[0] - region->winrct.xmin,
event_xy_win[1] - region->winrct.ymin,
};
float fpos[2] = {-1.0f, -1.0};
switch (area->spacetype) {
case SPACE_IMAGE: {
SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
ED_space_image_get_position(sima, region, region_mval, fpos);
ED_space_image_get_position(sima, region, mval, fpos);
break;
}
case SPACE_NODE: {
Main *bmain = CTX_data_main(C);
SpaceNode *snode = static_cast<SpaceNode *>(area->spacedata.first);
ED_space_node_get_position(bmain, snode, region, region_mval, fpos);
ED_space_node_get_position(bmain, snode, region, mval, fpos);
break;
}
case SPACE_CLIP: {
SpaceClip *sc = static_cast<SpaceClip *>(area->spacedata.first);
ED_space_clip_get_position(sc, region, region_mval, fpos);
ED_space_clip_get_position(sc, region, mval, fpos);
break;
}
default: {
@ -340,33 +343,36 @@ void eyedropper_color_sample_fl(bContext *C, const int event_xy[2], float r_col[
{
ScrArea *area = nullptr;
int mval[2];
wmWindow *win = WM_window_find_under_cursor(CTX_wm_window(C), event_xy, mval);
int event_xy_win[2];
wmWindow *win = WM_window_find_under_cursor(CTX_wm_window(C), event_xy, event_xy_win);
if (win) {
bScreen *screen = WM_window_get_active_screen(win);
area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mval);
area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event_xy_win);
}
if (area) {
ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mval);
ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, event_xy_win);
if (region) {
const int region_mval[2] = {mval[0] - region->winrct.xmin, mval[1] - region->winrct.ymin};
const int mval[2] = {
event_xy_win[0] - region->winrct.xmin,
event_xy_win[1] - region->winrct.ymin,
};
if (area->spacetype == SPACE_IMAGE) {
SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
if (ED_space_image_color_sample(sima, region, region_mval, r_col, nullptr)) {
if (ED_space_image_color_sample(sima, region, mval, r_col, nullptr)) {
return;
}
}
else if (area->spacetype == SPACE_NODE) {
SpaceNode *snode = static_cast<SpaceNode *>(area->spacedata.first);
Main *bmain = CTX_data_main(C);
if (ED_space_node_color_sample(bmain, snode, region, region_mval, r_col)) {
if (ED_space_node_color_sample(bmain, snode, region, mval, r_col)) {
return;
}
}
else if (area->spacetype == SPACE_CLIP) {
SpaceClip *sc = static_cast<SpaceClip *>(area->spacedata.first);
if (ED_space_clip_color_sample(sc, region, region_mval, r_col)) {
if (ED_space_clip_color_sample(sc, region, mval, r_col)) {
return;
}
}
@ -375,8 +381,8 @@ void eyedropper_color_sample_fl(bContext *C, const int event_xy[2], float r_col[
if (win) {
/* Other areas within a Blender window. */
if (!WM_window_pixels_read_sample(C, win, mval, r_col)) {
WM_window_pixels_read_sample_from_offscreen(C, win, mval, r_col);
if (!WM_window_pixels_read_sample(C, win, event_xy_win, r_col)) {
WM_window_pixels_read_sample_from_offscreen(C, win, event_xy_win, r_col);
}
const char *display_device = CTX_data_scene(C)->display_settings.display_device;
ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);

View File

@ -394,8 +394,8 @@ static int view_edge_pan_modal(bContext *C, wmOperator *op, const wmEvent *event
View2DEdgePanData *vpd = static_cast<View2DEdgePanData *>(op->customdata);
wmWindow *source_win = CTX_wm_window(C);
int r_mval[2];
wmWindow *target_win = WM_window_find_under_cursor(source_win, event->xy, &r_mval[0]);
int event_xy_target[2];
wmWindow *target_win = WM_window_find_under_cursor(source_win, event->xy, &event_xy_target[0]);
/* Exit if we release the mouse button, hit escape, or enter a different window. */
if (event->val == KM_RELEASE || event->type == EVT_ESCKEY || source_win != target_win) {

View File

@ -75,8 +75,7 @@ bool ED_lattice_deselect_all_multi_ex(Base **bases, const uint bases_len)
bool ED_lattice_deselect_all_multi(bContext *C)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
uint bases_len = 0;
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
vc.scene, vc.view_layer, vc.v3d, &bases_len);
@ -620,12 +619,11 @@ static BPoint *findnearestLattvert(ViewContext *vc, bool select, Base **r_base)
bool ED_lattice_select_pick(bContext *C, const int mval[2], const SelectPick_Params *params)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
BPoint *bp = nullptr;
Base *basact = nullptr;
bool changed = false;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
vc.mval[0] = mval[0];
vc.mval[1] = mval[1];

View File

@ -456,8 +456,7 @@ void paintface_select_loop(bContext *C, Object *ob, const int mval[2], const boo
using namespace blender;
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
ED_view3d_select_id_validate(&vc);
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);

View File

@ -25,6 +25,7 @@
#include "RNA_define.hh"
#include "RNA_enum_types.hh"
#include "ED_geometry.hh"
#include "ED_mesh.hh"
#include "ED_object.hh"
#include "ED_screen.hh"
@ -88,33 +89,6 @@ static bool mesh_active_attribute_poll(bContext *C)
namespace set_attribute {
static StringRefNull rna_property_name_for_type(const eCustomDataType type)
{
switch (type) {
case CD_PROP_FLOAT:
return "value_float";
case CD_PROP_FLOAT2:
return "value_float_vector_2d";
case CD_PROP_FLOAT3:
return "value_float_vector_3d";
case CD_PROP_COLOR:
case CD_PROP_BYTE_COLOR:
return "value_color";
case CD_PROP_BOOL:
return "value_bool";
case CD_PROP_INT8:
case CD_PROP_INT32:
return "value_int";
case CD_PROP_INT32_2D:
return "value_int_vector_2d";
case CD_PROP_QUATERNION:
return "value_quat";
default:
BLI_assert_unreachable();
return "";
}
}
static void bmesh_vert_edge_face_layer_selected_values_set(BMesh &bm,
const BMIterType iter_type,
const GPointer value,
@ -186,48 +160,9 @@ static int mesh_set_attribute_exec(bContext *C, wmOperator *op)
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
BLI_SCOPED_DEFER([&]() { type.destruct(buffer); });
const GPointer value = geometry::rna_property_for_attribute_type_retrieve_value(
*op->ptr, active_type, buffer);
const StringRefNull prop_name = rna_property_name_for_type(active_type);
switch (active_type) {
case CD_PROP_FLOAT:
*static_cast<float *>(buffer) = RNA_float_get(op->ptr, prop_name.c_str());
break;
case CD_PROP_FLOAT2:
RNA_float_get_array(op->ptr, prop_name.c_str(), static_cast<float *>(buffer));
break;
case CD_PROP_FLOAT3:
RNA_float_get_array(op->ptr, prop_name.c_str(), static_cast<float *>(buffer));
break;
case CD_PROP_COLOR:
RNA_float_get_array(op->ptr, prop_name.c_str(), static_cast<float *>(buffer));
break;
case CD_PROP_QUATERNION: {
float4 value;
RNA_float_get_array(op->ptr, prop_name.c_str(), value);
*static_cast<math::Quaternion *>(buffer) = math::normalize(math::Quaternion(value));
break;
}
case CD_PROP_BYTE_COLOR:
ColorGeometry4f value;
RNA_float_get_array(op->ptr, prop_name.c_str(), value);
*static_cast<ColorGeometry4b *>(buffer) = value.encode();
break;
case CD_PROP_BOOL:
*static_cast<bool *>(buffer) = RNA_boolean_get(op->ptr, prop_name.c_str());
break;
case CD_PROP_INT8:
*static_cast<int8_t *>(buffer) = RNA_int_get(op->ptr, prop_name.c_str());
break;
case CD_PROP_INT32:
*static_cast<int32_t *>(buffer) = RNA_int_get(op->ptr, prop_name.c_str());
break;
case CD_PROP_INT32_2D:
RNA_int_get_array(op->ptr, prop_name.c_str(), static_cast<int *>(buffer));
break;
default:
BLI_assert_unreachable();
}
const GPointer value(type, buffer);
const bke::DataTypeConversions &conversions = bke::get_implicit_type_conversions();
bool changed = false;
@ -305,48 +240,12 @@ static int mesh_set_attribute_invoke(bContext *C, wmOperator *op, const wmEvent
return WM_operator_props_popup(C, op, event);
}
const StringRefNull prop_name = rna_property_name_for_type(data_type);
const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type);
const GPointer active_value(type, POINTER_OFFSET(active_elem->head.data, layer->offset));
PropertyRNA *prop = RNA_struct_find_property(op->ptr, prop_name.c_str());
PropertyRNA *prop = geometry::rna_property_for_type(*op->ptr, data_type);
if (!RNA_property_is_set(op->ptr, prop)) {
switch (data_type) {
case CD_PROP_FLOAT:
RNA_property_float_set(op->ptr, prop, *active_value.get<float>());
break;
case CD_PROP_FLOAT2:
RNA_property_float_set_array(op->ptr, prop, *active_value.get<float2>());
break;
case CD_PROP_FLOAT3:
RNA_property_float_set_array(op->ptr, prop, *active_value.get<float3>());
break;
case CD_PROP_BYTE_COLOR:
RNA_property_float_set_array(op->ptr, prop, active_value.get<ColorGeometry4b>()->decode());
break;
case CD_PROP_COLOR:
RNA_property_float_set_array(op->ptr, prop, *active_value.get<ColorGeometry4f>());
break;
case CD_PROP_BOOL:
RNA_property_boolean_set(op->ptr, prop, *active_value.get<bool>());
break;
case CD_PROP_INT8:
RNA_property_int_set(op->ptr, prop, *active_value.get<int8_t>());
break;
case CD_PROP_INT32:
RNA_property_int_set(op->ptr, prop, *active_value.get<int32_t>());
break;
case CD_PROP_INT32_2D:
RNA_property_int_set_array(op->ptr, prop, *active_value.get<int2>());
break;
case CD_PROP_QUATERNION: {
const math::Quaternion value = math::normalize(*active_value.get<math::Quaternion>());
RNA_property_float_set_array(op->ptr, prop, float4(value));
break;
}
default:
BLI_assert_unreachable();
}
geometry::rna_property_for_attribute_type_set_value(*op->ptr, *prop, active_value);
}
return WM_operator_props_popup(C, op, event);
@ -361,7 +260,7 @@ static void mesh_set_attribute_ui(bContext *C, wmOperator *op)
Mesh *mesh = ED_mesh_context(C);
CustomDataLayer *active_attribute = BKE_id_attributes_active_get(&mesh->id);
const eCustomDataType active_type = eCustomDataType(active_attribute->type);
const StringRefNull prop_name = rna_property_name_for_type(active_type);
const StringRefNull prop_name = geometry::rna_property_name_for_type(active_type);
const char *name = active_attribute->name;
uiItemR(layout, op->ptr, prop_name.c_str(), UI_ITEM_NONE, name, ICON_NONE);
}
@ -385,53 +284,7 @@ void MESH_OT_attribute_set(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
static blender::float4 color_default(1);
RNA_def_float(ot->srna, "value_float", 0.0f, -FLT_MAX, FLT_MAX, "Value", "", -FLT_MAX, FLT_MAX);
RNA_def_float_array(ot->srna,
"value_float_vector_2d",
2,
nullptr,
-FLT_MAX,
FLT_MAX,
"Value",
"",
-FLT_MAX,
FLT_MAX);
RNA_def_float_array(ot->srna,
"value_float_vector_3d",
3,
nullptr,
-FLT_MAX,
FLT_MAX,
"Value",
"",
-FLT_MAX,
FLT_MAX);
RNA_def_int(ot->srna, "value_int", 0, INT_MIN, INT_MAX, "Value", "", INT_MIN, INT_MAX);
RNA_def_int_array(ot->srna,
"value_int_vector_2d",
2,
nullptr,
INT_MIN,
INT_MAX,
"Value",
"",
INT_MIN,
INT_MAX);
RNA_def_float_color(
ot->srna, "value_color", 4, color_default, -FLT_MAX, FLT_MAX, "Value", "", 0.0f, 1.0f);
RNA_def_boolean(ot->srna, "value_bool", false, "Value", "");
RNA_def_float_array(ot->srna,
"value_quat",
4,
rna_default_quaternion,
-FLT_MAX,
FLT_MAX,
"Value",
"",
FLT_MAX,
FLT_MAX);
blender::ed::geometry::register_rna_properties_for_attribute_types(*ot->srna);
}
/** \} */

View File

@ -703,13 +703,12 @@ void MESH_OT_extrude_faces_indiv(wmOperatorType *ot)
static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
BMVert *v1;
BMIter iter;
float center[3];
uint verts_len;
em_setup_viewcontext(C, &vc);
ViewContext vc = em_setup_viewcontext(C);
const Object *object_active = vc.obact;
const bool rot_src = RNA_boolean_get(op->ptr, "rotate_source");

View File

@ -4810,10 +4810,9 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const float angle_snapping_increment = RAD2DEGF(
RNA_float_get(op->ptr, "angle_snapping_increment"));
ViewContext vc;
KnifeTool_OpData *kcd;
em_setup_viewcontext(C, &vc);
ViewContext vc = em_setup_viewcontext(C);
/* alloc new customdata */
kcd = static_cast<KnifeTool_OpData *>(

View File

@ -123,8 +123,7 @@ static int knifeproject_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
ViewContext vc;
em_setup_viewcontext(C, &vc);
ViewContext vc = em_setup_viewcontext(C);
uint objects_len;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(

View File

@ -282,7 +282,7 @@ static int ringsel_init(bContext *C, wmOperator *op, bool do_cut)
lcd = static_cast<RingSelOpData *>(
op->customdata = MEM_callocN(sizeof(RingSelOpData), "ringsel Modal Op Data"));
em_setup_viewcontext(C, &lcd->vc);
lcd->vc = em_setup_viewcontext(C);
lcd->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
@ -554,7 +554,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
bool show_cuts = false;
const bool has_numinput = hasNumInput(&lcd->num);
em_setup_viewcontext(C, &lcd->vc);
lcd->vc = em_setup_viewcontext(C);
lcd->region = lcd->vc.region;
view3d_operator_needs_opengl(C);

View File

@ -713,10 +713,9 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE
BMEdge *eed = nullptr;
BMFace *efa = nullptr;
ViewContext vc;
bool track_active = true;
em_setup_viewcontext(C, &vc);
ViewContext vc = em_setup_viewcontext(C);
copy_v2_v2_int(vc.mval, event->mval);
BKE_view_layer_synced_ensure(vc.scene, vc.view_layer);
Base *basact = BKE_view_layer_active_base_get(vc.view_layer);

View File

@ -104,27 +104,25 @@ static bool edbm_preselect_or_active(bContext *C, const View3D *v3d, Base **r_ba
return (*r_ele != nullptr);
}
static bool edbm_preselect_or_active_init_viewcontext(bContext *C,
ViewContext *vc,
Base **r_base,
BMElem **r_ele)
static ViewContext edbm_preselect_or_active_init_viewcontext(bContext *C,
Base **r_base,
BMElem **r_ele)
{
em_setup_viewcontext(C, vc);
bool ok = edbm_preselect_or_active(C, vc->v3d, r_base, r_ele);
ViewContext vc = em_setup_viewcontext(C);
bool ok = edbm_preselect_or_active(C, vc.v3d, r_base, r_ele);
if (ok) {
ED_view3d_viewcontext_init_object(vc, (*r_base)->object);
ED_view3d_viewcontext_init_object(&vc, (*r_base)->object);
}
return ok;
return vc;
}
static int edbm_polybuild_transform_at_cursor_invoke(bContext *C,
wmOperator * /*op*/,
const wmEvent * /*event*/)
{
ViewContext vc;
Base *basact = nullptr;
BMElem *ele_act = nullptr;
edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
ViewContext vc = edbm_preselect_or_active_init_viewcontext(C, &basact, &ele_act);
BMEditMesh *em = vc.em;
BMesh *bm = em->bm;
@ -187,11 +185,9 @@ static int edbm_polybuild_delete_at_cursor_invoke(bContext *C,
const wmEvent * /*event*/)
{
bool changed = false;
ViewContext vc;
Base *basact = nullptr;
BMElem *ele_act = nullptr;
edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
ViewContext vc = edbm_preselect_or_active_init_viewcontext(C, &basact, &ele_act);
BMEditMesh *em = vc.em;
BMesh *bm = em->bm;
@ -282,10 +278,9 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, con
float center[3];
bool changed = false;
ViewContext vc;
Base *basact = nullptr;
BMElem *ele_act = nullptr;
edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
ViewContext vc = edbm_preselect_or_active_init_viewcontext(C, &basact, &ele_act);
BMEditMesh *em = vc.em;
BMesh *bm = em->bm;
@ -460,10 +455,9 @@ static int edbm_polybuild_split_at_cursor_invoke(bContext *C,
float center[3];
bool changed = false;
ViewContext vc;
Base *basact = nullptr;
BMElem *ele_act = nullptr;
edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
ViewContext vc = edbm_preselect_or_active_init_viewcontext(C, &basact, &ele_act);
BMEditMesh *em = vc.em;
BMesh *bm = em->bm;
@ -544,10 +538,9 @@ static int edbm_polybuild_dissolve_at_cursor_invoke(bContext *C,
{
bool changed = false;
ViewContext vc;
Base *basact = nullptr;
BMElem *ele_act = nullptr;
edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
ViewContext vc = edbm_preselect_or_active_init_viewcontext(C, &basact, &ele_act);
BMEditMesh *em = vc.em;
BMesh *bm = em->bm;

View File

@ -6,6 +6,8 @@
* \ingroup edmesh
*/
#include <optional>
#include "MEM_guardedalloc.h"
#include "BLI_bitmap.h"
@ -1689,14 +1691,13 @@ static bool mouse_mesh_loop(
BMEdge *eed = nullptr;
BMFace *efa = nullptr;
ViewContext vc;
BMEditMesh *em;
bool select = true;
bool select_clear = false;
bool select_cycle = true;
float mvalf[2];
em_setup_viewcontext(C, &vc);
ViewContext vc = em_setup_viewcontext(C);
mvalf[0] = float(vc.mval[0] = mval[0]);
mvalf[1] = float(vc.mval[1] = mval[1]);
@ -2049,15 +2050,13 @@ void MESH_OT_select_interior_faces(wmOperatorType *ot)
bool EDBM_select_pick(bContext *C, const int mval[2], const SelectPick_Params *params)
{
ViewContext vc;
int base_index_active = -1;
BMVert *eve = nullptr;
BMEdge *eed = nullptr;
BMFace *efa = nullptr;
/* setup view context for argument to callbacks */
em_setup_viewcontext(C, &vc);
ViewContext vc = em_setup_viewcontext(C);
vc.mval[0] = mval[0];
vc.mval[1] = mval[1];
@ -2737,8 +2736,7 @@ bool EDBM_mesh_deselect_all_multi_ex(Base **bases, const uint bases_len)
bool EDBM_mesh_deselect_all_multi(bContext *C)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
uint bases_len = 0;
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
vc.scene, vc.view_layer, vc.v3d, &bases_len);
@ -2772,8 +2770,7 @@ bool EDBM_selectmode_disable_multi(bContext *C,
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Scene *scene = CTX_data_scene(C);
ViewContext vc;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
uint bases_len = 0;
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
vc.scene, vc.view_layer, nullptr, &bases_len);
@ -3615,7 +3612,6 @@ static void edbm_select_linked_pick_ex(BMEditMesh *em, BMElem *ele, bool sel, in
static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewContext vc;
Base *basact = nullptr;
BMVert *eve;
BMEdge *eed;
@ -3631,7 +3627,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
view3d_operator_needs_opengl(C);
/* setup view context for argument to callbacks */
em_setup_viewcontext(C, &vc);
ViewContext vc = em_setup_viewcontext(C);
uint bases_len;
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(
@ -4386,14 +4382,15 @@ void MESH_OT_select_nth(wmOperatorType *ot)
WM_operator_properties_checker_interval(ot, false);
}
void em_setup_viewcontext(bContext *C, ViewContext *vc)
ViewContext em_setup_viewcontext(bContext *C)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ED_view3d_viewcontext_init(C, vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
if (vc->obedit) {
vc->em = BKE_editmesh_from_object(vc->obedit);
if (vc.obedit) {
vc.em = BKE_editmesh_from_object(vc.obedit);
}
return vc;
}
/** \} */
@ -5358,4 +5355,108 @@ void MESH_OT_loop_to_region(wmOperatorType *ot)
"Select bigger regions instead of smaller ones");
}
static bool edbm_select_by_attribute_poll(bContext *C)
{
if (!ED_operator_editmesh(C)) {
return false;
}
Object *obedit = CTX_data_edit_object(C);
const Mesh *mesh = static_cast<const Mesh *>(obedit->data);
const CustomDataLayer *layer = BKE_id_attributes_active_get(&const_cast<ID &>(mesh->id));
if (!layer) {
CTX_wm_operator_poll_msg_set(C, "There must be an active attribute");
return false;
}
if (layer->type != CD_PROP_BOOL) {
CTX_wm_operator_poll_msg_set(C, "The active attribute must have a boolean type");
return false;
}
if (BKE_id_attribute_domain(&mesh->id, layer) == ATTR_DOMAIN_CORNER) {
CTX_wm_operator_poll_msg_set(
C, "The active attribute must be on the vertex, edge, or face domain");
return false;
}
return true;
}
static std::optional<BMIterType> domain_to_iter_type(const eAttrDomain domain)
{
switch (domain) {
case ATTR_DOMAIN_POINT:
return BM_VERTS_OF_MESH;
case ATTR_DOMAIN_EDGE:
return BM_EDGES_OF_MESH;
case ATTR_DOMAIN_FACE:
return BM_FACES_OF_MESH;
default:
return std::nullopt;
}
}
static int edbm_select_by_attribute_exec(bContext *C, wmOperator * /*op*/)
{
const Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
scene, view_layer, CTX_wm_view3d(C), &objects_len);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
Mesh *mesh = static_cast<Mesh *>(obedit->data);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
const CustomDataLayer *layer = BKE_id_attributes_active_get(&mesh->id);
if (!layer) {
continue;
}
if (layer->type != CD_PROP_BOOL) {
continue;
}
if (BKE_id_attribute_domain(&mesh->id, layer) == ATTR_DOMAIN_CORNER) {
continue;
}
const std::optional<BMIterType> iter_type = domain_to_iter_type(
BKE_id_attribute_domain(&mesh->id, layer));
if (!iter_type) {
continue;
}
bool changed = false;
BMElem *elem;
BMIter iter;
BM_ITER_MESH (elem, &iter, bm, *iter_type) {
if (BM_elem_flag_test(elem, BM_ELEM_HIDDEN | BM_ELEM_SELECT)) {
continue;
}
if (BM_ELEM_CD_GET_BOOL(elem, layer->offset)) {
BM_elem_select_set(bm, elem, true);
changed = true;
}
}
if (changed) {
EDBM_selectmode_flush(em);
DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
}
MEM_freeN(objects);
return OPERATOR_FINISHED;
}
void MESH_OT_select_by_attribute(wmOperatorType *ot)
{
ot->name = "Select by Attribute";
ot->idname = "MESH_OT_select_by_attribute";
ot->description = "Select elements based on the active boolean attribute";
ot->exec = edbm_select_by_attribute_exec;
ot->poll = edbm_select_by_attribute_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */

View File

@ -228,6 +228,7 @@ void MESH_OT_select_ungrouped(struct wmOperatorType *ot);
void MESH_OT_select_axis(struct wmOperatorType *ot);
void MESH_OT_region_to_loop(struct wmOperatorType *ot);
void MESH_OT_loop_to_region(struct wmOperatorType *ot);
void MESH_OT_select_by_attribute(struct wmOperatorType *ot);
void MESH_OT_shortest_path_select(struct wmOperatorType *ot);
extern struct EnumPropertyItem *corner_type_items;

View File

@ -73,6 +73,7 @@ void ED_operatortypes_mesh()
WM_operatortype_append(MESH_OT_edge_rotate);
WM_operatortype_append(MESH_OT_shortest_path_select);
WM_operatortype_append(MESH_OT_loop_to_region);
WM_operatortype_append(MESH_OT_select_by_attribute);
WM_operatortype_append(MESH_OT_region_to_loop);
WM_operatortype_append(MESH_OT_select_axis);

View File

@ -1164,7 +1164,6 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval)
bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px, uint *r_index)
{
ViewContext vc;
Mesh *me = static_cast<Mesh *>(ob->data);
BLI_assert(me && GS(me->id.name) == ID_ME);
@ -1174,7 +1173,7 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px,
}
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
ED_view3d_select_id_validate(&vc);
if (dist_px) {
@ -1336,7 +1335,6 @@ static void ed_mesh_pick_vert__mapFunc(void *user_data,
bool ED_mesh_pick_vert(
bContext *C, Object *ob, const int mval[2], uint dist_px, bool use_zbuf, uint *r_index)
{
ViewContext vc;
Mesh *me = static_cast<Mesh *>(ob->data);
BLI_assert(me && GS(me->id.name) == ID_ME);
@ -1346,7 +1344,7 @@ bool ED_mesh_pick_vert(
}
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
ED_view3d_select_id_validate(&vc);
if (use_zbuf) {

View File

@ -87,8 +87,7 @@ void ED_mball_editmball_load(Object * /*obedit*/) {}
bool ED_mball_deselect_all_multi(bContext *C)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
uint bases_len = 0;
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
vc.scene, vc.view_layer, vc.v3d, &bases_len);
@ -771,13 +770,12 @@ static bool ed_mball_findnearest_metaelem(bContext *C,
uint *r_selmask)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
int a, hits;
GPUSelectResult buffer[MAXPICKELEMS];
rcti rect;
bool found = false;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
BLI_rcti_init_pt_radius(&rect, mval, 12);

View File

@ -2084,8 +2084,7 @@ static void object_transform_axis_target_cancel(bContext *C, wmOperator *op)
static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
if (vc.obact == nullptr || !object_is_target_compat(vc.obact)) {
/* Falls back to texture space transform. */

View File

@ -512,7 +512,7 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
{
PE_set_data(C, data);
ED_view3d_viewcontext_init(C, &data->vc, data->depsgraph);
data->vc = ED_view3d_viewcontext_init(C, data->depsgraph);
if (!XRAY_ENABLED(data->vc.v3d)) {
ED_view3d_depth_override(data->depsgraph,

View File

@ -29,6 +29,17 @@ namespace blender::ed::sculpt_paint::greasepencil {
static constexpr float POINT_OVERRIDE_THRESHOLD_PX = 3.0f;
static constexpr float POINT_RESAMPLE_MIN_DISTANCE_PX = 10.0f;
static float calc_brush_radius(ViewContext *vc,
const Brush *brush,
const Scene *scene,
const float3 location)
{
if (!BKE_brush_use_locked_size(scene, brush)) {
return paint_calc_object_space_radius(vc, location, BKE_brush_size_get(scene, brush));
}
return BKE_brush_unprojected_radius_get(scene, brush);
}
template<typename T>
static inline void linear_interpolation(const T &a, const T &b, MutableSpan<T> dst)
{
@ -110,12 +121,11 @@ class PaintOperation : public GreasePencilStrokeOperation {
* because it avoids passing a very large number of parameters between functions.
*/
struct PaintOperationExecutor {
Scene *scene_;
ARegion *region_;
GreasePencil *grease_pencil_;
Brush *brush_;
int brush_size_;
float brush_alpha_;
BrushGpencilSettings *settings_;
float4 vertex_color_;
@ -126,18 +136,16 @@ struct PaintOperationExecutor {
PaintOperationExecutor(const bContext &C)
{
Scene *scene = CTX_data_scene(&C);
scene_ = CTX_data_scene(&C);
region_ = CTX_wm_region(&C);
Object *object = CTX_data_active_object(&C);
grease_pencil_ = static_cast<GreasePencil *>(object->data);
Paint *paint = &scene->toolsettings->gp_paint->paint;
Paint *paint = &scene_->toolsettings->gp_paint->paint;
brush_ = BKE_paint_brush(paint);
settings_ = brush_->gpencil_settings;
brush_size_ = BKE_brush_size_get(scene, brush_);
brush_alpha_ = BKE_brush_alpha_get(scene, brush_);
const bool use_vertex_color = (scene->toolsettings->gp_paint->mode ==
const bool use_vertex_color = (scene_->toolsettings->gp_paint->mode ==
GPPAINT_FLAG_USE_VERTEXCOLOR);
const bool use_vertex_color_stroke = use_vertex_color && ELEM(settings_->vertex_mode,
GPPAINT_MODE_STROKE,
@ -154,7 +162,7 @@ struct PaintOperationExecutor {
/* The object should have an active layer. */
BLI_assert(grease_pencil_->has_active_layer());
bke::greasepencil::Layer &active_layer = *grease_pencil_->get_active_layer_for_write();
const int drawing_index = active_layer.drawing_index_at(scene->r.cfra);
const int drawing_index = active_layer.drawing_index_at(scene_->r.cfra);
/* Drawing should exist. */
BLI_assert(drawing_index >= 0);
@ -174,9 +182,12 @@ struct PaintOperationExecutor {
return math::transform_point(transforms_.world_space_to_layer_space, proj_point);
}
float radius_from_input_sample(const InputSample &sample)
float radius_from_input_sample(const bContext &C, const InputSample &sample)
{
float radius = brush_size_ / 2.0f;
ViewContext vc = ED_view3d_viewcontext_init(const_cast<bContext *>(&C),
CTX_data_depsgraph_pointer(&C));
float radius = calc_brush_radius(
&vc, brush_, scene_, screen_space_to_drawing_plane(sample.mouse_position));
if (BKE_brush_use_size_pressure(brush_)) {
radius *= BKE_curvemapping_evaluateF(settings_->curve_sensitivity, 0, sample.pressure);
}
@ -185,7 +196,7 @@ struct PaintOperationExecutor {
float opacity_from_input_sample(const InputSample &sample)
{
float opacity = brush_alpha_;
float opacity = BKE_brush_alpha_get(scene_, brush_);
if (BKE_brush_use_alpha_pressure(brush_)) {
opacity *= BKE_curvemapping_evaluateF(settings_->curve_strength, 0, sample.pressure);
}
@ -193,11 +204,12 @@ struct PaintOperationExecutor {
}
void process_start_sample(PaintOperation &self,
const bContext &C,
const InputSample &start_sample,
const int material_index)
{
const float2 start_coords = start_sample.mouse_position;
const float start_radius = this->radius_from_input_sample(start_sample);
const float start_radius = this->radius_from_input_sample(C, start_sample);
const float start_opacity = this->opacity_from_input_sample(start_sample);
const ColorGeometry4f start_vertex_color = ColorGeometry4f(vertex_color_);
@ -332,11 +344,12 @@ struct PaintOperationExecutor {
}
void process_extension_sample(PaintOperation &self,
const bContext &C,
const InputSample &extension_sample,
const int curve_index)
{
const float2 coords = extension_sample.mouse_position;
const float radius = this->radius_from_input_sample(extension_sample);
const float radius = this->radius_from_input_sample(C, extension_sample);
const float opacity = this->opacity_from_input_sample(extension_sample);
const ColorGeometry4f vertex_color = ColorGeometry4f(vertex_color_);
@ -403,11 +416,11 @@ struct PaintOperationExecutor {
self, points, points.index_range().drop_front(self.active_smooth_index_));
}
void execute(PaintOperation &self, const InputSample &extension_sample)
void execute(PaintOperation &self, const bContext &C, const InputSample &extension_sample)
{
/* New curve was created in `process_start_sample`.*/
const int curve_index = drawing_->strokes().curves_range().last();
this->process_extension_sample(self, extension_sample, curve_index);
this->process_extension_sample(self, C, extension_sample, curve_index);
drawing_->tag_topology_changed();
}
};
@ -436,7 +449,7 @@ void PaintOperation::on_stroke_begin(const bContext &C, const InputSample &start
const int material_index = BKE_grease_pencil_object_material_index_get(object, material);
PaintOperationExecutor executor{C};
executor.process_start_sample(*this, start_sample, material_index);
executor.process_start_sample(*this, C, start_sample, material_index);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(&C, NC_GEOM | ND_DATA, grease_pencil);
@ -448,7 +461,7 @@ void PaintOperation::on_stroke_extended(const bContext &C, const InputSample &ex
GreasePencil *grease_pencil = static_cast<GreasePencil *>(object->data);
PaintOperationExecutor executor{C};
executor.execute(*this, extension_sample);
executor.execute(*this, C, extension_sample);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(&C, NC_GEOM | ND_DATA, grease_pencil);

View File

@ -1307,7 +1307,7 @@ static bool paint_cursor_context_init(bContext *C,
}
pcontext->mode = BKE_paintmode_get_active_from_context(C);
ED_view3d_viewcontext_init(C, &pcontext->vc, pcontext->depsgraph);
pcontext->vc = ED_view3d_viewcontext_init(C, pcontext->depsgraph);
if (pcontext->brush->flag & BRUSH_CURVE) {
pcontext->cursor_type = PAINT_CURSOR_CURVE;
@ -1539,6 +1539,9 @@ static void grease_pencil_brush_cursor_draw(PaintCursorContext *pcontext)
return;
}
/* Note: For now, there is only as screen space sized cursor. */
radius = BKE_brush_size_get(pcontext->scene, brush);
/* Get current drawing material. */
Material *ma = BKE_grease_pencil_object_material_from_brush_get(object, brush);
if (ma) {
@ -1560,9 +1563,6 @@ static void grease_pencil_brush_cursor_draw(PaintCursorContext *pcontext)
GPPAINT_MODE_STROKE,
GPPAINT_MODE_BOTH);
radius = ed::greasepencil::brush_radius_world_space(
*pcontext->C, pcontext->x, pcontext->y);
copy_v3_v3(color, use_vertex_color_stroke ? brush->rgb : gp_style->stroke_rgba);
}
}

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