Attributes: Add quaternion rotation type #108678

Merged
Hans Goudey merged 10 commits from HooglyBoogly/blender:attributes-quaternion-type into main 2023-06-12 15:49:57 +02:00
357 changed files with 6416 additions and 2948 deletions
Showing only changes of commit 4a24514851 - 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

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

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

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

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

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

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

@ -22,6 +22,7 @@ typedef struct AssetRepresentation AssetRepresentation;
const char *AS_asset_representation_name_get(const AssetRepresentation *asset)
ATTR_WARN_UNUSED_RESULT;
int 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)

View File

@ -42,6 +42,7 @@ class AssetRepresentation {
struct ExternalAsset {
std::string name;
int id_type = 0;
std::unique_ptr<AssetMetaData> metadata_ = nullptr;
};
union {
@ -55,6 +56,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 +87,7 @@ class AssetRepresentation {
std::unique_ptr<AssetWeakReference> make_weak_reference() const;
StringRefNull get_name() const;
int 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 +117,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

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;
}
int AssetRepresentation::get_id_type() const
{
if (is_local_id_) {
return GS(local_asset_id_->name);
}
return 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();
}
int 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,7 +27,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 4
#define BLENDER_FILE_SUBVERSION 5
/* 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

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

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

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

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

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

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

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

@ -331,7 +331,6 @@ static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket
case SOCK_BOOLEAN:
case SOCK_INT:
case SOCK_STRING:
case __SOCK_MESH:
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:
@ -479,7 +478,6 @@ static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *so
case SOCK_CUSTOM:
/* Custom node sockets where default_value is defined uses custom properties for storage. */
break;
case __SOCK_MESH:
case SOCK_SHADER:
case SOCK_GEOMETRY:
BLI_assert_unreachable();
@ -923,7 +921,6 @@ static void lib_link_node_socket(BlendLibReader *reader, ID *self_id, bNodeSocke
case SOCK_BOOLEAN:
case SOCK_INT:
case SOCK_STRING:
case __SOCK_MESH:
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:
@ -1016,7 +1013,6 @@ static void expand_node_socket(BlendExpander *expander, bNodeSocket *sock)
case SOCK_BOOLEAN:
case SOCK_INT:
case SOCK_STRING:
case __SOCK_MESH:
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:
@ -1705,7 +1701,6 @@ static void socket_id_user_increment(bNodeSocket *sock)
case SOCK_BOOLEAN:
case SOCK_INT:
case SOCK_STRING:
case __SOCK_MESH:
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:
@ -1751,7 +1746,6 @@ static bool socket_id_user_decrement(bNodeSocket *sock)
case SOCK_BOOLEAN:
case SOCK_INT:
case SOCK_STRING:
case __SOCK_MESH:
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:
@ -1804,7 +1798,6 @@ void nodeModifySocketType(bNodeTree *ntree,
case SOCK_SHADER:
case SOCK_BOOLEAN:
case SOCK_CUSTOM:
case __SOCK_MESH:
case SOCK_OBJECT:
case SOCK_IMAGE:
case SOCK_GEOMETRY:
@ -1943,7 +1936,7 @@ const char *nodeStaticSocketType(const int type, const int subtype)
return "NodeSocketTexture";
case SOCK_MATERIAL:
return "NodeSocketMaterial";
default:
case SOCK_CUSTOM:
break;
}
return nullptr;
@ -2022,7 +2015,7 @@ const char *nodeStaticSocketInterfaceType(const int type, const int subtype)
return "NodeSocketInterfaceTexture";
case SOCK_MATERIAL:
return "NodeSocketInterfaceMaterial";
default:
case SOCK_CUSTOM:
break;
}
return nullptr;
@ -2057,7 +2050,7 @@ const char *nodeStaticSocketLabel(const int type, const int /*subtype*/)
return "Texture";
case SOCK_MATERIAL:
return "Material";
default:
case SOCK_CUSTOM:
break;
}
return nullptr;
@ -2579,7 +2572,6 @@ static void *socket_value_storage(bNodeSocket &socket)
case SOCK_STRING:
/* We don't want do this now! */
return nullptr;
case __SOCK_MESH:
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:

View File

@ -3489,12 +3489,14 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
}
}
hair_create_input_mesh(sim, totpoint, totedge, &psys->hair_in_mesh);
/* Free hair_out_mesh before modifying hair_in_mesh in hair_create_input_mesh() to avoid copying
* on write since they share some data */
if (psys->hair_out_mesh) {
BKE_id_free(NULL, psys->hair_out_mesh);
}
hair_create_input_mesh(sim, totpoint, totedge, &psys->hair_in_mesh);
psys->clmd->point_cache = psys->pointcache;
/* for hair sim we replace the internal cloth effector weights temporarily
* to use the particle settings

View File

@ -705,22 +705,15 @@ bool BKE_texture_dependsOnTime(const Tex *texture)
/* ------------------------------------------------------------------------- */
void BKE_texture_get_value_ex(const Scene *scene,
Tex *texture,
void BKE_texture_get_value_ex(Tex *texture,
const float *tex_co,
TexResult *texres,
ImagePool *pool,
bool use_color_management)
{
int result_type;
bool do_color_manage = false;
if (scene && use_color_management) {
do_color_manage = BKE_scene_check_color_management_enabled(scene);
}
/* no node textures for now */
result_type = multitex_ext_safe(texture, tex_co, texres, pool, do_color_manage, false);
const int result_type = multitex_ext_safe(
texture, tex_co, texres, pool, use_color_management, false);
/* if the texture gave an RGB value, we assume it didn't give a valid
* intensity, since this is in the context of modifiers don't use perceptual color conversion.
@ -734,13 +727,12 @@ void BKE_texture_get_value_ex(const Scene *scene,
}
}
void BKE_texture_get_value(const Scene *scene,
Tex *texture,
void BKE_texture_get_value(Tex *texture,
const float *tex_co,
TexResult *texres,
bool use_color_management)
{
BKE_texture_get_value_ex(scene, texture, tex_co, texres, nullptr, use_color_management);
BKE_texture_get_value_ex(texture, tex_co, texres, nullptr, use_color_management);
}
static void texture_nodes_fetch_images_for_pool(Tex *texture, bNodeTree *ntree, ImagePool *pool)

View File

@ -6,6 +6,7 @@
* \ingroup bke
*/
#include <cstdint>
#include <limits.h>
#include <math.h>
#include <memory.h>
@ -23,9 +24,12 @@
#include "BLI_bitmap_draw_2d.h"
#include "BLI_ghash.h"
#include "BLI_hash.hh"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_math_base.h"
#include "BLI_math_vector.h"
#include "BLI_math_vector_types.hh"
#include "BLI_string.h"
#include "BLI_string_utils.h"
#include "BLI_threads.h"
@ -2197,6 +2201,66 @@ void BKE_tracking_camera_principal_point_pixel_set(MovieClip *clip,
principal_point_pixel, frame_width, frame_height, camera->principal_point);
}
bool BKE_tracking_camera_distortion_equal(const MovieTrackingCamera *a,
const MovieTrackingCamera *b)
{
if (a->pixel_aspect != b->pixel_aspect || a->focal != b->focal ||
!equals_v2v2(a->principal_point, b->principal_point))
{
return false;
}
if (a->distortion_model != b->distortion_model) {
return false;
}
switch (a->distortion_model) {
case TRACKING_DISTORTION_MODEL_POLYNOMIAL:
return a->k1 == b->k1 && a->k2 == b->k2 && a->k3 == b->k3;
case TRACKING_DISTORTION_MODEL_DIVISION:
return a->division_k1 == b->division_k1 && a->division_k2 == b->division_k2;
case TRACKING_DISTORTION_MODEL_NUKE:
return a->nuke_k1 == b->nuke_k1 && a->nuke_k2 == b->nuke_k2;
case TRACKING_DISTORTION_MODEL_BROWN:
return a->brown_k1 == b->brown_k1 && a->brown_k2 == b->brown_k2 &&
a->brown_k3 == b->brown_k3 && a->brown_k4 == b->brown_k4 &&
a->brown_p1 == b->brown_p1 && a->brown_p2 == b->brown_p2;
}
BLI_assert_unreachable();
return false;
}
uint64_t BKE_tracking_camera_distortion_hash(const MovieTrackingCamera *camera)
{
using namespace blender;
switch (camera->distortion_model) {
case TRACKING_DISTORTION_MODEL_POLYNOMIAL:
return get_default_hash_4(camera->distortion_model,
float2(camera->pixel_aspect, camera->focal),
float2(camera->principal_point),
float3(camera->k1, camera->k2, camera->k3));
case TRACKING_DISTORTION_MODEL_DIVISION:
return get_default_hash_4(camera->distortion_model,
float2(camera->pixel_aspect, camera->focal),
float2(camera->principal_point),
float2(camera->division_k1, camera->division_k2));
case TRACKING_DISTORTION_MODEL_NUKE:
return get_default_hash_4(camera->distortion_model,
float2(camera->pixel_aspect, camera->focal),
float2(camera->principal_point),
float2(camera->nuke_k1, camera->nuke_k2));
case TRACKING_DISTORTION_MODEL_BROWN:
return get_default_hash_4(
float2(camera->pixel_aspect, camera->focal),
float2(camera->principal_point),
float4(camera->brown_k1, camera->brown_k2, camera->brown_k3, camera->brown_k4),
float2(camera->brown_p1, camera->brown_p2));
}
BLI_assert_unreachable();
return 0;
}
/* --------------------------------------------------------------------
* (Un)distortion.
*/

View File

@ -179,94 +179,98 @@ static void libmv_frame_to_normalized_relative(const float frame_coord[2],
/** \name Conversion of markers between Blender's DNA and Libmv.
* \{ */
static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
const MovieTrackingMarker *marker,
int clip,
int track_index,
int frame_width,
int frame_height,
bool backwards,
libmv_Marker *libmv_marker)
static libmv_Marker dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack &track,
const MovieTrackingMarker &marker,
const int clip,
const int track_index,
const int frame_width,
const int frame_height,
const bool backwards)
{
const int frame_dimensions[2] = {frame_width, frame_height};
libmv_marker->clip = clip;
libmv_marker->frame = marker->framenr;
libmv_marker->track = track_index;
libmv_Marker libmv_marker{};
normalized_to_libmv_frame(marker->pos, frame_dimensions, libmv_marker->center);
const int frame_dimensions[2] = {frame_width, frame_height};
libmv_marker.clip = clip;
libmv_marker.frame = marker.framenr;
libmv_marker.track = track_index;
normalized_to_libmv_frame(marker.pos, frame_dimensions, libmv_marker.center);
for (int i = 0; i < 4; i++) {
normalized_relative_to_libmv_frame(
marker->pattern_corners[i], marker->pos, frame_dimensions, libmv_marker->patch[i]);
marker.pattern_corners[i], marker.pos, frame_dimensions, libmv_marker.patch[i]);
}
normalized_relative_to_libmv_frame(
marker->search_min, marker->pos, frame_dimensions, libmv_marker->search_region_min);
marker.search_min, marker.pos, frame_dimensions, libmv_marker.search_region_min);
normalized_relative_to_libmv_frame(
marker->search_max, marker->pos, frame_dimensions, libmv_marker->search_region_max);
marker.search_max, marker.pos, frame_dimensions, libmv_marker.search_region_max);
/* NOTE: All the markers does have 1.0 weight.
* Might support in the future, but will require more elaborated process which will involve
* F-Curve evaluation. */
libmv_marker->weight = 1.0f;
libmv_marker.weight = 1.0f;
if (marker->flag & MARKER_TRACKED) {
libmv_marker->source = LIBMV_MARKER_SOURCE_TRACKED;
if (marker.flag & MARKER_TRACKED) {
libmv_marker.source = LIBMV_MARKER_SOURCE_TRACKED;
}
else {
libmv_marker->source = LIBMV_MARKER_SOURCE_MANUAL;
libmv_marker.source = LIBMV_MARKER_SOURCE_MANUAL;
}
libmv_marker->status = LIBMV_MARKER_STATUS_UNKNOWN;
libmv_marker->model_type = LIBMV_MARKER_MODEL_TYPE_POINT;
libmv_marker->model_id = 0;
libmv_marker.status = LIBMV_MARKER_STATUS_UNKNOWN;
libmv_marker.model_type = LIBMV_MARKER_MODEL_TYPE_POINT;
libmv_marker.model_id = 0;
/* NOTE: We currently don't support reference marker from different clip. */
libmv_marker->reference_clip = clip;
libmv_marker.reference_clip = clip;
if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
if (track.pattern_match == TRACK_MATCH_KEYFRAME) {
const MovieTrackingMarker *keyframe_marker = tracking_get_keyframed_marker(
track, marker->framenr, backwards);
libmv_marker->reference_frame = keyframe_marker->framenr;
&track, marker.framenr, backwards);
libmv_marker.reference_frame = keyframe_marker->framenr;
}
else {
libmv_marker->reference_frame = backwards ? marker->framenr - 1 : marker->framenr;
libmv_marker.reference_frame = backwards ? marker.framenr - 1 : marker.framenr;
}
libmv_marker->disabled_channels =
((track->flag & TRACK_DISABLE_RED) ? LIBMV_MARKER_CHANNEL_R : 0) |
((track->flag & TRACK_DISABLE_GREEN) ? LIBMV_MARKER_CHANNEL_G : 0) |
((track->flag & TRACK_DISABLE_BLUE) ? LIBMV_MARKER_CHANNEL_B : 0);
libmv_marker.disabled_channels =
((track.flag & TRACK_DISABLE_RED) ? LIBMV_MARKER_CHANNEL_R : 0) |
((track.flag & TRACK_DISABLE_GREEN) ? LIBMV_MARKER_CHANNEL_G : 0) |
((track.flag & TRACK_DISABLE_BLUE) ? LIBMV_MARKER_CHANNEL_B : 0);
return libmv_marker;
}
static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker,
int frame_width,
int frame_height,
MovieTrackingMarker *marker)
static MovieTrackingMarker libmv_marker_to_dna_marker(const libmv_Marker &libmv_marker,
const int frame_width,
const int frame_height)
{
const int frame_dimensions[2] = {frame_width, frame_height};
marker->framenr = libmv_marker->frame;
MovieTrackingMarker marker{};
libmv_frame_to_normalized(libmv_marker->center, frame_dimensions, marker->pos);
const int frame_dimensions[2] = {frame_width, frame_height};
marker.framenr = libmv_marker.frame;
libmv_frame_to_normalized(libmv_marker.center, frame_dimensions, marker.pos);
for (int i = 0; i < 4; i++) {
libmv_frame_to_normalized_relative(libmv_marker->patch[i],
libmv_marker->center,
frame_dimensions,
marker->pattern_corners[i]);
libmv_frame_to_normalized_relative(
libmv_marker.patch[i], libmv_marker.center, frame_dimensions, marker.pattern_corners[i]);
}
libmv_frame_to_normalized_relative(
libmv_marker->search_region_min, libmv_marker->center, frame_dimensions, marker->search_min);
libmv_marker.search_region_min, libmv_marker.center, frame_dimensions, marker.search_min);
libmv_frame_to_normalized_relative(
libmv_marker->search_region_max, libmv_marker->center, frame_dimensions, marker->search_max);
libmv_marker.search_region_max, libmv_marker.center, frame_dimensions, marker.search_max);
marker->flag = 0;
if (libmv_marker->source == LIBMV_MARKER_SOURCE_TRACKED) {
marker->flag |= MARKER_TRACKED;
marker.flag = 0;
if (libmv_marker.source == LIBMV_MARKER_SOURCE_TRACKED) {
marker.flag |= MARKER_TRACKED;
}
else {
marker->flag &= ~MARKER_TRACKED;
marker.flag &= ~MARKER_TRACKED;
}
return marker;
}
/** \} */
@ -279,29 +283,28 @@ static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker,
* \{ */
/* Returns false if marker crossed margin area from frame bounds. */
static bool tracking_check_marker_margin(const libmv_Marker *libmv_marker,
int margin,
int frame_width,
int frame_height)
static bool tracking_check_marker_margin(const libmv_Marker &libmv_marker,
const int margin,
const int frame_width,
const int frame_height)
{
float patch_min[2], patch_max[2];
float margin_left, margin_top, margin_right, margin_bottom;
INIT_MINMAX2(patch_min, patch_max);
minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[0]);
minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[1]);
minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[2]);
minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[3]);
minmax_v2v2_v2(patch_min, patch_max, libmv_marker.patch[0]);
minmax_v2v2_v2(patch_min, patch_max, libmv_marker.patch[1]);
minmax_v2v2_v2(patch_min, patch_max, libmv_marker.patch[2]);
minmax_v2v2_v2(patch_min, patch_max, libmv_marker.patch[3]);
margin_left = max_ff(libmv_marker->center[0] - patch_min[0], margin);
margin_top = max_ff(patch_max[1] - libmv_marker->center[1], margin);
margin_right = max_ff(patch_max[0] - libmv_marker->center[0], margin);
margin_bottom = max_ff(libmv_marker->center[1] - patch_min[1], margin);
margin_left = max_ff(libmv_marker.center[0] - patch_min[0], margin);
margin_top = max_ff(patch_max[1] - libmv_marker.center[1], margin);
margin_right = max_ff(patch_max[0] - libmv_marker.center[0], margin);
margin_bottom = max_ff(libmv_marker.center[1] - patch_min[1], margin);
if (libmv_marker->center[0] < margin_left ||
libmv_marker->center[0] > frame_width - margin_right ||
libmv_marker->center[1] < margin_bottom ||
libmv_marker->center[1] > frame_height - margin_top)
if (libmv_marker.center[0] < margin_left ||
libmv_marker.center[0] > frame_width - margin_right ||
libmv_marker.center[1] < margin_bottom || libmv_marker.center[1] > frame_height - margin_top)
{
return false;
}
@ -315,9 +318,9 @@ static bool tracking_check_marker_margin(const libmv_Marker *libmv_marker,
/** \name Auto-Track Context Initialization
* \{ */
static bool autotrack_is_marker_usable(const MovieTrackingMarker *marker)
static bool autotrack_is_marker_usable(const MovieTrackingMarker &marker)
{
if (marker->flag & MARKER_DISABLED) {
if (marker.flag & MARKER_DISABLED) {
return false;
}
return true;
@ -334,7 +337,7 @@ static bool autotrack_is_track_trackable(const AutoTrackContext *context,
clip, context->start_scene_frame);
const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame_number);
return autotrack_is_marker_usable(marker);
return autotrack_is_marker_usable(*marker);
}
return false;
}
@ -430,7 +433,7 @@ static size_t autotrack_count_all_usable_markers(AutoTrackContext *context)
for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
const MovieTrackingTrack *track = context->all_autotrack_tracks[track_index].track;
for (int marker_index = 0; marker_index < track->markersnr; ++marker_index) {
const MovieTrackingMarker *marker = &track->markers[marker_index];
const MovieTrackingMarker &marker = track->markers[marker_index];
if (!autotrack_is_marker_usable(marker)) {
continue;
}
@ -475,21 +478,21 @@ static void autotrack_context_init_autotrack(AutoTrackContext *context)
int num_filled_libmv_markers = 0;
for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
/*const*/ MovieTrackingTrack *track = autotrack_track->track;
for (int marker_index = 0; marker_index < track->markersnr; ++marker_index) {
/*const*/ MovieTrackingMarker *marker = &track->markers[marker_index];
/*const*/ MovieTrackingTrack &track = *autotrack_track->track;
for (int marker_index = 0; marker_index < track.markersnr; ++marker_index) {
/*const*/ MovieTrackingMarker &marker = track.markers[marker_index];
if (!autotrack_is_marker_usable(marker)) {
continue;
}
const AutoTrackClip *autotrack_clip = &context->autotrack_clips[autotrack_track->clip_index];
dna_marker_to_libmv_marker(track,
marker,
autotrack_track->clip_index,
track_index,
autotrack_clip->width,
autotrack_clip->height,
context->is_backwards,
&libmv_markers[num_filled_libmv_markers++]);
libmv_markers[num_filled_libmv_markers++] = dna_marker_to_libmv_marker(
track,
marker,
autotrack_track->clip_index,
track_index,
autotrack_clip->width,
autotrack_clip->height,
context->is_backwards);
}
}
@ -525,18 +528,17 @@ static void autotrack_context_init_markers(AutoTrackContext *context)
const int clip_frame_number = BKE_movieclip_remap_scene_to_clip_frame(
clip, context->start_scene_frame);
/*const*/ MovieTrackingTrack *track = context->all_autotrack_tracks[track_index].track;
const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame_number);
/*const*/ MovieTrackingTrack &track = *context->all_autotrack_tracks[track_index].track;
const MovieTrackingMarker &marker = *BKE_tracking_marker_get(&track, clip_frame_number);
AutoTrackMarker *autotrack_marker = &context->autotrack_markers[autotrack_marker_index++];
dna_marker_to_libmv_marker(track,
marker,
autotrack_track->clip_index,
track_index,
autotrack_clip->width,
autotrack_clip->height,
context->is_backwards,
&autotrack_marker->libmv_marker);
autotrack_marker->libmv_marker = dna_marker_to_libmv_marker(track,
marker,
autotrack_track->clip_index,
track_index,
autotrack_clip->width,
autotrack_clip->height,
context->is_backwards);
}
}
@ -633,35 +635,35 @@ static void autotrack_context_step_cb(void *__restrict userdata,
AutoTrackContext *context = static_cast<AutoTrackContext *>(userdata);
AutoTrackTLS *autotrack_tls = (AutoTrackTLS *)tls->userdata_chunk;
const AutoTrackMarker *autotrack_marker = &context->autotrack_markers[marker_index];
const libmv_Marker *libmv_current_marker = &autotrack_marker->libmv_marker;
const AutoTrackMarker &autotrack_marker = context->autotrack_markers[marker_index];
const libmv_Marker &libmv_current_marker = autotrack_marker.libmv_marker;
const int frame_delta = context->is_backwards ? -1 : 1;
const int clip_index = libmv_current_marker->clip;
const int track_index = libmv_current_marker->track;
const int clip_index = libmv_current_marker.clip;
const int track_index = libmv_current_marker.track;
const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
const MovieTrackingTrack *track = autotrack_track->track;
const AutoTrackClip &autotrack_clip = context->autotrack_clips[clip_index];
const AutoTrackTrack &autotrack_track = context->all_autotrack_tracks[track_index];
const MovieTrackingTrack &track = *autotrack_track.track;
/* Check whether marker is going outside of allowed frame margin. */
if (!tracking_check_marker_margin(
libmv_current_marker, track->margin, autotrack_clip->width, autotrack_clip->height))
libmv_current_marker, track.margin, autotrack_clip.width, autotrack_clip.height))
{
return;
}
const int new_marker_frame = libmv_current_marker->frame + frame_delta;
const int new_marker_frame = libmv_current_marker.frame + frame_delta;
AutoTrackTrackingResult *autotrack_result = MEM_cnew<AutoTrackTrackingResult>(
"autotrack result");
autotrack_result->libmv_marker = *libmv_current_marker;
autotrack_result->libmv_marker = libmv_current_marker;
autotrack_result->libmv_marker.frame = new_marker_frame;
/* Update reference frame. */
libmv_Marker libmv_reference_marker;
if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
autotrack_result->libmv_marker.reference_frame = libmv_current_marker->reference_frame;
if (track.pattern_match == TRACK_MATCH_KEYFRAME) {
autotrack_result->libmv_marker.reference_frame = libmv_current_marker.reference_frame;
libmv_autoTrackGetMarker(context->autotrack,
clip_index,
autotrack_result->libmv_marker.reference_frame,
@ -669,14 +671,14 @@ static void autotrack_context_step_cb(void *__restrict userdata,
&libmv_reference_marker);
}
else {
BLI_assert(track->pattern_match == TRACK_MATCH_PREVIOS_FRAME);
autotrack_result->libmv_marker.reference_frame = libmv_current_marker->frame;
libmv_reference_marker = *libmv_current_marker;
BLI_assert(track.pattern_match == TRACK_MATCH_PREVIOUS_FRAME);
autotrack_result->libmv_marker.reference_frame = libmv_current_marker.frame;
libmv_reference_marker = libmv_current_marker;
}
/* Perform actual tracking. */
autotrack_result->success = libmv_autoTrackMarker(context->autotrack,
&autotrack_track->track_region_options,
&autotrack_track.track_region_options,
&autotrack_result->libmv_marker,
&autotrack_result->libmv_result);
@ -684,7 +686,7 @@ static void autotrack_context_step_cb(void *__restrict userdata,
* This is how Blender side is currently expecting failed track to be handled. Without this the
* marker is left in an arbitrary position which did not provide good correlation. */
if (!autotrack_result->success) {
autotrack_result->libmv_marker = *libmv_current_marker;
autotrack_result->libmv_marker = libmv_current_marker;
autotrack_result->libmv_marker.frame = new_marker_frame;
}
@ -768,22 +770,21 @@ void BKE_autotrack_context_sync(AutoTrackContext *context)
BLI_spin_unlock(&context->spin_lock);
LISTBASE_FOREACH_MUTABLE (AutoTrackTrackingResult *, autotrack_result, &results_to_sync) {
const libmv_Marker *libmv_marker = &autotrack_result->libmv_marker;
const int clip_index = libmv_marker->clip;
const int track_index = libmv_marker->track;
const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
const MovieClip *clip = autotrack_clip->clip;
const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
MovieTrackingTrack *track = autotrack_track->track;
const libmv_Marker &libmv_marker = autotrack_result->libmv_marker;
const int clip_index = libmv_marker.clip;
const int track_index = libmv_marker.track;
const AutoTrackClip &autotrack_clip = context->autotrack_clips[clip_index];
const MovieClip *clip = autotrack_clip.clip;
const AutoTrackTrack &autotrack_track = context->all_autotrack_tracks[track_index];
MovieTrackingTrack *track = autotrack_track.track;
const int start_clip_frame = BKE_movieclip_remap_scene_to_clip_frame(
clip, context->start_scene_frame);
const int first_result_frame = start_clip_frame + frame_delta;
/* Insert marker which corresponds to the tracking result. */
MovieTrackingMarker marker;
libmv_marker_to_dna_marker(
&autotrack_result->libmv_marker, autotrack_clip->width, autotrack_clip->height, &marker);
MovieTrackingMarker marker = libmv_marker_to_dna_marker(
autotrack_result->libmv_marker, autotrack_clip.width, autotrack_clip.height);
if (!autotrack_result->success) {
marker.flag |= MARKER_DISABLED;
}

View File

@ -205,8 +205,8 @@ eFileAttributes BLI_file_attributes(const char *path);
* Usage of this function is strongly discouraged as it is not thread safe. It will likely cause
* issues if there is an operation on another thread that does not expect the current working
* directory to change. This has been added to support USDZ export, which has a problematic
* "feature" described in this issue https://projects.blender.org/blender/blender/issues/99807. It
* will be removed if it is possible to resolve that issue upstream in the USD library.
* "feature" described in this issue #99807. It will be removed if it is possible to resolve
* that issue upstream in the USD library.
*
* \return true on success, false otherwise.
*/

View File

@ -91,6 +91,11 @@ template<typename T> inline T floor(const T &a)
return std::floor(a);
}
template<typename T> inline T round(const T &a)
{
return std::round(a);
}
/**
* Repeats the saw-tooth pattern even on negative numbers.
* ex: `mod_periodic(-3, 4) = 1`, `mod(-3, 4)= -3`
@ -127,6 +132,20 @@ template<typename T> inline T sqrt(const T &a)
return std::sqrt(a);
}
/* Inverse value.
* If the input is zero the output is NaN. */
template<typename T> inline T rcp(const T &a)
{
return T(1) / a;
}
/* Inverse value.
* If the input is zero the output is zero. */
template<typename T> inline T safe_rcp(const T &a)
{
return a ? T(1) / a : T(0);
}
template<typename T> inline T cos(const T &a)
{
return std::cos(a);

View File

@ -111,7 +111,7 @@ template<typename T, int Size>
{
VecBase<T, Size> result = a;
for (int i = 0; i < Size; i++) {
result[i] = std::clamp(result[i], min[i], max[i]);
result[i] = math::clamp(result[i], min[i], max[i]);
}
return result;
}
@ -121,7 +121,7 @@ template<typename T, int Size>
{
VecBase<T, Size> result = a;
for (int i = 0; i < Size; i++) {
result[i] = std::clamp(result[i], min, max);
result[i] = math::clamp(result[i], min, max);
}
return result;
}
@ -132,7 +132,7 @@ template<typename T, int Size>
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
BLI_assert(b[i] != 0);
result[i] = std::fmod(a[i], b[i]);
result[i] = math::mod(a[i], b[i]);
}
return result;
}
@ -143,7 +143,7 @@ template<typename T, int Size>
BLI_assert(b != 0);
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = std::fmod(a[i], b);
result[i] = math::mod(a[i], b);
}
return result;
}
@ -157,7 +157,7 @@ template<typename T, int Size>
{
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = (b[i] != 0) ? std::fmod(a[i], b[i]) : 0;
result[i] = (b[i] != 0) ? math::mod(a[i], b[i]) : 0;
}
return result;
}
@ -173,7 +173,7 @@ template<typename T, int Size>
}
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = std::fmod(a[i], b);
result[i] = math::mod(a[i], b);
}
return result;
}
@ -187,7 +187,7 @@ template<typename T, int Size>
{
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = std::pow(x[i], y);
result[i] = math::pow(x[i], y);
}
return result;
}
@ -201,7 +201,7 @@ template<typename T, int Size>
{
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = std::pow(x[i], y[i]);
result[i] = math::pow(x[i], y[i]);
}
return result;
}
@ -276,7 +276,7 @@ template<typename T, int Size>
{
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = std::floor(a[i]);
result[i] = math::floor(a[i]);
}
return result;
}
@ -286,7 +286,7 @@ template<typename T, int Size>
{
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = std::round(a[i]);
result[i] = math::round(a[i]);
}
return result;
}
@ -296,7 +296,62 @@ template<typename T, int Size>
{
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = std::ceil(a[i]);
result[i] = math::ceil(a[i]);
}
return result;
}
/**
* Per-element square root.
* Negative elements are evaluated to NaN.
*/
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> sqrt(const VecBase<T, Size> &a)
{
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = math::sqrt(a[i]);
}
return result;
}
/**
* Per-element square root.
* Negative elements are evaluated to zero.
*/
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> safe_sqrt(const VecBase<T, Size> &a)
{
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = a[i] >= T(0) ? math ::sqrt(a[i]) : T(0);
}
return result;
}
/**
* Per-element inverse.
* Zero elements are evaluated to NaN.
*/
template<typename T, int Size> [[nodiscard]] inline VecBase<T, Size> rcp(const VecBase<T, Size> &a)
{
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = math::rcp(a[i]);
}
return result;
}
/**
* Per-element inverse.
* Zero elements are evaluated to zero.
*/
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> safe_rcp(const VecBase<T, Size> &a)
{
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = math::safe_rcp(a[i]);
}
return result;
}
@ -306,7 +361,7 @@ template<typename T, int Size>
{
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = a[i] - std::floor(a[i]);
result[i] = math::fract(a[i]);
}
return result;
}
@ -332,9 +387,9 @@ template<typename T, int Size>
*/
template<typename T, int Size> [[nodiscard]] inline T length_manhattan(const VecBase<T, Size> &a)
{
T result = std::abs(a[0]);
T result = math::abs(a[0]);
for (int i = 1; i < Size; i++) {
result += std::abs(a[i]);
result += math::abs(a[i]);
}
return result;
}
@ -346,7 +401,7 @@ template<typename T, int Size> [[nodiscard]] inline T length_squared(const VecBa
template<typename T, int Size> [[nodiscard]] inline T length(const VecBase<T, Size> &a)
{
return std::sqrt(length_squared(a));
return math::sqrt(length_squared(a));
}
/** Return true if each individual column is unit scaled. Mainly for assert usage. */
@ -356,8 +411,8 @@ template<typename T, int Size> [[nodiscard]] inline bool is_unit_scale(const Vec
* normalized and in the case we don't want NAN to be raising asserts since there
* is nothing to be done in that case. */
const T test_unit = math::length_squared(v);
return (!(std::abs(test_unit - T(1)) >= AssertUnitEpsilon<T>::value) ||
!(std::abs(test_unit) >= AssertUnitEpsilon<T>::value));
return (!(math::abs(test_unit - T(1)) >= AssertUnitEpsilon<T>::value) ||
!(math::abs(test_unit) >= AssertUnitEpsilon<T>::value));
}
template<typename T, int Size>
@ -593,7 +648,7 @@ template<typename T, int Size>
const T epsilon = T(0))
{
for (int i = 0; i < Size; i++) {
if (std::abs(a[i] - b[i]) > epsilon) {
if (math::abs(a[i] - b[i]) > epsilon) {
return false;
}
}

View File

@ -253,7 +253,7 @@ static float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], int
i_prev = i;
}
return (area_best != FLT_MAX) ? atan2f(dvec_best[0], dvec_best[1]) : 0.0f;
return (area_best != FLT_MAX) ? (float)atan2(dvec_best[0], dvec_best[1]) : 0.0f;
}
float BLI_convexhull_aabb_fit_points_2d(const float (*points)[2], int n)

View File

@ -136,4 +136,40 @@ TEST(math_vector, Sign)
EXPECT_FLOAT_EQ(result.z, 0);
}
TEST(math_vector, sqrt)
{
const float3 a(1.0f, 4.0f, 9.0f);
const float3 result = math::sqrt(a);
EXPECT_NEAR(result.x, 1.0f, 1e-6f);
EXPECT_NEAR(result.y, 2.0f, 1e-6f);
EXPECT_NEAR(result.z, 3.0f, 1e-6f);
}
TEST(math_vector, safe_sqrt)
{
const float3 a(1.0f, -4.0f, 9.0f);
const float3 result = math::safe_sqrt(a);
EXPECT_NEAR(result.x, 1.0f, 1e-6f);
EXPECT_NEAR(result.y, 0.0f, 1e-6f);
EXPECT_NEAR(result.z, 3.0f, 1e-6f);
}
TEST(math_vector, rcp)
{
const float3 a(1.0f, 2.0f, 4.0f);
const float3 result = math::rcp(a);
EXPECT_NEAR(result.x, 1.0f, 1e-6f);
EXPECT_NEAR(result.y, 0.5f, 1e-6f);
EXPECT_NEAR(result.z, 0.25f, 1e-6f);
}
TEST(math_vector, safe_rcp)
{
const float3 a(1.0f, 0.0f, 4.0f);
const float3 result = math::safe_rcp(a);
EXPECT_NEAR(result.x, 1.0f, 1e-6f);
EXPECT_NEAR(result.y, 0.0f, 1e-6f);
EXPECT_NEAR(result.z, 0.25f, 1e-6f);
}
} // namespace blender::tests

