USD export: prototype invoking Python chasers #108823

Merged
Michael Kowalski merged 35 commits from makowalski/blender:test-usd-export-chaser into main 2023-08-07 23:02:54 +02:00
491 changed files with 7976 additions and 5722 deletions
Showing only changes of commit 58b679584e - Show all commits

View File

@ -914,10 +914,9 @@ set_and_warn_dependency(WITH_TBB WITH_MOD_FLUID OFF)
# NanoVDB requires OpenVDB to convert the data structure
set_and_warn_dependency(WITH_OPENVDB WITH_NANOVDB OFF)
# OpenVDB, Alembic and Vulkan, OSL uses 'half' or 'imath' from OpenEXR
# OpenVDB, Alembic and OSL uses 'half' or 'imath' from OpenEXR
set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_OPENVDB OFF)
set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_ALEMBIC OFF)
set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_VULKAN_BACKEND OFF)
set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_CYCLES_OSL OFF)
# auto enable openimageio for cycles

View File

@ -95,7 +95,7 @@ set(USD_EXTRA_ARGS
# Ray: I'm not sure if the other platforms relied on this or not but this is no longer
# needed for windows. If mac/lin confirm, this can be removed.
if(NOT WIN32)
LIST(append USD_EXTRA_ARGS
list(APPEND USD_EXTRA_ARGS
# USD wants the tbb debug lib set even when you are doing a release build
# Otherwise it will error out during the cmake configure phase.
-DTBB_LIBRARIES_DEBUG=${LIBDIR}/tbb/lib/${LIBPREFIX}${TBB_LIBRARY}${SHAREDLIBEXT}

View File

@ -5,8 +5,24 @@
#ifdef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
# undef DEBUG_UNDEFINED_FROM_WRAP_PYTHON_H
-# define _DEBUG
+// BLENDER: TBB excepts this to have a value.
+// BLENDER: TBB expects this to have a value.
+# define _DEBUG 1
# ifdef _CRT_NOFORCE_MANIFEST_DEFINED_FROM_WRAP_PYTHON_H
# undef _CRT_NOFORCE_MANIFEST_DEFINED_FROM_WRAP_PYTHON_H
# undef _CRT_NOFORCE_MANIFEST
--- a/boost/config/stdlib/libcpp.hpp 2022-08-03 22:47:07.000000000 -0400
+++ b/boost/config/stdlib/libcpp.hpp 2022-09-16 22:16:17.044119011 -0400
@@ -168,4 +168,13 @@
# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
#endif
+#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 15000
+//
+// Unary function is now deprecated in C++11 and later:
+//
+#if __cplusplus >= 201103L
+#define BOOST_NO_CXX98_FUNCTION_BASE
+#endif
+#endif
+
// --- end ---

View File

@ -1,5 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-or-later
if(CMAKE_COMPILER_IS_GNUCC)
# NOTE: Resolved up-stream, quiet noisy compiler warnings for now.
add_cxx_flag("-Wno-uninitialized")
endif()
set(INC
include
)

View File

@ -104,7 +104,7 @@ ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc,
float cosHI = fabsf(dot(wi, H));
float cosNH = dot(N, H);
if (!(fabsf(cosNI) > 1e-5f && fabsf(cosNH) < 1.0f - 1e-5f && cosHI > 1e-5f)) {
if (!(cosNI > 1e-5f && fabsf(cosNH) < 1.0f - 1e-5f && cosHI > 1e-5f)) {
*pdf = 0.0f;
*eval = zero_spectrum();
return LABEL_NONE;

View File

@ -79,6 +79,7 @@ struct CCLShadowContext
#endif
IntegratorShadowState isect_s;
float throughput;
float max_t;
bool opaque_hit;
numhit_t max_hits;
numhit_t num_hits;
@ -314,7 +315,7 @@ ccl_device_forceinline void kernel_embree_filter_occluded_shadow_all_func_impl(
/* Current implementation in Cycles assumes only single-ray intersection queries. */
assert(args->N == 1);
RTCRay *ray = (RTCRay *)args->ray;
const RTCRay *ray = (RTCRay *)args->ray;
RTCHit *hit = (RTCHit *)args->hit;
#if EMBREE_MAJOR_VERSION >= 4
CCLShadowContext *ctx = (CCLShadowContext *)(args->context);
@ -367,42 +368,51 @@ ccl_device_forceinline void kernel_embree_filter_occluded_shadow_all_func_impl(
}
}
/* Test if we need to record this transparent intersection. */
const numhit_t max_record_hits = min(ctx->max_hits, numhit_t(INTEGRATOR_SHADOW_ISECT_SIZE));
if (ctx->num_recorded_hits < max_record_hits) {
/* If maximum number of hits was reached, replace the intersection with the
* highest distance. We want to find the N closest intersections. */
const numhit_t num_recorded_hits = min(ctx->num_recorded_hits, max_record_hits);
numhit_t isect_index = num_recorded_hits;
if (num_recorded_hits + 1 >= max_record_hits) {
float max_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, 0, t);
numhit_t max_recorded_hit = numhit_t(0);
for (numhit_t i = numhit_t(1); i < num_recorded_hits; ++i) {
const float isect_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, i, t);
if (isect_t > max_t) {
max_recorded_hit = i;
max_t = isect_t;
}
}
if (num_recorded_hits >= max_record_hits) {
isect_index = max_recorded_hit;
}
/* Limit the ray distance and stop counting hits beyond this. */
ray->tfar = max(current_isect.t, max_t);
}
integrator_state_write_shadow_isect(ctx->isect_s, &current_isect, isect_index);
}
numhit_t isect_index = ctx->num_recorded_hits;
/* Always increase the number of recorded hits, even beyond the maximum,
* so that we can detect this and trace another ray if needed. */
* so that we can detect this and trace another ray if needed.
* More details about the related logic can be found in implementation of
* "shadow_intersections_has_remaining" and "integrate_transparent_shadow"
* functions. */
++ctx->num_recorded_hits;
/* This tells Embree to continue tracing. */
*args->valid = 0;
const numhit_t max_record_hits = min(ctx->max_hits, numhit_t(INTEGRATOR_SHADOW_ISECT_SIZE));
/* If the maximum number of hits was reached, replace the furthest intersection
* with a closer one so we get the N closest intersections. */
if (isect_index >= max_record_hits) {
/* When recording only N closest hits, max_t will always only decrease.
* So let's test if we are already not meeting criteria and can skip max_t recalculation. */
if (current_isect.t >= ctx->max_t) {
return;
}
float max_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, 0, t);
numhit_t max_recorded_hit = numhit_t(0);
for (numhit_t i = numhit_t(1); i < max_record_hits; ++i) {
const float isect_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, i, t);
if (isect_t > max_t) {
max_recorded_hit = i;
max_t = isect_t;
}
}
isect_index = max_recorded_hit;
/* Limit the ray distance and avoid processing hits beyond this. */
ctx->max_t = max_t;
/* If it's further away than max_t, we don't record this transparent intersection. */
if (current_isect.t >= max_t) {
return;
}
}
integrator_state_write_shadow_isect(ctx->isect_s, &current_isect, isect_index);
}
ccl_device_forceinline void kernel_embree_filter_occluded_local_func_impl(

View File

@ -197,8 +197,14 @@ ccl_device_inline void object_normal_transform(KernelGlobals kg,
}
#endif
Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
*N = normalize(transform_direction_transposed(&tfm, *N));
if (sd->object != OBJECT_NONE) {
Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
*N = normalize(transform_direction_transposed(&tfm, *N));
}
else if (sd->type == PRIMITIVE_LAMP) {
Transform tfm = lamp_fetch_transform(kg, sd->lamp, true);
*N = normalize(transform_direction_transposed(&tfm, *N));
}
}
ccl_device_inline bool object_negative_scale_applied(const int object_flag)

View File

@ -155,12 +155,15 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals kg,
sd->Ng = Ng;
sd->wi = I;
sd->shader = shader;
if (prim != PRIM_NONE)
sd->type = PRIMITIVE_TRIANGLE;
else if (lamp != LAMP_NONE)
if (lamp != LAMP_NONE) {
sd->type = PRIMITIVE_LAMP;
else
}
else if (prim != PRIM_NONE) {
sd->type = PRIMITIVE_TRIANGLE;
}
else {
sd->type = PRIMITIVE_NONE;
}
/* primitive */
sd->object = object;

View File

@ -224,7 +224,7 @@ ccl_device void osl_closure_dielectric_bsdf_setup(KernelGlobals kg,
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
}
}
/* GGX (either single- or multiscattering) */
/* GGX (either single- or multi-scattering). */
else {
if (has_reflection && has_transmission) {
sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
@ -278,7 +278,7 @@ ccl_device void osl_closure_conductor_bsdf_setup(KernelGlobals kg,
if (closure->distribution == make_string("beckmann", 14712237670914973463ull)) {
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
}
/* GGX (either single- or multiscattering) */
/* GGX (either single- or multi-scattering) */
else {
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
preserve_energy = (closure->distribution == make_string("multi_ggx", 16842698693386468366ull));
@ -338,7 +338,7 @@ ccl_device void osl_closure_generalized_schlick_bsdf_setup(
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
}
}
/* GGX (either single- or multiscattering) */
/* GGX (either single- or multi-scattering) */
else {
if (has_reflection && has_transmission) {
sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
@ -414,7 +414,7 @@ ccl_device void osl_closure_microfacet_setup(KernelGlobals kg,
else if (closure->distribution == make_string("ashikhmin_shirley", 11318482998918370922ull)) {
sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf);
}
/* GGX (either single- or multiscattering) */
/* GGX (either single- or multi-scattering) */
else {
if (closure->refract == 1) {
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
@ -523,7 +523,7 @@ ccl_device void osl_closure_microfacet_aniso_fresnel_setup(
bsdf->ior = closure->ior;
bsdf->T = closure->T;
/* Only GGX (either single- or multiscattering) supported here */
/* Only GGX (either single- or multi-scattering) supported here */
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
const bool preserve_energy = (closure->distribution ==

View File

@ -47,7 +47,9 @@ shader node_texture_coordinate(
if (!getattribute("geom:generated", Generated)) {
Generated = transform("object", P);
}
getattribute("geom:uv", UV);
if (!getattribute("geom:uv", UV)) {
UV = point(1.0 - u - v, u, 0.0);
}
}
if (use_transform) {

View File

@ -26,7 +26,7 @@ closure color principled_diffuse(normal N, float roughness) BUILTIN;
closure color principled_sheen(normal N) BUILTIN;
closure color principled_clearcoat(normal N, float clearcoat, float clearcoat_roughness) BUILTIN;
/* Needed to pass along the color for multiscattering saturation adjustment,
/* Needed to pass along the color for multi-scattering saturation adjustment,
* otherwise could be replaced by microfacet() */
closure color microfacet_multi_ggx_glass(normal N, float ag, float eta, color C) BUILTIN;
closure color microfacet_multi_ggx_aniso(normal N, vector T, float ax, float ay, color C) BUILTIN;

View File

@ -71,6 +71,11 @@ ccl_device_noinline void svm_node_attr(KernelGlobals kg,
}
#endif
if (sd->type == PRIMITIVE_LAMP && node.y == ATTR_STD_UV) {
stack_store_float3(stack, out_offset, make_float3(1.0f - sd->u - sd->v, sd->u, 0.0f));
return;
}
if (node.y == ATTR_STD_GENERATED && desc.element == ATTR_ELEMENT_NONE) {
/* No generated attribute, fall back to object coordinates. */
float3 f = sd->P;

View File

@ -25,7 +25,7 @@ ccl_device_noinline void svm_node_vector_transform(KernelGlobals kg,
NodeVectorTransformConvertSpace to = (NodeVectorTransformConvertSpace)ito;
Transform tfm;
bool is_object = (sd->object != OBJECT_NONE);
bool is_object = (sd->object != OBJECT_NONE) || (sd->type == PRIMITIVE_LAMP);
bool is_normal = (type == NODE_VECTOR_TRANSFORM_TYPE_NORMAL);
bool is_direction = (type == NODE_VECTOR_TRANSFORM_TYPE_VECTOR);

View File

@ -162,7 +162,7 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
* \param height: The height the window.
* \param state: The state of the window when opened.
* \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized.
* \param glSettings: Misc OpenGL options.
* \param gpuSettings: Misc GPU options.
* \return A handle to the new window ( == NULL if creation failed).
*/
extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
@ -174,17 +174,17 @@ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
uint32_t height,
GHOST_TWindowState state,
bool is_dialog,
GHOST_GLSettings glSettings);
GHOST_GPUSettings gpuSettings);
/**
* Create a new off-screen context.
* Never explicitly delete the context, use #disposeContext() instead.
* \param systemhandle: The handle to the system.
* \param glSettings: Misc OpenGL options.
* \param gpuSettings: Misc GPU options.
* \return A handle to the new context ( == NULL if creation failed).
*/
extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_GLSettings glSettings);
extern GHOST_ContextHandle GHOST_CreateGPUContext(GHOST_SystemHandle systemhandle,
GHOST_GPUSettings gpuSettings);
/**
* Dispose of a context.
@ -192,8 +192,8 @@ extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemha
* \param contexthandle: Handle to the context to be disposed.
* \return Indication of success.
*/
extern GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_ContextHandle contexthandle);
extern GHOST_TSuccess GHOST_DisposeGPUContext(GHOST_SystemHandle systemhandle,
GHOST_ContextHandle contexthandle);
/**
* Returns the window user data.
@ -730,24 +730,24 @@ extern GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle);
* \param contexthandle: The handle to the context.
* \return A success indicator.
*/
extern GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle);
extern GHOST_TSuccess GHOST_ActivateGPUContext(GHOST_ContextHandle contexthandle);
/**
* Release the drawing context bound to this thread.
* \param contexthandle: The handle to the context.
* \return A success indicator.
*/
extern GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle);
extern GHOST_TSuccess GHOST_ReleaseGPUContext(GHOST_ContextHandle contexthandle);
/**
* Get the OpenGL frame-buffer handle that serves as a default frame-buffer.
* Get the GPU frame-buffer handle that serves as a default frame-buffer.
*/
extern unsigned int GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle);
extern unsigned int GHOST_GetContextDefaultGPUFramebuffer(GHOST_ContextHandle contexthandle);
/**
* Get the OpenGL frame-buffer handle that serves as a default frame-buffer.
* Get the GPU frame-buffer handle that serves as a default frame-buffer.
*/
extern unsigned int GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windowhandle);
extern unsigned int GHOST_GetDefaultGPUFramebuffer(GHOST_WindowHandle windowhandle);
/**
* Use multi-touch gestures if supported.
@ -1072,7 +1072,7 @@ int GHOST_XrSessionIsRunning(const GHOST_XrContextHandle xr_context);
/**
* Check if \a xr_context has a session that requires an upside-down frame-buffer (compared to
* OpenGL). If true, the render result should be flipped vertically for correct output.
* GPU). If true, the render result should be flipped vertically for correct output.
* \note Only to be called after session start, may otherwise result in a false negative.
*/
int GHOST_XrSessionNeedsUpsideDownDrawing(const GHOST_XrContextHandle xr_context);

View File

@ -230,7 +230,7 @@ class GHOST_ISystem {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
* \param glSettings: Misc OpenGL settings.
* \param gpuSettings: Misc GPU settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized.
* \param parentWindow: Parent (embedder) window
@ -242,7 +242,7 @@ class GHOST_ISystem {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = NULL) = 0;
@ -259,7 +259,7 @@ class GHOST_ISystem {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
virtual GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) = 0;
virtual GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) = 0;
/**
* Dispose of a context.

View File

@ -64,9 +64,9 @@ typedef struct {
} GHOST_CursorBitmapRef;
typedef enum {
GHOST_glStereoVisual = (1 << 0),
GHOST_glDebugContext = (1 << 1),
} GHOST_GLFlags;
GHOST_gpuStereoVisual = (1 << 0),
GHOST_gpuDebugContext = (1 << 1),
} GHOST_GPUFlags;
typedef enum GHOST_DialogOptions {
GHOST_DialogWarning = (1 << 0),
@ -170,14 +170,15 @@ typedef enum {
GHOST_kModifierKeyNum
} GHOST_TModifierKey;
/**
* \note these values are stored in #wmWindow::windowstate,
* don't change, only add new values.
*/
typedef enum {
GHOST_kWindowStateNormal = 0,
GHOST_kWindowStateMaximized,
GHOST_kWindowStateMinimized,
GHOST_kWindowStateFullScreen,
GHOST_kWindowStateEmbedded,
// GHOST_kWindowStateModified,
// GHOST_kWindowStateUnModified,
GHOST_kWindowStateMaximized = 1,
GHOST_kWindowStateMinimized = 2,
GHOST_kWindowStateFullScreen = 3,
} GHOST_TWindowState;
typedef enum {
@ -680,7 +681,7 @@ typedef struct {
typedef struct {
int flags;
GHOST_TDrawingContextType context_type;
} GHOST_GLSettings;
} GHOST_GPUSettings;
typedef enum {
/** Axis that cursor grab will wrap. */

View File

@ -135,16 +135,16 @@ void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
system->getAllDisplayDimensions(*width, *height);
}
GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_GLSettings glSettings)
GHOST_ContextHandle GHOST_CreateGPUContext(GHOST_SystemHandle systemhandle,
GHOST_GPUSettings gpuSettings)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
return (GHOST_ContextHandle)system->createOffscreenContext(glSettings);
return (GHOST_ContextHandle)system->createOffscreenContext(gpuSettings);
}
GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_ContextHandle contexthandle)
GHOST_TSuccess GHOST_DisposeGPUContext(GHOST_SystemHandle systemhandle,
GHOST_ContextHandle contexthandle)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
@ -161,7 +161,7 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
uint32_t height,
GHOST_TWindowState state,
bool is_dialog,
GHOST_GLSettings glSettings)
GHOST_GPUSettings gpuSettings)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
@ -171,7 +171,7 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
width,
height,
state,
glSettings,
gpuSettings,
false,
is_dialog,
(GHOST_IWindow *)parent_windowhandle);
@ -716,7 +716,7 @@ GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandl
return window->activateDrawingContext();
}
GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle)
GHOST_TSuccess GHOST_ActivateGPUContext(GHOST_ContextHandle contexthandle)
{
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
if (context) {
@ -726,21 +726,21 @@ GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle)
return GHOST_kFailure;
}
GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle)
GHOST_TSuccess GHOST_ReleaseGPUContext(GHOST_ContextHandle contexthandle)
{
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
return context->releaseDrawingContext();
}
uint GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle)
uint GHOST_GetContextDefaultGPUFramebuffer(GHOST_ContextHandle contexthandle)
{
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
return context->getDefaultFramebuffer();
}
uint GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windowhandle)
uint GHOST_GetDefaultGPUFramebuffer(GHOST_WindowHandle windowhandle)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;

