UI: Asset Shelf (Experimental Feature) #104831
|
@ -8,7 +8,7 @@
|
|||
# It also supports non-standard names for the library components.
|
||||
#
|
||||
# To use a custom IlmBase:
|
||||
# - Set the variable ILMBASE_CUSTOM to True
|
||||
# - Set the variable ILMBASE_CUSTOM to TRUE
|
||||
# - Set the variable ILMBASE_CUSTOM_LIBRARIES to a list of the libraries to
|
||||
# use, e.g. "SpiImath SpiHalf SpiIlmThread SpiIex"
|
||||
# - Optionally set the variable ILMBASE_CUSTOM_INCLUDE_DIR to any
|
||||
|
@ -20,7 +20,7 @@
|
|||
#
|
||||
# ILMBASE_INCLUDE_DIR - where to find half.h, IlmBaseConfig.h, etc.
|
||||
# ILMBASE_LIBRARIES - list of libraries to link against when using IlmBase.
|
||||
# ILMBASE_FOUND - True if IlmBase was found.
|
||||
# ILMBASE_FOUND - TRUE if IlmBase was found.
|
||||
|
||||
# Other standard issue macros
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
# It also supports non-standard names for the library components.
|
||||
#
|
||||
# To use a custom OpenEXR
|
||||
# - Set the variable OPENEXR_CUSTOM to True
|
||||
# - Set the variable OPENEXR_CUSTOM to TRUE
|
||||
# - Set the variable OPENEXR_CUSTOM_LIBRARY to the name of the library to
|
||||
# use, e.g. "SpiIlmImf"
|
||||
# - Optionally set the variable OPENEXR_CUSTOM_INCLUDE_DIR to any
|
||||
|
@ -22,7 +22,7 @@
|
|||
# OPENEXR_LIBRARIES - list of libraries to link against when using OpenEXR.
|
||||
# This list does NOT include the IlmBase libraries.
|
||||
# These are defined by the FindIlmBase module.
|
||||
# OPENEXR_FOUND - True if OpenEXR was found.
|
||||
# OPENEXR_FOUND - TRUE if OpenEXR was found.
|
||||
|
||||
# Other standard issue macros
|
||||
include(SelectLibraryConfigurations)
|
||||
|
|
|
@ -20,14 +20,14 @@ else()
|
|||
# Choose the best suitable libraries.
|
||||
if(EXISTS ${LIBDIR_NATIVE_ABI})
|
||||
set(LIBDIR ${LIBDIR_NATIVE_ABI})
|
||||
set(WITH_LIBC_MALLOC_HOOK_WORKAROUND True)
|
||||
set(WITH_LIBC_MALLOC_HOOK_WORKAROUND TRUE)
|
||||
elseif(EXISTS ${LIBDIR_GLIBC228_ABI})
|
||||
set(LIBDIR ${LIBDIR_GLIBC228_ABI})
|
||||
if(WITH_MEM_JEMALLOC)
|
||||
# jemalloc provides malloc hooks.
|
||||
set(WITH_LIBC_MALLOC_HOOK_WORKAROUND False)
|
||||
set(WITH_LIBC_MALLOC_HOOK_WORKAROUND FALSE)
|
||||
else()
|
||||
set(WITH_LIBC_MALLOC_HOOK_WORKAROUND True)
|
||||
set(WITH_LIBC_MALLOC_HOOK_WORKAROUND TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
|
|
@ -1034,7 +1034,7 @@ endif()
|
|||
|
||||
if(WITH_VULKAN_BACKEND)
|
||||
if(EXISTS ${LIBDIR}/vulkan)
|
||||
set(VULKAN_FOUND On)
|
||||
set(VULKAN_FOUND ON)
|
||||
set(VULKAN_ROOT_DIR ${LIBDIR}/vulkan)
|
||||
set(VULKAN_INCLUDE_DIR ${VULKAN_ROOT_DIR}/include)
|
||||
set(VULKAN_INCLUDE_DIRS ${VULKAN_INCLUDE_DIR})
|
||||
|
@ -1048,7 +1048,7 @@ endif()
|
|||
|
||||
if(WITH_VULKAN_BACKEND)
|
||||
if(EXISTS ${LIBDIR}/shaderc)
|
||||
set(SHADERC_FOUND On)
|
||||
set(SHADERC_FOUND ON)
|
||||
set(SHADERC_ROOT_DIR ${LIBDIR}/shaderc)
|
||||
set(SHADERC_INCLUDE_DIR ${SHADERC_ROOT_DIR}/include)
|
||||
set(SHADERC_INCLUDE_DIRS ${SHADERC_INCLUDE_DIR})
|
||||
|
|
|
@ -8,3 +8,5 @@ Local modifications:
|
|||
* Added special definitions of HAVE_SNPRINTF and HAVE_LIB_GFLAGS
|
||||
in Windows' specific config.h.
|
||||
* Silenced syscall deprecation warnings on macOS >= 10.12.
|
||||
* Usage of syscall() is not allowed and use getthrid() to
|
||||
retreive the thread ID on OpenBSD
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include "config_mac.h"
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
#include "config_freebsd.h"
|
||||
#elif defined(__OpenBSD__)
|
||||
#include "config_openbsd.h"
|
||||
#elif defined(__MINGW32__)
|
||||
#include "windows/config.h"
|
||||
#elif defined(__linux__)
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
/* define if glog doesn't use RTTI */
|
||||
/* #undef DISABLE_RTTI */
|
||||
|
||||
/* Namespace for Google classes */
|
||||
#define GOOGLE_NAMESPACE google
|
||||
|
||||
/* Define if you have the `dladdr' function */
|
||||
/* #undef HAVE_DLADDR */
|
||||
|
||||
/* Define if you have the `snprintf' function */
|
||||
#define HAVE_SNPRINTF
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the <execinfo.h> header file. */
|
||||
/* #undef HAVE_EXECINFO_H */
|
||||
|
||||
/* Define if you have the `fcntl' function */
|
||||
#define HAVE_FCNTL
|
||||
|
||||
/* Define to 1 if you have the <glob.h> header file. */
|
||||
#define HAVE_GLOB_H
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the `pthread' library (-lpthread). */
|
||||
#define HAVE_LIBPTHREAD
|
||||
|
||||
/* Define to 1 if you have the <libunwind.h> header file. */
|
||||
/* #undef HAVE_LIBUNWIND_H */
|
||||
|
||||
/* define if you have google gflags library */
|
||||
#define HAVE_LIB_GFLAGS
|
||||
|
||||
/* define if you have google gmock library */
|
||||
/* #undef HAVE_LIB_GMOCK */
|
||||
|
||||
/* define if you have google gtest library */
|
||||
/* #undef HAVE_LIB_GTEST */
|
||||
|
||||
/* define if you have libunwind */
|
||||
/* #undef HAVE_LIB_UNWIND */
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H
|
||||
|
||||
/* define to disable multithreading support. */
|
||||
/* #undef NO_THREADS */
|
||||
|
||||
/* define if the compiler implements namespaces */
|
||||
#define HAVE_NAMESPACES
|
||||
|
||||
/* Define if you have the 'pread' function */
|
||||
#define HAVE_PREAD
|
||||
|
||||
/* Define if you have POSIX threads libraries and header files. */
|
||||
#define HAVE_PTHREAD
|
||||
|
||||
/* Define to 1 if you have the <pwd.h> header file. */
|
||||
#define HAVE_PWD_H
|
||||
|
||||
/* Define if you have the 'pwrite' function */
|
||||
#define HAVE_PWRITE
|
||||
|
||||
/* define if the compiler implements pthread_rwlock_* */
|
||||
#define HAVE_RWLOCK 1
|
||||
|
||||
/* Define if you have the 'sigaction' function */
|
||||
#define HAVE_SIGACTION
|
||||
|
||||
/* Define if you have the `sigaltstack' function */
|
||||
#define HAVE_SIGALTSTACK 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <syscall.h> header file. */
|
||||
/* #undef HAVE_SYSCALL_H */
|
||||
|
||||
/* Define to 1 if you have the <syslog.h> header file. */
|
||||
#define HAVE_SYSLOG_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/syscall.h> header file. */
|
||||
#define HAVE_SYS_SYSCALL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#define HAVE_SYS_TIME_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/ucontext.h> header file. */
|
||||
/* #undef HAVE_SYS_UCONTEXT_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/utsname.h> header file. */
|
||||
#define HAVE_SYS_UTSNAME_H
|
||||
|
||||
/* Define to 1 if you have the <ucontext.h> header file. */
|
||||
/* #undef HAVE_UCONTEXT_H */
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the <unwind.h> header file. */
|
||||
#define HAVE_UNWIND_H 1
|
||||
|
||||
/* define if the compiler supports using expression for operator */
|
||||
#define HAVE_USING_OPERATOR
|
||||
|
||||
/* define if your compiler has __attribute__ */
|
||||
#define HAVE___ATTRIBUTE__
|
||||
|
||||
/* define if your compiler has __builtin_expect */
|
||||
#define HAVE___BUILTIN_EXPECT 1
|
||||
|
||||
/* define if your compiler has __sync_val_compare_and_swap */
|
||||
#define HAVE___SYNC_VAL_COMPARE_AND_SWAP
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
/* #undef LT_OBJDIR */
|
||||
|
||||
/* Name of package */
|
||||
/* #undef PACKAGE */
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
/* #undef PACKAGE_BUGREPORT */
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
/* #undef PACKAGE_NAME */
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
/* #undef PACKAGE_STRING */
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
/* #undef PACKAGE_TARNAME */
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
/* #undef PACKAGE_URL */
|
||||
|
||||
/* Define to the version of this package. */
|
||||
/* #undef PACKAGE_VERSION */
|
||||
|
||||
/* How to access the PC from a struct ucontext */
|
||||
/* #undef PC_FROM_UCONTEXT */
|
||||
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||
your system. */
|
||||
/* #undef PTHREAD_CREATE_JOINABLE */
|
||||
|
||||
/* The size of `void *', as computed by sizeof. */
|
||||
#define SIZEOF_VOID_P 8
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* the namespace where STL code like vector<> is defined */
|
||||
#define STL_NAMESPACE std
|
||||
|
||||
/* location of source code */
|
||||
#define TEST_SRC_DIR "."
|
||||
|
||||
/* Version number of package */
|
||||
/* #undef VERSION */
|
||||
|
||||
/* Stops putting the code inside the Google namespace */
|
||||
#define _END_GOOGLE_NAMESPACE_ }
|
||||
|
||||
/* Puts following code inside the Google namespace */
|
||||
#define _START_GOOGLE_NAMESPACE_ namespace google {
|
||||
|
||||
#define GOOGLE_GLOG_DLL_DECL
|
||||
|
||||
/* isn't getting defined by configure script when clang compilers are used
|
||||
and cuases compilation errors in stactrace/unwind modules */
|
||||
#ifdef __clang__
|
||||
# define NO_FRAME_POINTER
|
||||
#endif
|
|
@ -59,7 +59,8 @@
|
|||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if (defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)) && (!(defined OS_MACOSX))
|
||||
#if (defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)) && \
|
||||
(!(defined OS_MACOSX) && !(defined OS_OPENBSD))
|
||||
# define safe_write(fd, s, len) syscall(SYS_write, fd, s, len)
|
||||
#else
|
||||
// Not so safe, but what can you do?
|
||||
|
|
|
@ -282,6 +282,8 @@ pid_t GetTID() {
|
|||
return getpid(); // Linux: getpid returns thread ID when gettid is absent
|
||||
#elif defined OS_WINDOWS && !defined OS_CYGWIN
|
||||
return GetCurrentThreadId();
|
||||
#elif defined OS_OPENBSD
|
||||
return getthrid();
|
||||
#else
|
||||
// If none of the techniques above worked, we use pthread_self().
|
||||
return (pid_t)(uintptr_t)pthread_self();
|
||||
|
|
|
@ -67,7 +67,7 @@ if(UNIX AND NOT APPLE)
|
|||
add_subdirectory(libc_compat)
|
||||
endif()
|
||||
|
||||
if (WITH_RENDERDOC)
|
||||
if(WITH_RENDERDOC)
|
||||
add_subdirectory(renderdoc_dynload)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -262,6 +262,11 @@ string OneapiDevice::oneapi_error_message()
|
|||
return string(oneapi_error_string_);
|
||||
}
|
||||
|
||||
int OneapiDevice::scene_max_shaders()
|
||||
{
|
||||
return scene_max_shaders_;
|
||||
}
|
||||
|
||||
void *OneapiDevice::kernel_globals_device_pointer()
|
||||
{
|
||||
return kg_memory_device_;
|
||||
|
@ -436,6 +441,9 @@ void OneapiDevice::const_copy_to(const char *name, void *host, size_t size)
|
|||
/* Update scene handle(since it is different for each device on multi devices) */
|
||||
KernelData *const data = (KernelData *)host;
|
||||
data->device_bvh = embree_scene;
|
||||
|
||||
/* We need this number later for proper local memory allocation. */
|
||||
scene_max_shaders_ = data->max_shaders;
|
||||
}
|
||||
# endif
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ class OneapiDevice : public Device {
|
|||
std::string oneapi_error_string_;
|
||||
bool use_hardware_raytracing = false;
|
||||
unsigned int kernel_features = 0;
|
||||
int scene_max_shaders_ = 0;
|
||||
|
||||
public:
|
||||
virtual BVHLayoutMask get_bvh_layout_mask(uint kernel_features) const override;
|
||||
|
@ -61,6 +62,8 @@ class OneapiDevice : public Device {
|
|||
|
||||
string oneapi_error_message();
|
||||
|
||||
int scene_max_shaders();
|
||||
|
||||
void *kernel_globals_device_pointer();
|
||||
|
||||
void mem_alloc(device_memory &mem) override;
|
||||
|
|
|
@ -59,7 +59,7 @@ void OneapiDeviceQueue::init_execution()
|
|||
void *kg_dptr = (void *)oneapi_device_->kernel_globals_device_pointer();
|
||||
assert(device_queue);
|
||||
assert(kg_dptr);
|
||||
kernel_context_ = new KernelContext{device_queue, kg_dptr};
|
||||
kernel_context_ = new KernelContext{device_queue, kg_dptr, 0};
|
||||
|
||||
debug_init_execution();
|
||||
}
|
||||
|
@ -78,12 +78,13 @@ bool OneapiDeviceQueue::enqueue(DeviceKernel kernel,
|
|||
assert(signed_kernel_work_size >= 0);
|
||||
size_t kernel_work_size = (size_t)signed_kernel_work_size;
|
||||
|
||||
assert(kernel_context_);
|
||||
kernel_context_->scene_max_shaders = oneapi_device_->scene_max_shaders();
|
||||
|
||||
size_t kernel_local_size = oneapi_kernel_preferred_local_size(
|
||||
kernel_context_->queue, (::DeviceKernel)kernel, kernel_work_size);
|
||||
size_t uniformed_kernel_work_size = round_up(kernel_work_size, kernel_local_size);
|
||||
|
||||
assert(kernel_context_);
|
||||
|
||||
/* Call the oneAPI kernel DLL to launch the requested kernel. */
|
||||
bool is_finished_ok = oneapi_device_->enqueue_kernel(
|
||||
kernel_context_, kernel, uniformed_kernel_work_size, args);
|
||||
|
|
|
@ -39,6 +39,11 @@ class OneapiDeviceQueue : public DeviceQueue {
|
|||
virtual void copy_to_device(device_memory &mem) override;
|
||||
virtual void copy_from_device(device_memory &mem) override;
|
||||
|
||||
virtual bool supports_local_atomic_sort() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
OneapiDevice *oneapi_device_;
|
||||
KernelContext *kernel_context_;
|
||||
|
|
|
@ -385,11 +385,17 @@ void PathTraceWorkGPU::enqueue_reset()
|
|||
|
||||
queue_->enqueue(DEVICE_KERNEL_INTEGRATOR_RESET, max_num_paths_, args);
|
||||
queue_->zero_to_device(integrator_queue_counter_);
|
||||
queue_->zero_to_device(integrator_shader_sort_counter_);
|
||||
if (device_scene_->data.kernel_features & KERNEL_FEATURE_NODE_RAYTRACE) {
|
||||
if (integrator_shader_sort_counter_.size() != 0) {
|
||||
queue_->zero_to_device(integrator_shader_sort_counter_);
|
||||
}
|
||||
if (device_scene_->data.kernel_features & KERNEL_FEATURE_NODE_RAYTRACE &&
|
||||
integrator_shader_raytrace_sort_counter_.size() != 0)
|
||||
{
|
||||
queue_->zero_to_device(integrator_shader_raytrace_sort_counter_);
|
||||
}
|
||||
if (device_scene_->data.kernel_features & KERNEL_FEATURE_MNEE) {
|
||||
if (device_scene_->data.kernel_features & KERNEL_FEATURE_MNEE &&
|
||||
integrator_shader_mnee_sort_counter_.size() != 0)
|
||||
{
|
||||
queue_->zero_to_device(integrator_shader_mnee_sort_counter_);
|
||||
}
|
||||
|
||||
|
|
|
@ -847,6 +847,7 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
|
|||
-DWITH_ONEAPI
|
||||
-ffast-math
|
||||
-O2
|
||||
-D__KERNEL_LOCAL_ATOMIC_SORT__
|
||||
-o"${cycles_kernel_oneapi_lib}"
|
||||
-I"${CMAKE_CURRENT_SOURCE_DIR}/.."
|
||||
${SYCL_CPP_FLAGS}
|
||||
|
|
|
@ -432,6 +432,17 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
|
|||
}
|
||||
ccl_gpu_kernel_postfix
|
||||
|
||||
/* oneAPI verion needs the local_mem accessor in the arguments. */
|
||||
#ifdef __KERNEL_ONEAPI__
|
||||
ccl_gpu_kernel_threads(GPU_PARALLEL_SORT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_signature(integrator_sort_bucket_pass,
|
||||
int num_states,
|
||||
int partition_size,
|
||||
int num_states_limit,
|
||||
ccl_global int *indices,
|
||||
int kernel_index,
|
||||
sycl::local_accessor<int> &local_mem)
|
||||
#else
|
||||
ccl_gpu_kernel_threads(GPU_PARALLEL_SORT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_signature(integrator_sort_bucket_pass,
|
||||
int num_states,
|
||||
|
@ -439,9 +450,9 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORT_BLOCK_SIZE)
|
|||
int num_states_limit,
|
||||
ccl_global int *indices,
|
||||
int kernel_index)
|
||||
#endif
|
||||
{
|
||||
#if defined(__KERNEL_LOCAL_ATOMIC_SORT__)
|
||||
int max_shaders = context.launch_params_metal.data.max_shaders;
|
||||
ccl_global ushort *d_queued_kernel = (ccl_global ushort *)
|
||||
kernel_integrator_state.path.queued_kernel;
|
||||
ccl_global uint *d_shader_sort_key = (ccl_global uint *)
|
||||
|
@ -449,6 +460,20 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORT_BLOCK_SIZE)
|
|||
ccl_global int *key_offsets = (ccl_global int *)
|
||||
kernel_integrator_state.sort_partition_key_offsets;
|
||||
|
||||
# ifdef __KERNEL_METAL__
|
||||
int max_shaders = context.launch_params_metal.data.max_shaders;
|
||||
# endif
|
||||
|
||||
# ifdef __KERNEL_ONEAPI__
|
||||
/* Metal backend doesn't have these particular ccl_gpu_* defines and current kernel code
|
||||
* uses metal_*, we need the below to be compatible with these kernels. */
|
||||
int max_shaders = ((ONEAPIKernelContext *)kg)->__data->max_shaders;
|
||||
int metal_local_id = ccl_gpu_thread_idx_x;
|
||||
int metal_local_size = ccl_gpu_block_dim_x;
|
||||
int metal_grid_id = ccl_gpu_block_idx_x;
|
||||
ccl_gpu_shared int *threadgroup_array = local_mem.get_pointer();
|
||||
# endif
|
||||
|
||||
gpu_parallel_sort_bucket_pass(num_states,
|
||||
partition_size,
|
||||
max_shaders,
|
||||
|
@ -456,7 +481,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORT_BLOCK_SIZE)
|
|||
d_queued_kernel,
|
||||
d_shader_sort_key,
|
||||
key_offsets,
|
||||
(threadgroup int *)threadgroup_array,
|
||||
(ccl_gpu_shared int *)threadgroup_array,
|
||||
metal_local_id,
|
||||
metal_local_size,
|
||||
metal_grid_id);
|
||||
|
@ -464,6 +489,17 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORT_BLOCK_SIZE)
|
|||
}
|
||||
ccl_gpu_kernel_postfix
|
||||
|
||||
/* oneAPI verion needs the local_mem accessor in the arguments. */
|
||||
#ifdef __KERNEL_ONEAPI__
|
||||
ccl_gpu_kernel_threads(GPU_PARALLEL_SORT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_signature(integrator_sort_write_pass,
|
||||
int num_states,
|
||||
int partition_size,
|
||||
int num_states_limit,
|
||||
ccl_global int *indices,
|
||||
int kernel_index,
|
||||
sycl::local_accessor<int> &local_mem)
|
||||
#else
|
||||
ccl_gpu_kernel_threads(GPU_PARALLEL_SORT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_signature(integrator_sort_write_pass,
|
||||
int num_states,
|
||||
|
@ -471,9 +507,10 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORT_BLOCK_SIZE)
|
|||
int num_states_limit,
|
||||
ccl_global int *indices,
|
||||
int kernel_index)
|
||||
#endif
|
||||
|
||||
{
|
||||
#if defined(__KERNEL_LOCAL_ATOMIC_SORT__)
|
||||
int max_shaders = context.launch_params_metal.data.max_shaders;
|
||||
ccl_global ushort *d_queued_kernel = (ccl_global ushort *)
|
||||
kernel_integrator_state.path.queued_kernel;
|
||||
ccl_global uint *d_shader_sort_key = (ccl_global uint *)
|
||||
|
@ -481,6 +518,20 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORT_BLOCK_SIZE)
|
|||
ccl_global int *key_offsets = (ccl_global int *)
|
||||
kernel_integrator_state.sort_partition_key_offsets;
|
||||
|
||||
# ifdef __KERNEL_METAL__
|
||||
int max_shaders = context.launch_params_metal.data.max_shaders;
|
||||
# endif
|
||||
|
||||
# ifdef __KERNEL_ONEAPI__
|
||||
/* Metal backend doesn't have these particular ccl_gpu_* defines and current kernel code
|
||||
* uses metal_*, we need the below to be compatible with these kernels. */
|
||||
int max_shaders = ((ONEAPIKernelContext *)kg)->__data->max_shaders;
|
||||
int metal_local_id = ccl_gpu_thread_idx_x;
|
||||
int metal_local_size = ccl_gpu_block_dim_x;
|
||||
int metal_grid_id = ccl_gpu_block_idx_x;
|
||||
ccl_gpu_shared int *threadgroup_array = local_mem.get_pointer();
|
||||
# endif
|
||||
|
||||
gpu_parallel_sort_write_pass(num_states,
|
||||
partition_size,
|
||||
max_shaders,
|
||||
|
@ -490,7 +541,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORT_BLOCK_SIZE)
|
|||
d_queued_kernel,
|
||||
d_shader_sort_key,
|
||||
key_offsets,
|
||||
(threadgroup int *)threadgroup_array,
|
||||
(ccl_gpu_shared int *)threadgroup_array,
|
||||
metal_local_id,
|
||||
metal_local_size,
|
||||
metal_grid_id);
|
||||
|
|
|
@ -23,11 +23,6 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
#if defined(__KERNEL_LOCAL_ATOMIC_SORT__)
|
||||
|
||||
# define atomic_store_local(p, x) \
|
||||
atomic_store_explicit((threadgroup atomic_int *)p, x, memory_order_relaxed)
|
||||
# define atomic_load_local(p) \
|
||||
atomic_load_explicit((threadgroup atomic_int *)p, memory_order_relaxed)
|
||||
|
||||
ccl_device_inline void gpu_parallel_sort_bucket_pass(const uint num_states,
|
||||
const uint partition_size,
|
||||
const uint max_shaders,
|
||||
|
@ -45,7 +40,13 @@ ccl_device_inline void gpu_parallel_sort_bucket_pass(const uint num_states,
|
|||
atomic_store_local(&buckets[local_id], 0);
|
||||
}
|
||||
|
||||
# ifdef __KERNEL_ONEAPI__
|
||||
/* NOTE(@nsirgien): For us here only local memory writing (buckets) is important,
|
||||
* so faster local barriers can be used. */
|
||||
ccl_gpu_local_syncthreads();
|
||||
# else
|
||||
ccl_gpu_syncthreads();
|
||||
# endif
|
||||
|
||||
/* Determine bucket sizes within the partitions. */
|
||||
|
||||
|
@ -58,11 +59,17 @@ ccl_device_inline void gpu_parallel_sort_bucket_pass(const uint num_states,
|
|||
ushort kernel_index = d_queued_kernel[state_index];
|
||||
if (kernel_index == queued_kernel) {
|
||||
uint key = d_shader_sort_key[state_index] % max_shaders;
|
||||
atomic_fetch_and_add_uint32(&buckets[key], 1);
|
||||
atomic_fetch_and_add_uint32_shared(&buckets[key], 1);
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef __KERNEL_ONEAPI__
|
||||
/* NOTE(@nsirgien): For us here only local memory writing (buckets) is important,
|
||||
* so faster local barriers can be used. */
|
||||
ccl_gpu_local_syncthreads();
|
||||
# else
|
||||
ccl_gpu_syncthreads();
|
||||
# endif
|
||||
|
||||
/* Calculate the partition's local offsets from the prefix sum of bucket sizes. */
|
||||
|
||||
|
@ -106,7 +113,13 @@ ccl_device_inline void gpu_parallel_sort_write_pass(const uint num_states,
|
|||
atomic_store_local(&local_offset[local_id], key_offsets[local_id] + partition_offset);
|
||||
}
|
||||
|
||||
# ifdef __KERNEL_ONEAPI__
|
||||
/* NOTE(@nsirgien): For us here only local memory writing (local_offset) is important,
|
||||
* so faster local barriers can be used. */
|
||||
ccl_gpu_local_syncthreads();
|
||||
# else
|
||||
ccl_gpu_syncthreads();
|
||||
# endif
|
||||
|
||||
/* Write the sorted active indices. */
|
||||
|
||||
|
@ -121,7 +134,7 @@ ccl_device_inline void gpu_parallel_sort_write_pass(const uint num_states,
|
|||
ushort kernel_index = d_queued_kernel[state_index];
|
||||
if (kernel_index == queued_kernel) {
|
||||
uint key = d_shader_sort_key[state_index] % max_shaders;
|
||||
int index = atomic_fetch_and_add_uint32(&local_offset[key], 1);
|
||||
int index = atomic_fetch_and_add_uint32_shared(&local_offset[key], 1);
|
||||
if (index < num_states_limit) {
|
||||
indices[index] = state_index;
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#define ccl_loop_no_unroll
|
||||
#define ccl_optional_struct_init
|
||||
#define ccl_private
|
||||
#define ccl_gpu_shared
|
||||
#define ATTR_FALLTHROUGH __attribute__((fallthrough))
|
||||
#define ccl_constant const
|
||||
#define ccl_try_align(...) __attribute__((aligned(__VA_ARGS__)))
|
||||
|
|
|
@ -2,8 +2,40 @@
|
|||
* Copyright 2021-2022 Intel Corporation */
|
||||
|
||||
#ifdef WITH_NANOVDB
|
||||
/* Data type to replace `double` used in the NanoVDB headers. Cycles don't need doubles, and is
|
||||
* safer and more portable to never use double datatype on GPU.
|
||||
* Use a special structure, so that the following is true:
|
||||
* - No unnoticed implicit cast or mathematical operations used on scalar 64bit type
|
||||
* (which rules out trick like using `uint64_t` as a drop-in replacement for double).
|
||||
* - Padding rules are matching exactly `double`
|
||||
* (which rules out array of `uint8_t`). */
|
||||
typedef struct ccl_vdb_double_t {
|
||||
union ccl_vdb_helper_t {
|
||||
double d;
|
||||
uint64_t i;
|
||||
};
|
||||
|
||||
uint64_t i;
|
||||
ccl_vdb_double_t(double value)
|
||||
{
|
||||
ccl_vdb_helper_t helper;
|
||||
helper.d = value;
|
||||
i = helper.i;
|
||||
}
|
||||
/* We intentionally allow conversion to float in order to workaround compilation errors
|
||||
* for defined math functions that take doubles. */
|
||||
operator float() const
|
||||
{
|
||||
ccl_vdb_helper_t helper;
|
||||
helper.i = i;
|
||||
return (float)helper.d;
|
||||
}
|
||||
} ccl_vdb_double_t;
|
||||
|
||||
# define double ccl_vdb_double_t
|
||||
# include <nanovdb/NanoVDB.h>
|
||||
# include <nanovdb/util/SampleFromVoxels.h>
|
||||
# undef double
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
|
|
|
@ -109,7 +109,10 @@ size_t oneapi_kernel_preferred_local_size(SyclQueue *queue,
|
|||
assert(queue);
|
||||
(void)kernel_global_size;
|
||||
const static size_t preferred_work_group_size_intersect_shading = 32;
|
||||
const static size_t preferred_work_group_size_technical = 1024;
|
||||
/* Shader evalutation kernels seems to use some amount of shared memory, so better
|
||||
* to avoid usage of maximum work group sizes for them. */
|
||||
const static size_t preferred_work_group_size_shader_evaluation = 256;
|
||||
const static size_t preferred_work_group_size_default = 1024;
|
||||
|
||||
size_t preferred_work_group_size = 0;
|
||||
switch (kernel) {
|
||||
|
@ -133,19 +136,36 @@ size_t oneapi_kernel_preferred_local_size(SyclQueue *queue,
|
|||
case DEVICE_KERNEL_INTEGRATOR_QUEUED_SHADOW_PATHS_ARRAY:
|
||||
case DEVICE_KERNEL_INTEGRATOR_ACTIVE_PATHS_ARRAY:
|
||||
case DEVICE_KERNEL_INTEGRATOR_TERMINATED_PATHS_ARRAY:
|
||||
case DEVICE_KERNEL_INTEGRATOR_SORTED_PATHS_ARRAY:
|
||||
case DEVICE_KERNEL_INTEGRATOR_COMPACT_PATHS_ARRAY:
|
||||
case DEVICE_KERNEL_INTEGRATOR_COMPACT_STATES:
|
||||
case DEVICE_KERNEL_INTEGRATOR_TERMINATED_SHADOW_PATHS_ARRAY:
|
||||
case DEVICE_KERNEL_INTEGRATOR_COMPACT_PATHS_ARRAY:
|
||||
case DEVICE_KERNEL_INTEGRATOR_COMPACT_SHADOW_PATHS_ARRAY:
|
||||
preferred_work_group_size = GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE;
|
||||
break;
|
||||
|
||||
case DEVICE_KERNEL_INTEGRATOR_SORTED_PATHS_ARRAY:
|
||||
case DEVICE_KERNEL_INTEGRATOR_COMPACT_STATES:
|
||||
case DEVICE_KERNEL_INTEGRATOR_COMPACT_SHADOW_STATES:
|
||||
case DEVICE_KERNEL_INTEGRATOR_RESET:
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADOW_CATCHER_COUNT_POSSIBLE_SPLITS:
|
||||
preferred_work_group_size = preferred_work_group_size_technical;
|
||||
preferred_work_group_size = GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE;
|
||||
break;
|
||||
|
||||
case DEVICE_KERNEL_INTEGRATOR_SORT_BUCKET_PASS:
|
||||
case DEVICE_KERNEL_INTEGRATOR_SORT_WRITE_PASS:
|
||||
preferred_work_group_size = GPU_PARALLEL_SORT_BLOCK_SIZE;
|
||||
break;
|
||||
|
||||
case DEVICE_KERNEL_PREFIX_SUM:
|
||||
preferred_work_group_size = GPU_PARALLEL_PREFIX_SUM_DEFAULT_BLOCK_SIZE;
|
||||
break;
|
||||
|
||||
case DEVICE_KERNEL_SHADER_EVAL_DISPLACE:
|
||||
case DEVICE_KERNEL_SHADER_EVAL_BACKGROUND:
|
||||
case DEVICE_KERNEL_SHADER_EVAL_CURVE_SHADOW_TRANSPARENCY:
|
||||
preferred_work_group_size = preferred_work_group_size_shader_evaluation;
|
||||
break;
|
||||
|
||||
default:
|
||||
preferred_work_group_size = 512;
|
||||
preferred_work_group_size = preferred_work_group_size_default;
|
||||
break;
|
||||
}
|
||||
|
||||
const size_t limit_work_group_size = reinterpret_cast<sycl::queue *>(queue)
|
||||
|
@ -316,12 +336,6 @@ bool oneapi_enqueue_kernel(KernelContext *kernel_context,
|
|||
kernel_context->queue, device_kernel, global_size);
|
||||
assert(global_size % local_size == 0);
|
||||
|
||||
/* Local size for DEVICE_KERNEL_INTEGRATOR_ACTIVE_PATHS_ARRAY needs to be enforced so we
|
||||
* overwrite it outside of oneapi_kernel_preferred_local_size. */
|
||||
if (device_kernel == DEVICE_KERNEL_INTEGRATOR_ACTIVE_PATHS_ARRAY) {
|
||||
local_size = GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/* Kernels listed below need a specific number of work groups. */
|
||||
if (device_kernel == DEVICE_KERNEL_INTEGRATOR_ACTIVE_PATHS_ARRAY ||
|
||||
device_kernel == DEVICE_KERNEL_INTEGRATOR_QUEUED_PATHS_ARRAY ||
|
||||
|
@ -353,6 +367,14 @@ bool oneapi_enqueue_kernel(KernelContext *kernel_context,
|
|||
# pragma GCC diagnostic error "-Wswitch"
|
||||
# endif
|
||||
|
||||
int max_shaders = 0;
|
||||
|
||||
if (device_kernel == DEVICE_KERNEL_INTEGRATOR_SORT_BUCKET_PASS ||
|
||||
device_kernel == DEVICE_KERNEL_INTEGRATOR_SORT_WRITE_PASS)
|
||||
{
|
||||
max_shaders = (kernel_context->scene_max_shaders);
|
||||
}
|
||||
|
||||
try {
|
||||
queue->submit([&](sycl::handler &cgh) {
|
||||
# ifdef WITH_EMBREE_GPU
|
||||
|
@ -495,13 +517,31 @@ bool oneapi_enqueue_kernel(KernelContext *kernel_context,
|
|||
break;
|
||||
}
|
||||
case DEVICE_KERNEL_INTEGRATOR_SORT_BUCKET_PASS: {
|
||||
oneapi_call(
|
||||
kg, cgh, global_size, local_size, args, oneapi_kernel_integrator_sort_bucket_pass);
|
||||
sycl::local_accessor<int> local_mem(max_shaders, cgh);
|
||||
oneapi_kernel_integrator_sort_bucket_pass(kg,
|
||||
global_size,
|
||||
local_size,
|
||||
cgh,
|
||||
*(int *)(args[0]),
|
||||
*(int *)(args[1]),
|
||||
*(int *)(args[2]),
|
||||
*(int **)(args[3]),
|
||||
*(int *)(args[4]),
|
||||
local_mem);
|
||||
break;
|
||||
}
|
||||
case DEVICE_KERNEL_INTEGRATOR_SORT_WRITE_PASS: {
|
||||
oneapi_call(
|
||||
kg, cgh, global_size, local_size, args, oneapi_kernel_integrator_sort_write_pass);
|
||||
sycl::local_accessor<int> local_mem(max_shaders, cgh);
|
||||
oneapi_kernel_integrator_sort_write_pass(kg,
|
||||
global_size,
|
||||
local_size,
|
||||
cgh,
|
||||
*(int *)(args[0]),
|
||||
*(int *)(args[1]),
|
||||
*(int *)(args[2]),
|
||||
*(int **)(args[3]),
|
||||
*(int *)(args[4]),
|
||||
local_mem);
|
||||
break;
|
||||
}
|
||||
case DEVICE_KERNEL_INTEGRATOR_COMPACT_PATHS_ARRAY: {
|
||||
|
|
|
@ -32,6 +32,8 @@ struct KernelContext {
|
|||
SyclQueue *queue;
|
||||
/* Pointer to USM device memory with all global/constant allocation on this device */
|
||||
void *kernel_globals;
|
||||
/* We needs this additional data for some kernels. */
|
||||
int scene_max_shaders;
|
||||
};
|
||||
|
||||
/* Use extern C linking so that the symbols can be easily load from the dynamic library at runtime.
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
#else /* __KERNEL_GPU__ */
|
||||
|
||||
# ifndef __KERNEL_ONEAPI__
|
||||
# define atomic_fetch_and_add_uint32_shared atomic_fetch_and_add_uint32
|
||||
# endif
|
||||
|
||||
# if defined(__KERNEL_CUDA__) || defined(__KERNEL_HIP__)
|
||||
|
||||
# define atomic_add_and_fetch_float(p, x) (atomicAdd((float *)(p), (float)(x)) + (float)(x))
|
||||
|
@ -140,6 +144,11 @@ ccl_device_inline float atomic_compare_and_swap_float(volatile ccl_global float
|
|||
# define atomic_store(p, x) atomic_store_explicit(p, x, memory_order_relaxed)
|
||||
# define atomic_fetch(p) atomic_load_explicit(p, memory_order_relaxed)
|
||||
|
||||
# define atomic_store_local(p, x) \
|
||||
atomic_store_explicit((ccl_gpu_shared atomic_int *)p, x, memory_order_relaxed)
|
||||
# define atomic_load_local(p) \
|
||||
atomic_load_explicit((ccl_gpu_shared atomic_int *)p, memory_order_relaxed)
|
||||
|
||||
# define CCL_LOCAL_MEM_FENCE mem_flags::mem_threadgroup
|
||||
# define ccl_barrier(flags) threadgroup_barrier(flags)
|
||||
|
||||
|
@ -191,6 +200,16 @@ ccl_device_inline int atomic_fetch_and_add_uint32(ccl_global int *p, int x)
|
|||
return atomic.fetch_add(x);
|
||||
}
|
||||
|
||||
ccl_device_inline int atomic_fetch_and_add_uint32_shared(int *p, int x)
|
||||
{
|
||||
sycl::atomic_ref<int,
|
||||
sycl::memory_order::relaxed,
|
||||
sycl::memory_scope::device,
|
||||
sycl::access::address_space::local_space>
|
||||
atomic(*p);
|
||||
return atomic.fetch_add(x);
|
||||
}
|
||||
|
||||
ccl_device_inline unsigned int atomic_fetch_and_sub_uint32(ccl_global unsigned int *p,
|
||||
unsigned int x)
|
||||
{
|
||||
|
@ -253,6 +272,26 @@ ccl_device_inline int atomic_fetch_and_or_uint32(ccl_global int *p, int x)
|
|||
return atomic.fetch_or(x);
|
||||
}
|
||||
|
||||
ccl_device_inline void atomic_store_local(int *p, int x)
|
||||
{
|
||||
sycl::atomic_ref<int,
|
||||
sycl::memory_order::relaxed,
|
||||
sycl::memory_scope::device,
|
||||
sycl::access::address_space::local_space>
|
||||
atomic(*p);
|
||||
atomic.store(x);
|
||||
}
|
||||
|
||||
ccl_device_inline int atomic_load_local(int *p)
|
||||
{
|
||||
sycl::atomic_ref<int,
|
||||
sycl::memory_order::relaxed,
|
||||
sycl::memory_scope::device,
|
||||
sycl::access::address_space::local_space>
|
||||
atomic(*p);
|
||||
return atomic.load();
|
||||
}
|
||||
|
||||
# endif /* __KERNEL_ONEAPI__ */
|
||||
|
||||
#endif /* __KERNEL_GPU__ */
|
||||
|
|
|
@ -134,6 +134,21 @@ ccl_device_inline float len(const float2 a)
|
|||
return sqrtf(dot(a, a));
|
||||
}
|
||||
|
||||
ccl_device_inline float reduce_min(const float2 a)
|
||||
{
|
||||
return min(a.x, a.y);
|
||||
}
|
||||
|
||||
ccl_device_inline float reduce_max(const float2 a)
|
||||
{
|
||||
return max(a.x, a.y);
|
||||
}
|
||||
|
||||
ccl_device_inline float reduce_add(const float2 a)
|
||||
{
|
||||
return a.x + a.y;
|
||||
}
|
||||
|
||||
ccl_device_inline float len_squared(const float2 a)
|
||||
{
|
||||
return dot(a, a);
|
||||
|
|
|
@ -9,9 +9,9 @@ set(INC_SYS
|
|||
)
|
||||
|
||||
set(SRC
|
||||
intern/renderdoc_api.cc
|
||||
intern/renderdoc_api.cc
|
||||
|
||||
include/renderdoc_api.hh
|
||||
include/renderdoc_api.hh
|
||||
)
|
||||
|
||||
blender_add_lib(bf_intern_renderdoc_dynload "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
|
Binary file not shown.
|
@ -204,7 +204,7 @@ def dump_rna_messages(msgs, reports, settings, verbose=False):
|
|||
def class_blacklist():
|
||||
blacklist_rna_class = {getattr(bpy.types, cls_id) for cls_id in (
|
||||
# core classes
|
||||
"Context", "Event", "Function", "UILayout", "UnknownType", "Property", "Struct",
|
||||
"Context", "Event", "Function", "UILayout", "UnknownType", "Struct",
|
||||
# registerable classes
|
||||
"Panel", "Menu", "Header", "RenderEngine", "Operator", "OperatorMacro", "Macro", "KeyingSetInfo",
|
||||
)
|
||||
|
|
|
@ -256,6 +256,25 @@ PYGETTEXT_KEYWORDS = (() +
|
|||
tuple(("{}\\((?:[^,]+,){{2}}\\s*" + _msg_re + r"\s*(?:\)|,)").format(it)
|
||||
for it in ("modifier_subpanel_register", "gpencil_modifier_subpanel_register")) +
|
||||
|
||||
# Node socket declarations: contextless names
|
||||
tuple((r"\.{}<decl::.*?>\(\s*" + _msg_re + r"(?:,[^),]+)*\s*\)").format(it)
|
||||
for it in ("add_input", "add_output")) +
|
||||
|
||||
# Node socket declarations: names with contexts
|
||||
tuple((r"\.{}<decl::.*?>\(\s*" + _msg_re + r"[^;]*\.translation_context\(\s*" + _ctxt_re + r"\s*\)").format(it)
|
||||
for it in ("add_input", "add_output")) +
|
||||
|
||||
# Node socket declarations: description and error messages
|
||||
tuple((r"\.{}\(\s*" + _msg_re + r"\s*\)").format(it)
|
||||
for it in ("description", "error_message_add")) +
|
||||
|
||||
# Node socket labels
|
||||
tuple((r"{}\(\s*[^,]+,\s*" + _msg_re + r"\s*\)").format(it)
|
||||
for it in ("node_sock_label",)) +
|
||||
|
||||
# Geometry Nodes field inputs
|
||||
((r"FieldInput\(CPPType::get<.*?>\(\),\s*" + _msg_re + r"\s*\)"),) +
|
||||
|
||||
# bUnitDef unit names.
|
||||
# NOTE: regex is a bit more complex than it would need too. Since the actual
|
||||
# identifier (`B_UNIT_DEF_`) is at the end, if it's simpler/too general it
|
||||
|
|
|
@ -9,7 +9,10 @@ from bpy.props import (
|
|||
FloatProperty,
|
||||
IntProperty,
|
||||
)
|
||||
from bpy.app.translations import pgettext_tip as tip_
|
||||
from bpy.app.translations import (
|
||||
pgettext_tip as tip_,
|
||||
pgettext_data as data_,
|
||||
)
|
||||
|
||||
|
||||
def object_ensure_material(obj, mat_name):
|
||||
|
@ -119,7 +122,7 @@ class QuickFur(ObjectModeOperator, Operator):
|
|||
noise_group = bpy.data.node_groups["Hair Curves Noise"] if self.use_noise else None
|
||||
frizz_group = bpy.data.node_groups["Frizz Hair Curves"] if self.use_frizz else None
|
||||
|
||||
material = bpy.data.materials.new("Fur Material")
|
||||
material = bpy.data.materials.new(data_("Fur Material"))
|
||||
|
||||
mesh_with_zero_area = False
|
||||
mesh_missing_uv_map = False
|
||||
|
@ -146,7 +149,7 @@ class QuickFur(ObjectModeOperator, Operator):
|
|||
else:
|
||||
density = count / area
|
||||
|
||||
generate_modifier = curves_object.modifiers.new(name="Generate", type='NODES')
|
||||
generate_modifier = curves_object.modifiers.new(name=data_("Generate"), type='NODES')
|
||||
generate_modifier.node_group = generate_group
|
||||
generate_modifier["Input_2"] = mesh_object
|
||||
generate_modifier["Input_18_attribute_name"] = curves.surface_uv_map
|
||||
|
@ -155,11 +158,11 @@ class QuickFur(ObjectModeOperator, Operator):
|
|||
generate_modifier["Input_22"] = material
|
||||
generate_modifier["Input_15"] = density * 0.01
|
||||
|
||||
radius_modifier = curves_object.modifiers.new(name="Set Hair Curve Profile", type='NODES')
|
||||
radius_modifier = curves_object.modifiers.new(name=data_("Set Hair Curve Profile"), type='NODES')
|
||||
radius_modifier.node_group = radius_group
|
||||
radius_modifier["Input_3"] = self.radius
|
||||
|
||||
interpolate_modifier = curves_object.modifiers.new(name="Interpolate Hair Curves", type='NODES')
|
||||
interpolate_modifier = curves_object.modifiers.new(name=data_("Interpolate Hair Curves"), type='NODES')
|
||||
interpolate_modifier.node_group = interpolate_group
|
||||
interpolate_modifier["Input_2"] = mesh_object
|
||||
interpolate_modifier["Input_18_attribute_name"] = curves.surface_uv_map
|
||||
|
@ -169,11 +172,11 @@ class QuickFur(ObjectModeOperator, Operator):
|
|||
interpolate_modifier["Input_24"] = True
|
||||
|
||||
if noise_group:
|
||||
noise_modifier = curves_object.modifiers.new(name="Hair Curves Noise", type='NODES')
|
||||
noise_modifier = curves_object.modifiers.new(name=data_("Hair Curves Noise"), type='NODES')
|
||||
noise_modifier.node_group = noise_group
|
||||
|
||||
if frizz_group:
|
||||
frizz_modifier = curves_object.modifiers.new(name="Frizz Hair Curves", type='NODES')
|
||||
frizz_modifier = curves_object.modifiers.new(name=data_("Frizz Hair Curves"), type='NODES')
|
||||
frizz_modifier.node_group = frizz_group
|
||||
|
||||
if self.apply_hair_guides:
|
||||
|
|
|
@ -613,6 +613,7 @@ class NODE_MT_category_GEO_VOLUME(Menu):
|
|||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeanFilterSDFVolume")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeOffsetSDFVolume")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSampleVolume")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSDFVolumeSphere")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputSignedDistance")
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
|
|
@ -148,7 +148,7 @@ class BONE_PT_curved(BoneButtonsPanel, Panel):
|
|||
|
||||
col = topcol.column(align=True)
|
||||
col.prop(bbone, "bbone_rollin", text="Roll In")
|
||||
col.prop(bbone, "bbone_rollout", text="Out")
|
||||
col.prop(bbone, "bbone_rollout", text="Out", text_ctxt=i18n_contexts.id_armature)
|
||||
col.prop(bone, "use_endroll_as_inroll")
|
||||
|
||||
col = topcol.column(align=True)
|
||||
|
|
|
@ -810,7 +810,7 @@ class ASSETBROWSER_UL_metadata_tags(UIList):
|
|||
row = layout.row(align=True)
|
||||
# Non-editable entries would show grayed-out, which is bad in this specific case, so switch to mere label.
|
||||
if tag.is_property_readonly("name"):
|
||||
row.label(text=tag.name, icon_value=icon)
|
||||
row.label(text=tag.name, icon_value=icon, translate=False)
|
||||
else:
|
||||
row.prop(tag, "name", text="", emboss=False, icon_value=icon)
|
||||
|
||||
|
|
|
@ -886,7 +886,8 @@ class NodeTreeInterfacePanel(Panel):
|
|||
props = property_row.operator_menu_enum(
|
||||
"node.tree_socket_change_type",
|
||||
"socket_type",
|
||||
text=active_socket.bl_label if active_socket.bl_label else active_socket.bl_idname,
|
||||
text=(iface_(active_socket.bl_label) if active_socket.bl_label
|
||||
else iface_(active_socket.bl_idname)),
|
||||
)
|
||||
props.in_out = in_out
|
||||
|
||||
|
@ -904,10 +905,8 @@ class NodeTreeInterfacePanel(Panel):
|
|||
props = property_row.operator_menu_enum(
|
||||
"node.tree_socket_change_subtype",
|
||||
"socket_subtype",
|
||||
text=(
|
||||
active_socket.bl_subtype_label if active_socket.bl_subtype_label else
|
||||
active_socket.bl_idname
|
||||
),
|
||||
text=(iface_(active_socket.bl_subtype_label) if active_socket.bl_subtype_label
|
||||
else iface_(active_socket.bl_idname)),
|
||||
)
|
||||
|
||||
layout.use_property_split = True
|
||||
|
|
|
@ -500,23 +500,21 @@ class _defs_view3d_add:
|
|||
# Layout tweaks here would be good to avoid,
|
||||
# this shows limits in layout engine, as buttons are using a lot of space.
|
||||
@staticmethod
|
||||
def draw_settings_interactive_add(layout, tool, extra):
|
||||
def draw_settings_interactive_add(layout, tool_settings, tool, extra):
|
||||
show_extra = False
|
||||
props = tool.operator_properties("view3d.interactive_add")
|
||||
if not extra:
|
||||
row = layout.row()
|
||||
row.label(text="Depth:")
|
||||
row = layout.row()
|
||||
row.prop(props, "plane_depth", text="")
|
||||
row.prop(tool_settings, "plane_depth", text="")
|
||||
row = layout.row()
|
||||
row.label(text="Orientation:")
|
||||
row = layout.row()
|
||||
row.prop(props, "plane_orientation", text="")
|
||||
row.prop(tool_settings, "plane_orientation", text="")
|
||||
row = layout.row()
|
||||
row.prop(props, "snap_target")
|
||||
row.prop(tool_settings, "snap_elements_tool")
|
||||
|
||||
region_is_header = bpy.context.region.type == 'TOOL_HEADER'
|
||||
|
||||
if region_is_header:
|
||||
# Don't draw the "extra" popover here as we might have other settings & this should be last.
|
||||
show_extra = True
|
||||
|
@ -524,9 +522,10 @@ class _defs_view3d_add:
|
|||
extra = True
|
||||
|
||||
if extra:
|
||||
props = tool.operator_properties("view3d.interactive_add")
|
||||
layout.use_property_split = True
|
||||
layout.row().prop(props, "plane_axis", expand=True)
|
||||
layout.row().prop(props, "plane_axis_auto")
|
||||
layout.row().prop(tool_settings, "plane_axis", expand=True)
|
||||
layout.row().prop(tool_settings, "plane_axis_auto")
|
||||
|
||||
layout.label(text="Base")
|
||||
layout.row().prop(props, "plane_origin_base", expand=True)
|
||||
|
@ -538,8 +537,8 @@ class _defs_view3d_add:
|
|||
|
||||
@ToolDef.from_fn
|
||||
def cube_add():
|
||||
def draw_settings(_context, layout, tool, *, extra=False):
|
||||
show_extra = _defs_view3d_add.draw_settings_interactive_add(layout, tool, extra)
|
||||
def draw_settings(context, layout, tool, *, extra=False):
|
||||
show_extra = _defs_view3d_add.draw_settings_interactive_add(layout, context.tool_settings, tool, extra)
|
||||
if show_extra:
|
||||
layout.popover("TOPBAR_PT_tool_settings_extra", text="...")
|
||||
|
||||
|
@ -557,8 +556,8 @@ class _defs_view3d_add:
|
|||
|
||||
@ToolDef.from_fn
|
||||
def cone_add():
|
||||
def draw_settings(_context, layout, tool, *, extra=False):
|
||||
show_extra = _defs_view3d_add.draw_settings_interactive_add(layout, tool, extra)
|
||||
def draw_settings(context, layout, tool, *, extra=False):
|
||||
show_extra = _defs_view3d_add.draw_settings_interactive_add(layout, context.tool_settings, tool, extra)
|
||||
if extra:
|
||||
return
|
||||
|
||||
|
@ -583,8 +582,8 @@ class _defs_view3d_add:
|
|||
|
||||
@ToolDef.from_fn
|
||||
def cylinder_add():
|
||||
def draw_settings(_context, layout, tool, *, extra=False):
|
||||
show_extra = _defs_view3d_add.draw_settings_interactive_add(layout, tool, extra)
|
||||
def draw_settings(context, layout, tool, *, extra=False):
|
||||
show_extra = _defs_view3d_add.draw_settings_interactive_add(layout, context.tool_settings, tool, extra)
|
||||
if extra:
|
||||
return
|
||||
|
||||
|
@ -608,8 +607,8 @@ class _defs_view3d_add:
|
|||
|
||||
@ToolDef.from_fn
|
||||
def uv_sphere_add():
|
||||
def draw_settings(_context, layout, tool, *, extra=False):
|
||||
show_extra = _defs_view3d_add.draw_settings_interactive_add(layout, tool, extra)
|
||||
def draw_settings(context, layout, tool, *, extra=False):
|
||||
show_extra = _defs_view3d_add.draw_settings_interactive_add(layout, context.tool_settings, tool, extra)
|
||||
if extra:
|
||||
return
|
||||
|
||||
|
@ -633,8 +632,8 @@ class _defs_view3d_add:
|
|||
|
||||
@ToolDef.from_fn
|
||||
def ico_sphere_add():
|
||||
def draw_settings(_context, layout, tool, *, extra=False):
|
||||
show_extra = _defs_view3d_add.draw_settings_interactive_add(layout, tool, extra)
|
||||
def draw_settings(context, layout, tool, *, extra=False):
|
||||
show_extra = _defs_view3d_add.draw_settings_interactive_add(layout, context.tool_settings, tool, extra)
|
||||
if extra:
|
||||
return
|
||||
|
||||
|
|
|
@ -61,8 +61,8 @@ set(SRC_DNA_INC
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_pointcache_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_pointcloud_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_rigidbody_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_scene_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_scene_enums.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_scene_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_screen_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_sdna_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_sequence_types.h
|
||||
|
|
|
@ -840,12 +840,12 @@ bool AssetCatalogDefinitionFile::write_to_disk(const CatalogFilePath &dest_file_
|
|||
return false;
|
||||
}
|
||||
if (BLI_exists(dest_file_path.c_str())) {
|
||||
if (BLI_rename(dest_file_path.c_str(), backup_path.c_str())) {
|
||||
if (BLI_rename_overwrite(dest_file_path.c_str(), backup_path.c_str())) {
|
||||
/* TODO: communicate what went wrong. */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (BLI_rename(writable_path.c_str(), dest_file_path.c_str())) {
|
||||
if (BLI_rename_overwrite(writable_path.c_str(), dest_file_path.c_str())) {
|
||||
/* TODO: communicate what went wrong. */
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 10
|
||||
#define BLENDER_FILE_SUBVERSION 11
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -111,12 +111,12 @@ typedef struct LibraryIDLinkCallbackData {
|
|||
* 'Real' ID, the one that might be in bmain, only differs from self_id when the later is an
|
||||
* embedded one.
|
||||
*/
|
||||
struct ID *id_owner;
|
||||
struct ID *owner_id;
|
||||
/**
|
||||
* ID from which the current ID pointer is being processed. It may be an embedded ID like master
|
||||
* collection or root node tree.
|
||||
*/
|
||||
struct ID *id_self;
|
||||
struct ID *self_id;
|
||||
struct ID **id_pointer;
|
||||
int cb_flag;
|
||||
} LibraryIDLinkCallbackData;
|
||||
|
@ -259,17 +259,17 @@ void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, int c
|
|||
int BKE_library_ID_use_ID(struct ID *id_user, struct ID *id_used);
|
||||
|
||||
/**
|
||||
* Say whether given \a id_owner may use (in any way) a data-block of \a id_type_used.
|
||||
* Say whether given \a owner_id may use (in any way) a data-block of \a id_type_used.
|
||||
*
|
||||
* This is a 'simplified' abstract version of #BKE_library_foreach_ID_link() above,
|
||||
* quite useful to reduce useless iterations in some cases.
|
||||
*/
|
||||
bool BKE_library_id_can_use_idtype(struct ID *id_owner, short id_type_used);
|
||||
bool BKE_library_id_can_use_idtype(struct ID *owner_id, short id_type_used);
|
||||
|
||||
/**
|
||||
* Given the id_owner return the type of id_types it can use as a filter_id.
|
||||
* Given the owner_id return the type of id_types it can use as a filter_id.
|
||||
*/
|
||||
uint64_t BKE_library_id_can_use_filter_id(const struct ID *id_owner, const bool include_ui);
|
||||
uint64_t BKE_library_id_can_use_filter_id(const struct ID *owner_id, const bool include_ui);
|
||||
|
||||
/**
|
||||
* Check whether given ID is used locally (i.e. by another non-linked ID).
|
||||
|
|
|
@ -120,7 +120,18 @@ enum {
|
|||
|
||||
typedef struct Main {
|
||||
struct Main *next, *prev;
|
||||
/** The file-path of this blend file, an empty string indicates an unsaved file. */
|
||||
/**
|
||||
* The file-path of this blend file, an empty string indicates an unsaved file.
|
||||
*
|
||||
* \note For the current loaded blend file this path should be absolute & normalized
|
||||
* to prevent redundant leading slashes or current-working-directory relative paths
|
||||
* from causing problems with absolute/relative patch conversion that relies on this being
|
||||
* an absolute path. See #BLI_path_canonicalize_native.
|
||||
*
|
||||
* This rule is not strictly enforced as in some cases loading a #Main is performed
|
||||
* to read data temporarily (preferences & startup) for e.g.
|
||||
* where the `filepath` is not persistent or used as a basis for other paths.
|
||||
*/
|
||||
char filepath[1024]; /* 1024 = FILE_MAX */
|
||||
short versionfile, subversionfile; /* see BLENDER_FILE_VERSION, BLENDER_FILE_SUBVERSION */
|
||||
short minversionfile, minsubversionfile;
|
||||
|
|
|
@ -1304,6 +1304,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
|
|||
#define GEO_NODE_SIMULATION_INPUT 2100
|
||||
#define GEO_NODE_SIMULATION_OUTPUT 2101
|
||||
#define GEO_NODE_INPUT_SIGNED_DISTANCE 2102
|
||||
#define GEO_NODE_SAMPLE_VOLUME 2103
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -39,8 +39,6 @@ bNodeTree *ntreeCopyTree(Main *bmain, const bNodeTree *ntree);
|
|||
|
||||
void ntreeFreeLocalNode(bNodeTree *ntree, bNode *node);
|
||||
|
||||
bNode *ntreeFindType(bNodeTree *ntree, int type);
|
||||
|
||||
void ntreeUpdateAllNew(Main *main);
|
||||
|
||||
void ntreeNodeFlagSet(const bNodeTree *ntree, int flag, bool enable);
|
||||
|
@ -215,44 +213,38 @@ void nodeParentsIter(bNode *node, bool (*callback)(bNode *, void *), void *userd
|
|||
* A dangling reroute node is a reroute node that does *not* have a "data source", i.e. no
|
||||
* non-reroute node is connected to its input.
|
||||
*/
|
||||
bool nodeIsDanglingReroute(const struct bNodeTree *ntree, const struct bNode *node);
|
||||
bool nodeIsDanglingReroute(const bNodeTree *ntree, const bNode *node);
|
||||
|
||||
struct bNodeLink *nodeFindLink(struct bNodeTree *ntree,
|
||||
const struct bNodeSocket *from,
|
||||
const struct bNodeSocket *to);
|
||||
|
||||
struct bNode *nodeGetActivePaintCanvas(struct bNodeTree *ntree);
|
||||
bNode *nodeGetActivePaintCanvas(bNodeTree *ntree);
|
||||
|
||||
/**
|
||||
* \brief Does the given node supports the sub active flag.
|
||||
*
|
||||
* \param sub_active: The active flag to check. #NODE_ACTIVE_TEXTURE / #NODE_ACTIVE_PAINT_CANVAS.
|
||||
*/
|
||||
bool nodeSupportsActiveFlag(const struct bNode *node, int sub_active);
|
||||
bool nodeSupportsActiveFlag(const bNode *node, int sub_active);
|
||||
|
||||
void nodeSetSocketAvailability(struct bNodeTree *ntree,
|
||||
struct bNodeSocket *sock,
|
||||
bool is_available);
|
||||
void nodeSetSocketAvailability(bNodeTree *ntree, bNodeSocket *sock, bool is_available);
|
||||
|
||||
/**
|
||||
* If the node implements a `declare` function, this function makes sure that `node->declaration`
|
||||
* is up to date. It is expected that the sockets of the node are up to date already.
|
||||
*/
|
||||
bool nodeDeclarationEnsure(struct bNodeTree *ntree, struct bNode *node);
|
||||
bool nodeDeclarationEnsure(bNodeTree *ntree, bNode *node);
|
||||
|
||||
/**
|
||||
* Just update `node->declaration` if necessary. This can also be called on nodes that may not be
|
||||
* up to date (e.g. because the need versioning or are dynamic).
|
||||
*/
|
||||
bool nodeDeclarationEnsureOnOutdatedNode(struct bNodeTree *ntree, struct bNode *node);
|
||||
bool nodeDeclarationEnsureOnOutdatedNode(bNodeTree *ntree, bNode *node);
|
||||
|
||||
/**
|
||||
* Update `socket->declaration` for all sockets in the node. This assumes that the node declaration
|
||||
* and sockets are up to date already.
|
||||
*/
|
||||
void nodeSocketDeclarationsUpdate(struct bNode *node);
|
||||
void nodeSocketDeclarationsUpdate(bNode *node);
|
||||
|
||||
typedef GHashIterator bNodeInstanceHashIterator;
|
||||
using bNodeInstanceHashIterator = GHashIterator;
|
||||
|
||||
BLI_INLINE bNodeInstanceHashIterator *node_instance_hash_iterator_new(bNodeInstanceHash *hash)
|
||||
{
|
||||
|
@ -316,6 +308,7 @@ void node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, bool re
|
|||
/* -------------------------------------------------------------------- */
|
||||
/** \name Node Type Access
|
||||
* \{ */
|
||||
|
||||
void nodeLabel(const bNodeTree *ntree, const bNode *node, char *label, int maxlen);
|
||||
|
||||
/**
|
||||
|
@ -347,7 +340,7 @@ void node_type_size_preset(bNodeType *ntype, eNodeSizePreset size);
|
|||
/** \name Node Generic Functions
|
||||
* \{ */
|
||||
|
||||
bool node_is_connected_to_output(const struct bNodeTree *ntree, const struct bNode *node);
|
||||
bool node_is_connected_to_output(const bNodeTree *ntree, const bNode *node);
|
||||
|
||||
bNodeSocket *node_find_enabled_socket(bNode &node, eNodeSocketInOut in_out, StringRef name);
|
||||
|
||||
|
|
|
@ -154,6 +154,8 @@ void BKE_sound_set_scene_sound_volume(void *handle, float volume, char animated)
|
|||
|
||||
void BKE_sound_set_scene_sound_pitch(void *handle, float pitch, char animated);
|
||||
|
||||
void BKE_sound_set_scene_sound_pitch_at_frame(void *handle, int frame, float pitch, char animated);
|
||||
|
||||
void BKE_sound_set_scene_sound_pitch_constant_range(void *handle,
|
||||
int frame_start,
|
||||
int frame_end,
|
||||
|
|
|
@ -443,6 +443,7 @@ set(SRC
|
|||
BKE_multires.h
|
||||
BKE_nla.h
|
||||
BKE_node.h
|
||||
BKE_node.hh
|
||||
BKE_node_runtime.hh
|
||||
BKE_node_tree_update.h
|
||||
BKE_node_tree_zones.hh
|
||||
|
|
|
@ -897,8 +897,7 @@ void BKE_appdir_program_path_init(const char *argv0)
|
|||
* Otherwise other methods of detecting the binary that override this argument
|
||||
* which must point to the Python module for data-files to be detected. */
|
||||
STRNCPY(g_app.program_filepath, argv0);
|
||||
BLI_path_abs_from_cwd(g_app.program_filepath, sizeof(g_app.program_filepath));
|
||||
BLI_path_normalize_native(g_app.program_filepath);
|
||||
BLI_path_canonicalize_native(g_app.program_filepath, sizeof(g_app.program_filepath));
|
||||
|
||||
if (g_app.program_dirname[0] == '\0') {
|
||||
/* First time initializing, the file binary path isn't valid from a Python module.
|
||||
|
|
|
@ -952,7 +952,7 @@ static int foreach_libblock_link_append_callback(LibraryIDLinkCallbackData *cb_d
|
|||
* meshes for shape keys e.g.), or this is an unsupported case (two shape-keys depending on
|
||||
* each-other need to be also 'linked' in by their respective meshes, independent shape-keys
|
||||
* are not allowed). ref #96048. */
|
||||
if (id != cb_data->id_self && BKE_idtype_idcode_is_linkable(GS(cb_data->id_self->name))) {
|
||||
if (id != cb_data->self_id && BKE_idtype_idcode_is_linkable(GS(cb_data->self_id->name))) {
|
||||
BKE_library_foreach_ID_link(
|
||||
cb_data->bmain, id, foreach_libblock_link_append_callback, data, IDWALK_NOP);
|
||||
}
|
||||
|
@ -972,7 +972,7 @@ static int foreach_libblock_link_append_callback(LibraryIDLinkCallbackData *cb_d
|
|||
const bool do_recursive = (data->lapp_context->params->flag & BLO_LIBLINK_APPEND_RECURSIVE) !=
|
||||
0 ||
|
||||
do_link;
|
||||
if (!do_recursive && cb_data->id_owner->lib != id->lib) {
|
||||
if (!do_recursive && cb_data->owner_id->lib != id->lib) {
|
||||
return IDWALK_RET_NOP;
|
||||
}
|
||||
|
||||
|
|
|
@ -513,7 +513,14 @@ static bool relative_convert_foreach_path_cb(BPathForeachPathData *bpath_data,
|
|||
data->count_changed++;
|
||||
}
|
||||
else {
|
||||
BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made relative", path_src);
|
||||
const char *type_name = BKE_idtype_get_info_from_id(bpath_data->owner_id)->name;
|
||||
const char *id_name = bpath_data->owner_id->name + 2;
|
||||
BKE_reportf(data->reports,
|
||||
RPT_WARNING,
|
||||
"Path '%s' cannot be made relative for %s '%s'",
|
||||
path_src,
|
||||
type_name,
|
||||
id_name);
|
||||
data->count_failed++;
|
||||
}
|
||||
return true;
|
||||
|
@ -537,7 +544,14 @@ static bool absolute_convert_foreach_path_cb(BPathForeachPathData *bpath_data,
|
|||
data->count_changed++;
|
||||
}
|
||||
else {
|
||||
BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made absolute", path_src);
|
||||
const char *type_name = BKE_idtype_get_info_from_id(bpath_data->owner_id)->name;
|
||||
const char *id_name = bpath_data->owner_id->name + 2;
|
||||
BKE_reportf(data->reports,
|
||||
RPT_WARNING,
|
||||
"Path '%s' cannot be made absolute for %s '%s'",
|
||||
path_src,
|
||||
type_name,
|
||||
id_name);
|
||||
data->count_failed++;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -1733,7 +1733,8 @@ static void sizelimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *U
|
|||
float obsize[3], size[3];
|
||||
|
||||
mat4_to_size(size, cob->matrix);
|
||||
mat4_to_size(obsize, cob->matrix);
|
||||
|
||||
copy_v3_v3(obsize, size);
|
||||
|
||||
if (data->flag & LIMIT_XMIN) {
|
||||
if (size[0] < data->xmin) {
|
||||
|
|
|
@ -173,7 +173,7 @@ static int lib_id_clear_library_data_users_update_cb(LibraryIDLinkCallbackData *
|
|||
/* Even though the ID itself remain the same after being made local, from depsgraph point of
|
||||
* view this is a different ID. Hence we need to tag all of its users for COW update. */
|
||||
DEG_id_tag_update_ex(
|
||||
cb_data->bmain, cb_data->id_owner, ID_RECALC_TAG_FOR_UNDO | ID_RECALC_COPY_ON_WRITE);
|
||||
cb_data->bmain, cb_data->owner_id, ID_RECALC_TAG_FOR_UNDO | ID_RECALC_COPY_ON_WRITE);
|
||||
return IDWALK_RET_STOP_ITER;
|
||||
}
|
||||
return IDWALK_RET_NOP;
|
||||
|
@ -396,7 +396,7 @@ void BKE_id_newptr_and_tag_clear(ID *id)
|
|||
static int lib_id_expand_local_cb(LibraryIDLinkCallbackData *cb_data)
|
||||
{
|
||||
Main *bmain = cb_data->bmain;
|
||||
ID *id_self = cb_data->id_self;
|
||||
ID *self_id = cb_data->self_id;
|
||||
ID **id_pointer = cb_data->id_pointer;
|
||||
int const cb_flag = cb_data->cb_flag;
|
||||
const int flags = POINTER_AS_INT(cb_data->user_data);
|
||||
|
@ -412,7 +412,7 @@ static int lib_id_expand_local_cb(LibraryIDLinkCallbackData *cb_data)
|
|||
* local directly), its embedded IDs should also have already been duplicated, and hence be
|
||||
* fully local here already. */
|
||||
if (*id_pointer != NULL && ID_IS_LINKED(*id_pointer)) {
|
||||
BLI_assert(*id_pointer != id_self);
|
||||
BLI_assert(*id_pointer != self_id);
|
||||
|
||||
BKE_lib_id_clear_library_data(bmain, *id_pointer, flags);
|
||||
}
|
||||
|
@ -423,7 +423,7 @@ static int lib_id_expand_local_cb(LibraryIDLinkCallbackData *cb_data)
|
|||
* (through drivers)...
|
||||
* Just skip it, shape key can only be either indirectly linked, or fully local, period.
|
||||
* And let's curse one more time that stupid useless shape-key ID type! */
|
||||
if (*id_pointer && *id_pointer != id_self &&
|
||||
if (*id_pointer && *id_pointer != self_id &&
|
||||
BKE_idtype_idcode_is_linkable(GS((*id_pointer)->name)))
|
||||
{
|
||||
id_lib_extern(*id_pointer);
|
||||
|
@ -583,14 +583,14 @@ static int id_copy_libmanagement_cb(LibraryIDLinkCallbackData *cb_data)
|
|||
|
||||
/* Remap self-references to new copied ID. */
|
||||
if (id == data->id_src) {
|
||||
/* We cannot use id_self here, it is not *always* id_dst (thanks to $£!+@#&/? nodetrees). */
|
||||
/* We cannot use self_id here, it is not *always* id_dst (thanks to $£!+@#&/? nodetrees). */
|
||||
id = *id_pointer = data->id_dst;
|
||||
}
|
||||
|
||||
/* Increase used IDs refcount if needed and required. */
|
||||
if ((data->flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0 && (cb_flag & IDWALK_CB_USER)) {
|
||||
if ((data->flag & LIB_ID_CREATE_NO_MAIN) != 0) {
|
||||
BLI_assert(cb_data->id_self->tag & LIB_TAG_NO_MAIN);
|
||||
BLI_assert(cb_data->self_id->tag & LIB_TAG_NO_MAIN);
|
||||
id_us_plus_no_lib(id);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -373,7 +373,7 @@ bool BKE_lib_override_library_property_is_animated(const ID *id,
|
|||
|
||||
static int foreachid_is_hierarchy_leaf_fn(LibraryIDLinkCallbackData *cb_data)
|
||||
{
|
||||
ID *id_owner = cb_data->id_owner;
|
||||
ID *id_owner = cb_data->owner_id;
|
||||
ID *id = *cb_data->id_pointer;
|
||||
bool *is_leaf = static_cast<bool *>(cb_data->user_data);
|
||||
|
||||
|
@ -3194,7 +3194,7 @@ static int lib_override_sort_libraries_func(LibraryIDLinkCallbackData *cb_data)
|
|||
if (cb_data->cb_flag & IDWALK_CB_LOOPBACK) {
|
||||
return IDWALK_RET_NOP;
|
||||
}
|
||||
ID *id_owner = cb_data->id_owner;
|
||||
ID *id_owner = cb_data->owner_id;
|
||||
ID *id = *cb_data->id_pointer;
|
||||
if (id != nullptr && ID_IS_LINKED(id) && id->lib != id_owner->lib) {
|
||||
const int owner_library_indirect_level = ID_IS_LINKED(id_owner) ? id_owner->lib->temp_index :
|
||||
|
|
|
@ -87,8 +87,8 @@ void BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, int
|
|||
const int callback_return = data->callback(
|
||||
&(struct LibraryIDLinkCallbackData){.user_data = data->user_data,
|
||||
.bmain = data->bmain,
|
||||
.id_owner = data->owner_id,
|
||||
.id_self = data->self_id,
|
||||
.owner_id = data->owner_id,
|
||||
.self_id = data->self_id,
|
||||
.id_pointer = id_pp,
|
||||
.cb_flag = cb_flag});
|
||||
if (flag & IDWALK_READONLY) {
|
||||
|
@ -126,7 +126,7 @@ int BKE_lib_query_foreachid_process_callback_flag_override(LibraryForeachIDData
|
|||
}
|
||||
|
||||
static bool library_foreach_ID_link(Main *bmain,
|
||||
ID *id_owner,
|
||||
ID *owner_id,
|
||||
ID *id,
|
||||
LibraryIDLinkCallback callback,
|
||||
void *user_data,
|
||||
|
@ -192,7 +192,7 @@ static void library_foreach_ID_data_cleanup(LibraryForeachIDData *data)
|
|||
|
||||
/** \return false in case iteration over ID pointers must be stopped, true otherwise. */
|
||||
static bool library_foreach_ID_link(Main *bmain,
|
||||
ID *id_owner,
|
||||
ID *owner_id,
|
||||
ID *id,
|
||||
LibraryIDLinkCallback callback,
|
||||
void *user_data,
|
||||
|
@ -259,7 +259,7 @@ static bool library_foreach_ID_link(Main *bmain,
|
|||
* knowledge of the owner ID then.
|
||||
* While not great, and that should be probably sanitized at some point, we cal live with it
|
||||
* for now. */
|
||||
data.owner_id = ((id->flag & LIB_EMBEDDED_DATA) != 0 && id_owner != NULL) ? id_owner :
|
||||
data.owner_id = ((id->flag & LIB_EMBEDDED_DATA) != 0 && owner_id != NULL) ? owner_id :
|
||||
data.self_id;
|
||||
|
||||
/* inherit_data is non-NULL when this function is called for some sub-data ID
|
||||
|
@ -374,13 +374,13 @@ void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag)
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t BKE_library_id_can_use_filter_id(const ID *id_owner, const bool include_ui)
|
||||
uint64_t BKE_library_id_can_use_filter_id(const ID *owner_id, const bool include_ui)
|
||||
{
|
||||
/* any type of ID can be used in custom props. */
|
||||
if (id_owner->properties) {
|
||||
if (owner_id->properties) {
|
||||
return FILTER_ID_ALL;
|
||||
}
|
||||
const short id_type_owner = GS(id_owner->name);
|
||||
const short id_type_owner = GS(owner_id->name);
|
||||
|
||||
/* IDProps of armature bones and nodes, and bNode->id can use virtually any type of ID. */
|
||||
if (ELEM(id_type_owner, ID_NT, ID_AR)) {
|
||||
|
@ -395,16 +395,16 @@ uint64_t BKE_library_id_can_use_filter_id(const ID *id_owner, const bool include
|
|||
/* Casting to non const.
|
||||
* TODO(jbakker): We should introduce a ntree_id_has_tree function as we are actually not
|
||||
* interested in the result. */
|
||||
if (ntreeFromID((ID *)id_owner)) {
|
||||
if (ntreeFromID((ID *)owner_id)) {
|
||||
return FILTER_ID_ALL;
|
||||
}
|
||||
|
||||
if (BKE_animdata_from_id(id_owner)) {
|
||||
if (BKE_animdata_from_id(owner_id)) {
|
||||
/* AnimationData can use virtually any kind of data-blocks, through drivers especially. */
|
||||
return FILTER_ID_ALL;
|
||||
}
|
||||
|
||||
if (ID_IS_OVERRIDE_LIBRARY_REAL(id_owner)) {
|
||||
if (ID_IS_OVERRIDE_LIBRARY_REAL(owner_id)) {
|
||||
/* LibOverride data 'hierarchy root' can virtually point back to any type of ID. */
|
||||
return FILTER_ID_ALL;
|
||||
}
|
||||
|
@ -496,14 +496,14 @@ uint64_t BKE_library_id_can_use_filter_id(const ID *id_owner, const bool include
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
|
||||
bool BKE_library_id_can_use_idtype(ID *owner_id, const short id_type_used)
|
||||
{
|
||||
/* any type of ID can be used in custom props. */
|
||||
if (id_owner->properties) {
|
||||
if (owner_id->properties) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const short id_type_owner = GS(id_owner->name);
|
||||
const short id_type_owner = GS(owner_id->name);
|
||||
/* Exception for ID_LI as they don't exist as a filter. */
|
||||
if (id_type_used == ID_LI) {
|
||||
return id_type_owner == ID_LI;
|
||||
|
@ -520,7 +520,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
|
|||
}
|
||||
|
||||
const uint64_t filter_id_type_used = BKE_idtype_idcode_to_idfilter(id_type_used);
|
||||
const uint64_t can_be_used = BKE_library_id_can_use_filter_id(id_owner, false);
|
||||
const uint64_t can_be_used = BKE_library_id_can_use_filter_id(owner_id, false);
|
||||
return (can_be_used & filter_id_type_used) != 0;
|
||||
}
|
||||
|
||||
|
@ -866,7 +866,7 @@ void BKE_lib_query_unused_ids_tag(Main *bmain,
|
|||
|
||||
static int foreach_libblock_used_linked_data_tag_clear_cb(LibraryIDLinkCallbackData *cb_data)
|
||||
{
|
||||
ID *self_id = cb_data->id_self;
|
||||
ID *self_id = cb_data->self_id;
|
||||
ID **id_p = cb_data->id_pointer;
|
||||
const int cb_flag = cb_data->cb_flag;
|
||||
bool *is_changed = cb_data->user_data;
|
||||
|
|
|
@ -177,8 +177,8 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
|
|||
return IDWALK_RET_NOP;
|
||||
}
|
||||
|
||||
ID *id_owner = cb_data->id_owner;
|
||||
ID *id_self = cb_data->id_self;
|
||||
ID *id_owner = cb_data->owner_id;
|
||||
ID *id_self = cb_data->self_id;
|
||||
ID **id_p = cb_data->id_pointer;
|
||||
IDRemap *id_remap_data = cb_data->user_data;
|
||||
|
||||
|
|
|
@ -230,22 +230,22 @@ void BKE_main_unlock(struct Main *bmain)
|
|||
static int main_relations_create_idlink_cb(LibraryIDLinkCallbackData *cb_data)
|
||||
{
|
||||
MainIDRelations *bmain_relations = cb_data->user_data;
|
||||
ID *id_self = cb_data->id_self;
|
||||
ID *self_id = cb_data->self_id;
|
||||
ID **id_pointer = cb_data->id_pointer;
|
||||
const int cb_flag = cb_data->cb_flag;
|
||||
|
||||
if (*id_pointer) {
|
||||
MainIDRelationsEntry **entry_p;
|
||||
|
||||
/* Add `id_pointer` as child of `id_self`. */
|
||||
/* Add `id_pointer` as child of `self_id`. */
|
||||
{
|
||||
if (!BLI_ghash_ensure_p(
|
||||
bmain_relations->relations_from_pointers, id_self, (void ***)&entry_p)) {
|
||||
bmain_relations->relations_from_pointers, self_id, (void ***)&entry_p)) {
|
||||
*entry_p = MEM_callocN(sizeof(**entry_p), __func__);
|
||||
(*entry_p)->session_uuid = id_self->session_uuid;
|
||||
(*entry_p)->session_uuid = self_id->session_uuid;
|
||||
}
|
||||
else {
|
||||
BLI_assert((*entry_p)->session_uuid == id_self->session_uuid);
|
||||
BLI_assert((*entry_p)->session_uuid == self_id->session_uuid);
|
||||
}
|
||||
MainIDRelationsEntryItem *to_id_entry = BLI_mempool_alloc(bmain_relations->entry_items_pool);
|
||||
to_id_entry->next = (*entry_p)->to_ids;
|
||||
|
@ -256,7 +256,7 @@ static int main_relations_create_idlink_cb(LibraryIDLinkCallbackData *cb_data)
|
|||
(*entry_p)->to_ids = to_id_entry;
|
||||
}
|
||||
|
||||
/* Add `id_self` as parent of `id_pointer`. */
|
||||
/* Add `self_id` as parent of `id_pointer`. */
|
||||
if (*id_pointer != NULL) {
|
||||
if (!BLI_ghash_ensure_p(
|
||||
bmain_relations->relations_from_pointers, *id_pointer, (void ***)&entry_p)) {
|
||||
|
@ -269,8 +269,8 @@ static int main_relations_create_idlink_cb(LibraryIDLinkCallbackData *cb_data)
|
|||
MainIDRelationsEntryItem *from_id_entry = BLI_mempool_alloc(
|
||||
bmain_relations->entry_items_pool);
|
||||
from_id_entry->next = (*entry_p)->from_ids;
|
||||
from_id_entry->id_pointer.from = id_self;
|
||||
from_id_entry->session_uuid = id_self->session_uuid;
|
||||
from_id_entry->id_pointer.from = self_id;
|
||||
from_id_entry->session_uuid = self_id->session_uuid;
|
||||
from_id_entry->usage_flag = cb_flag;
|
||||
(*entry_p)->from_ids = from_id_entry;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -335,7 +335,7 @@ int BKE_packedfile_write_to_file(ReportList *reports,
|
|||
|
||||
if (remove_tmp) {
|
||||
if (ret_value == RET_ERROR) {
|
||||
if (BLI_rename(filepath_temp, filepath) != 0) {
|
||||
if (BLI_rename_overwrite(filepath_temp, filepath) != 0) {
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
"Error restoring temp file (check files '%s' '%s')",
|
||||
|
|
|
@ -3531,7 +3531,7 @@ void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const c
|
|||
if (frame != -1) {
|
||||
BLI_path_join(old_path_full, sizeof(old_path_full), path, de->d_name);
|
||||
ptcache_filepath(pid, new_path_full, frame, true, true);
|
||||
BLI_rename(old_path_full, new_path_full);
|
||||
BLI_rename_overwrite(old_path_full, new_path_full);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -819,6 +819,11 @@ void BKE_sound_set_scene_sound_pitch(void *handle, float pitch, char animated)
|
|||
AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PITCH, sound_cfra, &pitch, animated);
|
||||
}
|
||||
|
||||
void BKE_sound_set_scene_sound_pitch_at_frame(void *handle, int frame, float pitch, char animated)
|
||||
{
|
||||
AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PITCH, frame, &pitch, animated);
|
||||
}
|
||||
|
||||
void BKE_sound_set_scene_sound_pitch_constant_range(void *handle,
|
||||
int frame_start,
|
||||
int frame_end,
|
||||
|
@ -1379,6 +1384,12 @@ void BKE_sound_set_scene_sound_pitch(void *UNUSED(handle),
|
|||
char UNUSED(animated))
|
||||
{
|
||||
}
|
||||
void BKE_sound_set_scene_sound_pitch_at_frame(void *UNUSED(handle),
|
||||
int UNUSED(frame),
|
||||
float UNUSED(pitch),
|
||||
char UNUSED(animated))
|
||||
{
|
||||
}
|
||||
void BKE_sound_set_scene_sound_pitch_constant_range(void *UNUSED(handle),
|
||||
int UNUSED(frame_start),
|
||||
int UNUSED(frame_end),
|
||||
|
|
|
@ -39,10 +39,29 @@ extern "C" {
|
|||
*/
|
||||
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
int BLI_copy(const char *file, const char *to) ATTR_NONNULL();
|
||||
|
||||
/**
|
||||
* Rename a file or directory.
|
||||
*
|
||||
* \return zero on success (matching 'rename' behavior).
|
||||
*/
|
||||
int BLI_rename(const char *from, const char *to) ATTR_NONNULL();
|
||||
int BLI_rename(const char *from, const char *to);
|
||||
|
||||
/**
|
||||
* Rename a file or directory.
|
||||
*
|
||||
* \warning It's up to the caller to ensure `from` & `to` don't point to the same file
|
||||
* as this will result in `to` being deleted to make room for `from`
|
||||
* (which will then also be deleted).
|
||||
*
|
||||
* See #BLI_path_move to move directories.
|
||||
*
|
||||
* \param from: The path to rename from (return failure if it does not exist).
|
||||
* \param to: The destination path.
|
||||
* This will be deleted if it already exists, unless it's a directory which will fail.
|
||||
* \return zero on success (matching 'rename' behavior).
|
||||
*/
|
||||
int BLI_rename_overwrite(const char *from, const char *to) ATTR_NONNULL();
|
||||
/**
|
||||
* Deletes the specified file or directory (depending on dir), optionally
|
||||
* doing recursive delete of directory contents.
|
||||
|
|
|
@ -242,6 +242,15 @@ MINLINE uint64_t ceil_to_multiple_ul(uint64_t a, uint64_t b);
|
|||
*/
|
||||
MINLINE int mod_i(int i, int n);
|
||||
|
||||
/**
|
||||
* Modulo that returns a positive result, regardless of the sign of \a f.
|
||||
*
|
||||
* For example, mod_f_positive(-0.1, 1.0) => 0.9.
|
||||
*
|
||||
* \returns a float in the interval [0, n).
|
||||
*/
|
||||
MINLINE float mod_f_positive(float f, float n);
|
||||
|
||||
/**
|
||||
* Round to closest even number, halfway cases are rounded away from zero.
|
||||
*/
|
||||
|
|
|
@ -41,6 +41,9 @@ bool BLI_path_name_at_index(const char *__restrict path,
|
|||
*/
|
||||
bool BLI_path_is_unc(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
bool BLI_path_is_win32_drive(const char *path);
|
||||
bool BLI_path_is_win32_drive_with_slash(const char *path);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -153,22 +156,27 @@ void BLI_path_to_display_name(char *display_name, int display_name_maxncpy, cons
|
|||
* such as `//../parent` or `../parent`.
|
||||
*
|
||||
* \param path: The path to a file or directory which can be absolute or relative.
|
||||
* \return the length of `path`.
|
||||
*/
|
||||
void BLI_path_normalize(char *path) ATTR_NONNULL(1);
|
||||
int BLI_path_normalize(char *path) ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* A version of #BLI_path_normalize without special handling of `//` blend file relative prefix.
|
||||
*
|
||||
* \note On UNIX `//path` is a valid path which gets normalized to `/path`.
|
||||
*
|
||||
* \return the length of `path`.
|
||||
*/
|
||||
void BLI_path_normalize_native(char *path) ATTR_NONNULL(1);
|
||||
int BLI_path_normalize_native(char *path) ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Cleanup file-path ensuring a trailing slash.
|
||||
*
|
||||
* \note Same as #BLI_path_normalize but adds a trailing slash.
|
||||
*
|
||||
* \return the length of `dir`.
|
||||
*/
|
||||
void BLI_path_normalize_dir(char *dir, size_t dir_maxncpy) ATTR_NONNULL(1);
|
||||
int BLI_path_normalize_dir(char *dir, size_t dir_maxncpy) ATTR_NONNULL(1);
|
||||
|
||||
#if defined(WIN32)
|
||||
void BLI_path_normalize_unc_16(wchar_t *path_16);
|
||||
|
@ -177,6 +185,28 @@ void BLI_path_normalize_unc(char *path, int path_maxncpy);
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Path Canonicalize
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Convert `path` to a canonical representation.
|
||||
* This is intended for system paths (passed in as command-line arguments of via scripts)
|
||||
* which are valid in that they resolve to a file/directory and but could be `CWD` relative or
|
||||
* contain redundant slashes that cause absolute/relative conversion to fail.
|
||||
* (specifically the "//" prefix used by Blender).
|
||||
*
|
||||
* Perform the following operations:
|
||||
*
|
||||
* - Make absolute (relative to the current working directory).
|
||||
* - Convert slash direction (WIN32 only, as other systems may use back-slashes in filenames).
|
||||
* - Normalize redundant slashes.
|
||||
* - Strip trailing slashes.
|
||||
*/
|
||||
int BLI_path_canonicalize_native(char *path, int path_maxncpy);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Path FileName Manipulation
|
||||
* \{ */
|
||||
|
@ -219,7 +249,14 @@ const char *BLI_path_slash_find(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUS
|
|||
const char *BLI_path_slash_rfind(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
/**
|
||||
* Appends a slash to path if there isn't one there already.
|
||||
* Returns the new length of the path.
|
||||
* \param path_len: The length of `path`.
|
||||
* \return the new length of the path.
|
||||
*/
|
||||
int BLI_path_slash_ensure_ex(char *path, size_t path_maxncpy, const size_t path_len)
|
||||
ATTR_NONNULL(1);
|
||||
/**
|
||||
* Appends a slash to path if there isn't one there already.
|
||||
* \return the new length of the path.
|
||||
*/
|
||||
int BLI_path_slash_ensure(char *path, size_t path_maxncpy) ATTR_NONNULL(1);
|
||||
/**
|
||||
|
|
|
@ -624,7 +624,11 @@ int BLI_string_find_split_words(const char *str,
|
|||
*/
|
||||
void BLI_string_debug_size_after_nil(char *str, size_t str_maxncpy);
|
||||
#else
|
||||
# define BLI_string_debug_size(str, str_maxncpy) (void)(0 ? ((str) + (str_maxncpy)) : 0)
|
||||
# define BLI_string_debug_size(str, str_maxncpy) \
|
||||
if (0) { \
|
||||
(void)str, (void)str_maxncpy; \
|
||||
} \
|
||||
((void)0)
|
||||
# define BLI_string_debug_size_after_nil(str, str_maxncpy) BLI_string_debug_size(str, str_maxncpy)
|
||||
#endif /* !WITH_STRSIZE_DEBUG */
|
||||
|
||||
|
|
|
@ -379,6 +379,43 @@ bool BLI_file_ensure_parent_dir_exists(const char *filepath)
|
|||
return BLI_dir_create_recursive(di);
|
||||
}
|
||||
|
||||
int BLI_rename(const char *from, const char *to)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return urename(from, to);
|
||||
#else
|
||||
return rename(from, to);
|
||||
#endif
|
||||
}
|
||||
|
||||
int BLI_rename_overwrite(const char *from, const char *to)
|
||||
{
|
||||
if (!BLI_exists(from)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* NOTE(@ideasman42): there are no checks that `from` & `to` *aren't* the same file.
|
||||
* It's up to the caller to ensure this. In practice these paths are often generated
|
||||
* and known to be different rather than arbitrary user input.
|
||||
* In the case of arbitrary paths (renaming a file in the file-selector for example),
|
||||
* the caller must ensure file renaming doesn't cause user data loss.
|
||||
*
|
||||
* Support for checking the files aren't the same could be added, however path comparison
|
||||
* alone is *not* a guarantee the files are different (given the possibility of accessing
|
||||
* the same file through different paths via symbolic-links), we could instead support a
|
||||
* verizon of Python's * `os.path.samefile(..)` which compares the I-node & device.
|
||||
* In this particular case we would not want to follow symbolic-links as well.
|
||||
* Since this functionality isn't required at the moment, leave this as-is.
|
||||
* Noting it as a potential improvement. */
|
||||
if (BLI_exists(to)) {
|
||||
if (BLI_delete(to, false, false)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return BLI_rename(from, to);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
static void callLocalErrorCallBack(const char *err)
|
||||
|
@ -691,23 +728,6 @@ int BLI_create_symlink(const char *file, const char *to)
|
|||
}
|
||||
# endif
|
||||
|
||||
/** \return true on success (i.e. given path now exists on FS), false otherwise. */
|
||||
int BLI_rename(const char *from, const char *to)
|
||||
{
|
||||
if (!BLI_exists(from)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure `from` & `to` are different (case insensitive) before removing. */
|
||||
if (BLI_exists(to) && BLI_strcasecmp(from, to)) {
|
||||
if (BLI_delete(to, false, false)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return urename(from, to);
|
||||
}
|
||||
|
||||
#else /* The UNIX world */
|
||||
|
||||
/* results from recursive_operation and its callbacks */
|
||||
|
@ -1323,19 +1343,4 @@ int BLI_create_symlink(const char *file, const char *to)
|
|||
}
|
||||
# endif
|
||||
|
||||
int BLI_rename(const char *from, const char *to)
|
||||
{
|
||||
if (!BLI_exists(from)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (BLI_exists(to)) {
|
||||
if (BLI_delete(to, false, false)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return rename(from, to);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -387,6 +387,16 @@ MINLINE int mod_i(int i, int n)
|
|||
return (i % n + n) % n;
|
||||
}
|
||||
|
||||
MINLINE float mod_f_positive(const float f, const float n)
|
||||
{
|
||||
const float modulo = fmodf(f, n);
|
||||
if (modulo < 0) {
|
||||
/* fmodf returns a value in the interval (-n, n). */
|
||||
return modulo + n;
|
||||
}
|
||||
return modulo;
|
||||
}
|
||||
|
||||
MINLINE float fractf(float a)
|
||||
{
|
||||
return a - floorf(a);
|
||||
|
|
|
@ -43,6 +43,7 @@ static int BLI_path_unc_prefix_len(const char *path);
|
|||
|
||||
#ifdef WIN32
|
||||
static bool BLI_path_is_abs_win32(const char *path);
|
||||
static int BLI_path_win32_prefix_len(const char *path);
|
||||
#endif /* WIN32 */
|
||||
|
||||
/**
|
||||
|
@ -135,7 +136,11 @@ void BLI_path_sequence_encode(char *path,
|
|||
BLI_snprintf(path, path_maxncpy, "%s%.*d%s", head, numlen, MAX2(0, pic), tail);
|
||||
}
|
||||
|
||||
static void path_normalize_impl(char *path, bool check_blend_relative_prefix)
|
||||
/**
|
||||
* Implementation for #BLI_path_normalize & #BLI_path_normalize_native.
|
||||
* \return The path length.
|
||||
*/
|
||||
static int path_normalize_impl(char *path, bool check_blend_relative_prefix)
|
||||
{
|
||||
const char *path_orig = path;
|
||||
int path_len = strlen(path);
|
||||
|
@ -173,7 +178,7 @@ static void path_normalize_impl(char *path, bool check_blend_relative_prefix)
|
|||
path += path_unc_len;
|
||||
path_len -= path_unc_len;
|
||||
}
|
||||
else if (isalpha(path[0]) && (path[1] == ':')) {
|
||||
else if (BLI_path_is_win32_drive(path)) { /* Check for `C:` (2 characters only). */
|
||||
path += 2;
|
||||
path_len -= 2;
|
||||
}
|
||||
|
@ -355,27 +360,52 @@ static void path_normalize_impl(char *path, bool check_blend_relative_prefix)
|
|||
BLI_assert(strlen(path) == path_len);
|
||||
|
||||
#undef IS_PARENT_DIR
|
||||
|
||||
return (path - path_orig) + path_len;
|
||||
}
|
||||
|
||||
void BLI_path_normalize(char *path)
|
||||
int BLI_path_normalize(char *path)
|
||||
{
|
||||
path_normalize_impl(path, true);
|
||||
return path_normalize_impl(path, true);
|
||||
}
|
||||
|
||||
void BLI_path_normalize_native(char *path)
|
||||
int BLI_path_normalize_native(char *path)
|
||||
{
|
||||
path_normalize_impl(path, false);
|
||||
return path_normalize_impl(path, false);
|
||||
}
|
||||
|
||||
void BLI_path_normalize_dir(char *dir, size_t dir_maxncpy)
|
||||
int BLI_path_normalize_dir(char *dir, size_t dir_maxncpy)
|
||||
{
|
||||
/* Would just create an unexpected "/" path, just early exit entirely. */
|
||||
if (dir[0] == '\0') {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BLI_path_normalize(dir);
|
||||
BLI_path_slash_ensure(dir, dir_maxncpy);
|
||||
int dir_len = BLI_path_normalize(dir);
|
||||
return BLI_path_slash_ensure_ex(dir, dir_maxncpy, dir_len);
|
||||
}
|
||||
|
||||
int BLI_path_canonicalize_native(char *path, int path_maxncpy)
|
||||
{
|
||||
BLI_path_abs_from_cwd(path, path_maxncpy);
|
||||
/* As these are system level paths, only convert slashes
|
||||
* if the alternate direction is accepted as a slash. */
|
||||
if (BLI_path_slash_is_native_compat(ALTSEP)) {
|
||||
BLI_path_slash_native(path);
|
||||
}
|
||||
int path_len = BLI_path_normalize_native(path);
|
||||
/* Strip trailing slash but don't strip `/` away to nothing. */
|
||||
if (path_len > 1 && path[path_len - 1] == SEP) {
|
||||
#ifdef WIN32
|
||||
/* Don't strip `C:\` -> `C:` as this is no longer a valid directory. */
|
||||
if (BLI_path_win32_prefix_len(path) + 1 < path_len)
|
||||
#endif
|
||||
{
|
||||
path_len -= 1;
|
||||
path[path_len] = '\0';
|
||||
}
|
||||
}
|
||||
return path_len;
|
||||
}
|
||||
|
||||
bool BLI_path_make_safe_filename_ex(char *fname, bool allow_tokens)
|
||||
|
@ -523,6 +553,26 @@ static int BLI_path_unc_prefix_len(const char *path)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
static int BLI_path_win32_prefix_len(const char *path)
|
||||
{
|
||||
if (BLI_path_is_win32_drive(path)) {
|
||||
return 2;
|
||||
}
|
||||
return BLI_path_unc_prefix_len(path);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool BLI_path_is_win32_drive(const char *path)
|
||||
{
|
||||
return isalpha(path[0]) && (path[1] == ':');
|
||||
}
|
||||
|
||||
bool BLI_path_is_win32_drive_with_slash(const char *path)
|
||||
{
|
||||
return isalpha(path[0]) && (path[1] == ':') && ELEM(path[2], '\\', '/');
|
||||
}
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
/**
|
||||
|
@ -535,7 +585,7 @@ static int BLI_path_unc_prefix_len(const char *path)
|
|||
*/
|
||||
static bool BLI_path_is_abs_win32(const char *path)
|
||||
{
|
||||
return (path[1] == ':' && ELEM(path[2], '\\', '/')) || BLI_path_is_unc(path);
|
||||
return BLI_path_is_win32_drive_with_slash(path) || BLI_path_is_unc(path);
|
||||
}
|
||||
|
||||
static wchar_t *next_slash(wchar_t *path)
|
||||
|
@ -1082,7 +1132,7 @@ bool BLI_path_abs(char path[FILE_MAX], const char *basepath)
|
|||
* Add a `/` prefix and lowercase the drive-letter, remove the `:`.
|
||||
* `C:\foo.JPG` -> `/c/foo.JPG` */
|
||||
|
||||
if (isalpha(tmp[0]) && (tmp[1] == ':') && ELEM(tmp[2], '\\', '/')) {
|
||||
if (BLI_path_is_win32_drive_with_slash(tmp)) {
|
||||
tmp[1] = tolower(tmp[0]); /* Replace `:` with drive-letter. */
|
||||
tmp[0] = '/';
|
||||
/* `\` the slash will be converted later. */
|
||||
|
@ -1602,35 +1652,20 @@ const char *BLI_path_extension(const char *filepath)
|
|||
|
||||
size_t BLI_path_append(char *__restrict dst, const size_t dst_maxncpy, const char *__restrict file)
|
||||
{
|
||||
BLI_string_debug_size_after_nil(dst, dst_maxncpy);
|
||||
|
||||
size_t dirlen = BLI_strnlen(dst, dst_maxncpy);
|
||||
/* Inline #BLI_path_slash_ensure. */
|
||||
if ((dirlen > 0) && !BLI_path_slash_is_native_compat(dst[dirlen - 1])) {
|
||||
dst[dirlen++] = SEP;
|
||||
dst[dirlen] = '\0';
|
||||
/* Slash ensure uses #BLI_string_debug_size */
|
||||
int dst_len = BLI_path_slash_ensure(dst, dst_maxncpy);
|
||||
if (dst_len + 1 < dst_maxncpy) {
|
||||
dst_len += BLI_strncpy_rlen(dst + dst_len, file, dst_maxncpy - dst_len);
|
||||
}
|
||||
|
||||
if (dirlen >= dst_maxncpy) {
|
||||
return dirlen; /* Fills the path. */
|
||||
}
|
||||
|
||||
return dirlen + BLI_strncpy_rlen(dst + dirlen, file, dst_maxncpy - dirlen);
|
||||
return dst_len;
|
||||
}
|
||||
|
||||
size_t BLI_path_append_dir(char *__restrict dst,
|
||||
const size_t dst_maxncpy,
|
||||
const char *__restrict dir)
|
||||
{
|
||||
size_t dirlen = BLI_path_append(dst, dst_maxncpy, dir);
|
||||
if (dirlen + 1 < dst_maxncpy) {
|
||||
/* Inline #BLI_path_slash_ensure. */
|
||||
if ((dirlen > 0) && !BLI_path_slash_is_native_compat(dst[dirlen - 1])) {
|
||||
dst[dirlen++] = SEP;
|
||||
dst[dirlen] = '\0';
|
||||
}
|
||||
}
|
||||
return dirlen;
|
||||
size_t dst_len = BLI_path_append(dst, dst_maxncpy, dir);
|
||||
return BLI_path_slash_ensure_ex(dst, dst_maxncpy, dst_len);
|
||||
}
|
||||
|
||||
size_t BLI_path_join_array(char *__restrict dst,
|
||||
|
@ -1885,21 +1920,24 @@ const char *BLI_path_slash_rfind(const char *path)
|
|||
return (lfslash > lbslash) ? lfslash : lbslash;
|
||||
}
|
||||
|
||||
int BLI_path_slash_ensure(char *path, size_t path_maxncpy)
|
||||
int BLI_path_slash_ensure_ex(char *path, size_t path_maxncpy, size_t path_len)
|
||||
{
|
||||
BLI_string_debug_size_after_nil(path, path_maxncpy);
|
||||
|
||||
int len = strlen(path);
|
||||
BLI_assert(len < path_maxncpy);
|
||||
if (len == 0 || !BLI_path_slash_is_native_compat(path[len - 1])) {
|
||||
BLI_assert(strlen(path) == path_len);
|
||||
BLI_assert(path_len < path_maxncpy);
|
||||
if (path_len == 0 || !BLI_path_slash_is_native_compat(path[path_len - 1])) {
|
||||
/* Avoid unlikely buffer overflow. */
|
||||
if (len + 1 < path_maxncpy) {
|
||||
path[len] = SEP;
|
||||
path[len + 1] = '\0';
|
||||
return len + 1;
|
||||
if (path_len + 1 < path_maxncpy) {
|
||||
path[path_len++] = SEP;
|
||||
path[path_len] = '\0';
|
||||
}
|
||||
}
|
||||
return len;
|
||||
return path_len;
|
||||
}
|
||||
|
||||
int BLI_path_slash_ensure(char *path, size_t path_maxncpy)
|
||||
{
|
||||
return BLI_path_slash_ensure_ex(path, path_maxncpy, strlen(path));
|
||||
}
|
||||
|
||||
void BLI_path_slash_rstrip(char *path)
|
||||
|
@ -1947,6 +1985,10 @@ int BLI_path_cmp_normalized(const char *p1, const char *p2)
|
|||
BLI_path_slash_native(norm_p1);
|
||||
BLI_path_slash_native(norm_p2);
|
||||
|
||||
/* One of the paths ending with a slash does not make them different, strip both. */
|
||||
BLI_path_slash_rstrip(norm_p1);
|
||||
BLI_path_slash_rstrip(norm_p2);
|
||||
|
||||
BLI_path_normalize(norm_p1);
|
||||
BLI_path_normalize(norm_p2);
|
||||
|
||||
|
|
|
@ -602,30 +602,12 @@ void BLI_file_free_lines(LinkNode *lines)
|
|||
|
||||
bool BLI_file_older(const char *file1, const char *file2)
|
||||
{
|
||||
#ifdef WIN32
|
||||
struct _stat st1, st2;
|
||||
|
||||
UTF16_ENCODE(file1);
|
||||
UTF16_ENCODE(file2);
|
||||
|
||||
if (_wstat(file1_16, &st1)) {
|
||||
BLI_stat_t st1, st2;
|
||||
if (BLI_stat(file1, &st1)) {
|
||||
return false;
|
||||
}
|
||||
if (_wstat(file2_16, &st2)) {
|
||||
if (BLI_stat(file2, &st2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UTF16_UN_ENCODE(file2);
|
||||
UTF16_UN_ENCODE(file1);
|
||||
#else
|
||||
struct stat st1, st2;
|
||||
|
||||
if (stat(file1, &st1)) {
|
||||
return false;
|
||||
}
|
||||
if (stat(file2, &st2)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return (st1.st_mtime < st2.st_mtime);
|
||||
}
|
||||
|
|
|
@ -156,4 +156,11 @@ TEST(math_base, InterpolateInt)
|
|||
EXPECT_EQ(math::interpolate(100, 200, 0.4f), 140);
|
||||
}
|
||||
|
||||
TEST(math_base, ModFPositive)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(mod_f_positive(3.27f, 1.57f), 0.12999988f);
|
||||
EXPECT_FLOAT_EQ(mod_f_positive(327.f, 47.f), 45.f);
|
||||
EXPECT_FLOAT_EQ(mod_f_positive(-0.1f, 1.0f), 0.9f);
|
||||
}
|
||||
|
||||
} // namespace blender::tests
|
||||
|
|
|
@ -48,11 +48,12 @@ static char *str_replace_char_strdup(const char *str, char src, char dst)
|
|||
if (SEP == '\\') { \
|
||||
str_replace_char_with_relative_exception(path, '/', '\\'); \
|
||||
} \
|
||||
BLI_path_normalize(path); \
|
||||
const int path_len_test = BLI_path_normalize(path); \
|
||||
if (SEP == '\\') { \
|
||||
BLI_str_replace_char(path, '\\', '/'); \
|
||||
} \
|
||||
EXPECT_STREQ(path, output_expect); \
|
||||
EXPECT_EQ(path_len_test, strlen(path)); \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
|
@ -155,6 +156,26 @@ TEST(path_util, Normalize_UnbalancedRelativeTrailing)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Tests for: #BLI_path_cmp_normalized
|
||||
*
|
||||
* \note #BLI_path_normalize tests handle most of the corner cases.
|
||||
* \{ */
|
||||
|
||||
TEST(path_util, CompareNormalized)
|
||||
{
|
||||
/* Trailing slash should not matter. */
|
||||
EXPECT_EQ(BLI_path_cmp_normalized("/tmp/", "/tmp"), 0);
|
||||
/* Slash direction should not matter. */
|
||||
EXPECT_EQ(BLI_path_cmp_normalized("c:\\tmp\\", "c:/tmp/"), 0);
|
||||
/* Empty paths should be supported. */
|
||||
EXPECT_EQ(BLI_path_cmp_normalized("", ""), 0);
|
||||
|
||||
EXPECT_NE(BLI_path_cmp_normalized("A", "B"), 0);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Tests for: #BLI_path_parent_dir
|
||||
* \{ */
|
||||
|
@ -560,6 +581,47 @@ TEST(path_util, JoinRelativePrefix)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Tests for: #BLI_path_append
|
||||
* \{ */
|
||||
|
||||
/* For systems with `/` path separator (non WIN32). */
|
||||
#define APPEND(str_expect, size, path, filename) \
|
||||
{ \
|
||||
const char *expect = str_expect; \
|
||||
char result[(size) + 1024] = path; \
|
||||
char filename_native[] = filename; \
|
||||
/* Check we don't write past the last byte. */ \
|
||||
if (SEP == '\\') { \
|
||||
BLI_str_replace_char(filename_native, '/', '\\'); \
|
||||
BLI_str_replace_char(result, '/', '\\'); \
|
||||
} \
|
||||
BLI_path_append(result, size, filename_native); \
|
||||
if (SEP == '\\') { \
|
||||
BLI_str_replace_char(result, '\\', '/'); \
|
||||
} \
|
||||
EXPECT_STREQ(result, expect); \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
TEST(path_util, AppendFile)
|
||||
{
|
||||
APPEND("a/b", 100, "a", "b");
|
||||
APPEND("a/b", 100, "a/", "b");
|
||||
}
|
||||
|
||||
TEST(path_util, AppendFile_Truncate)
|
||||
{
|
||||
APPEND("/A", 3, "/", "ABC");
|
||||
APPEND("/", 2, "/", "test");
|
||||
APPEND("X", 2, "X", "ABC");
|
||||
APPEND("X/", 3, "X/", "ABC");
|
||||
}
|
||||
|
||||
#undef APPEND
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Tests for: #BLI_path_frame
|
||||
* \{ */
|
||||
|
|
|
@ -4391,6 +4391,14 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 306, 10)) {
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
/* Set default values for new members. */
|
||||
scene->toolsettings->snap_mode_tools = SCE_SNAP_MODE_GEOM;
|
||||
scene->toolsettings->plane_axis = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 306, 11)) {
|
||||
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
|
||||
|
|
|
@ -103,7 +103,7 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
|
|||
FROM_DEFAULT_V4_UCHAR(space_action.simulated_frames);
|
||||
}
|
||||
|
||||
if (!USER_VERSION_ATLEAST(306, 10)) {
|
||||
if (!USER_VERSION_ATLEAST(306, 11)) {
|
||||
FROM_DEFAULT_V4_UCHAR(space_view3d.asset_shelf.back);
|
||||
FROM_DEFAULT_V4_UCHAR(space_view3d.asset_shelf.header_back);
|
||||
}
|
||||
|
|
|
@ -1165,17 +1165,17 @@ static void id_buffer_init_from_id(BLO_Write_IDBuffer *id_buffer, ID *id, const
|
|||
* linked data is tagged accordingly. */
|
||||
static int write_id_direct_linked_data_process_cb(LibraryIDLinkCallbackData *cb_data)
|
||||
{
|
||||
ID *id_self = cb_data->id_self;
|
||||
ID *self_id = cb_data->self_id;
|
||||
ID *id = *cb_data->id_pointer;
|
||||
const int cb_flag = cb_data->cb_flag;
|
||||
|
||||
if (id == nullptr || !ID_IS_LINKED(id)) {
|
||||
return IDWALK_RET_NOP;
|
||||
}
|
||||
BLI_assert(!ID_IS_LINKED(id_self));
|
||||
BLI_assert(!ID_IS_LINKED(self_id));
|
||||
BLI_assert((cb_flag & IDWALK_CB_INDIRECT_USAGE) == 0);
|
||||
|
||||
if (id_self->tag & LIB_TAG_RUNTIME) {
|
||||
if (self_id->tag & LIB_TAG_RUNTIME) {
|
||||
return IDWALK_RET_NOP;
|
||||
}
|
||||
|
||||
|
@ -1383,7 +1383,7 @@ static bool do_history(const char *name, ReportList *reports)
|
|||
if (BLI_exists(tempname1)) {
|
||||
SNPRINTF(tempname2, "%s%d", name, hisnr);
|
||||
|
||||
if (BLI_rename(tempname1, tempname2)) {
|
||||
if (BLI_rename_overwrite(tempname1, tempname2)) {
|
||||
BKE_report(reports, RPT_ERROR, "Unable to make version backup");
|
||||
return true;
|
||||
}
|
||||
|
@ -1395,7 +1395,7 @@ static bool do_history(const char *name, ReportList *reports)
|
|||
if (BLI_exists(name)) {
|
||||
SNPRINTF(tempname1, "%s%d", name, hisnr);
|
||||
|
||||
if (BLI_rename(name, tempname1)) {
|
||||
if (BLI_rename_overwrite(name, tempname1)) {
|
||||
BKE_report(reports, RPT_ERROR, "Unable to make version backup");
|
||||
return true;
|
||||
}
|
||||
|
@ -1562,7 +1562,7 @@ bool BLO_write_file(Main *mainvar,
|
|||
}
|
||||
}
|
||||
|
||||
if (BLI_rename(tempname, filepath) != 0) {
|
||||
if (BLI_rename_overwrite(tempname, filepath) != 0) {
|
||||
BKE_report(reports, RPT_ERROR, "Cannot change old file (file saved with @)");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -462,7 +462,7 @@ static int foreach_id_cow_detect_need_for_update_callback(LibraryIDLinkCallbackD
|
|||
}
|
||||
|
||||
DepsgraphNodeBuilder *builder = static_cast<DepsgraphNodeBuilder *>(cb_data->user_data);
|
||||
ID *id_cow_self = cb_data->id_self;
|
||||
ID *id_cow_self = cb_data->self_id;
|
||||
|
||||
return builder->foreach_id_cow_detect_need_for_update_callback(id_cow_self, id);
|
||||
}
|
||||
|
|
|
@ -180,6 +180,7 @@ set(SRC
|
|||
engines/workbench/workbench_state.cc
|
||||
engines/workbench/workbench_transparent.c
|
||||
engines/workbench/workbench_volume.c
|
||||
engines/workbench/workbench_volume_next.cc
|
||||
engines/external/external_engine.c
|
||||
engines/gpencil/gpencil_antialiasing.c
|
||||
engines/gpencil/gpencil_cache_utils.c
|
||||
|
@ -272,6 +273,7 @@ set(SRC
|
|||
engines/eevee_next/eevee_depth_of_field.hh
|
||||
engines/eevee_next/eevee_engine.h
|
||||
engines/eevee_next/eevee_film.hh
|
||||
engines/eevee_next/eevee_gbuffer.hh
|
||||
engines/eevee_next/eevee_hizbuffer.hh
|
||||
engines/eevee_next/eevee_instance.hh
|
||||
engines/eevee_next/eevee_irradiance_cache.hh
|
||||
|
|
|
@ -57,6 +57,25 @@ bNodeTree *DefaultWorldNodeTree::nodetree_get(::World *wo)
|
|||
*
|
||||
* \{ */
|
||||
|
||||
World::~World()
|
||||
{
|
||||
if (default_world_ != nullptr) {
|
||||
BKE_id_free(nullptr, default_world_);
|
||||
}
|
||||
}
|
||||
|
||||
::World *World::default_world_get()
|
||||
{
|
||||
if (default_world_ == nullptr) {
|
||||
default_world_ = static_cast<::World *>(BKE_id_new_nomain(ID_WO, "EEVEEE default world"));
|
||||
copy_v3_fl(&default_world_->horr, 0.0f);
|
||||
default_world_->use_nodes = 0;
|
||||
default_world_->nodetree = nullptr;
|
||||
BLI_listbase_clear(&default_world_->gpumaterial);
|
||||
}
|
||||
return default_world_;
|
||||
}
|
||||
|
||||
void World::sync()
|
||||
{
|
||||
// if (inst_.lookdev.sync_world()) {
|
||||
|
@ -65,8 +84,7 @@ void World::sync()
|
|||
|
||||
::World *bl_world = inst_.scene->world;
|
||||
if (bl_world == nullptr) {
|
||||
// bl_world = BKE_world_default();
|
||||
return;
|
||||
bl_world = default_world_get();
|
||||
}
|
||||
|
||||
WorldHandle &wo_handle = inst_.sync.sync_world(bl_world);
|
||||
|
|
|
@ -53,8 +53,13 @@ class World {
|
|||
/* Used to detect if world change. */
|
||||
::World *prev_original_world = nullptr;
|
||||
|
||||
/* Used when the scene doesn't have a world. */
|
||||
::World *default_world_ = nullptr;
|
||||
::World *default_world_get();
|
||||
|
||||
public:
|
||||
World(Instance &inst) : inst_(inst){};
|
||||
~World();
|
||||
|
||||
void sync();
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
/** \name Volume shader base
|
||||
* \{ */
|
||||
|
||||
GPU_SHADER_CREATE_INFO(workbench_volume)
|
||||
GPU_SHADER_CREATE_INFO(workbench_volume_common)
|
||||
.vertex_in(0, Type::VEC3, "pos")
|
||||
.fragment_out(0, Type::VEC4, "fragColor")
|
||||
.sampler(0, ImageType::DEPTH_2D, "depthBuffer")
|
||||
|
@ -16,27 +16,44 @@ GPU_SHADER_CREATE_INFO(workbench_volume)
|
|||
.push_constant(Type::FLOAT, "stepLength")
|
||||
.push_constant(Type::FLOAT, "densityScale")
|
||||
.vertex_source("workbench_volume_vert.glsl")
|
||||
.fragment_source("workbench_volume_frag.glsl")
|
||||
.additional_info("draw_object_infos");
|
||||
.fragment_source("workbench_volume_frag.glsl");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(workbench_volume)
|
||||
.additional_info("workbench_volume_common", "draw_object_infos");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(workbench_next_volume)
|
||||
.define("WORKBENCH_NEXT")
|
||||
.additional_info("workbench_volume_common", "draw_object_infos_new", "draw_view");
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Smoke variation
|
||||
* \{ */
|
||||
|
||||
GPU_SHADER_CREATE_INFO(workbench_volume_smoke)
|
||||
GPU_SHADER_CREATE_INFO(workbench_volume_smoke_common)
|
||||
.define("VOLUME_SMOKE")
|
||||
.sampler(2, ImageType::FLOAT_3D, "flameTexture")
|
||||
.sampler(3, ImageType::FLOAT_1D, "flameColorTexture")
|
||||
.additional_info("draw_mesh", "draw_resource_id_varying");
|
||||
.additional_info("draw_resource_id_varying");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(workbench_volume_object)
|
||||
GPU_SHADER_CREATE_INFO(workbench_volume_object_common)
|
||||
.define("VOLUME_OBJECT")
|
||||
.push_constant(Type::MAT4, "volumeTextureToObject")
|
||||
/* FIXME(fclem): This overflow the push_constant limit. */
|
||||
.push_constant(Type::MAT4, "volumeObjectToTexture")
|
||||
.additional_info("draw_volume", "draw_resource_id_varying");
|
||||
.additional_info("draw_resource_id_varying");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(workbench_volume_smoke)
|
||||
.additional_info("workbench_volume_smoke_common", "draw_mesh");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(workbench_volume_object)
|
||||
.additional_info("workbench_volume_object_common", "draw_volume");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(workbench_next_volume_smoke)
|
||||
.additional_info("workbench_volume_smoke_common", "draw_modelmat_new");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(workbench_next_volume_object)
|
||||
.additional_info("workbench_volume_object_common", "draw_volume_new");
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@ -111,4 +128,10 @@ GPU_SHADER_CREATE_INFO(workbench_volume_slice)
|
|||
|
||||
WORKBENCH_VOLUME_SMOKE_VARIATIONS(workbench_volume, "workbench_volume")
|
||||
|
||||
#define WORKBENCH_NEXT_VOLUME_SMOKE_VARIATIONS(prefix, ...) \
|
||||
WORKBENCH_VOLUME_INTERP_VARIATIONS(prefix##_smoke, "workbench_next_volume_smoke", __VA_ARGS__) \
|
||||
WORKBENCH_VOLUME_INTERP_VARIATIONS(prefix##_object, "workbench_next_volume_object", __VA_ARGS__)
|
||||
|
||||
WORKBENCH_NEXT_VOLUME_SMOKE_VARIATIONS(workbench_next_volume, "workbench_next_volume")
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -209,6 +209,12 @@ vec4 volume_integration(vec3 ray_ori, vec3 ray_dir, float ray_inc, float ray_max
|
|||
/* accumulate and also take into account the transmittance from previous steps */
|
||||
final_scattering += final_transmittance * Lscat;
|
||||
final_transmittance *= Tr;
|
||||
|
||||
if (final_transmittance <= 0.01) {
|
||||
/* Early out */
|
||||
final_transmittance = 0.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return vec4(final_scattering, final_transmittance);
|
||||
|
|
|
@ -34,6 +34,7 @@ class Instance {
|
|||
TransparentDepthPass transparent_depth_ps;
|
||||
|
||||
ShadowPass shadow_ps;
|
||||
VolumePass volume_ps;
|
||||
OutlinePass outline_ps;
|
||||
DofPass dof_ps;
|
||||
AntiAliasingPass anti_aliasing_ps;
|
||||
|
@ -75,6 +76,7 @@ class Instance {
|
|||
transparent_depth_ps.sync(scene_state, resources);
|
||||
|
||||
shadow_ps.sync();
|
||||
volume_ps.sync(resources);
|
||||
outline_ps.sync(resources);
|
||||
dof_ps.sync(resources);
|
||||
anti_aliasing_ps.sync(resources, scene_state.resolution);
|
||||
|
@ -85,6 +87,26 @@ class Instance {
|
|||
resources.material_buf.push_update();
|
||||
}
|
||||
|
||||
Material get_material(ObjectRef ob_ref, eV3DShadingColorType color_type, int slot = 0)
|
||||
{
|
||||
switch (color_type) {
|
||||
case V3D_SHADING_OBJECT_COLOR:
|
||||
return Material(*ob_ref.object);
|
||||
case V3D_SHADING_RANDOM_COLOR:
|
||||
return Material(*ob_ref.object, true);
|
||||
case V3D_SHADING_SINGLE_COLOR:
|
||||
return scene_state.material_override;
|
||||
case V3D_SHADING_VERTEX_COLOR:
|
||||
return scene_state.material_attribute_color;
|
||||
case V3D_SHADING_MATERIAL_COLOR:
|
||||
if (::Material *_mat = BKE_object_material_get_eval(ob_ref.object, slot + 1)) {
|
||||
return Material(*_mat);
|
||||
}
|
||||
default:
|
||||
return Material(*BKE_material_default_empty());
|
||||
}
|
||||
}
|
||||
|
||||
void object_sync(Manager &manager, ObjectRef &ob_ref)
|
||||
{
|
||||
if (scene_state.render_finished) {
|
||||
|
@ -138,9 +160,8 @@ class Instance {
|
|||
if (md && BKE_modifier_is_enabled(scene_state.scene, md, eModifierMode_Realtime)) {
|
||||
FluidModifierData *fmd = (FluidModifierData *)md;
|
||||
if (fmd->domain) {
|
||||
#if 0 /* TODO(@pragma37): */
|
||||
workbench_volume_cache_populate(vedata, wpd->scene, ob, md, V3D_SHADING_SINGLE_COLOR);
|
||||
#endif
|
||||
volume_ps.object_sync_modifier(manager, resources, scene_state, ob_ref, md);
|
||||
|
||||
if (fmd->domain->type == FLUID_DOMAIN_TYPE_GAS) {
|
||||
return; /* Do not draw solid in this case. */
|
||||
}
|
||||
|
@ -163,14 +184,16 @@ class Instance {
|
|||
#if 0 /* TODO(@pragma37): */
|
||||
DRWShadingGroup *grp = workbench_material_hair_setup(
|
||||
wpd, ob, CURVES_MATERIAL_NR, object_state.color_type);
|
||||
DRW_shgroup_curves_create_sub(ob, grp, NULL);
|
||||
DRW_shgroup_curves_create_sub(ob, grp, nullptr);
|
||||
#endif
|
||||
}
|
||||
else if (ob->type == OB_VOLUME) {
|
||||
if (scene_state.shading.type != OB_WIRE) {
|
||||
#if 0 /* TODO(@pragma37): */
|
||||
workbench_volume_cache_populate(vedata, wpd->scene, ob, NULL, object_state.color_type);
|
||||
#endif
|
||||
volume_ps.object_sync_volume(manager,
|
||||
resources,
|
||||
scene_state,
|
||||
ob_ref,
|
||||
get_material(ob_ref, object_state.color_type).base_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -204,15 +227,7 @@ class Instance {
|
|||
continue;
|
||||
}
|
||||
|
||||
Material mat;
|
||||
|
||||
if (::Material *_mat = BKE_object_material_get_eval(ob_ref.object, i + 1)) {
|
||||
mat = Material(*_mat);
|
||||
}
|
||||
else {
|
||||
mat = Material(*BKE_material_default_empty());
|
||||
}
|
||||
|
||||
Material mat = get_material(ob_ref, object_state.color_type, i);
|
||||
has_transparent_material = has_transparent_material || mat.is_transparent();
|
||||
|
||||
::Image *image = nullptr;
|
||||
|
@ -244,24 +259,7 @@ class Instance {
|
|||
}
|
||||
|
||||
if (batch) {
|
||||
Material mat;
|
||||
|
||||
if (object_state.color_type == V3D_SHADING_OBJECT_COLOR) {
|
||||
mat = Material(*ob_ref.object);
|
||||
}
|
||||
else if (object_state.color_type == V3D_SHADING_RANDOM_COLOR) {
|
||||
mat = Material(*ob_ref.object, true);
|
||||
}
|
||||
else if (object_state.color_type == V3D_SHADING_SINGLE_COLOR) {
|
||||
mat = scene_state.material_override;
|
||||
}
|
||||
else if (object_state.color_type == V3D_SHADING_VERTEX_COLOR) {
|
||||
mat = scene_state.material_attribute_color;
|
||||
}
|
||||
else {
|
||||
mat = Material(*BKE_material_default_empty());
|
||||
}
|
||||
|
||||
Material mat = get_material(ob_ref, object_state.color_type);
|
||||
has_transparent_material = has_transparent_material || mat.is_transparent();
|
||||
|
||||
draw_mesh(ob_ref,
|
||||
|
@ -370,8 +368,7 @@ class Instance {
|
|||
transparent_ps.draw(manager, view, resources, resolution);
|
||||
transparent_depth_ps.draw(manager, view, resources);
|
||||
|
||||
// volume_ps.draw_prepass(manager, view, resources.depth_tx);
|
||||
|
||||
volume_ps.draw(manager, view, resources);
|
||||
outline_ps.draw(manager, resources);
|
||||
dof_ps.draw(manager, view, resources, resolution);
|
||||
anti_aliasing_ps.draw(manager, view, resources, resolution, depth_tx, color_tx);
|
||||
|
|
|
@ -324,6 +324,52 @@ class ShadowPass {
|
|||
bool force_fail_method);
|
||||
};
|
||||
|
||||
class VolumePass {
|
||||
bool active_ = true;
|
||||
|
||||
PassMain ps_ = {"Volume"};
|
||||
Framebuffer fb_ = {"Volume"};
|
||||
|
||||
Texture dummy_shadow_tx_ = {"Volume.Dummy Shadow Tx"};
|
||||
Texture dummy_volume_tx_ = {"Volume.Dummy Volume Tx"};
|
||||
Texture dummy_coba_tx_ = {"Volume.Dummy Coba Tx"};
|
||||
|
||||
GPUShader *shaders_[2 /*slice*/][2 /*coba*/][3 /*interpolation*/][2 /*smoke*/];
|
||||
|
||||
public:
|
||||
void sync(SceneResources &resources);
|
||||
|
||||
void object_sync_volume(Manager &manager,
|
||||
SceneResources &resources,
|
||||
const SceneState &scene_state,
|
||||
ObjectRef &ob_ref,
|
||||
float3 color);
|
||||
|
||||
void object_sync_modifier(Manager &manager,
|
||||
SceneResources &resources,
|
||||
const SceneState &scene_state,
|
||||
ObjectRef &ob_ref,
|
||||
ModifierData *md);
|
||||
|
||||
void draw(Manager &manager, View &view, SceneResources &resources);
|
||||
|
||||
private:
|
||||
GPUShader *get_shader(bool slice, bool coba, int interpolation, bool smoke);
|
||||
|
||||
void draw_slice_ps(Manager &manager,
|
||||
PassMain::Sub &ps,
|
||||
ObjectRef &ob_ref,
|
||||
int slice_axis_enum,
|
||||
float slice_depth);
|
||||
|
||||
void draw_volume_ps(Manager &manager,
|
||||
PassMain::Sub &ps,
|
||||
ObjectRef &ob_ref,
|
||||
int taa_sample,
|
||||
float3 slice_count,
|
||||
float3 world_size);
|
||||
};
|
||||
|
||||
class OutlinePass {
|
||||
private:
|
||||
bool enabled_ = false;
|
||||
|
|
|
@ -0,0 +1,256 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "workbench_private.hh"
|
||||
|
||||
#include "BKE_volume.h"
|
||||
#include "BKE_volume_render.h"
|
||||
#include "BLI_rand.h"
|
||||
#include "DNA_fluid_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
|
||||
namespace blender::workbench {
|
||||
|
||||
void VolumePass::sync(SceneResources &resources)
|
||||
{
|
||||
active_ = false;
|
||||
ps_.init();
|
||||
ps_.bind_ubo(WB_WORLD_SLOT, resources.world_buf);
|
||||
|
||||
dummy_shadow_tx_.ensure_3d(GPU_RGBA8, int3(1), GPU_TEXTURE_USAGE_SHADER_READ, float4(1));
|
||||
dummy_volume_tx_.ensure_3d(GPU_RGBA8, int3(1), GPU_TEXTURE_USAGE_SHADER_READ, float4(0));
|
||||
dummy_coba_tx_.ensure_1d(GPU_RGBA8, 1, GPU_TEXTURE_USAGE_SHADER_READ, float4(0));
|
||||
}
|
||||
|
||||
void VolumePass::object_sync_volume(Manager &manager,
|
||||
SceneResources &resources,
|
||||
const SceneState &scene_state,
|
||||
ObjectRef &ob_ref,
|
||||
float3 color)
|
||||
{
|
||||
Object *ob = ob_ref.object;
|
||||
/* Create 3D textures. */
|
||||
Volume *volume = static_cast<Volume *>(ob->data);
|
||||
BKE_volume_load(volume, G.main);
|
||||
const VolumeGrid *volume_grid = BKE_volume_grid_active_get_for_read(volume);
|
||||
if (volume_grid == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
DRWVolumeGrid *grid = DRW_volume_batch_cache_get_grid(volume, volume_grid);
|
||||
if (grid == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
active_ = true;
|
||||
|
||||
PassMain::Sub &sub_ps = ps_.sub(ob->id.name);
|
||||
|
||||
const bool use_slice = (volume->display.axis_slice_method == AXIS_SLICE_SINGLE);
|
||||
|
||||
sub_ps.shader_set(get_shader(use_slice, false, volume->display.interpolation_method, false));
|
||||
|
||||
const float density_scale = volume->display.density *
|
||||
BKE_volume_density_scale(volume, ob->object_to_world);
|
||||
|
||||
sub_ps.bind_texture("depthBuffer", &resources.depth_tx);
|
||||
sub_ps.bind_texture("densityTexture", grid->texture);
|
||||
/* TODO: implement shadow texture, see manta_smoke_calc_transparency. */
|
||||
sub_ps.bind_texture("shadowTexture", dummy_shadow_tx_);
|
||||
sub_ps.push_constant("activeColor", color);
|
||||
sub_ps.push_constant("densityScale", density_scale);
|
||||
sub_ps.push_constant("volumeObjectToTexture", float4x4(grid->object_to_texture));
|
||||
sub_ps.push_constant("volumeTextureToObject", float4x4(grid->texture_to_object));
|
||||
|
||||
if (use_slice) {
|
||||
draw_slice_ps(
|
||||
manager, sub_ps, ob_ref, volume->display.slice_axis, volume->display.slice_depth);
|
||||
}
|
||||
else {
|
||||
float3 world_size;
|
||||
float4x4 texture_to_world = float4x4(ob->object_to_world) * float4x4(grid->texture_to_object);
|
||||
math::normalize_and_get_size(float3x3(texture_to_world), world_size);
|
||||
|
||||
int3 resolution;
|
||||
GPU_texture_get_mipmap_size(grid->texture, 0, resolution);
|
||||
float3 slice_count = float3(resolution) * 5.0f;
|
||||
|
||||
draw_volume_ps(manager, sub_ps, ob_ref, scene_state.sample, slice_count, world_size);
|
||||
}
|
||||
}
|
||||
|
||||
void VolumePass::object_sync_modifier(Manager &manager,
|
||||
SceneResources &resources,
|
||||
const SceneState &scene_state,
|
||||
ObjectRef &ob_ref,
|
||||
ModifierData *md)
|
||||
{
|
||||
Object *ob = ob_ref.object;
|
||||
|
||||
FluidModifierData *modifier = reinterpret_cast<FluidModifierData *>(md);
|
||||
FluidDomainSettings &settings = *modifier->domain;
|
||||
|
||||
if (!settings.fluid) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool can_load = false;
|
||||
if (settings.use_coba) {
|
||||
DRW_smoke_ensure_coba_field(modifier);
|
||||
can_load = settings.tex_field != nullptr;
|
||||
}
|
||||
else if (settings.type == FLUID_DOMAIN_TYPE_GAS) {
|
||||
DRW_smoke_ensure(modifier, settings.flags & FLUID_DOMAIN_USE_NOISE);
|
||||
can_load = settings.tex_density != nullptr || settings.tex_color != nullptr;
|
||||
}
|
||||
|
||||
if (!can_load) {
|
||||
return;
|
||||
}
|
||||
|
||||
active_ = true;
|
||||
|
||||
PassMain::Sub &sub_ps = ps_.sub(ob->id.name);
|
||||
|
||||
const bool use_slice = settings.axis_slice_method == AXIS_SLICE_SINGLE;
|
||||
|
||||
sub_ps.shader_set(get_shader(use_slice, settings.use_coba, settings.interp_method, true));
|
||||
|
||||
if (settings.use_coba) {
|
||||
const bool show_flags = settings.coba_field == FLUID_DOMAIN_FIELD_FLAGS;
|
||||
const bool show_pressure = settings.coba_field == FLUID_DOMAIN_FIELD_PRESSURE;
|
||||
const bool show_phi = ELEM(settings.coba_field,
|
||||
FLUID_DOMAIN_FIELD_PHI,
|
||||
FLUID_DOMAIN_FIELD_PHI_IN,
|
||||
FLUID_DOMAIN_FIELD_PHI_OUT,
|
||||
FLUID_DOMAIN_FIELD_PHI_OBSTACLE);
|
||||
|
||||
sub_ps.push_constant("showFlags", show_flags);
|
||||
sub_ps.push_constant("showPressure", show_pressure);
|
||||
sub_ps.push_constant("showPhi", show_phi);
|
||||
sub_ps.push_constant("gridScale", settings.grid_scale);
|
||||
|
||||
if (show_flags) {
|
||||
sub_ps.bind_texture("flagTexture", settings.tex_field);
|
||||
}
|
||||
else {
|
||||
sub_ps.bind_texture("densityTexture", settings.tex_field);
|
||||
}
|
||||
|
||||
if (!show_flags && !show_pressure && !show_phi) {
|
||||
sub_ps.bind_texture("transferTexture", settings.tex_coba);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool use_constant_color = ((settings.active_fields & FLUID_DOMAIN_ACTIVE_COLORS) == 0 &&
|
||||
(settings.active_fields & FLUID_DOMAIN_ACTIVE_COLOR_SET) != 0);
|
||||
|
||||
sub_ps.push_constant("activeColor",
|
||||
use_constant_color ? float3(settings.active_color) : float3(1));
|
||||
|
||||
sub_ps.bind_texture("densityTexture",
|
||||
settings.tex_color ? settings.tex_color : settings.tex_density);
|
||||
sub_ps.bind_texture("flameTexture",
|
||||
settings.tex_flame ? settings.tex_flame : dummy_volume_tx_);
|
||||
sub_ps.bind_texture("flameColorTexture",
|
||||
settings.tex_flame ? settings.tex_flame_coba : dummy_coba_tx_);
|
||||
sub_ps.bind_texture("shadowTexture", settings.tex_shadow);
|
||||
}
|
||||
|
||||
sub_ps.push_constant("densityScale", 10.0f * settings.display_thickness);
|
||||
sub_ps.bind_texture("depthBuffer", &resources.depth_tx);
|
||||
|
||||
if (use_slice) {
|
||||
draw_slice_ps(manager, sub_ps, ob_ref, settings.slice_axis, settings.slice_depth);
|
||||
}
|
||||
else {
|
||||
float3 world_size;
|
||||
BKE_object_dimensions_get(ob, world_size);
|
||||
|
||||
float3 slice_count = float3(settings.res) * std::max(0.001f, settings.slice_per_voxel);
|
||||
|
||||
draw_volume_ps(manager, sub_ps, ob_ref, scene_state.sample, slice_count, world_size);
|
||||
}
|
||||
}
|
||||
|
||||
void VolumePass::draw(Manager &manager, View &view, SceneResources &resources)
|
||||
{
|
||||
if (!active_) {
|
||||
return;
|
||||
}
|
||||
fb_.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(resources.color_tx));
|
||||
fb_.bind();
|
||||
manager.submit(ps_, view);
|
||||
}
|
||||
|
||||
GPUShader *VolumePass::get_shader(bool slice, bool coba, int interpolation, bool smoke)
|
||||
{
|
||||
GPUShader *&shader = shaders_[slice][coba][interpolation][smoke];
|
||||
|
||||
if (shader == nullptr) {
|
||||
std::string create_info_name = "workbench_next_volume";
|
||||
create_info_name += (smoke) ? "_smoke" : "_object";
|
||||
switch (interpolation) {
|
||||
case VOLUME_DISPLAY_INTERP_LINEAR:
|
||||
create_info_name += "_linear";
|
||||
break;
|
||||
case VOLUME_DISPLAY_INTERP_CUBIC:
|
||||
create_info_name += "_cubic";
|
||||
break;
|
||||
case VOLUME_DISPLAY_INTERP_CLOSEST:
|
||||
create_info_name += "_closest";
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
create_info_name += (coba) ? "_coba" : "_no_coba";
|
||||
create_info_name += (slice) ? "_slice" : "_no_slice";
|
||||
shader = GPU_shader_create_from_info_name(create_info_name.c_str());
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
void VolumePass::draw_slice_ps(
|
||||
Manager &manager, PassMain::Sub &ps, ObjectRef &ob_ref, int slice_axis_enum, float slice_depth)
|
||||
{
|
||||
float4x4 view_mat_inv;
|
||||
DRW_view_viewmat_get(nullptr, view_mat_inv.ptr(), true);
|
||||
|
||||
const int axis = (slice_axis_enum == SLICE_AXIS_AUTO) ?
|
||||
axis_dominant_v3_single(view_mat_inv[2]) :
|
||||
slice_axis_enum - 1;
|
||||
|
||||
float3 dimensions;
|
||||
BKE_object_dimensions_get(ob_ref.object, dimensions);
|
||||
/* 0.05f to achieve somewhat the same opacity as the full view. */
|
||||
float step_length = std::max(1e-16f, dimensions[axis] * 0.05f);
|
||||
|
||||
ps.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL);
|
||||
ps.push_constant("slicePosition", slice_depth);
|
||||
ps.push_constant("sliceAxis", axis);
|
||||
ps.push_constant("stepLength", step_length);
|
||||
|
||||
ps.draw(DRW_cache_quad_get(), manager.resource_handle(ob_ref));
|
||||
}
|
||||
|
||||
void VolumePass::draw_volume_ps(Manager &manager,
|
||||
PassMain::Sub &ps,
|
||||
ObjectRef &ob_ref,
|
||||
int taa_sample,
|
||||
float3 slice_count,
|
||||
float3 world_size)
|
||||
{
|
||||
double noise_offset;
|
||||
BLI_halton_1d(3, 0.0, taa_sample, &noise_offset);
|
||||
|
||||
int max_slice = std::max({UNPACK3(slice_count)});
|
||||
float step_length = math::length((1.0f / slice_count) * world_size);
|
||||
|
||||
ps.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL | DRW_STATE_CULL_FRONT);
|
||||
ps.push_constant("samplesLen", max_slice);
|
||||
ps.push_constant("stepLength", step_length);
|
||||
ps.push_constant("noiseOfs", float(noise_offset));
|
||||
|
||||
ps.draw(DRW_cache_cube_get(), manager.resource_handle(ob_ref));
|
||||
}
|
||||
|
||||
} // namespace blender::workbench
|
|
@ -126,6 +126,9 @@ GPU_SHADER_CREATE_INFO(draw_pointcloud)
|
|||
|
||||
GPU_SHADER_CREATE_INFO(draw_volume).additional_info("draw_modelmat", "draw_resource_id_uniform");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(draw_volume_new)
|
||||
.additional_info("draw_modelmat_new", "draw_resource_handle_new");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(draw_gpencil)
|
||||
.typedef_source("gpencil_shader_shared.h")
|
||||
.define("DRW_GPENCIL_INFO")
|
||||
|
|
|
@ -2360,13 +2360,14 @@ void ANIM_OT_keyframe_clear_v3d(wmOperatorType *ot)
|
|||
ot->idname = "ANIM_OT_keyframe_clear_v3d";
|
||||
|
||||
/* callbacks */
|
||||
ot->invoke = WM_operator_confirm;
|
||||
ot->invoke = WM_operator_confirm_or_exec;
|
||||
ot->exec = clear_anim_v3d_exec;
|
||||
|
||||
ot->poll = ED_operator_areaactive;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
WM_operator_properties_confirm_or_exec(ot);
|
||||
}
|
||||
|
||||
static int delete_key_v3d_without_keying_set(bContext *C, wmOperator *op)
|
||||
|
@ -2501,13 +2502,14 @@ void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot)
|
|||
ot->idname = "ANIM_OT_keyframe_delete_v3d";
|
||||
|
||||
/* callbacks */
|
||||
ot->invoke = WM_operator_confirm;
|
||||
ot->invoke = WM_operator_confirm_or_exec;
|
||||
ot->exec = delete_key_v3d_exec;
|
||||
|
||||
ot->poll = ED_operator_areaactive;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
WM_operator_properties_confirm_or_exec(ot);
|
||||
}
|
||||
|
||||
/* Insert Key Button Operator ------------------------ */
|
||||
|
|
|
@ -1290,12 +1290,13 @@ void ARMATURE_OT_delete(wmOperatorType *ot)
|
|||
ot->description = "Remove selected bones from the armature";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = WM_operator_confirm;
|
||||
ot->invoke = WM_operator_confirm_or_exec;
|
||||
ot->exec = armature_delete_selected_exec;
|
||||
ot->poll = ED_operator_editarmature;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
WM_operator_properties_confirm_or_exec(ot);
|
||||
}
|
||||
|
||||
static bool armature_dissolve_ebone_cb(const char *bone_name, void *arm_p)
|
||||
|
|
|
@ -709,12 +709,13 @@ void ARMATURE_OT_separate(wmOperatorType *ot)
|
|||
ot->description = "Isolate selected bones into a separate armature";
|
||||
|
||||
/* callbacks */
|
||||
ot->invoke = WM_operator_confirm;
|
||||
ot->invoke = WM_operator_confirm_or_exec;
|
||||
ot->exec = separate_armature_exec;
|
||||
ot->poll = ED_operator_editarmature;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
WM_operator_properties_confirm_or_exec(ot);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -218,9 +218,10 @@ void AssetList::ensurePreviewsJob(const bContext *C)
|
|||
int numfiles = filelist_files_ensure(files);
|
||||
|
||||
filelist_cache_previews_set(files, true);
|
||||
filelist_file_cache_slidingwindow_set(files, 128);
|
||||
/* TODO fetch all previews for now. */
|
||||
filelist_file_cache_block(files, numfiles / 2);
|
||||
/* Add one extra entry to ensure nothing is lost because of integer division. */
|
||||
filelist_file_cache_slidingwindow_set(files, numfiles / 2 + 1);
|
||||
filelist_file_cache_block(files, 0);
|
||||
filelist_cache_previews_update(files);
|
||||
|
||||
{
|
||||
|
|
|
@ -462,7 +462,7 @@ static int asset_catalog_new_exec(bContext *C, wmOperator *op)
|
|||
char *parent_path = RNA_string_get_alloc(op->ptr, "parent_path", nullptr, 0, nullptr);
|
||||
|
||||
blender::asset_system::AssetCatalog *new_catalog = ED_asset_catalog_add(
|
||||
asset_library, "Catalog", parent_path);
|
||||
asset_library, DATA_("Catalog"), parent_path);
|
||||
|
||||
if (sfile) {
|
||||
ED_fileselect_activate_asset_catalog(sfile, new_catalog->catalog_id);
|
||||
|
|
|
@ -1446,12 +1446,13 @@ void CURVE_OT_separate(wmOperatorType *ot)
|
|||
ot->description = "Separate selected points from connected unselected points into a new object";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = WM_operator_confirm;
|
||||
ot->invoke = WM_operator_confirm_or_exec;
|
||||
ot->exec = separate_exec;
|
||||
ot->poll = ED_operator_editsurfcurve;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
WM_operator_properties_confirm_or_exec(ot);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "BKE_node.hh"
|
||||
#include "BKE_node_runtime.hh"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "ED_curves.h"
|
||||
#include "ED_node.h"
|
||||
#include "ED_object.h"
|
||||
|
@ -63,9 +65,9 @@ void ensure_surface_deformation_node_exists(bContext &C, Object &curves_ob)
|
|||
Scene *scene = CTX_data_scene(&C);
|
||||
|
||||
ModifierData *md = ED_object_modifier_add(
|
||||
nullptr, bmain, scene, &curves_ob, "Surface Deform", eModifierType_Nodes);
|
||||
nullptr, bmain, scene, &curves_ob, DATA_("Surface Deform"), eModifierType_Nodes);
|
||||
NodesModifierData &nmd = *reinterpret_cast<NodesModifierData *>(md);
|
||||
nmd.node_group = ntreeAddTree(bmain, "Surface Deform", "GeometryNodeTree");
|
||||
nmd.node_group = ntreeAddTree(bmain, DATA_("Surface Deform"), "GeometryNodeTree");
|
||||
|
||||
bNodeTree *ntree = nmd.node_group;
|
||||
ntreeAddSocketInterface(ntree, SOCK_IN, "NodeSocketGeometry", "Geometry");
|
||||
|
|
|
@ -120,21 +120,6 @@ static V3DSnapCursorState *gizmo_snap_state_from_rna_get(struct PointerRNA *ptr)
|
|||
return ED_view3d_cursor_snap_state_active_get();
|
||||
}
|
||||
|
||||
static int gizmo_snap_rna_snap_elements_force_get_fn(struct PointerRNA *ptr,
|
||||
struct PropertyRNA *UNUSED(prop))
|
||||
{
|
||||
V3DSnapCursorState *snap_state = gizmo_snap_state_from_rna_get(ptr);
|
||||
return snap_state->snap_elem_force;
|
||||
}
|
||||
|
||||
static void gizmo_snap_rna_snap_elements_force_set_fn(struct PointerRNA *ptr,
|
||||
struct PropertyRNA *UNUSED(prop),
|
||||
int value)
|
||||
{
|
||||
V3DSnapCursorState *snap_state = gizmo_snap_state_from_rna_get(ptr);
|
||||
snap_state->snap_elem_force = (short)value;
|
||||
}
|
||||
|
||||
static void gizmo_snap_rna_prevpoint_get_fn(struct PointerRNA *ptr,
|
||||
struct PropertyRNA *UNUSED(prop),
|
||||
float *values)
|
||||
|
@ -336,17 +321,6 @@ static void GIZMO_GT_snap_3d(wmGizmoType *gzt)
|
|||
|
||||
/* Setup. */
|
||||
PropertyRNA *prop;
|
||||
prop = RNA_def_enum_flag(gzt->srna,
|
||||
"snap_elements_force",
|
||||
rna_enum_snap_element_items,
|
||||
SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE_RAYCAST,
|
||||
"Snap Elements",
|
||||
"");
|
||||
RNA_def_property_enum_funcs_runtime(prop,
|
||||
gizmo_snap_rna_snap_elements_force_get_fn,
|
||||
gizmo_snap_rna_snap_elements_force_set_fn,
|
||||
NULL);
|
||||
|
||||
prop = RNA_def_float_array(gzt->srna,
|
||||
"prev_point",
|
||||
3,
|
||||
|
|
|
@ -290,17 +290,6 @@ typedef enum {
|
|||
V3D_SNAPCURSOR_SNAP_EDIT_GEOM_CAGE = 1 << 4,
|
||||
} eV3DSnapCursor;
|
||||
|
||||
typedef enum {
|
||||
V3D_PLACE_DEPTH_SURFACE = 0,
|
||||
V3D_PLACE_DEPTH_CURSOR_PLANE = 1,
|
||||
V3D_PLACE_DEPTH_CURSOR_VIEW = 2,
|
||||
} eV3DPlaceDepth;
|
||||
|
||||
typedef enum {
|
||||
V3D_PLACE_ORIENT_SURFACE = 0,
|
||||
V3D_PLACE_ORIENT_DEFAULT = 1,
|
||||
} eV3DPlaceOrient;
|
||||
|
||||
typedef struct V3DSnapCursorData {
|
||||
eSnapMode snap_elem;
|
||||
float loc[3];
|
||||
|
@ -317,16 +306,11 @@ typedef struct V3DSnapCursorData {
|
|||
typedef struct V3DSnapCursorState {
|
||||
/* Setup. */
|
||||
eV3DSnapCursor flag;
|
||||
eV3DPlaceDepth plane_depth;
|
||||
eV3DPlaceOrient plane_orient;
|
||||
uchar color_line[4];
|
||||
uchar color_point[4];
|
||||
uchar color_box[4];
|
||||
float *prevpoint;
|
||||
float box_dimensions[3];
|
||||
eSnapMode snap_elem_force; /* If SCE_SNAP_MODE_NONE, use scene settings. */
|
||||
short plane_axis;
|
||||
bool use_plane_axis_auto;
|
||||
bool draw_point;
|
||||
bool draw_plane;
|
||||
bool draw_box;
|
||||
|
|
|
@ -191,8 +191,15 @@ static void ui_popup_menu_create_block(bContext *C,
|
|||
if (!pup->but) {
|
||||
pup->block->flag |= UI_BLOCK_NO_FLIP;
|
||||
}
|
||||
/* A title is only provided when a Menu has a label, this is not alwas the case, see e.g.
|
||||
* `VIEW3D_MT_edit_mesh_context_menu` -- this specifies its own label inside the draw function
|
||||
* depending on vertex/edge/face mode. We still want to flag the uiBlock (but only insert into
|
||||
* the puphash if we have a title provided). Choosing an entry in a menu will still handle
|
||||
* puphash later (see `button_activate_exit`) though multiple menus without a label might fight
|
||||
* for the same storage of the menu memory. Using idname instead (or in combination with the
|
||||
* label) for the hash could be looked at to solve this. */
|
||||
pup->block->flag |= UI_BLOCK_POPUP_MEMORY;
|
||||
if (title && title[0]) {
|
||||
pup->block->flag |= UI_BLOCK_POPUP_MEMORY;
|
||||
pup->block->puphash = ui_popup_menu_hash(title);
|
||||
}
|
||||
pup->layout = UI_block_layout(
|
||||
|
|
|
@ -1228,6 +1228,7 @@ static uiBut *template_id_def_new_but(uiBlock *block,
|
|||
BLT_I18NCONTEXT_ID_POINTCLOUD,
|
||||
BLT_I18NCONTEXT_ID_VOLUME,
|
||||
BLT_I18NCONTEXT_ID_SIMULATION, );
|
||||
BLT_I18N_MSGID_MULTI_CTXT("New", BLT_I18NCONTEXT_ID_PAINTCURVE, );
|
||||
/* NOTE: BLT_I18N_MSGID_MULTI_CTXT takes a maximum number of parameters,
|
||||
* check the definition to see if a new call must be added when the limit
|
||||
* is exceeded. */
|
||||
|
|
|
@ -1505,12 +1505,13 @@ void MASK_OT_delete(wmOperatorType *ot)
|
|||
ot->idname = "MASK_OT_delete";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = WM_operator_confirm;
|
||||
ot->invoke = WM_operator_confirm_or_exec;
|
||||
ot->exec = delete_exec;
|
||||
ot->poll = ED_maskedit_mask_visible_splines_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
WM_operator_properties_confirm_or_exec(ot);
|
||||
}
|
||||
|
||||
/* *** switch direction *** */
|
||||
|
|
|
@ -631,12 +631,13 @@ void MBALL_OT_delete_metaelems(wmOperatorType *ot)
|
|||
ot->idname = "MBALL_OT_delete_metaelems";
|
||||
|
||||
/* callback functions */
|
||||
ot->invoke = WM_operator_confirm;
|
||||
ot->invoke = WM_operator_confirm_or_exec;
|
||||
ot->exec = delete_metaelems_exec;
|
||||
ot->poll = ED_operator_editmball;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
WM_operator_properties_confirm_or_exec(ot);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -306,12 +306,13 @@ void OBJECT_OT_vertex_parent_set(wmOperatorType *ot)
|
|||
ot->idname = "OBJECT_OT_vertex_parent_set";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = WM_operator_confirm;
|
||||
ot->invoke = WM_operator_confirm_or_exec;
|
||||
ot->poll = vertex_parent_set_poll;
|
||||
ot->exec = vertex_parent_set_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
WM_operator_properties_confirm_or_exec(ot);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -1125,12 +1126,13 @@ void OBJECT_OT_parent_no_inverse_set(wmOperatorType *ot)
|
|||
ot->idname = "OBJECT_OT_parent_no_inverse_set";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = WM_operator_confirm;
|
||||
ot->invoke = WM_operator_confirm_or_exec;
|
||||
ot->exec = parent_noinv_set_exec;
|
||||
ot->poll = ED_operator_object_active_editable;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
WM_operator_properties_confirm_or_exec(ot);
|
||||
|
||||
RNA_def_boolean(ot->srna,
|
||||
"keep_transform",
|
||||
|
|
|
@ -200,6 +200,7 @@ void DPAINT_OT_type_toggle(wmOperatorType *ot)
|
|||
MOD_DYNAMICPAINT_TYPE_CANVAS,
|
||||
"Type",
|
||||
"");
|
||||
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SIMULATION);
|
||||
ot->prop = prop;
|
||||
}
|
||||
|
||||
|
|
|
@ -584,11 +584,11 @@ static int gather_frames_to_render_for_id(LibraryIDLinkCallbackData *cb_data)
|
|||
}
|
||||
ID *id = *id_p;
|
||||
|
||||
ID *id_self = cb_data->id_self;
|
||||
ID *self_id = cb_data->self_id;
|
||||
const int cb_flag = cb_data->cb_flag;
|
||||
if (cb_flag == IDWALK_CB_LOOPBACK || id == id_self) {
|
||||
if (cb_flag == IDWALK_CB_LOOPBACK || id == self_id) {
|
||||
/* IDs may end up referencing themselves one way or the other, and those
|
||||
* (the id_self ones) have always already been processed. */
|
||||
* (the self_id ones) have always already been processed. */
|
||||
return IDWALK_RET_STOP_RECURSION;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
#include "BLI_math_vector.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_paint.h"
|
||||
|
@ -147,7 +149,7 @@ static int paintcurve_new_exec(bContext *C, wmOperator * /*op*/)
|
|||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
if (p && p->brush) {
|
||||
p->brush->paint_curve = BKE_paint_curve_add(bmain, "PaintCurve");
|
||||
p->brush->paint_curve = BKE_paint_curve_add(bmain, DATA_("PaintCurve"));
|
||||
}
|
||||
|
||||
WM_event_add_notifier(C, NC_PAINTCURVE | NA_ADDED, nullptr);
|
||||
|
@ -181,7 +183,7 @@ static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2])
|
|||
|
||||
PaintCurve *pc = br->paint_curve;
|
||||
if (!pc) {
|
||||
br->paint_curve = pc = BKE_paint_curve_add(bmain, "PaintCurve");
|
||||
br->paint_curve = pc = BKE_paint_curve_add(bmain, DATA_("PaintCurve"));
|
||||
}
|
||||
|
||||
ED_paintcurve_undo_push_begin(op->type->name);
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
#include "BKE_mesh_mapping.h"
|
||||
#include "BKE_mesh_runtime.h"
|
||||
#include "BKE_node.hh"
|
||||
#include "BKE_node_runtime.hh"
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_scene.h"
|
||||
|
@ -6636,7 +6637,9 @@ static void default_paint_slot_color_get(int layer_type, Material *ma, float col
|
|||
case LAYER_ROUGHNESS:
|
||||
case LAYER_METALLIC: {
|
||||
bNodeTree *ntree = nullptr;
|
||||
bNode *in_node = ma ? blender::bke::ntreeFindType(ma->nodetree, SH_NODE_BSDF_PRINCIPLED) : nullptr;
|
||||
ma->nodetree->ensure_topology_cache();
|
||||
const blender::Span<bNode *> nodes = ma->nodetree->nodes_by_type("ShaderNodeBsdfPrincipled");
|
||||
bNode *in_node = nodes.is_empty() ? nullptr : nodes.first();
|
||||
if (!in_node) {
|
||||
/* An existing material or Principled BSDF node could not be found.
|
||||
* Copy default color values from a default Principled BSDF instead. */
|
||||
|
@ -6740,7 +6743,9 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
|
|||
nodeSetActive(ntree, new_node);
|
||||
|
||||
/* Connect to first available principled BSDF node. */
|
||||
bNode *in_node = blender::bke::ntreeFindType(ntree, SH_NODE_BSDF_PRINCIPLED);
|
||||
ntree->ensure_topology_cache();
|
||||
const blender::Span<bNode *> bsdf_nodes = ntree->nodes_by_type("ShaderNodeBsdfPrincipled");
|
||||
bNode *in_node = bsdf_nodes.is_empty() ? nullptr : bsdf_nodes.first();
|
||||
bNode *out_node = new_node;
|
||||
|
||||
if (in_node != nullptr) {
|
||||
|
@ -6776,7 +6781,9 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
|
|||
}
|
||||
else if (type == LAYER_DISPLACEMENT) {
|
||||
/* Connect to the displacement output socket */
|
||||
in_node = blender::bke::ntreeFindType(ntree, SH_NODE_OUTPUT_MATERIAL);
|
||||
const blender::Span<bNode *> output_nodes = ntree->nodes_by_type(
|
||||
"ShaderNodeOutputMaterial");
|
||||
in_node = output_nodes.is_empty() ? nullptr : output_nodes.first();
|
||||
|
||||
if (in_node != nullptr) {
|
||||
in_sock = nodeFindSocket(in_node, SOCK_IN, layer_type_items[type].name);
|
||||
|
|
|
@ -532,12 +532,13 @@ void CLIP_OT_graph_delete_curve(wmOperatorType *ot)
|
|||
ot->idname = "CLIP_OT_graph_delete_curve";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = WM_operator_confirm;
|
||||
ot->invoke = WM_operator_confirm_or_exec;
|
||||
ot->exec = delete_curve_exec;
|
||||
ot->poll = clip_graph_knots_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
WM_operator_properties_confirm_or_exec(ot);
|
||||
}
|
||||
|
||||
/******************** delete knot operator ********************/
|
||||
|
|
|
@ -250,12 +250,13 @@ void CLIP_OT_delete_track(wmOperatorType *ot)
|
|||
ot->description = "Delete selected tracks";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = WM_operator_confirm;
|
||||
ot->invoke = WM_operator_confirm_or_exec;
|
||||
ot->exec = delete_track_exec;
|
||||
ot->poll = ED_space_clip_tracking_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
WM_operator_properties_confirm_or_exec(ot);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -315,12 +316,13 @@ void CLIP_OT_delete_marker(wmOperatorType *ot)
|
|||
ot->description = "Delete marker for current frame from selected tracks";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = WM_operator_confirm;
|
||||
ot->invoke = WM_operator_confirm_or_exec;
|
||||
ot->exec = delete_marker_exec;
|
||||
ot->poll = ED_space_clip_tracking_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
WM_operator_properties_confirm_or_exec(ot);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -17,6 +17,7 @@ set(INC
|
|||
../../windowmanager
|
||||
../../../../intern/atomic
|
||||
../../../../intern/guardedalloc
|
||||
../../../../extern/fmtlib/include
|
||||
|
||||
# dna_type_offsets.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../../makesdna/intern
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue