GPv3: Cyclical set operator #111904
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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__)
|
||||
|
@ -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")
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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. */
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
@ -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 */
|
||||
/**
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -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
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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;
|
||||
|
@ -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}")
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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([&]() {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
227
source/blender/editors/curves/intern/attribute_set.cc
Normal file
227
source/blender/editors/curves/intern/attribute_set.cc
Normal 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
|
||||
|
||||
/** \} */
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
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
Hans Goudey
commented
```
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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -70,6 +70,14 @@ bool curves_poll(bContext *C);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Operators
|
||||
* \{ */
|
||||
|
||||
void CURVES_OT_attribute_set(wmOperatorType *ot);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Mask Functions
|
||||
* \{ */
|
||||
|
@ -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();
|
||||
|
||||
/**
|
||||
|
@ -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().
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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).
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -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");
|
||||
|
@ -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 *>(
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user
We're already in the
blender::
namespace, this shouldn't be necessary