View File

@ -215,6 +215,7 @@ class GHOST_DeviceVK {
device_features.geometryShader = VK_TRUE;
device_features.dualSrcBlend = VK_TRUE;
device_features.logicOp = VK_TRUE;
device_features.imageCubeArray = VK_TRUE;
#endif
VkDeviceCreateInfo device_create_info = {};
@ -309,7 +310,7 @@ static GHOST_TSuccess ensure_vulkan_device(VkInstance vk_instance,
#if STRICT_REQUIREMENTS
if (!device_vk.features.geometryShader || !device_vk.features.dualSrcBlend ||
!device_vk.features.logicOp)
!device_vk.features.logicOp || !device_vk.features.imageCubeArray)
{
continue;
}

View File

@ -397,12 +397,12 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
const GHOST_DisplaySetting &settings,
const bool stereoVisual)
{
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
if (stereoVisual) {
glSettings.flags |= GHOST_glStereoVisual;
gpuSettings.flags |= GHOST_gpuStereoVisual;
}
glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
gpuSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
/* NOTE: don't use #getCurrentDisplaySetting() because on X11 we may
* be zoomed in and the desktop may be bigger than the viewport. */
GHOST_ASSERT(m_displayManager,
@ -414,7 +414,7 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
settings.xPixels,
settings.yPixels,
GHOST_kWindowStateNormal,
glSettings,
gpuSettings,
true /* exclusive */);
return (*window == nullptr) ? GHOST_kFailure : GHOST_kSuccess;
}

View File

@ -101,7 +101,7 @@ class GHOST_System : public GHOST_ISystem {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
virtual GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) = 0;
virtual GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) = 0;
/**
* Returns whether a window is valid.

View File

@ -77,7 +77,7 @@ class GHOST_SystemCocoa : public GHOST_System {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
* \param glSettings: Misc OpenGL settings.
* \param gpuSettings: Misc GPU settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent (embedder) window.
* \return The new window (or 0 if creation failed).
@ -88,7 +88,7 @@ class GHOST_SystemCocoa : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = NULL);
@ -98,7 +98,7 @@ class GHOST_SystemCocoa : public GHOST_System {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings);
/**
* Dispose of a context.

View File

@ -696,7 +696,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive,
const bool is_dialog,
const GHOST_IWindow *parentWindow)
@ -725,9 +725,9 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
width,
height,
state,
glSettings.context_type,
glSettings.flags & GHOST_glStereoVisual,
glSettings.flags & GHOST_glDebugContext,
gpuSettings.context_type,
gpuSettings.flags & GHOST_gpuStereoVisual,
gpuSettings.flags & GHOST_gpuDebugContext,
is_dialog,
(GHOST_WindowCocoa *)parentWindow);
@ -755,11 +755,11 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GPUSettings gpuSettings)
{
#ifdef WITH_VULKAN_BACKEND
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
GHOST_Context *context = new GHOST_ContextVK(false, NULL, 1, 2, debug_context);
if (!context->initializeDrawingContext()) {
delete context;
@ -769,7 +769,7 @@ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSet
}
#endif
GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL, glSettings.context_type);
GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL, gpuSettings.context_type);
if (context->initializeDrawingContext())
return context;
else

View File

@ -79,7 +79,7 @@ class GHOST_SystemHeadless : public GHOST_System {
void getAllDisplayDimensions(uint32_t & /*width*/, uint32_t & /*height*/) const override
{ /* nop */
}
GHOST_IContext *createOffscreenContext(GHOST_GLSettings /*glSettings*/) override
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings /*gpuSettings*/) override
{
#ifdef __linux__
GHOST_Context *context;
@ -150,7 +150,7 @@ class GHOST_SystemHeadless : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool /*exclusive*/,
const bool /*is_dialog*/,
const GHOST_IWindow *parentWindow) override
@ -162,8 +162,8 @@ class GHOST_SystemHeadless : public GHOST_System {
height,
state,
parentWindow,
glSettings.context_type,
((glSettings.flags & GHOST_glStereoVisual) != 0));
gpuSettings.context_type,
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0));
}
GHOST_IWindow *getWindowUnderCursor(int32_t /*x*/, int32_t /*y*/) override

View File

@ -42,7 +42,7 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive,
const bool /* is_dialog */,
const GHOST_IWindow *parentWindow)
@ -56,8 +56,8 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
width,
height,
state,
glSettings.context_type,
((glSettings.flags & GHOST_glStereoVisual) != 0),
gpuSettings.context_type,
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
exclusive,
parentWindow);
@ -125,7 +125,7 @@ uint8_t GHOST_SystemSDL::getNumDisplays() const
return SDL_GetNumVideoDisplays();
}
GHOST_IContext *GHOST_SystemSDL::createOffscreenContext(GHOST_GLSettings /*glSettings*/)
GHOST_IContext *GHOST_SystemSDL::createOffscreenContext(GHOST_GPUSettings /*gpuSettings*/)
{
GHOST_Context *context = new GHOST_ContextSDL(false,
nullptr,

View File

@ -60,7 +60,7 @@ class GHOST_SystemSDL : public GHOST_System {
void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const override;
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) override;
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) override;
GHOST_TSuccess disposeContext(GHOST_IContext *context) override;
@ -73,7 +73,7 @@ class GHOST_SystemSDL : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = nullptr) override;

View File

@ -6279,7 +6279,7 @@ static GHOST_Context *createOffscreenContext_impl(GHOST_SystemWayland *system,
return nullptr;
}
GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GPUSettings gpuSettings)
{
#ifdef USE_EVENT_BACKGROUND_THREAD
std::lock_guard lock_server_guard{*server_mutex};
@ -6289,9 +6289,9 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings glS
wl_surface *wl_surface = wl_compositor_create_surface(wl_compositor());
#ifdef WITH_VULKAN_BACKEND
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
GHOST_Context *context = new GHOST_ContextVK(false,
GHOST_kVulkanPlatformWayland,
0,
@ -6310,7 +6310,7 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings glS
return context;
}
#else
(void)glSettings;
(void)gpuSettings;
#endif
wl_egl_window *egl_window = wl_surface ? wl_egl_window_create(wl_surface, 1, 1) : nullptr;
@ -6359,7 +6359,7 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
const uint32_t width,
const uint32_t height,
const GHOST_TWindowState state,
const GHOST_GLSettings glSettings,
const GHOST_GPUSettings gpuSettings,
const bool exclusive,
const bool is_dialog,
const GHOST_IWindow *parentWindow)
@ -6374,9 +6374,9 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
height,
state,
parentWindow,
glSettings.context_type,
gpuSettings.context_type,
is_dialog,
((glSettings.flags & GHOST_glStereoVisual) != 0),
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
exclusive);
if (window) {

View File

@ -157,7 +157,7 @@ class GHOST_SystemWayland : public GHOST_System {
void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const override;
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) override;
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) override;
GHOST_TSuccess disposeContext(GHOST_IContext *context) override;
@ -167,7 +167,7 @@ class GHOST_SystemWayland : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive,
const bool is_dialog,
const GHOST_IWindow *parentWindow) override;

View File