View File

@ -47,8 +47,8 @@ typedef struct WorkspaceConfigFileData {
typedef enum eBlenFileType {
BLENFILETYPE_BLEND = 1,
/* BLENFILETYPE_PUB = 2, */ /* UNUSED */
/* BLENFILETYPE_RUNTIME = 3, */ /* UNUSED */
// BLENFILETYPE_PUB = 2, /* UNUSED */
// BLENFILETYPE_RUNTIME = 3, /* UNUSED */
} eBlenFileType;
typedef struct BlendFileData {
@ -59,17 +59,24 @@ typedef struct BlendFileData {
int globalf;
char filepath[1024]; /* 1024 = FILE_MAX */
struct bScreen *curscreen; /* TODO: think this isn't needed anymore? */
/** TODO: think this isn't needed anymore? */
struct bScreen *curscreen;
struct Scene *curscene;
struct ViewLayer *cur_view_layer; /* layer to activate in workspaces when reading without UI */
/** Layer to activate in workspaces when reading without UI. */
struct ViewLayer *cur_view_layer;
eBlenFileType type;
} BlendFileData;
/** Data used by WM readfile code and BKE's setup_app_data to handle the complex preservation logic
* of WindowManager and other UI data-blocks across blendfile reading prcess. */
/**
* Data used by WM readfile code and BKE's setup_app_data to handle the complex preservation logic
* of WindowManager and other UI data-blocks across blend-file reading process.
*/
typedef struct BlendFileReadWMSetupData {
struct wmWindowManager *old_wm; /** The existing WM when filereading process is started. */
/** The existing WM when filereading process is started. */
struct wmWindowManager *old_wm;
bool is_read_homefile;
} BlendFileReadWMSetupData;
struct BlendFileReadParams {
@ -81,10 +88,10 @@ struct BlendFileReadParams {
};
typedef struct BlendFileReadReport {
/* General reports handling. */
/** General reports handling. */
struct ReportList *reports;
/* Timing information. */
/** Timing information. */
struct {
double whole;
double libraries;
@ -93,38 +100,44 @@ typedef struct BlendFileReadReport {
double lib_overrides_recursive_resync;
} duration;
/* Count information. */
/** Count information. */
struct {
/* Some numbers of IDs that ended up in a specific state, or required some specific process
* during this file read. */
/**
* Some numbers of IDs that ended up in a specific state, or required some specific process
* during this file read.
*/
int missing_libraries;
int missing_linked_id;
/* Some sub-categories of the above `missing_linked_id` counter. */
/** Some sub-categories of the above `missing_linked_id` counter. */
int missing_obdata;
int missing_obproxies;
/* Number of root override IDs that were resynced. */
/** Number of root override IDs that were resynced. */
int resynced_lib_overrides;
/* Number of proxies converted to library overrides. */
/** Number of proxies converted to library overrides. */
int proxies_to_lib_overrides_success;
/* Number of proxies that failed to convert to library overrides. */
/** Number of proxies that failed to convert to library overrides. */
int proxies_to_lib_overrides_failures;
/* Number of sequencer strips that were not read because were in non-supported channels. */
/** Number of sequencer strips that were not read because were in non-supported channels. */
int sequence_strips_skipped;
} count;
/* Number of libraries which had overrides that needed to be resynced, and a single linked list
* of those. */
/**
* Number of libraries which had overrides that needed to be resynced,
* and a single linked list of those.
*/
int resynced_lib_overrides_libraries_count;
bool do_resynced_lib_overrides_libraries_list;
struct LinkNode *resynced_lib_overrides_libraries;
} BlendFileReadReport;
/* skip reading some data-block types (may want to skip screen data too). */
/** Skip reading some data-block types (may want to skip screen data too). */
typedef enum eBLOReadSkip {
BLO_READ_SKIP_NONE = 0,
/** Skip #BLO_CODE_USER blocks. */
BLO_READ_SKIP_USERDEF = (1 << 0),
/** Only read #BLO_CODE_USER (and associated data). */
BLO_READ_SKIP_DATA = (1 << 1),
/** Do not attempt to re-use IDs from old bmain for unchanged ones in case of undo. */
BLO_READ_SKIP_UNDO_OLD_MAIN = (1 << 2),
@ -133,7 +146,7 @@ ENUM_OPERATORS(eBLOReadSkip, BLO_READ_SKIP_UNDO_OLD_MAIN)
#define BLO_READ_SKIP_ALL (BLO_READ_SKIP_USERDEF | BLO_READ_SKIP_DATA)
/**
* Open a blender file from a pathname. The function returns NULL
* Open a blender file from a `filepath`. The function returns NULL
* and sets a report in the list if it cannot open the file.
*
* \param filepath: The path of the file to open.
@ -189,10 +202,12 @@ typedef struct BLODataBlockInfo {
char name[64]; /* MAX_NAME */
struct AssetMetaData *asset_data;
bool free_asset_data;
/* Optimization: Tag data-blocks for which we know there is no preview.
/**
* Optimization: Tag data-blocks for which we know there is no preview.
* Knowing this can be used to skip the (potentially expensive) preview loading process. If this
* is set to true it means we looked for a preview and couldn't find one. False may mean that
* either no preview was found, or that it wasn't looked for in the first place. */
* either no preview was found, or that it wasn't looked for in the first place.
*/
bool no_preview_found;
} BLODataBlockInfo;
@ -336,9 +351,11 @@ typedef enum eBLOLibLinkFlags {
BLO_LIBLINK_FORCE_INDIRECT = 1 << 17,
/** Set fake user on appended IDs. */
BLO_LIBLINK_APPEND_SET_FAKEUSER = 1 << 19,
/** Append (make local) also indirect dependencies of appended IDs coming from other libraries.
/**
* Append (make local) also indirect dependencies of appended IDs coming from other libraries.
* NOTE: All IDs (including indirectly linked ones) coming from the same initial library are
* always made local. */
* always made local.
*/
BLO_LIBLINK_APPEND_RECURSIVE = 1 << 20,
/** Try to re-use previously appended matching ID on new append. */
BLO_LIBLINK_APPEND_LOCAL_ID_REUSE = 1 << 21,
@ -437,7 +454,7 @@ typedef struct TempLibraryContext {
struct LibraryLink_Params liblink_params;
struct Library *lib;
/* The ID datablock that was loaded. Is NULL if loading failed. */
/** The ID datablock that was loaded. Is NULL if loading failed. */
struct ID *temp_id;
} TempLibraryContext;
@ -485,7 +502,7 @@ void BLO_expand_main(void *fdhandle, struct Main *mainvar);
void BLO_update_defaults_startup_blend(struct Main *bmain, const char *app_template);
void BLO_update_defaults_workspace(struct WorkSpace *workspace, const char *app_template);
/* Disable unwanted experimental feature settings on startup. */
/** Disable unwanted experimental feature settings on startup. */
void BLO_sanitize_experimental_features_userpref_blend(struct UserDef *userdef);
/**
@ -498,8 +515,9 @@ void BLO_sanitize_experimental_features_userpref_blend(struct UserDef *userdef);
*/
struct BlendThumbnail *BLO_thumbnail_from_file(const char *filepath);
/* datafiles (generated theme) */
/** Default theme, see: `release/datafiles/userdef/userdef_default_theme.c`. */
extern const struct bTheme U_theme_default;
/** Default preferences, defined by: `release/datafiles/userdef/userdef_default.c`. */
extern const struct UserDef U_default;
#ifdef __cplusplus

View File

@ -126,7 +126,7 @@
* - read associated 'direct data'
* - link direct data (internal and to LibBlock)
* - read #FileGlobal
* - read #USER data, only when indicated (file is `~/.config/blender/X.XX/config/userpref.blend`)
* - read #USER data, only when indicated (file is `~/.config/blender/X.X/config/userpref.blend`)
* - free file
* - per Library (per #Main)
* - read file

View File

@ -206,7 +206,7 @@ bool BLO_memfile_write_file(MemFile *memfile, const char *filepath)
MemFileChunk *chunk;
int file, oflags;
/* NOTE: This is currently used for autosave and 'quit.blend',
/* NOTE: This is currently used for auto-save and `quit.blend`,
* where _not_ following symlinks is OK,
* however if this is ever executed explicitly by the user,
* we may want to allow writing to symlinks.

View File

@ -2184,46 +2184,6 @@ static void versioning_replace_legacy_mix_rgb_node(bNodeTree *ntree)
}
}
static void versioning_replace_legacy_glossy_node(bNodeTree *ntree)
{
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->type == SH_NODE_BSDF_GLOSSY_LEGACY) {
strcpy(node->idname, "ShaderNodeBsdfAnisotropic");
node->type = SH_NODE_BSDF_GLOSSY;
}
}
}
static void versioning_remove_microfacet_sharp_distribution(bNodeTree *ntree)
{
/* Find all glossy, glass and refraction BSDF nodes that have their distribution
* set to SHARP and set them to GGX, disconnect any link to the Roughness input
* and set its value to zero. */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (!ELEM(node->type, SH_NODE_BSDF_GLOSSY, SH_NODE_BSDF_GLASS, SH_NODE_BSDF_REFRACTION)) {
continue;
}
if (node->custom1 != SHD_GLOSSY_SHARP_DEPRECATED) {
continue;
}
node->custom1 = SHD_GLOSSY_GGX;
LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
if (!STREQ(socket->identifier, "Roughness")) {
continue;
}
if (socket->link != nullptr) {
nodeRemLink(ntree, socket->link);
}
bNodeSocketValueFloat *socket_value = (bNodeSocketValueFloat *)socket->default_value;
socket_value->value = 0.0f;
break;
}
}
}
static void version_fix_image_format_copy(Main *bmain, ImageFormatData *format)
{
/* Fix bug where curves in image format were not properly copied to file output
@ -4461,26 +4421,8 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
/**
* Versioning code until next subversion bump goes here.
*
* \note Be sure to check when bumping the version:
* - "versioning_userdef.c", #blo_do_versions_userdef
* - "versioning_userdef.c", #do_versions_theme
*
* \note Keep this message at the bottom of the function.
*/
{
/* Keep this block, even when empty. */
/* Convert anisotropic BSDF node to glossy BSDF. */
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
versioning_replace_legacy_glossy_node(ntree);
versioning_remove_microfacet_sharp_distribution(ntree);
}
FOREACH_NODETREE_END;
BKE_animdata_main_cb(bmain, version_liboverride_nla_frame_start_end, nullptr);
if (!MAIN_VERSION_ATLEAST(bmain, 306, 11)) {
BKE_animdata_main_cb(bmain, version_liboverride_nla_frame_start_end, NULL);
/* Store simulation bake directory in geometry nodes modifier. */
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
@ -4519,4 +4461,18 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
}
/**
* Versioning code until next subversion bump goes here.
*
* \note Be sure to check when bumping the version:
* - #do_versions_after_linking_300 in this file.
* - "versioning_userdef.c", #blo_do_versions_userdef
* - "versioning_userdef.c", #do_versions_theme
*
* \note Keep this message at the bottom of the function.
*/
{
/* Keep this block, even when empty. */
}
}

View File

@ -29,9 +29,23 @@
// static CLG_LogRef LOG = {"blo.readfile.doversion"};
void do_versions_after_linking_400(FileData * /*fd*/, Main *bmain)
void do_versions_after_linking_400(FileData * /*fd*/, Main * /*bmain*/)
{
UNUSED_VARS(bmain);
/**
* Versioning code until next subversion bump goes here.
*
* \note Be sure to check when bumping the version:
* - #blo_do_versions_400 in this file.
* - "versioning_cycles.cc", #blo_do_versions_cycles
* - "versioning_cycles.cc", #do_versions_after_linking_cycles
* - "versioning_userdef.c", #blo_do_versions_userdef
* - "versioning_userdef.c", #do_versions_theme
*
* \note Keep this message at the bottom of the function.
*/
{
/* Keep this block, even when empty. */
}
}
static void version_mesh_legacy_to_struct_of_array_format(Mesh &mesh)
@ -101,6 +115,46 @@ static void version_geometry_nodes_add_realize_instance_nodes(bNodeTree *ntree)
}
}
static void versioning_replace_legacy_glossy_node(bNodeTree *ntree)
{
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->type == SH_NODE_BSDF_GLOSSY_LEGACY) {
strcpy(node->idname, "ShaderNodeBsdfAnisotropic");
node->type = SH_NODE_BSDF_GLOSSY;
}
}
}
static void versioning_remove_microfacet_sharp_distribution(bNodeTree *ntree)
{
/* Find all glossy, glass and refraction BSDF nodes that have their distribution
* set to SHARP and set them to GGX, disconnect any link to the Roughness input
* and set its value to zero. */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (!ELEM(node->type, SH_NODE_BSDF_GLOSSY, SH_NODE_BSDF_GLASS, SH_NODE_BSDF_REFRACTION)) {
continue;
}
if (node->custom1 != SHD_GLOSSY_SHARP_DEPRECATED) {
continue;
}
node->custom1 = SHD_GLOSSY_GGX;
LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
if (!STREQ(socket->identifier, "Roughness")) {
continue;
}
if (socket->link != nullptr) {
nodeRemLink(ntree, socket->link);
}
bNodeSocketValueFloat *socket_value = (bNodeSocketValueFloat *)socket->default_value;
socket_value->value = 0.0f;
break;
}
}
}
void blo_do_versions_400(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
{
if (!MAIN_VERSION_ATLEAST(bmain, 400, 1)) {
@ -124,16 +178,38 @@ void blo_do_versions_400(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
}
}
/* 400 4 did not require any do_version here. */
if (!MAIN_VERSION_ATLEAST(bmain, 400, 5)) {
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
#define SCE_SNAP_PROJECT (1 << 3)
if (scene->toolsettings->snap_flag & SCE_SNAP_PROJECT) {
scene->toolsettings->snap_mode |= SCE_SNAP_MODE_FACE_RAYCAST;
}
#undef SCE_SNAP_PROJECT
}
}
/**
* Versioning code until next subversion bump goes here.
*
* \note Be sure to check when bumping the version:
* - #do_versions_after_linking_400 in this file.
* - "versioning_cycles.cc", #blo_do_versions_cycles
* - "versioning_cycles.cc", #do_versions_after_linking_cycles
* - "versioning_userdef.c", #blo_do_versions_userdef
* - "versioning_userdef.c", #do_versions_theme
*
* \note Keep this message at the bottom of the function.
*/
{
/* Convert anisotropic BSDF node to glossy BSDF. */
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
versioning_replace_legacy_glossy_node(ntree);
versioning_remove_microfacet_sharp_distribution(ntree);
}
FOREACH_NODETREE_END;
/* Keep this block, even when empty. */
}
}