@ -224,7 +224,7 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool /*exclusive*/,
const bool is_dialog,
const GHOST_IWindow *parentWindow)
@ -237,11 +237,11 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
width,
height,
state,
glSettings.context_type,
((glSettings.flags & GHOST_glStereoVisual) != 0),
gpuSettings.context_type,
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
false,
(GHOST_WindowWin32 *)parentWindow,
((glSettings.flags & GHOST_glDebugContext) != 0),
((gpuSettings.flags & GHOST_gpuDebugContext) != 0),
is_dialog);
if (window->getValid()) {
@ -263,15 +263,15 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
* Never explicitly delete the window, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_GPUSettings gpuSettings)
{
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
GHOST_Context *context = nullptr;
#ifdef WITH_VULKAN_BACKEND
/* Vulkan does not need a window. */
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
context = new GHOST_ContextVK(false, (HWND)0, 1, 2, debug_context);
if (!context->initializeDrawingContext()) {

View File

@ -103,7 +103,7 @@ class GHOST_SystemWin32 : public GHOST_System {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
* \param glSettings: Misc OpenGL settings.
* \param gpuSettings: Misc GPU settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent window.
* \return The new window (or 0 if creation failed).
@ -114,7 +114,7 @@ class GHOST_SystemWin32 : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = 0);
@ -124,7 +124,7 @@ class GHOST_SystemWin32 : public GHOST_System {
* Never explicitly delete the window, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings);
/**
* Dispose of a context.

View File

@ -304,7 +304,7 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive,
const bool is_dialog,
const GHOST_IWindow *parentWindow)
@ -324,11 +324,11 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
height,
state,
(GHOST_WindowX11 *)parentWindow,
glSettings.context_type,
gpuSettings.context_type,
is_dialog,
((glSettings.flags & GHOST_glStereoVisual) != 0),
((gpuSettings.flags & GHOST_gpuStereoVisual) != 0),
exclusive,
(glSettings.flags & GHOST_glDebugContext) != 0);
(gpuSettings.flags & GHOST_gpuDebugContext) != 0);
if (window) {
/* Both are now handle in GHOST_WindowX11.cc
@ -399,7 +399,7 @@ static GHOST_Context *create_glx_context(Display *display,
return nullptr;
}
GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GPUSettings gpuSettings)
{
/* During development:
* try 4.x compatibility profile
@ -411,11 +411,11 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
* try 3.3 core profile
* no fall-backs. */
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
const bool debug_context = (gpuSettings.flags & GHOST_gpuDebugContext) != 0;
GHOST_Context *context = nullptr;
#ifdef WITH_VULKAN_BACKEND
if (glSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
if (gpuSettings.context_type == GHOST_kDrawingContextTypeVulkan) {
context = new GHOST_ContextVK(
false, GHOST_kVulkanPlatformX11, 0, m_display, NULL, NULL, 1, 2, debug_context);

View File

@ -124,7 +124,7 @@ class GHOST_SystemX11 : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
GHOST_GLSettings glSettings,
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = nullptr) override;
@ -134,7 +134,7 @@ class GHOST_SystemX11 : public GHOST_System {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) override;
GHOST_IContext *createOffscreenContext(GHOST_GPUSettings gpuSettings) override;
/**
* Dispose of a context.

View File

@ -332,9 +332,6 @@ static bool gwl_window_state_set_for_libdecor(libdecor_frame *frame,
libdecor_frame_set_fullscreen(frame, nullptr);
break;
}
case GHOST_kWindowStateEmbedded: {
return false;
}
}
return true;
}
@ -377,9 +374,6 @@ static bool gwl_window_state_set_for_xdg(xdg_toplevel *toplevel,
xdg_toplevel_set_fullscreen(toplevel, nullptr);
break;
}
case GHOST_kWindowStateEmbedded: {
return false;
}
}
return true;
}

View File

@ -412,7 +412,7 @@ bool processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData)
int main(int argc, char **argv)
{
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
char *title1 = "gears - main window";
char *title2 = "gears - secondary window";
GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(processEvent, NULL);
@ -433,7 +433,7 @@ int main(int argc, char **argv)
GHOST_kWindowStateNormal,
false,
GHOST_kDrawingContextTypeOpenGL,
glSettings);
gpuSettings);
if (!sMainWindow) {
printf("could not create main window\n");
exit(-1);
@ -450,7 +450,7 @@ int main(int argc, char **argv)
GHOST_kWindowStateNormal,
false,
GHOST_kDrawingContextTypeOpenGL,
glSettings);
gpuSettings);
if (!sSecondaryWindow) {
printf("could not create secondary window\n");
exit(-1);

View File

@ -406,13 +406,13 @@ Application::Application(GHOST_ISystem *system)
m_exitRequested(false),
stereo(false)
{
GHOST_GLSettings glSettings = {0};
glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
GHOST_GPUSettings gpuSettings = {0};
gpuSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
fApp = this;
// Create the main window
m_mainWindow = system->createWindow(
"gears - main window", 10, 64, 320, 200, GHOST_kWindowStateNormal, glSettings);
"gears - main window", 10, 64, 320, 200, GHOST_kWindowStateNormal, gpuSettings);
if (!m_mainWindow) {
std::cout << "could not create main window\n";
@ -421,7 +421,7 @@ Application::Application(GHOST_ISystem *system)
// Create a secondary window
m_secondaryWindow = system->createWindow(
"gears - secondary window", 340, 64, 320, 200, GHOST_kWindowStateNormal, glSettings);
"gears - secondary window", 340, 64, 320, 200, GHOST_kWindowStateNormal, gpuSettings);
if (!m_secondaryWindow) {
std::cout << "could not create secondary window\n";
exit(-1);

View File

@ -306,7 +306,7 @@ MainWindow *mainwindow_new(MultiTestApp *app)
{
GHOST_SystemHandle sys = multitestapp_get_system(app);
GHOST_WindowHandle win;
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
win = GHOST_CreateWindow(sys,
NULL,
@ -318,7 +318,7 @@ MainWindow *mainwindow_new(MultiTestApp *app)
GHOST_kWindowStateNormal,
false,
GHOST_kDrawingContextTypeOpenGL,
glSettings);
gpuSettings);
if (win) {
MainWindow *mw = MEM_callocN(sizeof(*mw), "mainwindow_new");
@ -557,7 +557,7 @@ static void loggerwindow_handle(void *priv, GHOST_EventHandle evt)
LoggerWindow *loggerwindow_new(MultiTestApp *app)
{
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
GHOST_SystemHandle sys = multitestapp_get_system(app);
uint32_t screensize[2];
GHOST_WindowHandle win;
@ -573,7 +573,7 @@ LoggerWindow *loggerwindow_new(MultiTestApp *app)
GHOST_kWindowStateNormal,
false,
GHOST_kDrawingContextTypeOpenGL,
glSettings);
gpuSettings);
if (win) {
LoggerWindow *lw = MEM_callocN(sizeof(*lw), "loggerwindow_new");
@ -761,7 +761,7 @@ static void extrawindow_handle(void *priv, GHOST_EventHandle evt)
ExtraWindow *extrawindow_new(MultiTestApp *app)
{
GHOST_GLSettings glSettings = {0};
GHOST_GPUSettings gpuSettings = {0};
GHOST_SystemHandle sys = multitestapp_get_system(app);
GHOST_WindowHandle win;
@ -775,7 +775,7 @@ ExtraWindow *extrawindow_new(MultiTestApp *app)
GHOST_kWindowStateNormal,
false,
GHOST_kDrawingContextTypeOpenGL,
glSettings);
gpuSettings);
if (win) {
ExtraWindow *ew = MEM_callocN(sizeof(*ew), "mainwindow_new");

View File

@ -350,7 +350,7 @@ def main():
if name.rpartition(".")[2].isdigit():
continue
if not ob_eval.data.attributes.active_color:
if (not hasattr(ob_eval.data, 'attributes')) or not ob_eval.data.attributes.active_color:
print("Skipping:", name, "(no vertex colors)")
continue

View File

@ -38,6 +38,8 @@ const UserDef U_default = {
.sounddir = "//",
.i18ndir = "",
.image_editor = "",
.text_editor = "",
.text_editor_args = "",
.anim_player = "",
.anim_player_preset = 0,
.v2d_min_gridsize = 45,

View File

@ -80,7 +80,7 @@ def keyconfig_update(keyconfig_data, keyconfig_version):
km_items.append(('ROTATE_NORMALS', {"type": 'N', "value": 'PRESS'}, None))
break
if keyconfig_version <= (3, 6, 3):
if keyconfig_version <= (4, 0, 3):
if not has_copy:
keyconfig_data = copy.deepcopy(keyconfig_data)
has_copy = True

View File

@ -571,8 +571,6 @@ class KeyframesCo:
keyframe_points.foreach_set("co", co_buffer)
keyframe_points.foreach_set("interpolation", ipo_buffer)
# TODO: in Blender 4.0 the next lines can be replaced with one call to `fcurve.update()`.
# See https://projects.blender.org/blender/blender/issues/107126 for more info.
keyframe_points.sort()
keyframe_points.deduplicate()
keyframe_points.handles_recalc()
# This also deduplicates keys where baked keys were inserted on the
# same frame as existing ones.
fcurve.update()

View File

@ -1836,6 +1836,10 @@ def km_graph_editor(params):
("graph.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("confirm", False)]}),
("graph.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
("graph.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None),
("graph.keyframe_jump", {"type": 'UP_ARROW', "value": 'PRESS', "repeat": True},
{"properties": [("next", True)]}),
("graph.keyframe_jump", {"type": 'DOWN_ARROW', "value": 'PRESS', "repeat": True},
{"properties": [("next", False)]}),
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "ctrl": True}, None),
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "shift": True, "ctrl": True},
{"properties": [("extend", True)]}),

View File

@ -0,0 +1,6 @@
import bpy
filepaths = bpy.context.preferences.filepaths
filepaths.text_editor = ""
filepaths.text_editor_args = ""

View File

@ -0,0 +1,12 @@
import bpy
import platform
filepaths = bpy.context.preferences.filepaths
filepaths.text_editor_args = "-g $filepath:$line:$column"
match platform.system():
case "Windows":
filepaths.text_editor = "code.cmd"
case _:
filepaths.text_editor = "code"

View File

@ -28,6 +28,7 @@ _modules = [
"screen_play_rendered_anim",
"sequencer",
"spreadsheet",
"text",
"userpref",
"uvcalc_follow_active",
"uvcalc_lightmap",

View File

@ -44,8 +44,8 @@ def geometry_modifier_poll(context):
def get_context_modifier(context):
area = context.area
if (area is not None) and (area.type == 'PROPERTIES'):
# Context only has a 'modifier' attribute in the modifier extra operators dropdown.
if hasattr(context, 'modifier'):
modifier = context.modifier
else:
ob = context.object

View File

@ -413,6 +413,24 @@ class AddPresetHairDynamics(AddPresetBase, Operator):
]
class AddPresetTextEditor(AddPresetBase, Operator):
"""Add or remove a Text Editor Preset"""
bl_idname = "text_editor.preset_add"
bl_label = "Add Text Editor Preset"
preset_menu = "USERPREF_PT_text_editor_presets"
preset_defines = [
"filepaths = bpy.context.preferences.filepaths"
]
preset_values = [
"filepaths.text_editor",
"filepaths.text_editor_args"
]
preset_subdir = "text_editor"
class AddPresetTrackingCamera(AddPresetBase, Operator):
"""Add or remove a Tracking Camera Intrinsics Preset"""
bl_idname = "clip.camera_preset_add"
@ -692,6 +710,7 @@ classes = (
AddPresetOperator,
AddPresetRender,
AddPresetCameraSafeAreas,
AddPresetTextEditor,
AddPresetTrackingCamera,
AddPresetTrackingSettings,
AddPresetTrackingTrackColor,

View File

@ -8,7 +8,6 @@ from bpy.app.translations import pgettext_tip as tip_
def guess_player_path(preset):
import os
import sys
if preset == 'INTERNAL':
@ -17,6 +16,7 @@ def guess_player_path(preset):
elif preset == 'DJV':
player_path = "djv"
if sys.platform == "darwin":
import os
test_path = "/Applications/DJV2.app/Contents/Resources/bin/djv"
if os.path.exists(test_path):
player_path = test_path
@ -141,7 +141,15 @@ class PlayRenderedAnim(Operator):
opts = [file, "%d-%d" % (scene.frame_start, scene.frame_end)]
cmd.extend(opts)
elif preset == 'RV':
opts = ["-fps", str(rd.fps), "-play", "[ %s ]" % file]
opts = ["-fps", str(rd.fps), "-play"]
if scene.use_preview_range:
opts += [
"%s" % file.replace("#", "", file.count('#') - 1),
"%d-%d" % (frame_start, frame_end),
]
else:
opts.append(file)
cmd.extend(opts)
elif preset == 'MPLAYER':
opts = []

View File

@ -0,0 +1,83 @@
# SPDX-License-Identifier: GPL-2.0-or-later
import bpy
from bpy.types import Operator
from bpy.props import (
IntProperty,
StringProperty,
)
class TEXT_OT_jump_to_file_at_point(Operator):
bl_idname = "text.jump_to_file_at_point"
bl_label = "Open Text File at point"
bl_description = "Edit text file in external text editor"
filepath: StringProperty(name="filepath")
line: IntProperty(name="line")
column: IntProperty(name="column")
def execute(self, context):
import shlex
import subprocess
from string import Template
if not self.properties.is_property_set("filepath"):
text = getattr(getattr(context, "space_data", None), "text", None)
if not text:
return {'CANCELLED'}
self.filepath = text.filepath
self.line = text.current_line_index
self.column = text.current_character
text_editor = context.preferences.filepaths.text_editor
text_editor_args = context.preferences.filepaths.text_editor_args
# Use the internal text editor.
if not text_editor:
return bpy.ops.text.jump_to_file_at_point_internal(
filepath=self.filepath,
line=self.line,
column=self.column,
)
if not text_editor_args:
self.report(
{'ERROR_INVALID_INPUT'},
"Provide text editor argument format in File Paths/Applications Preferences, "
"see input field tool-tip for more information.",
)
return {'CANCELLED'}
if "$filepath" not in text_editor_args:
self.report({'ERROR_INVALID_INPUT'}, "Text Editor Args Format must contain $filepath")
return {'CANCELLED'}
args = [text_editor]
template_vars = {
"filepath": self.filepath,
"line": self.line + 1,
"column": self.column + 1,
"line0": self.line,
"column0": self.column,
}
try:
args.extend([Template(arg).substitute(**template_vars) for arg in shlex.split(text_editor_args)])
except Exception as ex:
self.report({'ERROR'}, "Exception parsing template: %r" % ex)
return {'CANCELLED'}
try:
# With `check=True` if `process.returncode != 0` an exception will be raised.
subprocess.run(args, check=True)
except Exception as ex:
self.report({'ERROR'}, "Exception running external editor: %r" % ex)
return {'CANCELLED'}
return {'FINISHED'}
classes = (
TEXT_OT_jump_to_file_at_point,
)

View File

@ -109,17 +109,6 @@ class MESH_UL_vgroups(UIList):
layout.label(text="", icon_value=icon)
class MESH_UL_fmaps(UIList):
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
# assert(isinstance(item, bpy.types.FaceMap))
fmap = item
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(fmap, "name", text="", emboss=False, icon='FACE_MAPS')
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
class MESH_UL_shape_keys(UIList):
def draw_item(self, _context, layout, _data, item, icon, active_data, _active_propname, index):
# assert(isinstance(item, bpy.types.ShapeKey))
@ -285,50 +274,6 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
layout.prop(context.tool_settings, "vertex_group_weight", text="Weight")
class DATA_PT_face_maps(MeshButtonsPanel, Panel):
bl_label = "Face Maps"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
obj = context.object
return (obj and obj.type == 'MESH')
def draw(self, context):
layout = self.layout
ob = context.object
facemap = ob.face_maps.active
rows = 2
if facemap:
rows = 4
row = layout.row()
row.template_list("MESH_UL_fmaps", "", ob, "face_maps", ob.face_maps, "active_index", rows=rows)
col = row.column(align=True)
col.operator("object.face_map_add", icon='ADD', text="")
col.operator("object.face_map_remove", icon='REMOVE', text="")
if facemap:
col.separator()
col.operator("object.face_map_move", icon='TRIA_UP', text="").direction = 'UP'
col.operator("object.face_map_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
if ob.face_maps and (ob.mode == 'EDIT' and ob.type == 'MESH'):
row = layout.row()
sub = row.row(align=True)
sub.operator("object.face_map_assign", text="Assign")
sub.operator("object.face_map_remove_from", text="Remove")
sub = row.row(align=True)
sub.operator("object.face_map_select", text="Select")
sub.operator("object.face_map_deselect", text="Deselect")
class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
bl_label = "Shape Keys"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'}
@ -717,7 +662,6 @@ classes = (
MESH_MT_color_attribute_context_menu,
MESH_MT_attribute_context_menu,
MESH_UL_vgroups,
MESH_UL_fmaps,
MESH_UL_shape_keys,
MESH_UL_uvmaps,
MESH_UL_attributes,
@ -726,7 +670,6 @@ classes = (
DATA_PT_shape_keys,
DATA_PT_uv_texture,
DATA_PT_vertex_colors,
DATA_PT_face_maps,
DATA_PT_mesh_attributes,
DATA_PT_normals,
DATA_PT_texture_space,

View File

@ -937,7 +937,6 @@ def brush_settings_advanced(layout, context, brush, popover=False):
col = layout.column(heading="Auto-Masking", align=True)
col = layout.column(align=True)
col.prop(brush, "use_automasking_topology", text="Topology")
col.prop(brush, "use_automasking_face_sets", text="Face Sets")

View File

@ -1221,7 +1221,7 @@ class IMAGE_PT_tools_brush_display(Panel, BrushButtonsPanel, DisplayPanel):
bl_context = ".paint_common_2d"
bl_parent_id = "IMAGE_PT_paint_settings"
bl_category = "Tool"
bl_label = "Brush Tip"
bl_label = "Cursor"
bl_options = {'DEFAULT_CLOSED'}
bl_ui_units_x = 15

View File

@ -764,20 +764,26 @@ class NODE_PT_quality(bpy.types.Panel):
tree = snode.node_tree
prefs = bpy.context.preferences
use_realtime = False
col = layout.column()
if prefs.experimental.use_full_frame_compositor:
if prefs.experimental.use_experimental_compositors:
col.prop(tree, "execution_mode")
use_realtime = tree.execution_mode == 'REALTIME'
col = layout.column()
col.active = not use_realtime
col.prop(tree, "render_quality", text="Render")
col.prop(tree, "edit_quality", text="Edit")
col.prop(tree, "chunk_size")
col = layout.column()
col.active = not use_realtime
col.prop(tree, "use_opencl")
col.prop(tree, "use_groupnode_buffer")
col.prop(tree, "use_two_pass")
col.prop(tree, "use_viewer_border")
col.separator()
col = layout.column()
col.prop(snode, "use_auto_render")

View File

@ -256,7 +256,13 @@ class TEXT_MT_text(Menu):
if text:
layout.separator()
layout.operator("text.reload")
row = layout.row()
row.operator("text.reload")
row.enabled = not text.is_in_memory
row = layout.row()
op = row.operator("text.jump_to_file_at_point", text="Edit Externally")
row.enabled = (not text.is_in_memory and context.preferences.filepaths.text_editor != "")
layout.separator()
layout.operator("text.save", icon='FILE_TICK')

View File

@ -25,7 +25,7 @@ if "_icon_cache" in locals():
del release
# (filename -> icon_value) map
# (icon_name -> icon_value) map
_icon_cache = {}
@ -236,14 +236,14 @@ class ToolSelectPanelHelper:
icon_value = _icon_cache.get(icon_name)
if icon_value is None:
dirname = bpy.utils.system_resource('DATAFILES', path="icons")
filename = os.path.join(dirname, icon_name + ".dat")
filepath = os.path.join(dirname, icon_name + ".dat")
try:
icon_value = bpy.app.icons.new_triangles_from_file(filename)
icon_value = bpy.app.icons.new_triangles_from_file(filepath)
except Exception as ex:
if not os.path.exists(filename):
print("Missing icons:", filename, ex)
if not os.path.exists(filepath):
print("Missing icons:", filepath, ex)
else:
print("Corrupt icon:", filename, ex)
print("Corrupt icon:", filepath, ex)
# Use none as a fallback (avoids layout issues).
if icon_name != "none":
icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle("none")

View File

@ -3111,7 +3111,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
*_tools_annotate,
],
'EDIT_GPENCIL': [
*_tools_gpencil_select,
*_tools_select,
_defs_view3d_generic.cursor,
None,
*_tools_transform,

View File

@ -10,6 +10,7 @@ from bpy.app.translations import (
pgettext_iface as iface_,
pgettext_tip as tip_,
)
from bl_ui.utils import PresetPanel
# -----------------------------------------------------------------------------
@ -1399,6 +1400,13 @@ class USERPREF_PT_file_paths_render(FilePathsPanel, Panel):
col.prop(paths, "render_cache_directory", text="Render Cache")
class USERPREF_PT_text_editor_presets(PresetPanel, Panel):
bl_label = "Text Editor Presets"
preset_subdir = "text_editor"
preset_operator = "script.execute_preset"
preset_add_operator = "text_editor.preset_add"
class USERPREF_PT_file_paths_applications(FilePathsPanel, Panel):
bl_label = "Applications"
@ -1416,6 +1424,25 @@ class USERPREF_PT_file_paths_applications(FilePathsPanel, Panel):
col.prop(paths, "animation_player", text="Player")
class USERPREF_PT_text_editor(FilePathsPanel, Panel):
bl_label = "Text Editor"
bl_parent_id = "USERPREF_PT_file_paths_applications"
def draw_header_preset(self, _context):
USERPREF_PT_text_editor_presets.draw_panel_header(self.layout)
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
paths = context.preferences.filepaths
col = layout.column()
col.prop(paths, "text_editor", text="Program")
col.prop(paths, "text_editor_args", text="Arguments")
class USERPREF_PT_file_paths_development(FilePathsPanel, Panel):
bl_label = "Development"
@ -2396,7 +2423,7 @@ class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
({"property": "use_new_curves_tools"}, ("blender/blender/issues/68981", "#68981")),
({"property": "use_new_point_cloud_type"}, ("blender/blender/issues/75717", "#75717")),
({"property": "use_sculpt_texture_paint"}, ("blender/blender/issues/96225", "#96225")),
({"property": "use_full_frame_compositor"}, ("blender/blender/issues/88150", "#88150")),
({"property": "use_experimental_compositors"}, ("blender/blender/issues/88150", "#88150")),
({"property": "enable_eevee_next"}, ("blender/blender/issues/93220", "#93220")),
({"property": "enable_workbench_next"}, ("blender/blender/issues/101619", "#101619")),
({"property": "use_grease_pencil_version3"}, ("blender/blender/projects/40", "Grease Pencil 3.0")),
@ -2510,6 +2537,8 @@ classes = (
USERPREF_PT_file_paths_script_directories,
USERPREF_PT_file_paths_render,
USERPREF_PT_file_paths_applications,
USERPREF_PT_text_editor,
USERPREF_PT_text_editor_presets,
USERPREF_PT_file_paths_development,
USERPREF_PT_file_paths_asset_libraries,

View File

@ -945,11 +945,11 @@ class VIEW3D_MT_editor_menus(Menu):
tool_settings.use_gpencil_select_mask_stroke or
tool_settings.use_gpencil_select_mask_segment)
):
layout.menu("VIEW3D_MT_select_gpencil")
layout.menu("VIEW3D_MT_select_edit_gpencil")
elif mode_string == 'EDIT_GPENCIL':
layout.menu("VIEW3D_MT_select_gpencil")
layout.menu("VIEW3D_MT_select_edit_gpencil")
elif mode_string == 'VERTEX_GPENCIL':
layout.menu("VIEW3D_MT_select_gpencil")
layout.menu("VIEW3D_MT_select_edit_gpencil")
elif mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
mesh = obj.data
if mesh.use_paint_mask:
@ -2028,7 +2028,7 @@ class VIEW3D_MT_select_edit_gpencil(Menu):
layout.operator("grease_pencil.select_all", text="None").action = 'DESELECT'
layout.operator("grease_pencil.select_all", text="Invert").action = 'INVERT'
layout.separator()
layout.separator()
class VIEW3D_MT_select_paint_mask(Menu):
@ -2103,7 +2103,7 @@ class VIEW3D_MT_select_edit_curves(Menu):
layout.separator()
layout.operator("curves.select_random", text="Random")
layout.operator("curves.select_end", text="Endpoints")
layout.operator("curves.select_ends", text="Endpoints")
layout.operator("curves.select_linked", text="Linked")
layout.separator()
@ -2121,7 +2121,7 @@ class VIEW3D_MT_select_sculpt_curves(Menu):
layout.operator("curves.select_all", text="None").action = 'DESELECT'
layout.operator("curves.select_all", text="Invert").action = 'INVERT'
layout.operator("sculpt_curves.select_random", text="Random")
layout.operator("curves.select_end", text="Endpoints")
layout.operator("curves.select_ends", text="Endpoints")
layout.operator("sculpt_curves.select_grow", text="Grow")
@ -7067,72 +7067,70 @@ class VIEW3D_PT_snapping(Panel):
def draw(self, context):
tool_settings = context.tool_settings
snap_elements = tool_settings.snap_elements
obj = context.active_object
object_mode = 'OBJECT' if obj is None else obj.mode
layout = self.layout
col = layout.column()
col.label(text="Snap With")
row = col.row(align=True)
row.prop(tool_settings, "snap_target", expand=True)
col.label(text="Snap To")
col.prop(tool_settings, "snap_elements", expand=True)
col.prop(tool_settings, "snap_elements_base", expand=True)
col.label(text="Snap Individual Elements To")
col.prop(tool_settings, "snap_elements_individual", expand=True)
col.separator()
if 'INCREMENT' in snap_elements:
if 'INCREMENT' in tool_settings.snap_elements:
col.prop(tool_settings, "use_snap_grid_absolute")
if snap_elements != {'INCREMENT'}:
if snap_elements != {'FACE_NEAREST'}:
col.label(text="Snap With")
row = col.row(align=True)
row.prop(tool_settings, "snap_target", expand=True)
if 'VOLUME' in tool_settings.snap_elements:
col.prop(tool_settings, "use_snap_peel_object")
if obj:
col.label(text="Target Selection")
col_targetsel = col.column(align=True)
if object_mode == 'EDIT' and obj.type not in {'LATTICE', 'META', 'FONT'}:
col_targetsel.prop(
tool_settings,
"use_snap_self",
text="Include Active",
icon='EDITMODE_HLT',
)
col_targetsel.prop(
tool_settings,
"use_snap_edit",
text="Include Edited",
icon='OUTLINER_DATA_MESH',
)
col_targetsel.prop(
tool_settings,
"use_snap_nonedit",
text="Include Non-Edited",
icon='OUTLINER_OB_MESH',
)
if 'FACE_NEAREST' in tool_settings.snap_elements:
col.prop(tool_settings, "use_snap_to_same_target")
if object_mode == 'EDIT':
col.prop(tool_settings, "snap_face_nearest_steps")
col.separator()
col.prop(tool_settings, "use_snap_align_rotation")
col.prop(tool_settings, "use_snap_backface_culling")
col.separator()
if obj:
col.label(text="Target Selection")
col_targetsel = col.column(align=True)
if object_mode == 'EDIT' and obj.type not in {'LATTICE', 'META', 'FONT'}:
col_targetsel.prop(
tool_settings,
"use_snap_selectable",
text="Exclude Non-Selectable",
icon='RESTRICT_SELECT_OFF',
"use_snap_self",
text="Include Active",
icon='EDITMODE_HLT',
)
if object_mode in {'OBJECT', 'POSE', 'EDIT', 'WEIGHT_PAINT'}:
col.prop(tool_settings, "use_snap_align_rotation")
col.prop(tool_settings, "use_snap_backface_culling")
is_face_nearest_enabled = 'FACE_NEAREST' in snap_elements
if is_face_nearest_enabled or 'FACE' in snap_elements:
sub = col.column()
sub.active = not is_face_nearest_enabled
sub.prop(tool_settings, "use_snap_project")
if is_face_nearest_enabled:
col.prop(tool_settings, "use_snap_to_same_target")
if object_mode == 'EDIT':
col.prop(tool_settings, "snap_face_nearest_steps")
if 'VOLUME' in snap_elements:
col.prop(tool_settings, "use_snap_peel_object")
col_targetsel.prop(
tool_settings,
"use_snap_edit",
text="Include Edited",
icon='OUTLINER_DATA_MESH',
)
col_targetsel.prop(
tool_settings,
"use_snap_nonedit",
text="Include Non-Edited",
icon='OUTLINER_OB_MESH',
)
col_targetsel.prop(
tool_settings,
"use_snap_selectable",
text="Exclude Non-Selectable",
icon='RESTRICT_SELECT_OFF',
)
col.label(text="Affect")
row = col.row(align=True)

View File

@ -335,6 +335,7 @@ compositor_node_categories = [
NodeItem("CompositorNodeSunBeams"),
NodeItem("CompositorNodeDenoise"),
NodeItem("CompositorNodeAntiAliasing"),
NodeItem("CompositorNodeKuwahara"),
]),
CompositorNodeCategory("CMP_OP_VECTOR", "Vector", items=[
NodeItem("CompositorNodeNormal"),

View File

@ -124,6 +124,7 @@ class AssetLibrary {
*/
AssetRepresentation &add_external_asset(StringRef relative_asset_path,
StringRef name,
int id_type,
std::unique_ptr<AssetMetaData> metadata);
/** See #AssetLibrary::add_external_asset(). */
AssetRepresentation &add_local_id_asset(StringRef relative_asset_path, ID &id);

View File

@ -10,6 +10,8 @@
#include "BLI_compiler_attrs.h"
#include "DNA_ID_enums.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -22,6 +24,8 @@ typedef struct AssetRepresentation AssetRepresentation;
const char *AS_asset_representation_name_get(const AssetRepresentation *asset)
ATTR_WARN_UNUSED_RESULT;
ID_Type AS_asset_representation_id_type_get(const AssetRepresentation *asset)
ATTR_WARN_UNUSED_RESULT;
AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *asset)
ATTR_WARN_UNUSED_RESULT;
struct ID *AS_asset_representation_local_id_get(const AssetRepresentation *asset)
@ -30,6 +34,9 @@ bool AS_asset_representation_is_local_id(const AssetRepresentation *asset) ATTR_
bool AS_asset_representation_is_never_link(const AssetRepresentation *asset)
ATTR_WARN_UNUSED_RESULT;
bool AS_asset_representation_may_override_import_method(const AssetRepresentation *asset);
bool AS_asset_representation_use_relative_path_get(const AssetRepresentation *asset);
/**
* C version of #AssetRepresentation::make_weak_reference. Returned pointer needs freeing with
* #MEM_delete() or #BKE_asset_weak_reference_free().

View File

@ -19,6 +19,7 @@
#include "BLI_string_ref.hh"
#include "DNA_ID_enums.h"
#include "DNA_asset_types.h"
#include "AS_asset_identifier.hh"
@ -42,6 +43,7 @@ class AssetRepresentation {
struct ExternalAsset {
std::string name;
int id_type = 0;
std::unique_ptr<AssetMetaData> metadata_ = nullptr;
};
union {
@ -55,6 +57,7 @@ class AssetRepresentation {
/** Constructs an asset representation for an external ID. The asset will not be editable. */
AssetRepresentation(AssetIdentifier &&identifier,
StringRef name,
int id_type,
std::unique_ptr<AssetMetaData> metadata,
const AssetLibrary &owner_asset_library);
/**
@ -85,6 +88,7 @@ class AssetRepresentation {
std::unique_ptr<AssetWeakReference> make_weak_reference() const;
StringRefNull get_name() const;
ID_Type get_id_type() const;
AssetMetaData &get_metadata() const;
/**
* Get the import method to use for this asset. A different one may be used if
@ -114,6 +118,9 @@ class AssetRepresentation {
/* C-Handle */
struct AssetRepresentation;
const blender::StringRefNull AS_asset_representation_library_relative_identifier_get(
const AssetRepresentation *asset_handle);
std::string AS_asset_representation_full_path_get(const ::AssetRepresentation *asset);
/**
* Get the absolute path to the .blend file containing the given asset. String will be empty if
@ -123,5 +130,3 @@ std::string AS_asset_representation_full_path_get(const ::AssetRepresentation *a
std::string AS_asset_representation_full_library_path_get(const ::AssetRepresentation *asset);
std::optional<eAssetImportMethod> AS_asset_representation_import_method_get(
const ::AssetRepresentation *asset_handle);
bool AS_asset_representation_may_override_import_method(const ::AssetRepresentation *asset_handle);
bool AS_asset_representation_use_relative_path_get(const ::AssetRepresentation *asset_handle);

View File

@ -230,11 +230,12 @@ void AssetLibrary::refresh()
AssetRepresentation &AssetLibrary::add_external_asset(StringRef relative_asset_path,
StringRef name,
const int id_type,
std::unique_ptr<AssetMetaData> metadata)
{
AssetIdentifier identifier = asset_identifier_from_library(relative_asset_path);
return asset_storage_->add_external_asset(
std::move(identifier), name, std::move(metadata), *this);
std::move(identifier), name, id_type, std::move(metadata), *this);
}
AssetRepresentation &AssetLibrary::add_local_id_asset(StringRef relative_asset_path, ID &id)

View File

@ -21,6 +21,7 @@ namespace blender::asset_system {
AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,
StringRef name,
const int id_type,
std::unique_ptr<AssetMetaData> metadata,
const AssetLibrary &owner_asset_library)
: identifier_(identifier),
@ -29,6 +30,7 @@ AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,
external_asset_()
{
external_asset_.name = name;
external_asset_.id_type = id_type;
external_asset_.metadata_ = std::move(metadata);
}
@ -87,6 +89,15 @@ StringRefNull AssetRepresentation::get_name() const
return external_asset_.name;
}
ID_Type AssetRepresentation::get_id_type() const
{
if (is_local_id_) {
return GS(local_asset_id_->name);
}
return ID_Type(external_asset_.id_type);
}
AssetMetaData &AssetRepresentation::get_metadata() const
{
return is_local_id_ ? *local_asset_id_->asset_data : *external_asset_.metadata_;
@ -135,6 +146,15 @@ const AssetLibrary &AssetRepresentation::owner_asset_library() const
using namespace blender;
const StringRefNull AS_asset_representation_library_relative_identifier_get(
const AssetRepresentation *asset_handle)
{
const asset_system::AssetRepresentation *asset =
reinterpret_cast<const asset_system::AssetRepresentation *>(asset_handle);
const asset_system::AssetIdentifier &identifier = asset->get_identifier();
return identifier.library_relative_identifier();
}
std::string AS_asset_representation_full_path_get(const AssetRepresentation *asset_handle)
{
const asset_system::AssetRepresentation *asset =
@ -183,6 +203,13 @@ const char *AS_asset_representation_name_get(const AssetRepresentation *asset_ha
return asset->get_name().c_str();
}
ID_Type AS_asset_representation_id_type_get(const AssetRepresentation *asset_handle)
{
const asset_system::AssetRepresentation *asset =
reinterpret_cast<const asset_system::AssetRepresentation *>(asset_handle);
return asset->get_id_type();
}
AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *asset_handle)
{
const asset_system::AssetRepresentation *asset =

View File

@ -27,11 +27,12 @@ AssetRepresentation &AssetStorage::add_local_id_asset(AssetIdentifier &&identifi
AssetRepresentation &AssetStorage::add_external_asset(AssetIdentifier &&identifier,
StringRef name,
const int id_type,
std::unique_ptr<AssetMetaData> metadata,
const AssetLibrary &owner_asset_library)
{
return *external_assets_.lookup_key_or_add(std::make_unique<AssetRepresentation>(
std::move(identifier), name, std::move(metadata), owner_asset_library));
std::move(identifier), name, id_type, std::move(metadata), owner_asset_library));
}
bool AssetStorage::remove_asset(AssetRepresentation &asset)

View File

@ -37,6 +37,7 @@ class AssetStorage {
/** See #AssetLibrary::add_external_asset(). */
AssetRepresentation &add_external_asset(AssetIdentifier &&identifier,
StringRef name,
int id_type,
std::unique_ptr<AssetMetaData> metadata,
const AssetLibrary &owner_asset_library);
/** See #AssetLibrary::add_external_asset(). */

View File

@ -32,7 +32,8 @@ class AssetRepresentationTest : public AssetLibraryTestBase {
AssetRepresentation &add_dummy_asset(AssetLibrary &library, StringRef relative_path)
{
std::unique_ptr<AssetMetaData> dummy_metadata = std::make_unique<AssetMetaData>();
return library.add_external_asset(relative_path, "Some asset name", std::move(dummy_metadata));
return library.add_external_asset(
relative_path, "Some asset name", 0, std::move(dummy_metadata));
}
};

View File

@ -38,6 +38,13 @@ typedef struct AssetTypeInfo {
struct AssetMetaData *BKE_asset_metadata_create(void);
void BKE_asset_metadata_free(struct AssetMetaData **asset_data);
/**
* Create a copy of the #AssetMetaData so that it can be assigned to another asset.
*
* The caller becomes the owner of the returned pointer.
*/
struct AssetMetaData *BKE_asset_metadata_copy(const struct AssetMetaData *source);
struct AssetTagEnsureResult {
struct AssetTag *tag;
/* Set to false if a tag of this name was already present. */

View File

@ -27,13 +27,13 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 4
#define BLENDER_FILE_SUBVERSION 6
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
* was written with too new a version. */
#define BLENDER_FILE_MIN_VERSION 400
#define BLENDER_FILE_MIN_SUBVERSION 2
#define BLENDER_FILE_MIN_SUBVERSION 3
/** User readable version string. */
const char *BKE_blender_version_string(void);

View File

@ -65,7 +65,7 @@ void BKE_blendfile_read_setup_readfile(struct bContext *C,
const char *startup_app_template);
/**
* Simpler version of #BKE_blendfile_read_setup_readfile used when reading undoe steps from
* Simpler version of #BKE_blendfile_read_setup_readfile used when reading undo steps from
* memfile. */
void BKE_blendfile_read_setup_undo(struct bContext *C,
struct BlendFileData *bfd,

View File

@ -51,5 +51,8 @@ struct GeometryDeformation {
GeometryDeformation get_evaluated_curves_deformation(const Object *ob_eval, const Object &ob_orig);
GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph,
const Object &ob_orig);
GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object *ob_eval,
const Object &ob_orig,
int drawing_index);
} // namespace blender::bke::crazyspace

View File

@ -733,7 +733,7 @@ enum {
typedef struct CustomDataTransferLayerMap {
struct CustomDataTransferLayerMap *next, *prev;
eCustomDataType data_type;
int data_type;
int mix_mode;
float mix_factor;
/** If non-NULL, array of weights, one for each dest item, replaces mix_factor. */

View File

@ -180,9 +180,6 @@ struct Mesh *BKE_mesh_new_nomain_from_curve_displist(const struct Object *ob,
bool BKE_mesh_attribute_required(const char *name);
bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me);
bool BKE_mesh_clear_facemap_customdata(struct Mesh *me);
float (*BKE_mesh_orco_verts_get(struct Object *ob))[3];
void BKE_mesh_orco_verts_transform(struct Mesh *me, float (*orco)[3], int totvert, int invert);

View File

@ -127,7 +127,7 @@ struct CornerNormalSpaceArray {
*/
Array<Array<int>> corners_by_space;
/** Whether to create the above map when calculating normals. */
bool create_corners_by_space;
bool create_corners_by_space = false;
};
void lnor_space_custom_normal_to_data(const CornerNormalSpace *lnor_space,

View File

@ -84,6 +84,8 @@ void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh);
void BKE_mesh_legacy_convert_loops_to_corners(struct Mesh *mesh);
void BKE_mesh_legacy_face_map_to_generic(struct Mesh *mesh);
#endif
#ifdef __cplusplus

View File

@ -1061,6 +1061,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define CMP_NODE_INPAINT 272
#define CMP_NODE_DESPECKLE 273
#define CMP_NODE_ANTIALIASING 274
#define CMP_NODE_KUWAHARA 275
#define CMP_NODE_GLARE 301
#define CMP_NODE_TONEMAP 302

View File

@ -1,37 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bke
* \brief Functions for dealing with object face-maps.
*/
#ifdef __cplusplus
extern "C" {
#endif
struct ListBase;
struct Object;
struct bFaceMap;
struct bFaceMap *BKE_object_facemap_add(struct Object *ob);
struct bFaceMap *BKE_object_facemap_add_name(struct Object *ob, const char *name);
void BKE_object_facemap_remove(struct Object *ob, struct bFaceMap *fmap);
void BKE_object_facemap_clear(struct Object *ob);
int BKE_object_facemap_name_index(struct Object *ob, const char *name);
void BKE_object_facemap_unique_name(struct Object *ob, struct bFaceMap *fmap);
struct bFaceMap *BKE_object_facemap_find_name(struct Object *ob, const char *name);
void BKE_object_facemap_copy_list(struct ListBase *outbase, const struct ListBase *inbase);
int *BKE_object_facemap_index_map_create(struct Object *ob_src,
struct Object *ob_dst,
int *r_map_len);
void BKE_object_facemap_index_map_apply(int *fmap, int fmap_len, const int *map, int map_len);
#ifdef __cplusplus
}
#endif

View File

@ -184,6 +184,7 @@ eObjectMode BKE_paint_object_mode_from_paintmode(ePaintMode mode);
bool BKE_paint_ensure_from_paintmode(struct Scene *sce, ePaintMode mode);
struct Paint *BKE_paint_get_active_from_paintmode(struct Scene *sce, ePaintMode mode);
const struct EnumPropertyItem *BKE_paint_get_tool_enum_from_paintmode(ePaintMode mode);
const char *BKE_paint_get_tool_enum_translation_context_from_paintmode(ePaintMode mode);
const char *BKE_paint_get_tool_prop_id_from_paintmode(ePaintMode mode);
uint BKE_paint_get_brush_tool_offset_from_paintmode(ePaintMode mode);
struct Paint *BKE_paint_get_active(struct Scene *sce, struct ViewLayer *view_layer);

View File

@ -255,7 +255,7 @@ typedef struct PanelType {
char idname[BKE_ST_MAXNAME]; /* unique name */
char label[BKE_ST_MAXNAME]; /* for panel header */
char *description; /* for panel tooltip */
const char *description; /* for panel tooltip */
char translation_context[BKE_ST_MAXNAME];
char context[BKE_ST_MAXNAME]; /* for buttons window */
char category[BKE_ST_MAXNAME]; /* for category tabs */

View File

@ -75,15 +75,13 @@ bool BKE_texture_dependsOnTime(const struct Tex *texture);
*/
bool BKE_texture_is_image_user(const struct Tex *tex);
void BKE_texture_get_value_ex(const struct Scene *scene,
struct Tex *texture,
void BKE_texture_get_value_ex(struct Tex *texture,
const float *tex_co,
struct TexResult *texres,
struct ImagePool *pool,
bool use_color_management);
void BKE_texture_get_value(const struct Scene *scene,
struct Tex *texture,
void BKE_texture_get_value(struct Tex *texture,
const float *tex_co,
struct TexResult *texres,
bool use_color_management);

View File

@ -21,6 +21,7 @@ struct MovieClipUser;
struct MovieDistortion;
struct MovieReconstructContext;
struct MovieTracking;
struct MovieTrackingCamera;
struct MovieTrackingMarker;
struct MovieTrackingObject;
struct MovieTrackingPlaneMarker;
@ -464,6 +465,16 @@ void BKE_tracking_camera_principal_point_pixel_get(struct MovieClip *clip,
void BKE_tracking_camera_principal_point_pixel_set(struct MovieClip *clip,
const float principal_point_pixel[2]);
/* Compares distortion related parameters of camera. Ideally, this implementation will be
* abstracted away in the future, but for now, one needs to be careful about it and handle any
* extra parameters of distortions models. */
bool BKE_tracking_camera_distortion_equal(const struct MovieTrackingCamera *a,
const struct MovieTrackingCamera *b);
/* Hashes distortion related parameters of camera. Ideally, this implementation will be
* abstracted away in the future, but for now, one needs to be careful about it and handle any
* extra parameters of distortions models. */
uint64_t BKE_tracking_camera_distortion_hash(const struct MovieTrackingCamera *camera);
/* --------------------------------------------------------------------
* (Un)distortion.
*/

View File

@ -37,6 +37,7 @@ set(INC
../../../intern/mikktspace
../../../intern/opensubdiv
../../../extern/curve_fit_nd
../../../extern/fmtlib/include
# dna_type_offsets.h
${CMAKE_CURRENT_BINARY_DIR}/../makesdna/intern
@ -240,7 +241,6 @@ set(SRC
intern/object.cc
intern/object_deform.c
intern/object_dupli.cc
intern/object_facemap.c
intern/object_update.cc
intern/ocean.c
intern/ocean_spectrum.c
@ -456,7 +456,6 @@ set(SRC
BKE_node_tree_zones.hh
BKE_object.h
BKE_object_deform.h
BKE_object_facemap.h
BKE_ocean.h
BKE_outliner_treehash.hh
BKE_packedFile.h
@ -554,6 +553,7 @@ set(LIB
bf_rna
bf_shader_fx
bf_simulation
extern_fmtlib
# For `vfontdata_freetype.c`.
${FREETYPE_LIBRARIES} ${BROTLI_LIBRARIES}

View File

@ -1852,7 +1852,7 @@ void BKE_pose_blend_write(BlendWriter *writer, bPose *pose, bArmature *arm)
animviz_motionpath_blend_write(writer, chan->mpath);
/* Prevent crashes with autosave,
/* Prevent crashes with auto-save,
* when a bone duplicated in edit-mode has not yet been assigned to its pose-channel.
* Also needed with memundo, in some cases we can store a step before pose has been
* properly rebuilt from previous undo step. */

View File

@ -114,10 +114,10 @@ AnimData *BKE_animdata_ensure_id(ID *id)
return NULL;
}
/* Action / Tmpact Setter shared code -------------------------
/* Action / `tmpact` Setter shared code -------------------------
*
* Both the action and tmpact setter functions have essentially
* identical semantics, because tmpact is just a place to temporarily
* Both the action and `tmpact` setter functions have essentially
* identical semantics, because `tmpact` is just a place to temporarily
* store the main action during tweaking. This function contains the
* shared code between those two setter functions, setting the action
* of the passed `act_slot` to `act`.

View File

@ -65,7 +65,7 @@ static void pchan_deform_accumulate(const DualQuat *deform_dq,
BLI_assert(!co_accum);
if (deform_dq->scale_weight) {
/* FIX https://projects.blender.org/blender/blender/issues/32022 */
/* FIX #32022. */
DualQuat mdq = *deform_dq;
float dst[3];
mul_v3_m4v3(dst, mdq.scale, co_in);

View File

@ -39,6 +39,38 @@ void BKE_asset_metadata_free(AssetMetaData **asset_data)
*asset_data = nullptr;
}
AssetMetaData *BKE_asset_metadata_copy(const AssetMetaData *source)
{
AssetMetaData *copy = BKE_asset_metadata_create();
copy->local_type_info = source->local_type_info;
if (source->properties) {
copy->properties = IDP_CopyProperty(source->properties);
}
BKE_asset_metadata_catalog_id_set(copy, source->catalog_id, source->catalog_simple_name);
if (source->author) {
copy->author = BLI_strdup(source->author);
}
if (source->description) {
copy->description = BLI_strdup(source->description);
}
if (source->copyright) {
copy->copyright = BLI_strdup(source->copyright);
}
if (source->license) {
copy->license = BLI_strdup(source->license);
}
BLI_duplicatelist(&copy->tags, &source->tags);
copy->active_tag = source->active_tag;
copy->tot_tags = source->tot_tags;
return copy;
}
AssetMetaData::~AssetMetaData()
{
if (properties) {

View File

@ -208,14 +208,13 @@ static void setup_app_userdef(BlendFileData *bfd)
BKE_blender_userdef_data_set_and_free(bfd->user);
bfd->user = nullptr;
/* Security issue: any blend file could include a USER block.
/* Security issue: any blend file could include a #BLO_CODE_USER block.
*
* Currently we load prefs from BLENDER_STARTUP_FILE and later on load BLENDER_USERPREF_FILE,
* to load the preferences defined in the users home dir.
* Preferences are loaded from #BLENDER_STARTUP_FILE and later on load #BLENDER_USERPREF_FILE,
* to load the preferences defined in the users home directory.
*
* This means we will never accidentally (or maliciously)
* enable scripts auto-execution by loading a '.blend' file.
*/
* enable scripts auto-execution by loading a `.blend` file. */
U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
}
}
@ -251,7 +250,7 @@ typedef struct ReuseOldBMainData {
* NOTE: The case where the `old_bmain` would be a library in the newly read one is not handled
* here, as it does not create explicit issues. The local data from `old_bmain` is either
* discarded, or added to the `new_bmain` as local data as well. Worst case, there will be a
* doublon of a linked data as a local one, without any known relationships between them. In
* double of a linked data as a local one, without any known relationships between them. In
* practice, this latter case is not expected to commonly happen.
*/
static IDRemapper *reuse_bmain_data_remapper_ensure(ReuseOldBMainData *reuse_data)
@ -747,7 +746,7 @@ static void setup_app_data(bContext *C,
wmWindow *win = nullptr;
bScreen *curscreen = nullptr;
/* Ensure that there is a valid scene and viewlayer. */
/* Ensure that there is a valid scene and view-layer. */
if (curscene == nullptr) {
curscene = static_cast<Scene *>(bfd->main->scenes.first);
}
@ -904,7 +903,7 @@ static void setup_app_data(bContext *C,
bmain->filepath[0] = '\0';
}
else if (recover) {
/* In case of autosave or quit.blend, use original filepath instead. */
/* In case of auto-save or quit.blend, use original filepath instead. */
bmain->recovered = true;
STRNCPY(bmain->filepath, bfd->filepath);
}

View File

@ -368,6 +368,10 @@ void clothModifier_do(ClothModifierData *clmd,
return;
}
/* Since implicit sharing is introduced, mesh data can be moved to other places.
* Therefore some fields in simulation data need to be updated accordingly */
clmd->clothObject->edges = reinterpret_cast<const vec2i *>(mesh->edges().data());
/* try to read from cache */
bool can_simulate = (framenr == clmd->clothObject->last_frame + 1) &&
!(cache->flag & PTCACHE_BAKED);

View File

@ -24,6 +24,7 @@
#include "BKE_curves.hh"
#include "BKE_editmesh.h"
#include "BKE_geometry_set.hh"
#include "BKE_grease_pencil.hh"
#include "BKE_lib_id.h"
#include "BKE_mesh.hh"
#include "BKE_mesh_wrapper.h"
@ -662,4 +663,37 @@ GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph,
return get_evaluated_curves_deformation(ob_eval, ob_orig);
}
GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object *ob_eval,
const Object &ob_orig,
const int drawing_index)
{
BLI_assert(ob_orig.type == OB_GREASE_PENCIL);
const GreasePencil &grease_pencil_orig = *static_cast<const GreasePencil *>(ob_orig.data);
GreasePencilDrawingBase *drawing_base = grease_pencil_orig.drawings()[drawing_index];
GeometryDeformation deformation;
if (drawing_base->type == GP_DRAWING) {
GreasePencilDrawing *drawing = reinterpret_cast<GreasePencilDrawing *>(drawing_base);
/* Use the undeformed positions by default. */
deformation.positions = drawing->geometry.wrap().positions();
}
else if (drawing_base->type == GP_DRAWING_REFERENCE) {
/* TODO */
}
if (ob_eval == nullptr) {
return deformation;
}
const GeometrySet *geometry_eval = ob_eval->runtime.geometry_set_eval;
if (geometry_eval == nullptr) {
return deformation;
}
/* TODO: Read `GeometryComponentEditData` from `geometry_eval` and populate deformation with it.
*/
return deformation;
}
} // namespace blender::bke::crazyspace

View File

@ -1257,20 +1257,6 @@ static void layerSwap_flnor(void *data, const int *corner_indices)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (`int`, #CD_FACEMAP)
* \{ */
static void layerDefault_fmap(void *data, const int count)
{
int *fmap_num = (int *)data;
for (int i = 0; i < count; i++) {
fmap_num[i] = -1;
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#MPropCol, #CD_PROP_COLOR)
* \{ */
@ -1628,8 +1614,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
nullptr,
nullptr,
layerCopyValue_normal},
/* 9: CD_FACEMAP */
{sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, layerDefault_fmap, nullptr},
/* 9: CD_FACEMAP */ /* DEPRECATED */
{sizeof(int), ""},
/* 10: CD_PROP_FLOAT */
{sizeof(MFloatProperty),
"MFloatProperty",
@ -1865,7 +1851,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 41: CD_CUSTOMLOOPNORMAL */
{sizeof(short[2]), "vec2s", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 42: CD_SCULPT_FACE_SETS */ /* DEPRECATED */
{sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
{sizeof(int), ""},
/* 43: CD_LOCATION */
{sizeof(float[3]), "vec3f", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 44: CD_RADIUS */
@ -2010,14 +1996,14 @@ const CustomData_MeshMasks CD_MASK_BAREMESH = {
/*vmask*/ CD_MASK_PROP_FLOAT3,
/*emask*/ CD_MASK_PROP_INT32_2D,
/*fmask*/ 0,
/*pmask*/ CD_MASK_FACEMAP,
/*pmask*/ 0,
/*lmask*/ CD_MASK_PROP_INT32,
};
const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX = {
/*vmask*/ CD_MASK_PROP_FLOAT3 | CD_MASK_ORIGINDEX,
/*emask*/ CD_MASK_PROP_INT32_2D | CD_MASK_ORIGINDEX,
/*fmask*/ 0,
/*pmask*/ CD_MASK_FACEMAP | CD_MASK_ORIGINDEX,
/*pmask*/ CD_MASK_ORIGINDEX,
/*lmask*/ CD_MASK_PROP_INT32,
};
const CustomData_MeshMasks CD_MASK_MESH = {
@ -2027,7 +2013,7 @@ const CustomData_MeshMasks CD_MASK_MESH = {
(CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_CREASE),
/*fmask*/ 0,
/*pmask*/
(CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
(CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/*lmask*/
(CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
@ -2039,7 +2025,7 @@ const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_CREASE),
/*fmask*/ (CD_MASK_ORIGINDEX | CD_MASK_ORIGSPACE | CD_MASK_PREVIEW_MCOL | CD_MASK_TANGENT),
/*pmask*/
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL),
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/*lmask*/
(CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
CD_MASK_PROP_ALL), /* XXX: MISSING #CD_MASK_MLOOPTANGENT ? */
@ -2050,7 +2036,7 @@ const CustomData_MeshMasks CD_MASK_BMESH = {
/*emask*/ (CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
/*fmask*/ 0,
/*pmask*/
(CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL),
(CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/*lmask*/
(CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
@ -2066,8 +2052,7 @@ const CustomData_MeshMasks CD_MASK_EVERYTHING = {
CD_MASK_ORIGSPACE | CD_MASK_TANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_PREVIEW_MCOL |
CD_MASK_PROP_ALL),
/*pmask*/
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE |
CD_MASK_PROP_ALL),
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/*lmask*/
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL |
CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
@ -4880,7 +4865,7 @@ static void customdata_data_transfer_interp_generic(const CustomDataTransferLaye
* more than 0.5 of weight. */
int best_src_idx = 0;
const eCustomDataType data_type = laymap->data_type;
const int data_type = laymap->data_type;
const int mix_mode = laymap->mix_mode;
size_t data_size;
@ -4898,7 +4883,7 @@ static void customdata_data_transfer_interp_generic(const CustomDataTransferLaye
data_size = laymap->data_size;
}
else {
const LayerTypeInfo *type_info = layerType_getInfo(data_type);
const LayerTypeInfo *type_info = layerType_getInfo(eCustomDataType(data_type));
data_size = size_t(type_info->size);
interp_cd = type_info->interp;
@ -4967,7 +4952,7 @@ static void customdata_data_transfer_interp_generic(const CustomDataTransferLaye
}
}
else if (!(int(data_type) & CD_FAKE)) {
CustomData_data_mix_value(data_type, tmp_dst, data_dst, mix_mode, mix_factor);
CustomData_data_mix_value(eCustomDataType(data_type), tmp_dst, data_dst, mix_mode, mix_factor);
}
/* Else we can do nothing by default, needs custom interp func!
* Note this is here only for sake of consistency, not expected to be used much actually? */
@ -4990,7 +4975,8 @@ void customdata_data_transfer_interp_normal_normals(const CustomDataTransferLaye
BLI_assert(weights != nullptr);
BLI_assert(count > 0);
const eCustomDataType data_type = laymap->data_type;
const eCustomDataType data_type = eCustomDataType(laymap->data_type);
BLI_assert(data_type == CD_NORMAL);
const int mix_mode = laymap->mix_mode;
SpaceTransform *space_transform = static_cast<SpaceTransform *>(laymap->interp_data);
@ -5000,8 +4986,6 @@ void customdata_data_transfer_interp_normal_normals(const CustomDataTransferLaye
float tmp_dst[3];
BLI_assert(data_type == CD_NORMAL);
if (!sources) {
/* Not supported here, abort. */
return;
@ -5022,7 +5006,7 @@ void CustomData_data_transfer(const MeshPairRemap *me_remap,
MeshPairRemapItem *mapit = me_remap->items;
const int totelem = me_remap->items_num;
const eCustomDataType data_type = laymap->data_type;
const int data_type = laymap->data_type;
const void *data_src = laymap->data_src;
void *data_dst = laymap->data_dst;
@ -5051,7 +5035,7 @@ void CustomData_data_transfer(const MeshPairRemap *me_remap,
data_offset = laymap->data_offset;
}
else {
const LayerTypeInfo *type_info = layerType_getInfo(data_type);
const LayerTypeInfo *type_info = layerType_getInfo(eCustomDataType(data_type));
/* NOTE: we can use 'fake' CDLayers for crease :/. */
data_size = size_t(type_info->size);
@ -5169,9 +5153,6 @@ void CustomData_blend_write(BlendWriter *writer,
case CD_GRID_PAINT_MASK:
write_grid_paint_mask(writer, count, static_cast<const GridPaintMask *>(layer.data));
break;
case CD_FACEMAP:
BLO_write_raw(writer, sizeof(int) * count, static_cast<const int *>(layer.data));
break;
case CD_PROP_BOOL:
BLO_write_raw(writer, sizeof(bool) * count, static_cast<const bool *>(layer.data));
break;

View File

@ -1931,7 +1931,7 @@ static void sample_mesh(FluidFlowSettings *ffs,
tex_co[1] = tex_co[1] * 2.0f - 1.0f;
tex_co[2] = ffs->texture_offset;
}
BKE_texture_get_value(nullptr, ffs->noise_texture, tex_co, &texres, false);
BKE_texture_get_value(ffs->noise_texture, tex_co, &texres, false);
emission_strength *= texres.tin;
}
}

View File

@ -18,8 +18,6 @@
#include "attribute_access_intern.hh"
using blender::GVArray;
/* -------------------------------------------------------------------- */
/** \name Geometry Component Implementation
* \{ */
@ -292,47 +290,43 @@ std::optional<eAttrDomain> CurveLengthFieldInput::preferred_domain(
/** \} */
} // namespace blender::bke
/* -------------------------------------------------------------------- */
/** \name Attribute Access Helper Functions
* \{ */
static void tag_component_topology_changed(void *owner)
{
blender::bke::CurvesGeometry &curves = *static_cast<blender::bke::CurvesGeometry *>(owner);
CurvesGeometry &curves = *static_cast<CurvesGeometry *>(owner);
curves.tag_topology_changed();
}
static void tag_component_curve_types_changed(void *owner)
{
blender::bke::CurvesGeometry &curves = *static_cast<blender::bke::CurvesGeometry *>(owner);
CurvesGeometry &curves = *static_cast<CurvesGeometry *>(owner);
curves.update_curve_types();
curves.tag_topology_changed();
}
static void tag_component_positions_changed(void *owner)
{
blender::bke::CurvesGeometry &curves = *static_cast<blender::bke::CurvesGeometry *>(owner);
CurvesGeometry &curves = *static_cast<CurvesGeometry *>(owner);
curves.tag_positions_changed();
}
static void tag_component_radii_changed(void *owner)
{
blender::bke::CurvesGeometry &curves = *static_cast<blender::bke::CurvesGeometry *>(owner);
CurvesGeometry &curves = *static_cast<CurvesGeometry *>(owner);
curves.tag_radii_changed();
}
static void tag_component_normals_changed(void *owner)
{
blender::bke::CurvesGeometry &curves = *static_cast<blender::bke::CurvesGeometry *>(owner);
CurvesGeometry &curves = *static_cast<CurvesGeometry *>(owner);
curves.tag_normals_changed();
}
/** \} */
namespace blender::bke {
/* -------------------------------------------------------------------- */
/** \name Attribute Provider Declaration
* \{ */
@ -590,7 +584,7 @@ static AttributeAccessorFunctions get_curves_accessor_functions()
return ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
};
fn.adapt_domain = [](const void *owner,
const blender::GVArray &varray,
const GVArray &varray,
const eAttrDomain from_domain,
const eAttrDomain to_domain) -> GVArray {
if (owner == nullptr) {

View File

@ -24,17 +24,6 @@
#include "BLI_cpp_type_make.hh"
using blender::float4x4;
using blender::GSpan;
using blender::IndexMask;
using blender::Map;
using blender::MutableSpan;
using blender::Set;
using blender::Span;
using blender::VectorSet;
using blender::bke::InstanceReference;
using blender::bke::Instances;
/* -------------------------------------------------------------------- */
/** \name Geometry Component Implementation
* \{ */
@ -50,7 +39,7 @@ GeometryComponent *InstancesComponent::copy() const
{
InstancesComponent *new_component = new InstancesComponent();
if (instances_ != nullptr) {
new_component->instances_ = new Instances(*instances_);
new_component->instances_ = new blender::bke::Instances(*instances_);
new_component->ownership_ = GeometryOwnershipType::Owned;
}
return new_component;
@ -99,13 +88,14 @@ blender::bke::Instances *InstancesComponent::get_for_write()
{
BLI_assert(this->is_mutable());
if (ownership_ == GeometryOwnershipType::ReadOnly) {
instances_ = new Instances(*instances_);
instances_ = new blender::bke::Instances(*instances_);
ownership_ = GeometryOwnershipType::Owned;
}
return instances_;
}
void InstancesComponent::replace(Instances *instances, GeometryOwnershipType ownership)
void InstancesComponent::replace(blender::bke::Instances *instances,
GeometryOwnershipType ownership)
{
BLI_assert(this->is_mutable());
this->clear();
@ -233,13 +223,13 @@ static AttributeAccessorFunctions get_instances_accessor_functions()
return domain == ATTR_DOMAIN_INSTANCE;
};
fn.adapt_domain = [](const void * /*owner*/,
const blender::GVArray &varray,
const GVArray &varray,
const eAttrDomain from_domain,
const eAttrDomain to_domain) {
if (from_domain == to_domain && from_domain == ATTR_DOMAIN_INSTANCE) {
return varray;
}
return blender::GVArray{};
return GVArray{};
};
return fn;
}

View File

@ -21,8 +21,6 @@
#include "attribute_access_intern.hh"
extern "C" MDeformVert *BKE_object_defgroup_data_create(ID *id);
/* -------------------------------------------------------------------- */
/** \name Geometry Component Implementation
* \{ */
@ -158,16 +156,12 @@ VArray<float3> mesh_normals_varray(const Mesh &mesh,
}
}
} // namespace blender::bke
/** \} */
/* -------------------------------------------------------------------- */
/** \name Attribute Access
* \{ */
namespace blender::bke {
template<typename T>
static void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh,
const VArray<T> &old_values,
@ -740,8 +734,6 @@ static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &v
return new_varray;
}
} // namespace blender::bke
static bool can_simple_adapt_for_single(const Mesh &mesh,
const eAttrDomain from_domain,
const eAttrDomain to_domain)
@ -780,10 +772,10 @@ static bool can_simple_adapt_for_single(const Mesh &mesh,
}
}
static blender::GVArray adapt_mesh_attribute_domain(const Mesh &mesh,
const blender::GVArray &varray,
const eAttrDomain from_domain,
const eAttrDomain to_domain)
static GVArray adapt_mesh_attribute_domain(const Mesh &mesh,
const GVArray &varray,
const eAttrDomain from_domain,
const eAttrDomain to_domain)
{
if (!varray) {
return {};
@ -798,8 +790,7 @@ static blender::GVArray adapt_mesh_attribute_domain(const Mesh &mesh,
if (can_simple_adapt_for_single(mesh, from_domain, to_domain)) {
BUFFER_FOR_CPP_TYPE_VALUE(varray.type(), value);
varray.get_internal_single(value);
return blender::GVArray::ForSingle(
varray.type(), mesh.attributes().domain_size(to_domain), value);
return GVArray::ForSingle(varray.type(), mesh.attributes().domain_size(to_domain), value);
}
}
@ -807,11 +798,11 @@ static blender::GVArray adapt_mesh_attribute_domain(const Mesh &mesh,
case ATTR_DOMAIN_CORNER: {
switch (to_domain) {
case ATTR_DOMAIN_POINT:
return blender::bke::adapt_mesh_domain_corner_to_point(mesh, varray);
return adapt_mesh_domain_corner_to_point(mesh, varray);
case ATTR_DOMAIN_FACE:
return blender::bke::adapt_mesh_domain_corner_to_face(mesh, varray);
return adapt_mesh_domain_corner_to_face(mesh, varray);
case ATTR_DOMAIN_EDGE:
return blender::bke::adapt_mesh_domain_corner_to_edge(mesh, varray);
return adapt_mesh_domain_corner_to_edge(mesh, varray);
default:
break;
}
@ -820,11 +811,11 @@ static blender::GVArray adapt_mesh_attribute_domain(const Mesh &mesh,
case ATTR_DOMAIN_POINT: {
switch (to_domain) {
case ATTR_DOMAIN_CORNER:
return blender::bke::adapt_mesh_domain_point_to_corner(mesh, varray);
return adapt_mesh_domain_point_to_corner(mesh, varray);
case ATTR_DOMAIN_FACE:
return blender::bke::adapt_mesh_domain_point_to_face(mesh, varray);
return adapt_mesh_domain_point_to_face(mesh, varray);
case ATTR_DOMAIN_EDGE:
return blender::bke::adapt_mesh_domain_point_to_edge(mesh, varray);
return adapt_mesh_domain_point_to_edge(mesh, varray);
default:
break;
}
@ -833,11 +824,11 @@ static blender::GVArray adapt_mesh_attribute_domain(const Mesh &mesh,
case ATTR_DOMAIN_FACE: {
switch (to_domain) {
case ATTR_DOMAIN_POINT:
return blender::bke::adapt_mesh_domain_face_to_point(mesh, varray);
return adapt_mesh_domain_face_to_point(mesh, varray);
case ATTR_DOMAIN_CORNER:
return blender::bke::adapt_mesh_domain_face_to_corner(mesh, varray);
return adapt_mesh_domain_face_to_corner(mesh, varray);
case ATTR_DOMAIN_EDGE:
return blender::bke::adapt_mesh_domain_face_to_edge(mesh, varray);
return adapt_mesh_domain_face_to_edge(mesh, varray);
default:
break;
}
@ -846,11 +837,11 @@ static blender::GVArray adapt_mesh_attribute_domain(const Mesh &mesh,
case ATTR_DOMAIN_EDGE: {
switch (to_domain) {
case ATTR_DOMAIN_CORNER:
return blender::bke::adapt_mesh_domain_edge_to_corner(mesh, varray);
return adapt_mesh_domain_edge_to_corner(mesh, varray);
case ATTR_DOMAIN_POINT:
return blender::bke::adapt_mesh_domain_edge_to_point(mesh, varray);
return adapt_mesh_domain_edge_to_point(mesh, varray);
case ATTR_DOMAIN_FACE:
return blender::bke::adapt_mesh_domain_edge_to_face(mesh, varray);
return adapt_mesh_domain_edge_to_face(mesh, varray);
default:
break;
}
@ -863,8 +854,6 @@ static blender::GVArray adapt_mesh_attribute_domain(const Mesh &mesh,
return {};
}
namespace blender::bke {
static void tag_component_positions_changed(void *owner)
{
Mesh *mesh = static_cast<Mesh *>(owner);
@ -1269,9 +1258,9 @@ static AttributeAccessorFunctions get_mesh_accessor_functions()
return ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE, ATTR_DOMAIN_FACE, ATTR_DOMAIN_CORNER);
};
fn.adapt_domain = [](const void *owner,
const blender::GVArray &varray,
const GVArray &varray,
const eAttrDomain from_domain,
const eAttrDomain to_domain) -> blender::GVArray {
const eAttrDomain to_domain) -> GVArray {
if (owner == nullptr) {
return {};
}

View File

@ -18,6 +18,8 @@
#include "BLT_translation.h"
#include <fmt/format.h>
namespace blender::bke {
MeshFieldContext::MeshFieldContext(const Mesh &mesh, const eAttrDomain domain)
@ -266,9 +268,7 @@ GVArray AttributeFieldInput::get_varray_for_context(const GeometryFieldContext &
std::string AttributeFieldInput::socket_inspection_name() const
{
std::stringstream ss;
ss << '"' << name_ << '"' << TIP_(" attribute from geometry");
return ss.str();
return fmt::format(TIP_("\"{}\" attribute from geometry"), name_);
}
uint64_t AttributeFieldInput::hash() const
@ -350,9 +350,7 @@ GVArray AnonymousAttributeFieldInput::get_varray_for_context(const GeometryField
std::string AnonymousAttributeFieldInput::socket_inspection_name() const
{
std::stringstream ss;
ss << '"' << debug_name_ << '"' << TIP_(" from ") << producer_name_;
return ss.str();
return fmt::format(TIP_("\"{}\" from {}"), TIP_(debug_name_.c_str()), producer_name_);
}
uint64_t AnonymousAttributeFieldInput::hash() const

View File

@ -1061,7 +1061,7 @@ enum ForeachDrawingMode {
static void foreach_drawing_ex(GreasePencil &grease_pencil,
int frame,
ForeachDrawingMode mode,
blender::FunctionRef<void(GreasePencilDrawing &)> function)
blender::FunctionRef<void(int, GreasePencilDrawing &)> function)
{
using namespace blender::bke::greasepencil;
@ -1089,7 +1089,7 @@ static void foreach_drawing_ex(GreasePencil &grease_pencil,
GreasePencilDrawingBase *drawing_base = drawings[index];
if (drawing_base->type == GP_DRAWING) {
GreasePencilDrawing *drawing = reinterpret_cast<GreasePencilDrawing *>(drawing_base);
function(*drawing);
function(index, *drawing);
}
else if (drawing_base->type == GP_DRAWING_REFERENCE) {
/* TODO */
@ -1098,13 +1098,13 @@ static void foreach_drawing_ex(GreasePencil &grease_pencil,
}
void GreasePencil::foreach_visible_drawing(
int frame, blender::FunctionRef<void(GreasePencilDrawing &)> function)
int frame, blender::FunctionRef<void(int, GreasePencilDrawing &)> function)
{
foreach_drawing_ex(*this, frame, VISIBLE, function);
}
void GreasePencil::foreach_editable_drawing(
int frame, blender::FunctionRef<void(GreasePencilDrawing &)> function)
int frame, blender::FunctionRef<void(int, GreasePencilDrawing &)> function)
{
foreach_drawing_ex(*this, frame, EDITABLE, function);
}

View File

@ -14,7 +14,7 @@
*
* Usage:
*
* ```
* \code{.cc}
* Image *image = ...;
* ImBuf *image_buffer = ...;
*
@ -44,8 +44,7 @@
*
* // Free partial_update_user.
* BKE_image_partial_update_free(partial_update_user);
*
* ```
* \endcode
*/
#include <optional>

View File

@ -808,44 +808,6 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me)
}
}
bool BKE_mesh_ensure_facemap_customdata(Mesh *me)
{
BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : nullptr;
bool changed = false;
if (bm) {
if (!CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
BM_data_layer_add(bm, &bm->pdata, CD_FACEMAP);
changed = true;
}
}
else {
if (!CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_SET_DEFAULT, me->totpoly);
changed = true;
}
}
return changed;
}
bool BKE_mesh_clear_facemap_customdata(Mesh *me)
{
BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : nullptr;
bool changed = false;
if (bm) {
if (CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
BM_data_layer_free(bm, &bm->pdata, CD_FACEMAP);
changed = true;
}
}
else {
if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
CustomData_free_layers(&me->pdata, CD_FACEMAP, me->totpoly);
changed = true;
}
}
return changed;
}
bool BKE_mesh_has_custom_loop_normals(Mesh *me)
{
if (me->edit_mesh) {

View File

@ -1305,6 +1305,40 @@ void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Face Map Conversion
* \{ */
void BKE_mesh_legacy_face_map_to_generic(Mesh *mesh)
{
using namespace blender;
if (mesh->attributes().contains("face_maps")) {
return;
}
void *data = nullptr;
const ImplicitSharingInfo *sharing_info = nullptr;
for (const int i : IndexRange(mesh->pdata.totlayer)) {
CustomDataLayer &layer = mesh->pdata.layers[i];
if (layer.type == CD_FACEMAP) {
data = layer.data;
sharing_info = layer.sharing_info;
layer.data = nullptr;
layer.sharing_info = nullptr;
CustomData_free_layer(&mesh->pdata, CD_FACEMAP, mesh->totpoly, i);
break;
}
}
if (data != nullptr) {
CustomData_add_layer_named_with_data(
&mesh->pdata, CD_PROP_INT32, data, mesh->totpoly, "face_maps", sharing_info);
}
if (sharing_info != nullptr) {
sharing_info->remove_user_and_delete_if_last();
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Bevel Weight Conversion
* \{ */

View File

@ -628,7 +628,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
if (mesh_remap_bvhtree_query_nearest(
&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
const int poly_index = looptri_polys[rayhit.index];
const int poly_index = looptri_polys[nearest.index];
if (mode == MREMAP_MODE_VERT_POLY_NEAREST) {
int index;
@ -886,7 +886,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist))
{
const int poly_index = looptri_polys[rayhit.index];
const int poly_index = looptri_polys[nearest.index];
const blender::IndexRange poly_src = polys_src[poly_index];
const int *corner_edge_src = &corner_edges_src[poly_src.start()];
int nloops = int(poly_src.size());

View File

@ -16,9 +16,9 @@
#include "MEM_guardedalloc.h"
#include "BLI_array.hh"
#include "BLI_array_utils.hh"
#include "BLI_index_range.hh"
#include "BLI_math_vector.h"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "BLI_task.hh"
@ -27,6 +27,7 @@
#include "BKE_attribute.h"
#include "BKE_attribute.hh"
#include "BKE_attribute_math.hh"
#include "BKE_bvhutils.h"
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
@ -35,6 +36,7 @@
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_remesh_voxel.h" /* own include */
#include "BKE_mesh_runtime.h"
#include "BKE_mesh_sample.hh"
#include "bmesh_tools.h"
@ -360,116 +362,104 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
{
BVHTreeFromMesh bvhtree = {nullptr};
BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2);
using namespace blender;
using namespace blender::bke;
const AttributeAccessor src_attributes = source->attributes();
MutableAttributeAccessor dst_attributes = target->attributes_for_write();
int i = 0;
const CustomDataLayer *layer;
Vector<AttributeIDRef> point_ids;
Vector<AttributeIDRef> corner_ids;
source->attributes().for_all([&](const AttributeIDRef &id, const AttributeMetaData &meta_data) {
if (CD_TYPE_AS_MASK(meta_data.data_type) & CD_MASK_COLOR_ALL) {
if (meta_data.domain == ATTR_DOMAIN_POINT) {
point_ids.append(id);
}
else if (meta_data.domain == ATTR_DOMAIN_CORNER) {
corner_ids.append(id);
}
}
return true;
});
if (point_ids.is_empty() && corner_ids.is_empty()) {
return;
}
Array<int> source_vert_to_loop_offsets;
Array<int> source_vert_to_loop_indices;
blender::GroupedSpan<int> source_lmap;
GroupedSpan<int> source_lmap;
Array<int> target_vert_to_loop_offsets;
Array<int> target_vert_to_loop_indices;
blender::GroupedSpan<int> target_lmap;
GroupedSpan<int> target_lmap;
BVHTreeFromMesh bvhtree = {nullptr};
threading::parallel_invoke(
[&]() { BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2); },
[&]() {
source_lmap = mesh::build_vert_to_loop_map(source->corner_verts(),
source->totvert,
source_vert_to_loop_offsets,
source_vert_to_loop_indices);
},
[&]() {
target_lmap = mesh::build_vert_to_loop_map(target->corner_verts(),
target->totvert,
target_vert_to_loop_offsets,
target_vert_to_loop_indices);
});
while ((layer = BKE_id_attribute_from_index(
const_cast<ID *>(&source->id), i++, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL)))
{
eAttrDomain domain = BKE_id_attribute_domain(&source->id, layer);
const eCustomDataType type = eCustomDataType(layer->type);
CustomData *target_cdata = domain == ATTR_DOMAIN_POINT ? &target->vdata : &target->ldata;
const CustomData *source_cdata = domain == ATTR_DOMAIN_POINT ? &source->vdata : &source->ldata;
/* Check attribute exists in target. */
int layer_i = CustomData_get_named_layer_index(target_cdata, type, layer->name);
if (layer_i == -1) {
int elem_num = domain == ATTR_DOMAIN_POINT ? target->totvert : target->totloop;
CustomData_add_layer_named(target_cdata, type, CD_SET_DEFAULT, elem_num, layer->name);
layer_i = CustomData_get_named_layer_index(target_cdata, type, layer->name);
const Span<float3> target_positions = target->vert_positions();
Array<int> nearest_src_verts(target_positions.size());
threading::parallel_for(target_positions.index_range(), 1024, [&](const IndexRange range) {
for (const int i : range) {
BVHTreeNearest nearest;
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
BLI_bvhtree_find_nearest(
bvhtree.tree, target_positions[i], &nearest, bvhtree.nearest_callback, &bvhtree);
nearest_src_verts[i] = nearest.index;
}
});
size_t data_size = CustomData_sizeof(type);
void *target_data = target_cdata->layers[layer_i].data;
void *source_data = layer->data;
const Span<float3> target_positions = target->vert_positions();
for (const AttributeIDRef &id : point_ids) {
const GVArraySpan src = *src_attributes.lookup(id, ATTR_DOMAIN_POINT);
GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
id, ATTR_DOMAIN_POINT, cpp_type_to_custom_data_type(src.type()));
attribute_math::gather(src, nearest_src_verts, dst.span);
dst.finish();
}
if (domain == ATTR_DOMAIN_POINT) {
blender::threading::parallel_for(
IndexRange(target->totvert), 4096, [&](const IndexRange range) {
for (const int i : range) {
BVHTreeNearest nearest;
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
BLI_bvhtree_find_nearest(
bvhtree.tree, target_positions[i], &nearest, bvhtree.nearest_callback, &bvhtree);
if (nearest.index != -1) {
memcpy(POINTER_OFFSET(target_data, size_t(i) * data_size),
POINTER_OFFSET(source_data, size_t(nearest.index) * data_size),
data_size);
if (!corner_ids.is_empty()) {
for (const AttributeIDRef &id : corner_ids) {
const GVArraySpan src = *src_attributes.lookup(id, ATTR_DOMAIN_CORNER);
GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
id, ATTR_DOMAIN_CORNER, cpp_type_to_custom_data_type(src.type()));
threading::parallel_for(target_positions.index_range(), 1024, [&](const IndexRange range) {
src.type().to_static_type_tag<ColorGeometry4b, ColorGeometry4f>([&](auto type_tag) {
using T = typename decltype(type_tag)::type;
if constexpr (std::is_void_v<T>) {
BLI_assert_unreachable();
}
else {
const Span<T> src_typed = src.typed<T>();
MutableSpan<T> dst_typed = dst.span.typed<T>();
for (const int dst_vert : range) {
/* Find the average value at the corners of the closest vertex on the
* source mesh. */
const int src_vert = nearest_src_verts[dst_vert];
T value;
typename blender::bke::attribute_math::DefaultMixer<T> mixer({&value, 1});
for (const int corner : source_lmap[src_vert]) {
mixer.mix_in(0, src_typed[corner]);
}
dst_typed.fill_indices(target_lmap[dst_vert], value);
}
});
}
else {
/* Lazily init vertex -> loop maps. */
if (source_lmap.is_empty()) {
source_lmap = blender::bke::mesh::build_vert_to_loop_map(source->corner_verts(),
source->totvert,
source_vert_to_loop_offsets,
source_vert_to_loop_indices);
target_lmap = blender::bke::mesh::build_vert_to_loop_map(target->corner_verts(),
target->totvert,
target_vert_to_loop_offsets,
target_vert_to_loop_indices);
}
}
});
});
blender::threading::parallel_for(
IndexRange(target->totvert), 2048, [&](const IndexRange range) {
for (const int i : range) {
BVHTreeNearest nearest;
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
BLI_bvhtree_find_nearest(
bvhtree.tree, target_positions[i], &nearest, bvhtree.nearest_callback, &bvhtree);
if (nearest.index == -1) {
continue;
}
const Span<int> source_loops = source_lmap[nearest.index];
const Span<int> target_loops = target_lmap[i];
if (target_loops.size() == 0 || source_loops.size() == 0) {
continue;
}
/*
* Average color data for loops around the source vertex into
* the first target loop around the target vertex
*/
CustomData_interp(source_cdata,
target_cdata,
source_loops.data(),
nullptr,
nullptr,
source_loops.size(),
target_loops[0]);
void *elem = POINTER_OFFSET(target_data, size_t(target_loops[0]) * data_size);
/* Copy to rest of target loops. */
for (int j = 1; j < target_loops.size(); j++) {
memcpy(POINTER_OFFSET(target_data, size_t(target_loops[j]) * data_size),
elem,
data_size);
}
}
});
dst.finish();
}
}

View File

@ -70,15 +70,8 @@ bool multiresModifier_reshapeFromObject(Depsgraph *depsgraph,
return false;
}
int num_deformed_verts;
float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(src_mesh_eval, &num_deformed_verts);
const bool result = multiresModifier_reshapeFromVertcos(
depsgraph, dst, mmd, deformed_verts, num_deformed_verts);
MEM_freeN(deformed_verts);
return result;
return multiresModifier_reshapeFromVertcos(
depsgraph, dst, mmd, BKE_mesh_vert_positions(src_mesh_eval), src_mesh_eval->totvert);
}
/** \} */

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