View File

@ -50,10 +50,12 @@
* - write library block
* - per LibBlock
* - write the ID of LibBlock
* - write #TEST (#RenderInfo struct. 128x128 blend file preview is optional).
* - write #GLOB (#FileGlobal struct) (some global vars).
* - write #DNA1 (#SDNA struct)
* - write #USER (#UserDef struct) if filename is `~/.config/blender/X.XX/config/startup.blend`.
* - write #BLO_CODE_GLOB (#RenderInfo struct. 128x128 blend file preview is optional).
* - write #BLO_CODE_GLOB (#FileGlobal struct) (some global vars).
* - write #BLO_CODE_DNA1 (#SDNA struct)
* - write #BLO_CODE_USER (#UserDef struct) for file paths:
- #BLENDER_STARTUP_FILE (on UNIX `~/.config/blender/X.X/config/startup.blend`).
- #BLENDER_USERPREF_FILE (on UNIX `~/.config/blender/X.X/config/userpref.blend`).
*/
#include <cerrno>
@ -971,10 +973,10 @@ static void write_libraries(WriteData *wd, Main *main)
}
}
/* To be able to restore 'quit.blend' and temp saves,
/* To be able to restore `quit.blend` and temp saves,
* the packed blend has to be in undo buffers... */
/* XXX needs rethink, just like save UI in undo files now -
* would be nice to append things only for the 'quit.blend' and temp saves. */
* would be nice to append things only for the `quit.blend` and temp saves. */
if (found_one) {
/* Not overridable. */

View File

@ -66,8 +66,7 @@ const char *BLT_pgettext(const char *msgctxt, const char *msgid)
bool BLT_translate(void)
{
#ifdef WITH_INTERNATIONAL
return true;
/* return BLI_thread_is_main(); */
return BLI_thread_is_main();
#else
return false;
#endif

View File

@ -322,6 +322,8 @@ if(WITH_COMPOSITOR_CPU)
nodes/COM_FilterNode.h
nodes/COM_InpaintNode.cc
nodes/COM_InpaintNode.h
nodes/COM_KuwaharaNode.h
nodes/COM_KuwaharaNode.cc
nodes/COM_PosterizeNode.cc
nodes/COM_PosterizeNode.h
@ -349,6 +351,10 @@ if(WITH_COMPOSITOR_CPU)
operations/COM_GaussianXBlurOperation.h
operations/COM_GaussianYBlurOperation.cc
operations/COM_GaussianYBlurOperation.h
operations/COM_KuwaharaClassicOperation.h
operations/COM_KuwaharaClassicOperation.cc
operations/COM_KuwaharaAnisotropicOperation.h
operations/COM_KuwaharaAnisotropicOperation.cc
operations/COM_MovieClipAttributeOperation.cc
operations/COM_MovieClipAttributeOperation.h
operations/COM_MovieDistortionOperation.cc

View File

@ -11,6 +11,8 @@
extern "C" {
#endif
struct Render;
/* Keep ascii art. */
/* clang-format off */
@ -294,6 +296,9 @@ extern "C" {
* It can be executed during editing (blenkernel/node.cc) or rendering
* (renderer/pipeline.c)
*
* \param render: [struct Render]
* Render instance for GPU context.
*
* \param render_data: [struct RenderData]
* Render data for this composite, this won't always belong to a scene.
*
@ -305,10 +310,10 @@ extern "C" {
* (true) or editing (false).
* based on this setting the system will work differently:
* - during rendering only Composite & the File output node will be calculated
* \see NodeOperation.is_output_program(int rendering) of the specific operations
* \see NodeOperation.is_output_program(bool rendering) of the specific operations
*
* - during editing all output nodes will be calculated
* \see NodeOperation.is_output_program(int rendering) of the specific operations
* \see NodeOperation.is_output_program(bool rendering) of the specific operations
*
* - another quality setting can be used bNodeTree.
* The quality is determined by the bNodeTree fields.
@ -326,10 +331,11 @@ extern "C" {
*/
/* clang-format off */
void COM_execute(RenderData *render_data,
void COM_execute(Render *render,
RenderData *render_data,
Scene *scene,
bNodeTree *node_tree,
int rendering,
bool rendering,
const char *view_name);
/**

View File

@ -62,6 +62,7 @@
#include "COM_InvertNode.h"
#include "COM_KeyingNode.h"
#include "COM_KeyingScreenNode.h"
#include "COM_KuwaharaNode.h"
#include "COM_LensDistortionNode.h"
#include "COM_LuminanceMatteNode.h"
#include "COM_MapRangeNode.h"
@ -436,6 +437,9 @@ Node *COM_convert_bnode(bNode *b_node)
case CMP_NODE_COMBINE_XYZ:
node = new CombineXYZNode(b_node);
break;
case CMP_NODE_KUWAHARA:
node = new KuwaharaNode(b_node);
break;
}
return node;
}

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