Cleanup: Move BKE_node.h to C++ #107790
|
@ -503,7 +503,7 @@ if(NOT APPLE)
|
|||
mark_as_advanced(WITH_CYCLES_DEVICE_CUDA)
|
||||
|
||||
option(WITH_CYCLES_CUDA_BINARIES "Build Cycles NVIDIA CUDA binaries" OFF)
|
||||
set(CYCLES_CUDA_BINARIES_ARCH sm_30 sm_35 sm_37 sm_50 sm_52 sm_60 sm_61 sm_70 sm_75 sm_86 compute_75 CACHE STRING "CUDA architectures to build binaries for")
|
||||
set(CYCLES_CUDA_BINARIES_ARCH sm_30 sm_35 sm_37 sm_50 sm_52 sm_60 sm_61 sm_70 sm_75 sm_86 sm_89 compute_75 CACHE STRING "CUDA architectures to build binaries for")
|
||||
option(WITH_CYCLES_CUDA_BUILD_SERIAL "Build cubins one after another (useful on machines with limited RAM)" OFF)
|
||||
option(WITH_CUDA_DYNLOAD "Dynamically load CUDA libraries at runtime (for developers, makes cuda-gdb work)" ON)
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ set(EMBREE_EXTRA_ARGS
|
|||
-DEMBREE_BACKFACE_CULLING=OFF
|
||||
-DEMBREE_BACKFACE_CULLING_CURVES=ON
|
||||
-DEMBREE_BACKFACE_CULLING_SPHERES=ON
|
||||
-DEMBREE_NO_SPLASH=ON
|
||||
-DEMBREE_TASKING_SYSTEM=TBB
|
||||
-DEMBREE_TBB_ROOT=${LIBDIR}/tbb
|
||||
-DTBB_ROOT=${LIBDIR}/tbb
|
||||
|
|
|
@ -477,9 +477,9 @@ set(SQLITE_HASH_TYPE SHA1)
|
|||
set(SQLITE_FILE sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz)
|
||||
set(SQLITE_CPE "cpe:2.3:a:sqlite:sqlite:${SQLITE_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(EMBREE_VERSION 4.0.1)
|
||||
set(EMBREE_VERSION 4.1.0)
|
||||
set(EMBREE_URI https://github.com/embree/embree/archive/v${EMBREE_VERSION}.zip)
|
||||
set(EMBREE_HASH dd26617719a587e126b341d1b32f7fd0)
|
||||
set(EMBREE_HASH 4b525955b08e1249a700dea5b5ffc8b2)
|
||||
set(EMBREE_HASH_TYPE MD5)
|
||||
set(EMBREE_FILE embree-v${EMBREE_VERSION}.zip)
|
||||
|
||||
|
|
|
@ -24,144 +24,3 @@ index 7c2f43d..106b1d5 100644
|
|||
DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX2})
|
||||
ADD_LIBRARY(embree_avx2 STATIC ${EMBREE_LIBRARY_FILES_AVX2})
|
||||
TARGET_LINK_LIBRARIES(embree_avx2 PRIVATE tasking)
|
||||
diff --git a/include/embree4/rtcore_device.h b/include/embree4/rtcore_device.h
|
||||
index 45bf95583..62ee7787d 100644
|
||||
--- a/include/embree4/rtcore_device.h
|
||||
+++ b/include/embree4/rtcore_device.h
|
||||
@@ -55,6 +55,7 @@ enum RTCDeviceProperty
|
||||
RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED = 66,
|
||||
RTC_DEVICE_PROPERTY_IGNORE_INVALID_RAYS_ENABLED = 67,
|
||||
RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED = 68,
|
||||
+ RTC_DEVICE_PROPERTY_BACKFACE_CULLING_SPHERES_ENABLED = 69,
|
||||
|
||||
RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED = 96,
|
||||
RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED = 97,
|
||||
diff --git a/kernels/common/device.cpp b/kernels/common/device.cpp
|
||||
index 3ffac7e37..215ccc961 100644
|
||||
--- a/kernels/common/device.cpp
|
||||
+++ b/kernels/common/device.cpp
|
||||
@@ -170,6 +170,9 @@ namespace embree
|
||||
#if defined (EMBREE_BACKFACE_CULLING_CURVES)
|
||||
v += "backfacecullingcurves ";
|
||||
#endif
|
||||
+#if defined (EMBREE_BACKFACE_CULLING_SPHERES)
|
||||
+ v += "backfacecullingspheres ";
|
||||
+#endif
|
||||
#if defined(EMBREE_FILTER_FUNCTION)
|
||||
v += "intersection_filter ";
|
||||
#endif
|
||||
@@ -477,6 +480,12 @@ namespace embree
|
||||
case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED: return 0;
|
||||
#endif
|
||||
|
||||
+#if defined(EMBREE_BACKFACE_CULLING_SPHERES)
|
||||
+ case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_SPHERES_ENABLED: return 1;
|
||||
+#else
|
||||
+ case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_SPHERES_ENABLED: return 0;
|
||||
+#endif
|
||||
+
|
||||
#if defined(EMBREE_COMPACT_POLYS)
|
||||
case RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED: return 1;
|
||||
#else
|
||||
diff --git a/kernels/config.h.in b/kernels/config.h.in
|
||||
index f02c90360..ba9acde56 100644
|
||||
--- a/kernels/config.h.in
|
||||
+++ b/kernels/config.h.in
|
||||
@@ -5,6 +5,7 @@
|
||||
#cmakedefine EMBREE_STAT_COUNTERS
|
||||
#cmakedefine EMBREE_BACKFACE_CULLING
|
||||
#cmakedefine EMBREE_BACKFACE_CULLING_CURVES
|
||||
+#cmakedefine EMBREE_BACKFACE_CULLING_SPHERES
|
||||
#cmakedefine EMBREE_FILTER_FUNCTION
|
||||
#cmakedefine EMBREE_IGNORE_INVALID_RAYS
|
||||
#cmakedefine EMBREE_GEOMETRY_TRIANGLE
|
||||
diff --git a/kernels/geometry/sphere_intersector.h b/kernels/geometry/sphere_intersector.h
|
||||
index 074f910a2..30f490818 100644
|
||||
--- a/kernels/geometry/sphere_intersector.h
|
||||
+++ b/kernels/geometry/sphere_intersector.h
|
||||
@@ -106,8 +106,13 @@ namespace embree
|
||||
const vbool<M> valid_front = valid & (ray.tnear() <= t_front) & (t_front <= ray.tfar);
|
||||
const vbool<M> valid_back = valid & (ray.tnear() <= t_back ) & (t_back <= ray.tfar);
|
||||
|
||||
+#if defined (EMBREE_BACKFACE_CULLING_SPHERES)
|
||||
+ /* check if there is a first hit */
|
||||
+ const vbool<M> valid_first = valid_front;
|
||||
+#else
|
||||
/* check if there is a first hit */
|
||||
const vbool<M> valid_first = valid_front | valid_back;
|
||||
+#endif
|
||||
if (unlikely(none(valid_first)))
|
||||
return false;
|
||||
|
||||
@@ -120,7 +125,8 @@ namespace embree
|
||||
|
||||
/* invoke intersection filter for first hit */
|
||||
const bool is_hit_first = epilog(valid_first, hit);
|
||||
-
|
||||
+
|
||||
+#if !defined (EMBREE_BACKFACE_CULLING_SPHERES)
|
||||
/* check for possible second hits before potentially accepted hit */
|
||||
const vfloat<M> t_second = t_back;
|
||||
const vbool<M> valid_second = valid_front & valid_back & (t_second <= ray.tfar);
|
||||
@@ -131,7 +137,9 @@ namespace embree
|
||||
const Vec3vf<M> Ng_second = td_back * ray_dir - perp;
|
||||
hit = SphereIntersectorHitM<M> (t_second, Ng_second);
|
||||
const bool is_hit_second = epilog(valid_second, hit);
|
||||
-
|
||||
+#else
|
||||
+ constexpr bool is_hit_second = false;
|
||||
+#endif
|
||||
return is_hit_first | is_hit_second;
|
||||
}
|
||||
|
||||
@@ -186,8 +194,13 @@ namespace embree
|
||||
const vbool<M> valid_front = valid & (ray.tnear()[k] <= t_front) & (t_front <= ray.tfar[k]);
|
||||
const vbool<M> valid_back = valid & (ray.tnear()[k] <= t_back ) & (t_back <= ray.tfar[k]);
|
||||
|
||||
+#if defined (EMBREE_BACKFACE_CULLING_SPHERES)
|
||||
+ /* check if there is a first hit */
|
||||
+ const vbool<M> valid_first = valid_front;
|
||||
+#else
|
||||
/* check if there is a first hit */
|
||||
const vbool<M> valid_first = valid_front | valid_back;
|
||||
+#endif
|
||||
if (unlikely(none(valid_first)))
|
||||
return false;
|
||||
|
||||
@@ -200,7 +213,8 @@ namespace embree
|
||||
|
||||
/* invoke intersection filter for first hit */
|
||||
const bool is_hit_first = epilog(valid_first, hit);
|
||||
-
|
||||
+
|
||||
+#if !defined (EMBREE_BACKFACE_CULLING_SPHERES)
|
||||
/* check for possible second hits before potentially accepted hit */
|
||||
const vfloat<M> t_second = t_back;
|
||||
const vbool<M> valid_second = valid_front & valid_back & (t_second <= ray.tfar[k]);
|
||||
@@ -211,7 +225,9 @@ namespace embree
|
||||
const Vec3vf<M> Ng_second = td_back * ray_dir - perp;
|
||||
hit = SphereIntersectorHitM<M> (t_second, Ng_second);
|
||||
const bool is_hit_second = epilog(valid_second, hit);
|
||||
-
|
||||
+#else
|
||||
+ constexpr bool is_hit_second = false;
|
||||
+#endif
|
||||
return is_hit_first | is_hit_second;
|
||||
}
|
||||
};
|
||||
diff -ruN a/kernels/sycl/rthwif_embree_builder.cpp b/kernels/sycl/rthwif_embree_builder.cpp
|
||||
--- a/kernels/sycl/rthwif_embree_builder.cpp 2023-03-28 17:23:06.429190200 +0200
|
||||
+++ b/kernels/sycl/rthwif_embree_builder.cpp 2023-03-28 17:35:01.291938600 +0200
|
||||
@@ -540,7 +540,12 @@
|
||||
assert(offset <= geomDescrData.size());
|
||||
}
|
||||
|
||||
+ /* Force running BVH building sequentially from the calling thread if using TBB < 2021, as it otherwise leads to runtime issues. */
|
||||
+#if TBB_VERSION_MAJOR<2021
|
||||
+ RTHWIF_PARALLEL_OPERATION parallelOperation = nullptr;
|
||||
+#else
|
||||
RTHWIF_PARALLEL_OPERATION parallelOperation = rthwifNewParallelOperation();
|
||||
+#endif
|
||||
|
||||
/* estimate static accel size */
|
||||
BBox1f time_range(0,1);
|
||||
|
|
|
@ -31,7 +31,8 @@ IF(NOT PYTHON_ROOT_DIR AND NOT $ENV{PYTHON_ROOT_DIR} STREQUAL "")
|
|||
SET(PYTHON_ROOT_DIR $ENV{PYTHON_ROOT_DIR})
|
||||
ENDIF()
|
||||
|
||||
SET(PYTHON_VERSION 3.10 CACHE STRING "Python Version (major and minor only)")
|
||||
SET(_PYTHON_VERSION_SUPPORTED 3.10)
|
||||
SET(PYTHON_VERSION ${_PYTHON_VERSION_SUPPORTED} CACHE STRING "Python Version (major and minor only)")
|
||||
MARK_AS_ADVANCED(PYTHON_VERSION)
|
||||
|
||||
|
||||
|
@ -178,8 +179,24 @@ UNSET(_IS_LIB_PATH_DEF)
|
|||
# handle the QUIETLY and REQUIRED arguments and SET PYTHONLIBSUNIX_FOUND to TRUE IF
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonLibsUnix DEFAULT_MSG
|
||||
PYTHON_LIBRARY PYTHON_LIBPATH PYTHON_INCLUDE_DIR PYTHON_INCLUDE_CONFIG_DIR)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonLibsUnix
|
||||
# NOTE(@ideasman42): Instead of `DEFAULT_MSG` use a custom message because users
|
||||
# may have newer versions Python and not be using pre-compiled libraries
|
||||
# (on other UNIX systems or using an esoteric architecture).
|
||||
# Some Python developers might want to use the newer features of Python too.
|
||||
# While we could automatically detect and use newer versions but this would result in
|
||||
# developers using a configuration which isn't officially supported without realizing it.
|
||||
# So warn that the officially supported Python version is not found and let the developer
|
||||
# explicitly set the newer version if they wish.
|
||||
# From a maintenance perspective it's typically not a problem to support newer versions,
|
||||
# doing so can help ease the process of upgrading too, nevertheless these versions don't
|
||||
# have the same level of testing & support.
|
||||
"\
|
||||
'PYTHON_VERSION=${_PYTHON_VERSION_SUPPORTED}' not found! \
|
||||
This is the only officially supported version. \
|
||||
If you wish to use a newer Python version you may set 'PYTHON_VERSION' \
|
||||
however we do not guarantee full compatibility in this case."
|
||||
PYTHON_LIBRARY PYTHON_LIBPATH PYTHON_INCLUDE_DIR PYTHON_INCLUDE_CONFIG_DIR)
|
||||
|
||||
IF(PYTHONLIBSUNIX_FOUND)
|
||||
# Assign cache items
|
||||
|
@ -215,6 +232,7 @@ IF(PYTHONLIBSUNIX_FOUND)
|
|||
ENDIF()
|
||||
|
||||
UNSET(_PYTHON_ABI_FLAGS)
|
||||
UNSET(_PYTHON_VERSION_SUPPORTED)
|
||||
UNSET(_python_SEARCH_DIRS)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
|
|
|
@ -8,6 +8,8 @@ buildbot:
|
|||
version: '10.1.243'
|
||||
cuda11:
|
||||
version: '11.4.1'
|
||||
cuda12:
|
||||
version: '12.1.1'
|
||||
hip:
|
||||
version: '5.5.30571'
|
||||
hiprt:
|
||||
|
|
|
@ -302,10 +302,6 @@
|
|||
* \ingroup imbuf
|
||||
*/
|
||||
|
||||
/** \defgroup imbdds DDS
|
||||
* \ingroup imbuf
|
||||
*/
|
||||
|
||||
/** \defgroup openexr OpenEXR
|
||||
* \ingroup imbuf
|
||||
*/
|
||||
|
|
|
@ -389,7 +389,7 @@ static float4 LerpCurveSegmentMotionCV(ParticleCurveData *CData, int sys, int cu
|
|||
}
|
||||
const float4 mP = CurveSegmentMotionCV(CData, sys, curve, first_curve_key + curvekey);
|
||||
const float4 mP2 = CurveSegmentMotionCV(CData, sys, curve, first_curve_key + curvekey2);
|
||||
return lerp(mP, mP2, remainder);
|
||||
return mix(mP, mP2, remainder);
|
||||
}
|
||||
|
||||
static void export_hair_motion_validate_attribute(Hair *hair,
|
||||
|
@ -899,9 +899,9 @@ static float4 interpolate_curve_points(const float (*b_attr_position)[3],
|
|||
const int point_a = clamp((int)curve_t, 0, num_points - 1);
|
||||
const int point_b = min(point_a + 1, num_points - 1);
|
||||
const float t = curve_t - (float)point_a;
|
||||
return lerp(curve_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_a),
|
||||
curve_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_b),
|
||||
t);
|
||||
return mix(curve_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_a),
|
||||
curve_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_b),
|
||||
t);
|
||||
}
|
||||
|
||||
static void export_hair_curves(Scene *scene,
|
||||
|
|
|
@ -515,6 +515,7 @@ void BlenderSession::render_frame_finish()
|
|||
static bool bake_setup_pass(Scene *scene, const string &bake_type_str, const int bake_filter)
|
||||
{
|
||||
Integrator *integrator = scene->integrator;
|
||||
Film *film = scene->film;
|
||||
const char *bake_type = bake_type_str.c_str();
|
||||
|
||||
PassType type = PASS_NONE;
|
||||
|
@ -542,13 +543,29 @@ static bool bake_setup_pass(Scene *scene, const string &bake_type_str, const int
|
|||
else if (strcmp(bake_type, "ENVIRONMENT") == 0) {
|
||||
type = PASS_BACKGROUND;
|
||||
}
|
||||
/* AO passes. */
|
||||
/* AO pass. */
|
||||
else if (strcmp(bake_type, "AO") == 0) {
|
||||
type = PASS_AO;
|
||||
}
|
||||
/* Shadow pass. */
|
||||
else if (strcmp(bake_type, "SHADOW") == 0) {
|
||||
/* Bake as combined pass, together with marking the object as a shadow catcher. */
|
||||
type = PASS_SHADOW_CATCHER;
|
||||
film->set_use_approximate_shadow_catcher(true);
|
||||
|
||||
use_direct_light = true;
|
||||
use_indirect_light = true;
|
||||
include_albedo = true;
|
||||
|
||||
integrator->set_use_diffuse(true);
|
||||
integrator->set_use_glossy(true);
|
||||
integrator->set_use_transmission(true);
|
||||
integrator->set_use_emission(true);
|
||||
}
|
||||
/* Combined pass. */
|
||||
else if (strcmp(bake_type, "COMBINED") == 0) {
|
||||
type = PASS_COMBINED;
|
||||
film->set_use_approximate_shadow_catcher(true);
|
||||
|
||||
use_direct_light = (bake_filter & BL::BakeSettings::pass_filter_DIRECT) != 0;
|
||||
use_indirect_light = (bake_filter & BL::BakeSettings::pass_filter_INDIRECT) != 0;
|
||||
|
@ -683,17 +700,23 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_,
|
|||
|
||||
/* Object might have been disabled for rendering or excluded in some
|
||||
* other way, in that case Blender will report a warning afterwards. */
|
||||
bool object_found = false;
|
||||
Object *bake_object = nullptr;
|
||||
if (!session->progress.get_cancel()) {
|
||||
foreach (Object *ob, scene->objects) {
|
||||
if (ob->name == b_object.name()) {
|
||||
object_found = true;
|
||||
bake_object = ob;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (object_found && !session->progress.get_cancel()) {
|
||||
/* For the shadow pass, temporarily mark the object as a shadow catcher. */
|
||||
const bool was_shadow_catcher = (bake_object) ? bake_object->get_is_shadow_catcher() : false;
|
||||
if (bake_object && bake_type == "SHADOW") {
|
||||
bake_object->set_is_shadow_catcher(true);
|
||||
}
|
||||
|
||||
if (bake_object && !session->progress.get_cancel()) {
|
||||
/* Get session and buffer parameters. */
|
||||
const SessionParams session_params = BlenderSync::get_session_params(
|
||||
b_engine, b_userpref, b_scene, background);
|
||||
|
@ -714,10 +737,15 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_,
|
|||
}
|
||||
|
||||
/* Perform bake. Check cancel to avoid crash with incomplete scene data. */
|
||||
if (object_found && !session->progress.get_cancel()) {
|
||||
if (bake_object && !session->progress.get_cancel()) {
|
||||
session->start();
|
||||
session->wait();
|
||||
}
|
||||
|
||||
/* Restore object state. */
|
||||
if (bake_object) {
|
||||
bake_object->set_is_shadow_catcher(was_shadow_catcher);
|
||||
}
|
||||
}
|
||||
|
||||
void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_)
|
||||
|
|
|
@ -360,7 +360,7 @@ void BVHSpatialSplit::split_triangle_primitive(const Mesh *mesh,
|
|||
|
||||
/* edge intersects the plane => insert intersection to both boxes. */
|
||||
if ((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
|
||||
float3 t = lerp(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
|
||||
float3 t = mix(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
|
||||
left_bounds.grow(t);
|
||||
right_bounds.grow(t);
|
||||
}
|
||||
|
@ -408,7 +408,7 @@ void BVHSpatialSplit::split_curve_primitive(const Hair *hair,
|
|||
|
||||
/* edge intersects the plane => insert intersection to both boxes. */
|
||||
if ((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
|
||||
float3 t = lerp(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
|
||||
float3 t = mix(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
|
||||
left_bounds.grow(t);
|
||||
right_bounds.grow(t);
|
||||
}
|
||||
|
|
|
@ -122,8 +122,12 @@ bool OneapiDevice::check_peer_access(Device * /*peer_device*/)
|
|||
|
||||
bool OneapiDevice::can_use_hardware_raytracing_for_features(uint requested_features) const
|
||||
{
|
||||
/* MNEE and Ray-trace kernels currently don't work correctly with HWRT. */
|
||||
/* MNEE and Raytrace kernels work correctly with Hardware Raytracing starting with Embree 4.1. */
|
||||
# if defined(RTC_VERSION) && RTC_VERSION < 40100
|
||||
return !(requested_features & (KERNEL_FEATURE_MNEE | KERNEL_FEATURE_NODE_RAYTRACE));
|
||||
# else
|
||||
return true;
|
||||
# endif
|
||||
}
|
||||
|
||||
BVHLayoutMask OneapiDevice::get_bvh_layout_mask(uint requested_features) const
|
||||
|
|
|
@ -62,7 +62,7 @@ bool work_balance_do_rebalance(vector<WorkBalanceInfo> &work_balance_infos)
|
|||
bool has_big_difference = false;
|
||||
|
||||
for (const WorkBalanceInfo &info : work_balance_infos) {
|
||||
const double time_target = lerp(info.time_spent, time_average, lerp_weight);
|
||||
const double time_target = mix(info.time_spent, time_average, lerp_weight);
|
||||
const double new_weight = info.weight * time_target / info.time_spent;
|
||||
new_weights.push_back(new_weight);
|
||||
total_weight += new_weight;
|
||||
|
|
|
@ -540,12 +540,12 @@ if(WITH_CYCLES_CUDA_BINARIES)
|
|||
elseif(${arch} MATCHES ".*_7." AND "${CUDA_VERSION}" LESS 100)
|
||||
message(STATUS "CUDA binaries for ${arch} require CUDA 10.0+, skipped.")
|
||||
elseif(${arch} MATCHES ".*_8.")
|
||||
if(DEFINED CUDA11_NVCC_EXECUTABLE)
|
||||
set(cuda_nvcc_executable ${CUDA11_NVCC_EXECUTABLE})
|
||||
set(cuda_toolkit_root_dir ${CUDA11_TOOLKIT_ROOT_DIR})
|
||||
elseif("${CUDA_VERSION}" GREATER_EQUAL 111) # Support for sm_86 was introduced in CUDA 11
|
||||
if("${CUDA_VERSION}" GREATER_EQUAL 111) # Support for sm_86 was introduced in CUDA 11
|
||||
set(cuda_nvcc_executable ${CUDA_NVCC_EXECUTABLE})
|
||||
set(cuda_toolkit_root_dir ${CUDA_TOOLKIT_ROOT_DIR})
|
||||
elseif(DEFINED CUDA11_NVCC_EXECUTABLE)
|
||||
set(cuda_nvcc_executable ${CUDA11_NVCC_EXECUTABLE})
|
||||
set(cuda_toolkit_root_dir ${CUDA11_TOOLKIT_ROOT_DIR})
|
||||
else()
|
||||
message(STATUS "CUDA binaries for ${arch} require CUDA 11.1+, skipped.")
|
||||
endif()
|
||||
|
|
|
@ -96,7 +96,7 @@ ccl_device_forceinline Spectrum interpolate_fresnel_color(float3 L,
|
|||
{
|
||||
/* Compute the real Fresnel term and remap it from real_F0..1 to F0..1.
|
||||
* The reason why we use this remapping instead of directly doing the
|
||||
* Schlick approximation lerp(F0, 1.0, (1.0-cosLH)^5) is that for cases
|
||||
* Schlick approximation mix(F0, 1.0, (1.0-cosLH)^5) is that for cases
|
||||
* with similar IORs (e.g. ice in water), the relative IOR can be close
|
||||
* enough to 1.0 that the Schlick approximation becomes inaccurate. */
|
||||
float real_F = fresnel_dielectric_cos(dot(L, H), ior);
|
||||
|
|
|
@ -174,27 +174,30 @@ bool oneapi_kernel_is_required_for_features(const std::string &kernel_name,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool oneapi_kernel_is_raytrace_or_mnee(const std::string &kernel_name)
|
||||
bool oneapi_kernel_is_compatible_with_hardware_raytracing(const std::string &kernel_name)
|
||||
{
|
||||
return (kernel_name.find(device_kernel_as_string(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE)) !=
|
||||
std::string::npos) ||
|
||||
/* MNEE and Raytrace kernels work correctly with Hardware Raytracing starting with Embree 4.1.
|
||||
*/
|
||||
# if defined(RTC_VERSION) && RTC_VERSION < 40100
|
||||
return (kernel_name.find(device_kernel_as_string(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE)) ==
|
||||
std::string::npos) &&
|
||||
(kernel_name.find(device_kernel_as_string(
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE)) != std::string::npos);
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE)) == std::string::npos);
|
||||
# else
|
||||
return true;
|
||||
# endif
|
||||
}
|
||||
|
||||
bool oneapi_kernel_is_using_embree(const std::string &kernel_name)
|
||||
bool oneapi_kernel_has_intersections(const std::string &kernel_name)
|
||||
{
|
||||
# ifdef WITH_EMBREE_GPU
|
||||
/* MNEE and Ray-trace kernels aren't yet enabled to use Embree. */
|
||||
for (int i = 0; i < (int)DEVICE_KERNEL_NUM; i++) {
|
||||
DeviceKernel kernel = (DeviceKernel)i;
|
||||
if (device_kernel_has_intersection(kernel)) {
|
||||
if (kernel_name.find(device_kernel_as_string(kernel)) != std::string::npos) {
|
||||
return !oneapi_kernel_is_raytrace_or_mnee(kernel_name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -217,7 +220,8 @@ bool oneapi_load_kernels(SyclQueue *queue_,
|
|||
const std::string &kernel_name = kernel_id.get_name();
|
||||
|
||||
if (!oneapi_kernel_is_required_for_features(kernel_name, kernel_features) ||
|
||||
!oneapi_kernel_is_using_embree(kernel_name))
|
||||
!(oneapi_kernel_has_intersections(kernel_name) &&
|
||||
oneapi_kernel_is_compatible_with_hardware_raytracing(kernel_name)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -260,14 +264,14 @@ bool oneapi_load_kernels(SyclQueue *queue_,
|
|||
/* In case HWRT is on, compilation of kernels using Embree is already handled in previous
|
||||
* block. */
|
||||
if (!oneapi_kernel_is_required_for_features(kernel_name, kernel_features) ||
|
||||
(use_hardware_raytracing && oneapi_kernel_is_using_embree(kernel_name)))
|
||||
(use_hardware_raytracing && oneapi_kernel_has_intersections(kernel_name) &&
|
||||
oneapi_kernel_is_compatible_with_hardware_raytracing(kernel_name)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
# ifdef WITH_EMBREE_GPU
|
||||
if (oneapi_kernel_is_using_embree(kernel_name) ||
|
||||
oneapi_kernel_is_raytrace_or_mnee(kernel_name)) {
|
||||
if (oneapi_kernel_has_intersections(kernel_name)) {
|
||||
sycl::kernel_bundle<sycl::bundle_state::input> one_kernel_bundle_input =
|
||||
sycl::get_kernel_bundle<sycl::bundle_state::input>(queue->get_context(), {kernel_id});
|
||||
one_kernel_bundle_input
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "kernel/film/adaptive_sampling.h"
|
||||
#include "kernel/film/light_passes.h"
|
||||
|
||||
#include "kernel/integrator/intersect_closest.h"
|
||||
#include "kernel/integrator/path_state.h"
|
||||
|
||||
#include "kernel/sample/pattern.h"
|
||||
|
@ -327,6 +328,8 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg,
|
|||
else {
|
||||
integrator_path_init_sorted(kg, state, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE, shader_index);
|
||||
}
|
||||
|
||||
integrator_split_shadow_catcher(kg, state, &isect, render_buffer);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -398,6 +398,7 @@ ccl_device_forceinline bool mnee_newton_solver(KernelGlobals kg,
|
|||
ccl_private const ShaderData *sd,
|
||||
ccl_private ShaderData *sd_vtx,
|
||||
ccl_private const LightSample *ls,
|
||||
const bool light_fixed_direction,
|
||||
int vertex_count,
|
||||
ccl_private ManifoldVertex *vertices)
|
||||
{
|
||||
|
@ -413,7 +414,6 @@ ccl_device_forceinline bool mnee_newton_solver(KernelGlobals kg,
|
|||
projection_ray.time = sd->time;
|
||||
Intersection projection_isect;
|
||||
|
||||
const bool light_fixed_direction = (ls->t == FLT_MAX);
|
||||
const float3 light_sample = light_fixed_direction ? ls->D : ls->P;
|
||||
|
||||
/* We start gently, potentially ramping up to beta = 1, since target configurations
|
||||
|
@ -639,6 +639,7 @@ ccl_device_forceinline Spectrum mnee_eval_bsdf_contribution(ccl_private ShaderCl
|
|||
/* Compute transfer matrix determinant |T1| = |dx1/dxn| (and |dh/dx| in the process) */
|
||||
ccl_device_forceinline bool mnee_compute_transfer_matrix(ccl_private const ShaderData *sd,
|
||||
ccl_private const LightSample *ls,
|
||||
const bool light_fixed_direction,
|
||||
int vertex_count,
|
||||
ccl_private ManifoldVertex *vertices,
|
||||
ccl_private float *dx1_dxlight,
|
||||
|
@ -692,7 +693,7 @@ ccl_device_forceinline bool mnee_compute_transfer_matrix(ccl_private const Shade
|
|||
float dxn_dwn;
|
||||
float4 dc_dlight;
|
||||
|
||||
if (ls->t == FLT_MAX) {
|
||||
if (light_fixed_direction) {
|
||||
/* Constant direction toward light sample. */
|
||||
float3 wo = ls->D;
|
||||
|
||||
|
@ -764,6 +765,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
|
|||
ccl_private ShaderData *sd,
|
||||
ccl_private ShaderData *sd_mnee,
|
||||
ccl_private LightSample *ls,
|
||||
const bool light_fixed_direction,
|
||||
int vertex_count,
|
||||
ccl_private ManifoldVertex *vertices,
|
||||
ccl_private BsdfEval *throughput)
|
||||
|
@ -807,7 +809,8 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
|
|||
|
||||
float dh_dx;
|
||||
float dx1_dxlight;
|
||||
if (!mnee_compute_transfer_matrix(sd, ls, vertex_count, vertices, &dx1_dxlight, &dh_dx))
|
||||
if (!mnee_compute_transfer_matrix(
|
||||
sd, ls, light_fixed_direction, vertex_count, vertices, &dx1_dxlight, &dh_dx))
|
||||
return false;
|
||||
|
||||
/* Receiver bsdf eval above already contains |n.wo|. */
|
||||
|
@ -882,7 +885,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
|
|||
kg, state, sd_mnee, NULL, PATH_RAY_DIFFUSE, true);
|
||||
|
||||
/* Set light looking dir. */
|
||||
wo = (vi == vertex_count - 1) ? (ls->t == FLT_MAX ? ls->D : ls->P - v.p) :
|
||||
wo = (vi == vertex_count - 1) ? (light_fixed_direction ? ls->D : ls->P - v.p) :
|
||||
vertices[vi + 1].p - v.p;
|
||||
wo = normalize_len(wo, &wo_len);
|
||||
|
||||
|
@ -1039,12 +1042,22 @@ ccl_device_forceinline int kernel_path_mnee_sample(KernelGlobals kg,
|
|||
* discontinuity is visible between direct and indirect contributions */
|
||||
INTEGRATOR_STATE_WRITE(state, path, mnee) |= PATH_MNEE_VALID;
|
||||
|
||||
/* 2. Walk on the specular manifold to find vertices on the
|
||||
* casters that satisfy snell's law for each interface
|
||||
*/
|
||||
if (mnee_newton_solver(kg, sd, sd_mnee, ls, vertex_count, vertices)) {
|
||||
/* Distant or environment light. */
|
||||
bool light_fixed_direction = (ls->t == FLT_MAX);
|
||||
if (ls->type == LIGHT_AREA) {
|
||||
const ccl_global KernelLight *klight = &kernel_data_fetch(lights, ls->lamp);
|
||||
if (klight->area.tan_half_spread == 0.0f) {
|
||||
/* Area light with zero spread also has fixed direction. */
|
||||
light_fixed_direction = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* 2. Walk on the specular manifold to find vertices on the casters that satisfy snell's law for
|
||||
* each interface. */
|
||||
if (mnee_newton_solver(kg, sd, sd_mnee, ls, light_fixed_direction, vertex_count, vertices)) {
|
||||
/* 3. If a solution exists, calculate contribution of the corresponding path */
|
||||
if (!mnee_path_contribution(kg, state, sd, sd_mnee, ls, vertex_count, vertices, throughput))
|
||||
if (!mnee_path_contribution(
|
||||
kg, state, sd, sd_mnee, ls, light_fixed_direction, vertex_count, vertices, throughput))
|
||||
return 0;
|
||||
|
||||
return vertex_count;
|
||||
|
|
|
@ -227,55 +227,43 @@ ccl_device bool area_light_spread_clamp_light(const float3 P,
|
|||
}
|
||||
|
||||
/* Common API. */
|
||||
|
||||
/* Compute `eval_fac` and `pdf`. Also sample a new position on the light if `sample_coord`. */
|
||||
template<bool in_volume_segment>
|
||||
ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight,
|
||||
const float randu,
|
||||
const float randv,
|
||||
const float3 P,
|
||||
ccl_private LightSample *ls)
|
||||
ccl_device_inline bool area_light_eval(const ccl_global KernelLight *klight,
|
||||
const float3 ray_P,
|
||||
ccl_private float3 *light_P,
|
||||
ccl_private LightSample *ccl_restrict ls,
|
||||
float randu,
|
||||
float randv,
|
||||
bool sample_coord)
|
||||
{
|
||||
ls->P = klight->co;
|
||||
float3 axis_u = klight->area.axis_u;
|
||||
float3 axis_v = klight->area.axis_v;
|
||||
float len_u = klight->area.len_u;
|
||||
float len_v = klight->area.len_v;
|
||||
|
||||
float3 Ng = klight->area.dir;
|
||||
const float3 Ng = klight->area.dir;
|
||||
const float invarea = fabsf(klight->area.invarea);
|
||||
bool sample_rectangle = (klight->area.invarea > 0.0f);
|
||||
|
||||
if (!in_volume_segment) {
|
||||
if (dot(ls->P - P, Ng) > 0.0f) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const float3 axis_u = klight->area.axis_u;
|
||||
const float3 axis_v = klight->area.axis_v;
|
||||
const float len_u = klight->area.len_u;
|
||||
const float len_v = klight->area.len_v;
|
||||
float invarea = fabsf(klight->area.invarea);
|
||||
bool is_ellipse = (klight->area.invarea < 0.0f);
|
||||
bool sample_rectangle = !is_ellipse;
|
||||
float3 inplane;
|
||||
float3 light_P_new = *light_P;
|
||||
|
||||
if (in_volume_segment) {
|
||||
inplane = sample_rectangle ?
|
||||
rectangle_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, randu, randv) :
|
||||
ellipse_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, randu, randv);
|
||||
ls->P += inplane;
|
||||
light_P_new += sample_rectangle ?
|
||||
rectangle_sample(
|
||||
axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, randu, randv) :
|
||||
ellipse_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, randu, randv);
|
||||
ls->pdf = invarea;
|
||||
}
|
||||
else {
|
||||
float3 old_P = ls->P;
|
||||
float3 sample_axis_u = axis_u;
|
||||
float3 sample_axis_v = axis_v;
|
||||
float sample_len_u = len_u;
|
||||
float sample_len_v = len_v;
|
||||
|
||||
if (klight->area.normalize_spread > 0) {
|
||||
if (!area_light_spread_clamp_light(P,
|
||||
if (!area_light_spread_clamp_light(ray_P,
|
||||
Ng,
|
||||
&ls->P,
|
||||
&sample_axis_u,
|
||||
&sample_len_u,
|
||||
&sample_axis_v,
|
||||
&sample_len_v,
|
||||
&light_P_new,
|
||||
&axis_u,
|
||||
&len_u,
|
||||
&axis_v,
|
||||
&len_v,
|
||||
klight->area.tan_half_spread,
|
||||
&sample_rectangle))
|
||||
{
|
||||
|
@ -285,53 +273,82 @@ ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight,
|
|||
|
||||
if (sample_rectangle) {
|
||||
ls->pdf = area_light_rect_sample(
|
||||
P, &ls->P, sample_axis_u, sample_len_u, sample_axis_v, sample_len_v, randu, randv, true);
|
||||
ray_P, &light_P_new, axis_u, len_u, axis_v, len_v, randu, randv, sample_coord);
|
||||
}
|
||||
else {
|
||||
if (klight->area.tan_half_spread == 0.0f) {
|
||||
ls->pdf = 1.0f;
|
||||
}
|
||||
else {
|
||||
ls->P += ellipse_sample(sample_axis_u * sample_len_u * 0.5f,
|
||||
sample_axis_v * sample_len_v * 0.5f,
|
||||
randu,
|
||||
randv);
|
||||
ls->pdf = 4.0f * M_1_PI_F / (sample_len_u * sample_len_v);
|
||||
if (sample_coord) {
|
||||
light_P_new += ellipse_sample(
|
||||
axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, randu, randv);
|
||||
}
|
||||
ls->pdf = 4.0f * M_1_PI_F / (len_u * len_v);
|
||||
}
|
||||
}
|
||||
inplane = ls->P - old_P;
|
||||
}
|
||||
|
||||
const float light_u = dot(inplane, axis_u) / len_u;
|
||||
const float light_v = dot(inplane, axis_v) / len_v;
|
||||
|
||||
/* Sampled point lies outside of the area light. */
|
||||
if (is_ellipse && (sqr(light_u) + sqr(light_v) > 0.25f)) {
|
||||
return false;
|
||||
if (sample_coord) {
|
||||
*light_P = light_P_new;
|
||||
ls->D = normalize_len(*light_P - ray_P, &ls->t);
|
||||
}
|
||||
if (!is_ellipse && (fabsf(light_u) > 0.5f || fabsf(light_v) > 0.5f)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
|
||||
ls->u = light_v + 0.5f;
|
||||
ls->v = -light_u - light_v;
|
||||
|
||||
ls->Ng = Ng;
|
||||
ls->D = normalize_len(ls->P - P, &ls->t);
|
||||
|
||||
ls->eval_fac = 0.25f * invarea;
|
||||
|
||||
if (klight->area.normalize_spread > 0) {
|
||||
/* Area Light spread angle attenuation */
|
||||
ls->eval_fac *= area_light_spread_attenuation(
|
||||
ls->D, ls->Ng, klight->area.tan_half_spread, klight->area.normalize_spread);
|
||||
ls->D, Ng, klight->area.tan_half_spread, klight->area.normalize_spread);
|
||||
}
|
||||
|
||||
if (!sample_rectangle && klight->area.tan_half_spread > 0) {
|
||||
if (in_volume_segment || (!sample_rectangle && klight->area.tan_half_spread > 0)) {
|
||||
ls->pdf *= lamp_light_pdf(Ng, -ls->D, ls->t);
|
||||
}
|
||||
|
||||
return ls->eval_fac > 0;
|
||||
}
|
||||
|
||||
template<bool in_volume_segment>
|
||||
ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight,
|
||||
const float randu,
|
||||
const float randv,
|
||||
const float3 P,
|
||||
ccl_private LightSample *ls)
|
||||
{
|
||||
ls->P = klight->co;
|
||||
ls->Ng = klight->area.dir;
|
||||
|
||||
if (!in_volume_segment) {
|
||||
if (dot(ls->P - P, ls->Ng) > 0.0f) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!area_light_eval<in_volume_segment>(klight, P, &ls->P, ls, randu, randv, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const float3 inplane = ls->P - klight->co;
|
||||
const float light_u = dot(inplane, klight->area.axis_u) / klight->area.len_u;
|
||||
const float light_v = dot(inplane, klight->area.axis_v) / klight->area.len_v;
|
||||
|
||||
if (!in_volume_segment) {
|
||||
const bool is_ellipse = (klight->area.invarea < 0.0f);
|
||||
|
||||
/* Sampled point lies outside of the area light. */
|
||||
if (is_ellipse && (sqr(light_u) + sqr(light_v) > 0.25f)) {
|
||||
return false;
|
||||
}
|
||||
if (!is_ellipse && (fabsf(light_u) > 0.5f || fabsf(light_v) > 0.5f)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
|
||||
ls->u = light_v + 0.5f;
|
||||
ls->v = -light_u - light_v;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -339,14 +356,15 @@ ccl_device_forceinline void area_light_update_position(const ccl_global KernelLi
|
|||
ccl_private LightSample *ls,
|
||||
const float3 P)
|
||||
{
|
||||
const float invarea = fabsf(klight->area.invarea);
|
||||
ls->D = normalize_len(ls->P - P, &ls->t);
|
||||
ls->pdf = invarea;
|
||||
|
||||
if (klight->area.normalize_spread > 0) {
|
||||
ls->eval_fac = 0.25f * invarea;
|
||||
ls->eval_fac *= area_light_spread_attenuation(
|
||||
ls->D, ls->Ng, klight->area.tan_half_spread, klight->area.normalize_spread);
|
||||
if (klight->area.tan_half_spread == 0) {
|
||||
/* Update position on the light to keep the direction fixed. */
|
||||
area_light_eval<false>(klight, P, &ls->P, ls, 0, 0, true);
|
||||
}
|
||||
else {
|
||||
ls->D = normalize_len(ls->P - P, &ls->t);
|
||||
area_light_eval<false>(klight, P, &ls->P, ls, 0, 0, false);
|
||||
/* Convert pdf to be in area measure. */
|
||||
ls->pdf /= lamp_light_pdf(ls->Ng, -ls->D, ls->t);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -397,60 +415,13 @@ ccl_device_inline bool area_light_sample_from_intersection(
|
|||
const float3 ray_D,
|
||||
ccl_private LightSample *ccl_restrict ls)
|
||||
{
|
||||
|
||||
/* area light */
|
||||
float invarea = fabsf(klight->area.invarea);
|
||||
|
||||
float3 Ng = klight->area.dir;
|
||||
float3 light_P = klight->co;
|
||||
|
||||
ls->u = isect->u;
|
||||
ls->v = isect->v;
|
||||
ls->D = ray_D;
|
||||
ls->Ng = Ng;
|
||||
ls->Ng = klight->area.dir;
|
||||
|
||||
float3 sample_axis_u = klight->area.axis_u;
|
||||
float3 sample_axis_v = klight->area.axis_v;
|
||||
float sample_len_u = klight->area.len_u;
|
||||
float sample_len_v = klight->area.len_v;
|
||||
bool is_ellipse = (klight->area.invarea < 0.0f);
|
||||
bool sample_rectangle = !is_ellipse;
|
||||
|
||||
if (klight->area.normalize_spread > 0) {
|
||||
if (!area_light_spread_clamp_light(ray_P,
|
||||
Ng,
|
||||
&light_P,
|
||||
&sample_axis_u,
|
||||
&sample_len_u,
|
||||
&sample_axis_v,
|
||||
&sample_len_v,
|
||||
klight->area.tan_half_spread,
|
||||
&sample_rectangle))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (sample_rectangle) {
|
||||
ls->pdf = area_light_rect_sample(
|
||||
ray_P, &light_P, sample_axis_u, sample_len_u, sample_axis_v, sample_len_v, 0, 0, false);
|
||||
}
|
||||
else {
|
||||
ls->pdf = klight->area.tan_half_spread == 0.0f ?
|
||||
1.0f :
|
||||
4.0f * M_1_PI_F / (sample_len_u * sample_len_v) *
|
||||
lamp_light_pdf(Ng, -ray_D, ls->t);
|
||||
}
|
||||
|
||||
ls->eval_fac = 0.25f * invarea;
|
||||
|
||||
if (klight->area.normalize_spread > 0) {
|
||||
/* Area Light spread angle attenuation */
|
||||
ls->eval_fac *= area_light_spread_attenuation(
|
||||
ls->D, ls->Ng, klight->area.tan_half_spread, klight->area.normalize_spread);
|
||||
}
|
||||
|
||||
return ls->eval_fac > 0;
|
||||
float3 light_P = klight->co;
|
||||
return area_light_eval<false>(klight, ray_P, &light_P, ls, 0, 0, false);
|
||||
}
|
||||
|
||||
template<bool in_volume_segment>
|
||||
|
|
|
@ -36,7 +36,7 @@ static float shutter_curve_eval(float x, array<float> &shutter_curve)
|
|||
int index = (int)x;
|
||||
float frac = x - index;
|
||||
if (index < shutter_curve.size() - 1) {
|
||||
return lerp(shutter_curve[index], shutter_curve[index + 1], frac);
|
||||
return mix(shutter_curve[index], shutter_curve[index + 1], frac);
|
||||
}
|
||||
else {
|
||||
return shutter_curve[shutter_curve.size() - 1];
|
||||
|
|
|
@ -1291,7 +1291,7 @@ template<class T> void init_test_curve(array<T> &buffer, T start, T end, int ste
|
|||
buffer.resize(steps);
|
||||
|
||||
for (int i = 0; i < steps; i++) {
|
||||
buffer[i] = lerp(start, end, float(i) / (steps - 1));
|
||||
buffer[i] = mix(start, end, float(i) / (steps - 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -555,16 +555,6 @@ CCL_NAMESPACE_END
|
|||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
#if !defined(__KERNEL_METAL__)
|
||||
/* Interpolation */
|
||||
|
||||
template<class A, class B> A lerp(const A &a, const A &b, const B &t)
|
||||
{
|
||||
return (A)(a * ((B)1 - t) + b * t);
|
||||
}
|
||||
|
||||
#endif /* __KERNEL_METAL__ */
|
||||
|
||||
/* Triangle */
|
||||
|
||||
ccl_device_inline float triangle_area(ccl_private const float3 &v1,
|
||||
|
|
|
@ -379,7 +379,7 @@ ccl_device_inline Transform transform_empty()
|
|||
|
||||
ccl_device_inline float4 quat_interpolate(float4 q1, float4 q2, float t)
|
||||
{
|
||||
/* Optix and MetalRT are using lerp to interpolate motion transformations. */
|
||||
/* Optix and MetalRT are using linear interpolation to interpolate motion transformations. */
|
||||
#if defined(__KERNEL_GPU_RAYTRACING__)
|
||||
return normalize((1.0f - t) * q1 + t * q2);
|
||||
#else /* defined(__KERNEL_GPU_RAYTRACING__) */
|
||||
|
|
|
@ -1018,9 +1018,44 @@ class WM_OT_url_open(Operator):
|
|||
description="URL to open",
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _add_utm_param_to_url(url, utm_source):
|
||||
import urllib
|
||||
|
||||
# Make sure we have a scheme otherwise we can't parse the url.
|
||||
if not url.startswith(("http://", "https://")):
|
||||
url = "https://" + url
|
||||
|
||||
# Parse the URL to get its domain and query parameters.
|
||||
parsed_url = urllib.parse.urlparse(url)
|
||||
domain = parsed_url.netloc
|
||||
|
||||
# Only add a utm source if it points to a blender.org domain.
|
||||
if not (domain.endswith(".blender.org") or domain == "blender.org"):
|
||||
return url
|
||||
|
||||
# Parse the query parameters and add or update the utm_source parameter.
|
||||
query_params = urllib.parse.parse_qs(parsed_url.query)
|
||||
query_params["utm_source"] = utm_source
|
||||
new_query = urllib.parse.urlencode(query_params, doseq=True)
|
||||
|
||||
# Create a new URL with the updated query parameters.
|
||||
new_url_parts = list(parsed_url)
|
||||
new_url_parts[4] = new_query
|
||||
new_url = urllib.parse.urlunparse(new_url_parts)
|
||||
|
||||
return new_url
|
||||
|
||||
@staticmethod
|
||||
def _get_utm_source():
|
||||
version = bpy.app.version_string
|
||||
formatted_version = version.replace(' ', '-').lower()
|
||||
return f"blender-{formatted_version}"
|
||||
|
||||
def execute(self, _context):
|
||||
import webbrowser
|
||||
webbrowser.open(self.url)
|
||||
complete_url = self._add_utm_param_to_url(self.url, self._get_utm_source())
|
||||
webbrowser.open(complete_url)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
|
@ -1102,10 +1137,7 @@ class WM_OT_url_open_preset(Operator):
|
|||
url = url(self, context)
|
||||
break
|
||||
|
||||
import webbrowser
|
||||
webbrowser.open(url)
|
||||
|
||||
return {'FINISHED'}
|
||||
return bpy.ops.wm.url_open(url=url)
|
||||
|
||||
|
||||
class WM_OT_path_open(Operator):
|
||||
|
@ -1307,9 +1339,7 @@ class WM_OT_doc_view_manual(Operator):
|
|||
)
|
||||
return {'CANCELLED'}
|
||||
else:
|
||||
import webbrowser
|
||||
webbrowser.open(url)
|
||||
return {'FINISHED'}
|
||||
return bpy.ops.wm.url_open(url=url)
|
||||
|
||||
|
||||
class WM_OT_doc_view(Operator):
|
||||
|
@ -1325,10 +1355,7 @@ class WM_OT_doc_view(Operator):
|
|||
if url is None:
|
||||
return {'CANCELLED'}
|
||||
|
||||
import webbrowser
|
||||
webbrowser.open(url)
|
||||
|
||||
return {'FINISHED'}
|
||||
return bpy.ops.wm.url_open(url=url)
|
||||
|
||||
|
||||
rna_path = StringProperty(
|
||||
|
|
|
@ -435,7 +435,9 @@ class IMAGE_MT_uvs(Menu):
|
|||
|
||||
layout.separator()
|
||||
|
||||
layout.operator_context = 'INVOKE_DEFAULT'
|
||||
layout.operator("uv.pack_islands")
|
||||
layout.operator_context = 'EXEC_REGION_WIN'
|
||||
layout.operator("uv.average_islands_scale")
|
||||
|
||||
layout.separator()
|
||||
|
|
|
@ -168,6 +168,7 @@ class TIME_MT_cache(Menu):
|
|||
col.prop(st, "cache_softbody")
|
||||
col.prop(st, "cache_particles")
|
||||
col.prop(st, "cache_cloth")
|
||||
col.prop(st, "cache_simulation_nodes")
|
||||
col.prop(st, "cache_smoke")
|
||||
col.prop(st, "cache_dynamicpaint")
|
||||
col.prop(st, "cache_rigidbody")
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "BLI_array.hh"
|
||||
#include "BLI_color.hh"
|
||||
#include "BLI_cpp_type.hh"
|
||||
#include "BLI_generic_span.hh"
|
||||
#include "BLI_generic_virtual_array.hh"
|
||||
#include "BLI_math_color.hh"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_math_vector.hh"
|
||||
|
@ -587,4 +589,16 @@ template<typename T> using DefaultMixer = typename DefaultMixerStruct<T>::type;
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Generic Array Utils Implementations
|
||||
*
|
||||
* Extra implementations of functions from #BLI_array_utils.hh for all attribute types,
|
||||
* used to avoid templating the same logic for each type in many places.
|
||||
* \{ */
|
||||
|
||||
void gather(GSpan src, Span<int> map, GMutableSpan dst);
|
||||
void gather(const GVArray &src, Span<int> map, GMutableSpan dst);
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::bke::attribute_math
|
||||
|
|
|
@ -31,7 +31,7 @@ extern "C" {
|
|||
* version. Older Blender versions will test this and show a warning if the file
|
||||
* was written with too new a version. */
|
||||
#define BLENDER_FILE_MIN_VERSION 305
|
||||
#define BLENDER_FILE_MIN_SUBVERSION 9
|
||||
#define BLENDER_FILE_MIN_SUBVERSION 10
|
||||
|
||||
/** User readable version string. */
|
||||
const char *BKE_blender_version_string(void);
|
||||
|
|
|
@ -303,6 +303,12 @@ void BKE_collection_parent_relations_rebuild(struct Collection *collection);
|
|||
*/
|
||||
void BKE_main_collections_parent_relations_rebuild(struct Main *bmain);
|
||||
|
||||
/**
|
||||
* Perform some validation on integrity of the data of this collection.
|
||||
*
|
||||
* \return `true` if everything is OK, false if some errors are detected. */
|
||||
bool BKE_collection_validate(struct Collection *collection);
|
||||
|
||||
/* .blend file I/O */
|
||||
|
||||
void BKE_collection_blend_write_nolib(struct BlendWriter *writer, struct Collection *collection);
|
||||
|
|
|
@ -47,7 +47,7 @@ float BKE_cryptomatte_hash_to_float(uint32_t cryptomatte_hash);
|
|||
bool BKE_cryptomatte_find_name(const struct CryptomatteSession *session,
|
||||
float encoded_hash,
|
||||
char *r_name,
|
||||
int name_len);
|
||||
int name_maxncpy);
|
||||
|
||||
char *BKE_cryptomatte_entries_to_matte_id(struct NodeCryptomatte *node_storage);
|
||||
void BKE_cryptomatte_matte_id_to_entries(struct NodeCryptomatte *node_storage,
|
||||
|
|
|
@ -118,9 +118,15 @@ struct CryptomatteStampDataCallbackData {
|
|||
static blender::StringRef extract_layer_hash(blender::StringRefNull key);
|
||||
|
||||
/* C type callback function (StampCallback). */
|
||||
static void extract_layer_names(void *_data, const char *propname, char *propvalue, int len);
|
||||
static void extract_layer_names(void *_data,
|
||||
const char *propname,
|
||||
char *propvalue,
|
||||
int propvalue_maxncpy);
|
||||
/* C type callback function (StampCallback). */
|
||||
static void extract_layer_manifest(void *_data, const char *propname, char *propvalue, int len);
|
||||
static void extract_layer_manifest(void *_data,
|
||||
const char *propname,
|
||||
char *propvalue,
|
||||
int propvalue_maxncpy);
|
||||
};
|
||||
|
||||
const blender::Vector<std::string> &BKE_cryptomatte_layer_names_get(
|
||||
|
|
|
@ -50,7 +50,10 @@ void BKE_image_free_gputextures(struct Image *ima);
|
|||
*/
|
||||
void BKE_image_free_data(struct Image *image);
|
||||
|
||||
typedef void(StampCallback)(void *data, const char *propname, char *propvalue, int len);
|
||||
typedef void(StampCallback)(void *data,
|
||||
const char *propname,
|
||||
char *propvalue,
|
||||
int propvalue_maxncpy);
|
||||
|
||||
void BKE_render_result_stamp_info(struct Scene *scene,
|
||||
struct Object *camera,
|
||||
|
|
|
@ -422,7 +422,7 @@ bActionGroup *action_groups_add_new(bAction *act, const char name[])
|
|||
|
||||
/* make it selected, with default name */
|
||||
agrp->flag = AGRP_SELECTED;
|
||||
STRNCPY(agrp->name, name[0] ? name : DATA_("Group"));
|
||||
STRNCPY_UTF8(agrp->name, name[0] ? name : DATA_("Group"));
|
||||
|
||||
/* add to action, and validate */
|
||||
BLI_addtail(&act->groups, agrp);
|
||||
|
|
|
@ -169,7 +169,7 @@ static void action_flip_pchan(Object *ob_arm,
|
|||
BLI_str_escape(pchan_name_esc, pchan->name, sizeof(pchan_name_esc));
|
||||
const int path_xform_prefix_len = SNPRINTF(path_xform, "pose.bones[\"%s\"]", pchan_name_esc);
|
||||
char *path_xform_suffix = path_xform + path_xform_prefix_len;
|
||||
const int path_xform_suffix_len = sizeof(path_xform) - path_xform_prefix_len;
|
||||
const int path_xform_suffix_maxncpy = sizeof(path_xform) - path_xform_prefix_len;
|
||||
|
||||
/* Lookup and assign all available #FCurve channels,
|
||||
* unavailable channels are left NULL. */
|
||||
|
@ -191,11 +191,11 @@ static void action_flip_pchan(Object *ob_arm,
|
|||
} fkc_pchan = {{{NULL}}};
|
||||
|
||||
#define FCURVE_ASSIGN_VALUE(id, path_test_suffix, index) \
|
||||
BLI_strncpy(path_xform_suffix, path_test_suffix, path_xform_suffix_len); \
|
||||
BLI_strncpy(path_xform_suffix, path_test_suffix, path_xform_suffix_maxncpy); \
|
||||
action_flip_pchan_cache_fcurve_assign_value(&fkc_pchan.id, index, path_xform, fcache)
|
||||
|
||||
#define FCURVE_ASSIGN_ARRAY(id, path_test_suffix) \
|
||||
BLI_strncpy(path_xform_suffix, path_test_suffix, path_xform_suffix_len); \
|
||||
BLI_strncpy(path_xform_suffix, path_test_suffix, path_xform_suffix_maxncpy); \
|
||||
action_flip_pchan_cache_fcurve_assign_array( \
|
||||
fkc_pchan.id, ARRAY_SIZE(fkc_pchan.id), path_xform, fcache)
|
||||
|
||||
|
|
|
@ -131,8 +131,8 @@ KeyingSet *BKE_keyingset_add(
|
|||
/* allocate new KeyingSet */
|
||||
ks = MEM_callocN(sizeof(KeyingSet), "KeyingSet");
|
||||
|
||||
STRNCPY(ks->idname, (idname) ? idname : (name) ? name : DATA_("KeyingSet"));
|
||||
STRNCPY(ks->name, (name) ? name : (idname) ? idname : DATA_("Keying Set"));
|
||||
STRNCPY_UTF8(ks->idname, (idname) ? idname : (name) ? name : DATA_("KeyingSet"));
|
||||
STRNCPY_UTF8(ks->name, (name) ? name : (idname) ? idname : DATA_("Keying Set"));
|
||||
|
||||
ks->flag = flag;
|
||||
ks->keyingflag = keyingflag;
|
||||
|
|
|
@ -173,10 +173,10 @@ bool BKE_id_attribute_rename(ID *id,
|
|||
* is clamped to it's maximum length, otherwise assigning an over-long name multiple times
|
||||
* will add `.001` suffix unnecessarily. */
|
||||
{
|
||||
const int maxlength = CustomData_name_max_length_calc(new_name);
|
||||
const int new_name_maxncpy = CustomData_name_max_length_calc(new_name);
|
||||
/* NOTE: A function that performs a clamped comparison without copying would be handy here. */
|
||||
char new_name_clamped[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
BLI_strncpy_utf8(new_name_clamped, new_name, maxlength);
|
||||
BLI_strncpy_utf8(new_name_clamped, new_name, new_name_maxncpy);
|
||||
if (STREQ(old_name, new_name_clamped)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -254,19 +254,14 @@ static bool unique_name_cb(void *arg, const char *name)
|
|||
bool BKE_id_attribute_calc_unique_name(ID *id, const char *name, char *outname)
|
||||
{
|
||||
AttrUniqueData data{id};
|
||||
const int maxlength = CustomData_name_max_length_calc(name);
|
||||
const int name_maxncpy = CustomData_name_max_length_calc(name);
|
||||
|
||||
/* Set default name if none specified.
|
||||
* NOTE: We only call IFACE_() if needed to avoid locale lookup overhead. */
|
||||
if (!name || name[0] == '\0') {
|
||||
BLI_strncpy(outname, IFACE_("Attribute"), maxlength);
|
||||
}
|
||||
else {
|
||||
BLI_strncpy_utf8(outname, name, maxlength);
|
||||
}
|
||||
BLI_strncpy_utf8(outname, (name && name[0]) ? name : IFACE_("Attribute"), name_maxncpy);
|
||||
|
||||
const char *defname = ""; /* Dummy argument, never used as `name` is never zero length. */
|
||||
return BLI_uniquename_cb(unique_name_cb, &data, defname, '.', outname, maxlength);
|
||||
return BLI_uniquename_cb(unique_name_cb, &data, defname, '.', outname, name_maxncpy);
|
||||
}
|
||||
|
||||
CustomDataLayer *BKE_id_attribute_new(ID *id,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_array_utils.hh"
|
||||
|
||||
#include "BKE_attribute_math.hh"
|
||||
|
||||
namespace blender::bke::attribute_math {
|
||||
|
@ -128,4 +130,20 @@ void ColorGeometry4bMixer::finalize(const IndexMask mask)
|
|||
});
|
||||
}
|
||||
|
||||
void gather(const GSpan src, const Span<int> map, GMutableSpan dst)
|
||||
{
|
||||
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
array_utils::gather(src.typed<T>(), map, dst.typed<T>());
|
||||
});
|
||||
}
|
||||
|
||||
void gather(const GVArray &src, const Span<int> map, GMutableSpan dst)
|
||||
{
|
||||
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
array_utils::gather(src.typed<T>(), map, dst.typed<T>());
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace blender::bke::attribute_math
|
||||
|
|
|
@ -1617,7 +1617,7 @@ BoidRule *boid_new_rule(int type)
|
|||
|
||||
rule->type = type;
|
||||
rule->flag |= BOIDRULE_IN_AIR | BOIDRULE_ON_LAND;
|
||||
STRNCPY(rule->name, DATA_(rna_enum_boidrule_type_items[type - 1].name));
|
||||
STRNCPY_UTF8(rule->name, DATA_(rna_enum_boidrule_type_items[type - 1].name));
|
||||
|
||||
return rule;
|
||||
}
|
||||
|
|
|
@ -1944,6 +1944,49 @@ void BKE_main_collections_parent_relations_rebuild(Main *bmain)
|
|||
}
|
||||
}
|
||||
|
||||
bool BKE_collection_validate(struct Collection *collection)
|
||||
{
|
||||
if (!BLI_listbase_validate(&collection->children)) {
|
||||
return false;
|
||||
}
|
||||
if (!BLI_listbase_validate(&collection->runtime.parents)) {
|
||||
return false;
|
||||
}
|
||||
if (BKE_collection_cycle_find(collection, NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_ok = true;
|
||||
|
||||
/* Check that children have each collection used/referenced only once. */
|
||||
GSet *processed_collections = BLI_gset_ptr_new(__func__);
|
||||
for (CollectionChild *child = collection->children.first; child; child = child->next) {
|
||||
void **r_key;
|
||||
if (BLI_gset_ensure_p_ex(processed_collections, child->collection, &r_key)) {
|
||||
is_ok = false;
|
||||
}
|
||||
else {
|
||||
*r_key = child->collection;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that parents have each collection used/referenced only once. */
|
||||
BLI_gset_clear(processed_collections, NULL);
|
||||
for (CollectionParent *parent = collection->runtime.parents.first; parent; parent = parent->next)
|
||||
{
|
||||
void **r_key;
|
||||
if (BLI_gset_ensure_p_ex(processed_collections, parent->collection, &r_key)) {
|
||||
is_ok = false;
|
||||
}
|
||||
else {
|
||||
*r_key = parent->collection;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_gset_free(processed_collections, NULL);
|
||||
return is_ok;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -219,14 +219,14 @@ float BKE_cryptomatte_hash_to_float(uint32_t cryptomatte_hash)
|
|||
bool BKE_cryptomatte_find_name(const CryptomatteSession *session,
|
||||
const float encoded_hash,
|
||||
char *r_name,
|
||||
int name_len)
|
||||
int name_maxncpy)
|
||||
{
|
||||
std::optional<std::string> name = (*session)[encoded_hash];
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BLI_strncpy(r_name, name->c_str(), name_len);
|
||||
BLI_strncpy(r_name, name->c_str(), name_maxncpy);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -580,7 +580,7 @@ blender::StringRef CryptomatteStampDataCallbackData::extract_layer_hash(blender:
|
|||
void CryptomatteStampDataCallbackData::extract_layer_names(void *_data,
|
||||
const char *propname,
|
||||
char *propvalue,
|
||||
int /*len*/)
|
||||
int /*propvalue_maxncpy*/)
|
||||
{
|
||||
CryptomatteStampDataCallbackData *data = static_cast<CryptomatteStampDataCallbackData *>(_data);
|
||||
|
||||
|
@ -598,7 +598,7 @@ void CryptomatteStampDataCallbackData::extract_layer_names(void *_data,
|
|||
void CryptomatteStampDataCallbackData::extract_layer_manifest(void *_data,
|
||||
const char *propname,
|
||||
char *propvalue,
|
||||
int /*len*/)
|
||||
int /*propvalue_maxncpy*/)
|
||||
{
|
||||
CryptomatteStampDataCallbackData *data = static_cast<CryptomatteStampDataCallbackData *>(_data);
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ TEST(cryptomatte, extract_layer_hash_from_metadata_key)
|
|||
static void validate_cryptomatte_session_from_stamp_data(void * /*data*/,
|
||||
const char *propname,
|
||||
char *propvalue,
|
||||
int /*len*/)
|
||||
int /*propvalue_maxncpy*/)
|
||||
{
|
||||
blender::StringRefNull prop_name(propname);
|
||||
if (!prop_name.startswith("cryptomatte/")) {
|
||||
|
|
|
@ -1124,14 +1124,6 @@ static void copy_construct_data(const GSpan src, GMutableSpan dst)
|
|||
src.type().copy_construct_n(src.data(), dst.data(), src.size());
|
||||
}
|
||||
|
||||
static void copy_with_map(const GSpan src, const Span<int> map, GMutableSpan dst)
|
||||
{
|
||||
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
array_utils::gather(src.typed<T>(), map, dst.typed<T>());
|
||||
});
|
||||
}
|
||||
|
||||
static CurvesGeometry copy_with_removed_points(
|
||||
const CurvesGeometry &curves,
|
||||
const IndexMask points_to_delete,
|
||||
|
@ -1216,7 +1208,7 @@ static CurvesGeometry copy_with_removed_points(
|
|||
attribute.dst.span.copy_from(attribute.src);
|
||||
}
|
||||
else {
|
||||
copy_with_map(attribute.src, new_curve_orig_indices, attribute.dst.span);
|
||||
bke::attribute_math::gather(attribute.src, new_curve_orig_indices, attribute.dst.span);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "BLI_span.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
|
@ -4413,7 +4414,7 @@ void CustomData_set_layer_unique_name(CustomData *data, const int index)
|
|||
/* Set default name if none specified. Note we only call DATA_() when
|
||||
* needed to avoid overhead of locale lookups in the depsgraph. */
|
||||
if (nlayer->name[0] == '\0') {
|
||||
STRNCPY(nlayer->name, DATA_(typeInfo->defaultname));
|
||||
STRNCPY_UTF8(nlayer->name, DATA_(typeInfo->defaultname));
|
||||
}
|
||||
|
||||
const char *defname = ""; /* Dummy argument, never used as `name` is never zero length. */
|
||||
|
@ -4437,10 +4438,10 @@ void CustomData_validate_layer_name(const CustomData *data,
|
|||
* deleted, so assign the active layer to name
|
||||
*/
|
||||
index = CustomData_get_active_layer_index(data, type);
|
||||
BLI_strncpy(outname, data->layers[index].name, MAX_CUSTOMDATA_LAYER_NAME);
|
||||
BLI_strncpy_utf8(outname, data->layers[index].name, MAX_CUSTOMDATA_LAYER_NAME);
|
||||
}
|
||||
else {
|
||||
BLI_strncpy(outname, name, MAX_CUSTOMDATA_LAYER_NAME);
|
||||
BLI_strncpy_utf8(outname, name, MAX_CUSTOMDATA_LAYER_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -405,7 +405,7 @@ static bool surface_duplicateNameExists(void *arg, const char *name)
|
|||
void dynamicPaintSurface_setUniqueName(DynamicPaintSurface *surface, const char *basename)
|
||||
{
|
||||
char name[64];
|
||||
STRNCPY(name, basename); /* in case basename is surface->name use a copy */
|
||||
STRNCPY_UTF8(name, basename); /* in case basename is surface->name use a copy */
|
||||
BLI_uniquename_cb(
|
||||
surface_duplicateNameExists, surface, name, '.', surface->name, sizeof(surface->name));
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "BLI_expr_pylike_eval.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
@ -955,7 +956,7 @@ DriverVar *driver_add_new_variable(ChannelDriver *driver)
|
|||
BLI_addtail(&driver->variables, dvar);
|
||||
|
||||
/* Give the variable a 'unique' name. */
|
||||
strcpy(dvar->name, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "var"));
|
||||
STRNCPY_UTF8(dvar->name, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "var"));
|
||||
BLI_uniquename(&driver->variables,
|
||||
dvar,
|
||||
CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "var"),
|
||||
|
|
|
@ -675,7 +675,7 @@ bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd,
|
|||
}
|
||||
|
||||
/* auto-name */
|
||||
STRNCPY(gpl->info, DATA_(name));
|
||||
STRNCPY_UTF8(gpl->info, DATA_(name));
|
||||
BLI_uniquename(&gpd->layers,
|
||||
gpl,
|
||||
(gpd->flag & GP_DATA_ANNOTATIONS) ? DATA_("Note") : DATA_("GP_Layer"),
|
||||
|
|
|
@ -356,7 +356,7 @@ GpencilModifierData *BKE_gpencil_modifier_new(int type)
|
|||
GpencilModifierData *md = MEM_callocN(mti->struct_size, mti->struct_name);
|
||||
|
||||
/* NOTE: this name must be made unique later. */
|
||||
STRNCPY(md->name, DATA_(mti->name));
|
||||
STRNCPY_UTF8(md->name, DATA_(mti->name));
|
||||
|
||||
md->type = type;
|
||||
md->mode = eGpencilModifierMode_Realtime | eGpencilModifierMode_Render;
|
||||
|
|
|
@ -2486,18 +2486,24 @@ void BKE_stamp_data_free(StampData *stamp_data)
|
|||
}
|
||||
|
||||
/* wrap for callback only */
|
||||
static void metadata_set_field(void *data, const char *propname, char *propvalue, int /*len*/)
|
||||
static void metadata_set_field(void *data,
|
||||
const char *propname,
|
||||
char *propvalue,
|
||||
int /*propvalue_maxncpy*/)
|
||||
{
|
||||
/* We know it is an ImBuf* because that's what we pass to BKE_stamp_info_callback. */
|
||||
ImBuf *imbuf = static_cast<ImBuf *>(data);
|
||||
IMB_metadata_set_field(imbuf->metadata, propname, propvalue);
|
||||
}
|
||||
|
||||
static void metadata_get_field(void *data, const char *propname, char *propvalue, int len)
|
||||
static void metadata_get_field(void *data,
|
||||
const char *propname,
|
||||
char *propvalue,
|
||||
int propvalue_maxncpy)
|
||||
{
|
||||
/* We know it is an ImBuf* because that's what we pass to BKE_stamp_info_callback. */
|
||||
ImBuf *imbuf = static_cast<ImBuf *>(data);
|
||||
IMB_metadata_get_field(imbuf->metadata, propname, propvalue, len);
|
||||
IMB_metadata_get_field(imbuf->metadata, propname, propvalue, propvalue_maxncpy);
|
||||
}
|
||||
|
||||
void BKE_imbuf_stamp_info(const RenderResult *rr, ImBuf *ibuf)
|
||||
|
|
|
@ -1845,7 +1845,7 @@ KeyBlock *BKE_keyblock_add(Key *key, const char *name)
|
|||
}
|
||||
else {
|
||||
if (tot == 1) {
|
||||
STRNCPY(kb->name, DATA_("Basis"));
|
||||
STRNCPY_UTF8(kb->name, DATA_("Basis"));
|
||||
}
|
||||
else {
|
||||
SNPRINTF(kb->name, DATA_("Key %d"), tot - 1);
|
||||
|
|
|
@ -787,7 +787,7 @@ void BKE_layer_collection_resync_allow(void)
|
|||
}
|
||||
|
||||
struct LayerCollectionResync {
|
||||
LayerCollectionResync *prev, *next;
|
||||
LayerCollectionResync *next, *prev;
|
||||
|
||||
/* Temp data used to generate a queue during valid layer search. See
|
||||
* #layer_collection_resync_find. */
|
||||
|
@ -1006,7 +1006,7 @@ void BKE_main_view_layers_synced_ensure(const Main *bmain)
|
|||
BKE_scene_view_layers_synced_ensure(scene);
|
||||
}
|
||||
|
||||
/* NOTE: This is not (yet?) covered by the dirty tag and differed re-sync system */
|
||||
/* NOTE: This is not (yet?) covered by the dirty tag and deffered re-sync system. */
|
||||
BKE_layer_collection_local_sync_all(bmain);
|
||||
}
|
||||
|
||||
|
@ -2522,7 +2522,7 @@ ViewLayerAOV *BKE_view_layer_add_aov(ViewLayer *view_layer)
|
|||
ViewLayerAOV *aov;
|
||||
aov = MEM_cnew<ViewLayerAOV>(__func__);
|
||||
aov->type = AOV_TYPE_COLOR;
|
||||
STRNCPY(aov->name, DATA_("AOV"));
|
||||
STRNCPY_UTF8(aov->name, DATA_("AOV"));
|
||||
BLI_addtail(&view_layer->aovs, aov);
|
||||
viewlayer_aov_active_set(view_layer, aov);
|
||||
viewlayer_aov_make_name_unique(view_layer);
|
||||
|
@ -2642,12 +2642,7 @@ ViewLayerLightgroup *BKE_view_layer_add_lightgroup(ViewLayer *view_layer, const
|
|||
{
|
||||
ViewLayerLightgroup *lightgroup;
|
||||
lightgroup = MEM_cnew<ViewLayerLightgroup>(__func__);
|
||||
if (name && name[0]) {
|
||||
STRNCPY(lightgroup->name, name);
|
||||
}
|
||||
else {
|
||||
STRNCPY(lightgroup->name, DATA_("Lightgroup"));
|
||||
}
|
||||
STRNCPY_UTF8(lightgroup->name, (name && name[0]) ? name : DATA_("Lightgroup"));
|
||||
BLI_addtail(&view_layer->lightgroups, lightgroup);
|
||||
viewlayer_lightgroup_active_set(view_layer, lightgroup);
|
||||
viewlayer_lightgroup_make_name_unique(view_layer, lightgroup);
|
||||
|
|
|
@ -1603,7 +1603,7 @@ bool BKE_id_new_name_validate(
|
|||
|
||||
if (name[0] == '\0') {
|
||||
/* Disallow empty names. */
|
||||
STRNCPY(name, DATA_(BKE_idtype_idcode_to_name(GS(id->name))));
|
||||
STRNCPY_UTF8(name, DATA_(BKE_idtype_idcode_to_name(GS(id->name))));
|
||||
}
|
||||
else {
|
||||
/* disallow non utf8 chars,
|
||||
|
|
|
@ -404,6 +404,11 @@ uint64_t BKE_library_id_can_use_filter_id(const ID *id_owner, const bool include
|
|||
return FILTER_ID_ALL;
|
||||
}
|
||||
|
||||
if (ID_IS_OVERRIDE_LIBRARY_REAL(id_owner)) {
|
||||
/* LibOverride data 'hierarchy root' can virtually point back to any type of ID. */
|
||||
return FILTER_ID_ALL;
|
||||
}
|
||||
|
||||
switch ((ID_Type)id_type_owner) {
|
||||
case ID_LI:
|
||||
return FILTER_ID_LI;
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "BLI_path_util.h"
|
||||
#include "BLI_session_uuid.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
|
@ -137,7 +138,7 @@ static ModifierData *modifier_allocate_and_init(ModifierType type)
|
|||
ModifierData *md = static_cast<ModifierData *>(MEM_callocN(mti->structSize, mti->structName));
|
||||
|
||||
/* NOTE: this name must be made unique later. */
|
||||
STRNCPY(md->name, DATA_(mti->name));
|
||||
STRNCPY_UTF8(md->name, DATA_(mti->name));
|
||||
|
||||
md->type = type;
|
||||
md->mode = eModifierMode_Realtime | eModifierMode_Render;
|
||||
|
|
|
@ -1521,8 +1521,10 @@ void multires_ensure_external_read(struct Mesh *mesh, int top_level)
|
|||
return;
|
||||
}
|
||||
|
||||
MDisps *mdisps = static_cast<MDisps *>(
|
||||
CustomData_get_layer_for_write(&mesh->ldata, CD_MDISPS, mesh->totloop));
|
||||
/* Modify the data array from the original mesh, not the evaluated mesh.
|
||||
* When multiple objects share the same mesh, this can lead to memory leaks. */
|
||||
MDisps *mdisps = const_cast<MDisps *>(
|
||||
static_cast<const MDisps *>(CustomData_get_layer(&mesh->ldata, CD_MDISPS)));
|
||||
if (mdisps == nullptr) {
|
||||
mdisps = static_cast<MDisps *>(
|
||||
CustomData_add_layer(&mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, mesh->totloop));
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "BLI_set.hh"
|
||||
#include "BLI_stack.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
@ -1161,7 +1162,7 @@ static void node_init(const bContext *C, bNodeTree *ntree, bNode *node)
|
|||
* Data have their own translation option!
|
||||
* This solution may be a bit rougher than nodeLabel()'s returned string, but it's simpler
|
||||
* than adding "do_translate" flags to this func (and labelfunc() as well). */
|
||||
STRNCPY(node->name, DATA_(ntype->ui_name));
|
||||
STRNCPY_UTF8(node->name, DATA_(ntype->ui_name));
|
||||
nodeUniqueName(ntree, node);
|
||||
|
||||
/* Generally sockets should be added after the initialization, because the set of sockets might
|
||||
|
|
|
@ -481,9 +481,9 @@ char *BKE_packedfile_unpack_to_file(ReportList *reports,
|
|||
static void unpack_generate_paths(const char *filepath,
|
||||
ID *id,
|
||||
char *r_abspath,
|
||||
size_t abspath_maxncpy,
|
||||
char *r_relpath,
|
||||
size_t abspathlen,
|
||||
size_t relpathlen)
|
||||
size_t relpath_maxncpy)
|
||||
{
|
||||
const short id_type = GS(id->name);
|
||||
char temp_filename[FILE_MAX];
|
||||
|
@ -545,13 +545,13 @@ static void unpack_generate_paths(const char *filepath,
|
|||
break;
|
||||
}
|
||||
if (dir_name) {
|
||||
BLI_path_join(r_relpath, relpathlen, "//", dir_name, temp_filename);
|
||||
BLI_path_join(r_relpath, relpath_maxncpy, "//", dir_name, temp_filename);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
size_t len = BLI_strncpy_rlen(r_abspath, temp_dirname, abspathlen);
|
||||
BLI_strncpy(r_abspath + len, temp_filename, abspathlen - len);
|
||||
size_t len = BLI_strncpy_rlen(r_abspath, temp_dirname, abspath_maxncpy);
|
||||
BLI_strncpy(r_abspath + len, temp_filename, abspath_maxncpy - len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -567,7 +567,7 @@ char *BKE_packedfile_unpack(Main *bmain,
|
|||
|
||||
if (id != NULL) {
|
||||
unpack_generate_paths(
|
||||
orig_file_path, id, absname, localname, sizeof(absname), sizeof(localname));
|
||||
orig_file_path, id, absname, sizeof(absname), localname, sizeof(localname));
|
||||
new_name = BKE_packedfile_unpack_to_file(
|
||||
reports, BKE_main_blendfile_path(bmain), absname, localname, pf, how);
|
||||
}
|
||||
|
|
|
@ -910,7 +910,7 @@ static bool seq_foreach_path_callback(Sequence *seq, void *user_data)
|
|||
BPathForeachPathData *bpath_data = (BPathForeachPathData *)user_data;
|
||||
|
||||
if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM) && se) {
|
||||
BKE_bpath_foreach_path_dirfile_fixed_process(bpath_data, seq->strip->dir, se->name);
|
||||
BKE_bpath_foreach_path_dirfile_fixed_process(bpath_data, seq->strip->dirpath, se->filename);
|
||||
}
|
||||
else if ((seq->type == SEQ_TYPE_IMAGE) && se) {
|
||||
/* NOTE: An option not to loop over all strips could be useful? */
|
||||
|
@ -923,12 +923,13 @@ static bool seq_foreach_path_callback(Sequence *seq, void *user_data)
|
|||
}
|
||||
|
||||
for (i = 0; i < len; i++, se++) {
|
||||
BKE_bpath_foreach_path_dirfile_fixed_process(bpath_data, seq->strip->dir, se->name);
|
||||
BKE_bpath_foreach_path_dirfile_fixed_process(
|
||||
bpath_data, seq->strip->dirpath, se->filename);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* simple case */
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, seq->strip->dir);
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, seq->strip->dirpath);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -65,7 +65,7 @@ ShaderFxData *BKE_shaderfx_new(int type)
|
|||
ShaderFxData *fx = MEM_callocN(fxi->struct_size, fxi->struct_name);
|
||||
|
||||
/* NOTE: this name must be made unique later. */
|
||||
STRNCPY(fx->name, DATA_(fxi->name));
|
||||
STRNCPY_UTF8(fx->name, DATA_(fxi->name));
|
||||
|
||||
fx->type = type;
|
||||
fx->mode = eShaderFxMode_Realtime | eShaderFxMode_Render;
|
||||
|
|
|
@ -68,7 +68,7 @@ void ModifierSimulationCache::try_discover_bake(const StringRefNull meta_dir,
|
|||
if (!dir_entry_path.endswith(".json")) {
|
||||
continue;
|
||||
}
|
||||
char modified_file_name[FILENAME_MAX];
|
||||
char modified_file_name[FILE_MAX];
|
||||
STRNCPY(modified_file_name, dir_entry.relname);
|
||||
BLI_str_replace_char(modified_file_name, '_', '.');
|
||||
|
||||
|
|
|
@ -1081,7 +1081,7 @@ static void ffmpeg_dict_set_int(AVDictionary **dict, const char *key, int value)
|
|||
static void ffmpeg_add_metadata_callback(void *data,
|
||||
const char *propname,
|
||||
char *propvalue,
|
||||
int UNUSED(len))
|
||||
int UNUSED(propvalue_maxncpy))
|
||||
{
|
||||
AVDictionary **metadata = (AVDictionary **)data;
|
||||
av_dict_set(metadata, propname, propvalue, 0);
|
||||
|
|
|
@ -285,6 +285,10 @@ BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
|
|||
lb->first = lb->last = (void *)0;
|
||||
}
|
||||
|
||||
/** Validate the integrity of a given ListBase, returns `true` if evrything is OK, false otherwise.
|
||||
*/
|
||||
bool BLI_listbase_validate(struct ListBase *lb);
|
||||
|
||||
/**
|
||||
* Equality check for ListBase.
|
||||
*
|
||||
|
|
|
@ -560,7 +560,7 @@ static bool delete_recursive(const char *dir)
|
|||
char path[FILE_MAXDIR];
|
||||
|
||||
/* dir listing produces dir path without trailing slash... */
|
||||
BLI_strncpy(path, fl->path, sizeof(path));
|
||||
STRNCPY(path, fl->path);
|
||||
BLI_path_slash_ensure(path, sizeof(path));
|
||||
|
||||
if (delete_recursive(path)) {
|
||||
|
@ -627,7 +627,7 @@ int BLI_path_move(const char *file, const char *to)
|
|||
* it has to be 'mv filepath filepath' and not
|
||||
* 'mv filepath destination_directory' */
|
||||
|
||||
BLI_strncpy(str, to, sizeof(str));
|
||||
STRNCPY(str, to);
|
||||
/* points 'to' to a directory ? */
|
||||
if (BLI_path_slash_rfind(str) == (str + strlen(str) - 1)) {
|
||||
if (BLI_path_slash_rfind(file) != NULL) {
|
||||
|
@ -658,7 +658,7 @@ int BLI_copy(const char *file, const char *to)
|
|||
* it has to be 'cp filepath filepath' and not
|
||||
* 'cp filepath destdir' */
|
||||
|
||||
BLI_strncpy(str, to, sizeof(str));
|
||||
STRNCPY(str, to);
|
||||
/* points 'to' to a directory ? */
|
||||
if (BLI_path_slash_rfind(str) == (str + strlen(str) - 1)) {
|
||||
if (BLI_path_slash_rfind(file) != NULL) {
|
||||
|
@ -741,9 +741,9 @@ static void join_dirfile_alloc(char **dst, size_t *alloc_len, const char *dir, c
|
|||
BLI_path_join(*dst, len + 1, dir, file);
|
||||
}
|
||||
|
||||
static char *strip_last_slash(const char *dir)
|
||||
static char *strip_last_slash(const char *dirpath)
|
||||
{
|
||||
char *result = BLI_strdup(dir);
|
||||
char *result = BLI_strdup(dirpath);
|
||||
BLI_path_slash_rstrip(result);
|
||||
|
||||
return result;
|
||||
|
|
|
@ -871,6 +871,47 @@ void BLI_listbase_rotate_last(ListBase *lb, void *vlink)
|
|||
((Link *)lb->last)->next = nullptr;
|
||||
}
|
||||
|
||||
bool BLI_listbase_validate(ListBase *lb)
|
||||
{
|
||||
if (lb->first == nullptr && lb->last == nullptr) {
|
||||
/* Empty list. */
|
||||
return true;
|
||||
}
|
||||
if (ELEM(nullptr, lb->first, lb->last)) {
|
||||
/* If one of the pointer is null, but not this other, this is a corrupted listbase. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Walk the list in bot directions to ensure all next & prev pointers are valid and consistent.
|
||||
*/
|
||||
for (Link *lb_link = static_cast<Link *>(lb->first); lb_link; lb_link = lb_link->next) {
|
||||
if (lb_link == lb->first) {
|
||||
if (lb_link->prev != nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (lb_link == lb->last) {
|
||||
if (lb_link->next != nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Link *lb_link = static_cast<Link *>(lb->last); lb_link; lb_link = lb_link->prev) {
|
||||
if (lb_link == lb->last) {
|
||||
if (lb_link->next != nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (lb_link == lb->first) {
|
||||
if (lb_link->prev != nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
LinkData *BLI_genericNodeN(void *data)
|
||||
{
|
||||
LinkData *ld;
|
||||
|
|
|
@ -43,6 +43,9 @@
|
|||
* - 254..255: invalid.
|
||||
*
|
||||
* Invalid values fall back to 1 byte or -1 (for an error value).
|
||||
*
|
||||
* \note From testing string copying via #BLI_strncpy_utf8 with large (multi-megabyte) strings,
|
||||
* using a function instead of a lookup-table is between 2 & 3 times faster.
|
||||
* \{ */
|
||||
|
||||
BLI_INLINE int utf8_char_compute_skip(const char c)
|
||||
|
@ -310,7 +313,7 @@ int BLI_str_utf8_invalid_strip(char *str, size_t length)
|
|||
BLI_INLINE char *str_utf8_copy_max_bytes_impl(char *dst, const char *src, size_t dst_maxncpy)
|
||||
{
|
||||
/* Cast to `uint8_t` is a no-op, quiets array subscript of type `char` warning.
|
||||
* No need to check `src` points to a nil byte, this will break out of the switch statement. */
|
||||
* No need to check `src` points to a nil byte as this will return from the switch statement. */
|
||||
size_t utf8_size;
|
||||
while ((utf8_size = (size_t)utf8_char_compute_skip(*src)) < dst_maxncpy) {
|
||||
dst_maxncpy -= utf8_size;
|
||||
|
@ -318,12 +321,12 @@ BLI_INLINE char *str_utf8_copy_max_bytes_impl(char *dst, const char *src, size_t
|
|||
/* NOLINTBEGIN: bugprone-assignment-in-if-condition */
|
||||
/* clang-format off */
|
||||
switch (utf8_size) {
|
||||
case 6: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++; ATTR_FALLTHROUGH;
|
||||
case 5: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++; ATTR_FALLTHROUGH;
|
||||
case 4: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++; ATTR_FALLTHROUGH;
|
||||
case 3: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++; ATTR_FALLTHROUGH;
|
||||
case 2: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++; ATTR_FALLTHROUGH;
|
||||
case 1: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++;
|
||||
case 6: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++; ATTR_FALLTHROUGH;
|
||||
case 5: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++; ATTR_FALLTHROUGH;
|
||||
case 4: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++; ATTR_FALLTHROUGH;
|
||||
case 3: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++; ATTR_FALLTHROUGH;
|
||||
case 2: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++; ATTR_FALLTHROUGH;
|
||||
case 1: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++;
|
||||
}
|
||||
/* clang-format on */
|
||||
/* NOLINTEND: bugprone-assignment-in-if-condition */
|
||||
|
|
|
@ -112,7 +112,7 @@ bool BLI_windows_register_blend_extension(const bool background)
|
|||
&hkey,
|
||||
&dwd);
|
||||
if (lresult == ERROR_SUCCESS) {
|
||||
BLI_snprintf(buffer, sizeof(buffer), "\"%s\" \"%%1\"", BlPath);
|
||||
SNPRINTF(buffer, "\"%s\" \"%%1\"", BlPath);
|
||||
lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
|
||||
RegCloseKey(hkey);
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ bool BLI_windows_register_blend_extension(const bool background)
|
|||
&hkey,
|
||||
&dwd);
|
||||
if (lresult == ERROR_SUCCESS) {
|
||||
BLI_snprintf(buffer, sizeof(buffer), "\"%s\", 1", BlPath);
|
||||
SNPRINTF(buffer, "\"%s\", 1", BlPath);
|
||||
lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
|
||||
RegCloseKey(hkey);
|
||||
}
|
||||
|
@ -169,12 +169,10 @@ bool BLI_windows_register_blend_extension(const bool background)
|
|||
RegCloseKey(root);
|
||||
printf("success (%s)\n", usr_mode ? "user" : "system");
|
||||
if (!background) {
|
||||
BLI_snprintf(MBox,
|
||||
sizeof(MBox),
|
||||
"File extension registered for %s.",
|
||||
usr_mode ?
|
||||
"the current user. To register for all users, run as an administrator" :
|
||||
"all users");
|
||||
SNPRINTF(MBox,
|
||||
"File extension registered for %s.",
|
||||
usr_mode ? "the current user. To register for all users, run as an administrator" :
|
||||
"all users");
|
||||
MessageBox(0, MBox, "Blender", MB_OK | MB_ICONINFORMATION);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -107,7 +107,7 @@ TEST(listbase, FindLinkOrIndex)
|
|||
TEST(listbase, FindLinkFromStringOrPointer)
|
||||
{
|
||||
struct TestLink {
|
||||
struct TestLink *prev, *next;
|
||||
struct TestLink *next, *prev;
|
||||
char name[64];
|
||||
const void *ptr;
|
||||
};
|
||||
|
|
|
@ -335,7 +335,7 @@ static void polyfill_to_obj(const char *id,
|
|||
FILE *f;
|
||||
uint i;
|
||||
|
||||
BLI_snprintf(path, sizeof(path), "%s.obj", id);
|
||||
SNPRINTF(path, "%s.obj", id);
|
||||
|
||||
f = fopen(path, "w");
|
||||
if (!f) {
|
||||
|
|
|
@ -632,7 +632,7 @@ static bool seq_sound_proxy_update_cb(Sequence *seq, void *user_data)
|
|||
Main *bmain = (Main *)user_data;
|
||||
if (seq->type == SEQ_TYPE_SOUND_HD) {
|
||||
char str[FILE_MAX];
|
||||
BLI_path_join(str, sizeof(str), seq->strip->dir, seq->strip->stripdata->name);
|
||||
BLI_path_join(str, sizeof(str), seq->strip->dirpath, seq->strip->stripdata->filename);
|
||||
BLI_path_abs(str, BKE_main_blendfile_path(bmain));
|
||||
seq->sound = BKE_sound_new_file(bmain, str);
|
||||
}
|
||||
|
@ -640,7 +640,7 @@ static bool seq_sound_proxy_update_cb(Sequence *seq, void *user_data)
|
|||
#define SEQ_USE_PROXY_CUSTOM_FILE (1 << 21)
|
||||
/* don't know, if anybody used that this way, but just in case, upgrade to new way... */
|
||||
if ((seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) && !(seq->flag & SEQ_USE_PROXY_CUSTOM_DIR)) {
|
||||
SNPRINTF(seq->strip->proxy->dir, "%s" SEP_STR "BL_proxy", seq->strip->dir);
|
||||
SNPRINTF(seq->strip->proxy->dirpath, "%s" SEP_STR "BL_proxy", seq->strip->dirpath);
|
||||
}
|
||||
#undef SEQ_USE_PROXY_CUSTOM_DIR
|
||||
#undef SEQ_USE_PROXY_CUSTOM_FILE
|
||||
|
|
|
@ -4355,6 +4355,27 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 306, 9)) {
|
||||
/* Fix sound strips with speed factor set to 0. See #107289. */
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
Editing *ed = SEQ_editing_get(scene);
|
||||
if (ed != nullptr) {
|
||||
SEQ_for_each_callback(&ed->seqbase, version_seq_fix_broken_sound_strips, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
|
||||
if (sl->spacetype == SPACE_ACTION) {
|
||||
SpaceAction *saction = reinterpret_cast<SpaceAction *>(sl);
|
||||
saction->cache_display |= TIME_CACHE_SIMULATION_NODES;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
|
@ -4366,13 +4387,5 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
|
||||
/* Fix sound strips with speed factor set to 0. See #107289. */
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
Editing *ed = SEQ_editing_get(scene);
|
||||
if (ed != nullptr) {
|
||||
SEQ_for_each_callback(&ed->seqbase, version_seq_fix_broken_sound_strips, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
|
@ -812,7 +813,7 @@ void blo_do_versions_userdef(UserDef *userdef)
|
|||
"Versioning user script path");
|
||||
|
||||
STRNCPY(script_dir->dir_path, userdef->pythondir_legacy);
|
||||
STRNCPY(script_dir->name, DATA_("Untitled"));
|
||||
STRNCPY_UTF8(script_dir->name, DATA_("Untitled"));
|
||||
BLI_addhead(&userdef->script_directories, script_dir);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1063,7 +1063,7 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
|
|||
#ifdef WITH_BUILDINFO
|
||||
/* TODO(sergey): Add branch name to file as well? */
|
||||
fg.build_commit_timestamp = build_commit_timestamp;
|
||||
BLI_strncpy(fg.build_hash, build_hash, sizeof(fg.build_hash));
|
||||
STRNCPY(fg.build_hash, build_hash);
|
||||
#else
|
||||
fg.build_commit_timestamp = 0;
|
||||
STRNCPY(fg.build_hash, "unknown");
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
* Copyright 2019 Blender Foundation. */
|
||||
#include "blendfile_loading_base_test.h"
|
||||
|
||||
#include "BLI_path_util.h"
|
||||
|
||||
class BlendfileLoadingTest : public BlendfileLoadingBaseTest {
|
||||
};
|
||||
|
||||
TEST_F(BlendfileLoadingTest, CanaryTest)
|
||||
{
|
||||
/* Load the smallest blend file we have in the SVN lib/tests directory. */
|
||||
if (!blendfile_load("modifier_stack/array_test.blend")) {
|
||||
if (!blendfile_load("modifier_stack" SEP_STR "array_test.blend")) {
|
||||
return;
|
||||
}
|
||||
depsgraph_create(DAG_EVAL_RENDER);
|
||||
|
|
|
@ -116,7 +116,7 @@ bool BlendfileLoadingBaseTest::blendfile_load(const char *filepath)
|
|||
return false;
|
||||
}
|
||||
|
||||
char abspath[FILENAME_MAX];
|
||||
char abspath[FILE_MAX];
|
||||
BLI_path_join(abspath, sizeof(abspath), test_assets_dir.c_str(), filepath);
|
||||
|
||||
BlendFileReadReport bf_reports = {nullptr};
|
||||
|
|
|
@ -453,15 +453,14 @@ void OutputOpenExrMultiLayerOperation::update_memory_buffer_partial(MemoryBuffer
|
|||
const rcti &area,
|
||||
Span<MemoryBuffer *> inputs)
|
||||
{
|
||||
const MemoryBuffer *input_image = inputs[0];
|
||||
for (int i = 0; i < layers_.size(); i++) {
|
||||
OutputOpenExrLayer &layer = layers_[i];
|
||||
int layer_num_channels = COM_data_type_num_channels(layer.datatype);
|
||||
if (layer.output_buffer) {
|
||||
MemoryBuffer output_buf(layer.output_buffer,
|
||||
COM_data_type_num_channels(layer.datatype),
|
||||
this->get_width(),
|
||||
this->get_height());
|
||||
output_buf.copy_from(input_image, area);
|
||||
MemoryBuffer output_buf(
|
||||
layer.output_buffer, layer_num_channels, this->get_width(), this->get_height());
|
||||
/* Input node always has 4 channels. Not all are needed depending on datatype. */
|
||||
output_buf.copy_from(inputs[i], area, 0, layer_num_channels, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ static void extract_tan_init_common(const MeshRenderData *mr,
|
|||
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
|
||||
const char *layer_name = CustomData_get_layer_name(r_loop_data, CD_TANGENT, 0);
|
||||
GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
|
||||
BLI_snprintf(attr_name, sizeof(*attr_name), "t%s", attr_safe_name);
|
||||
SNPRINTF(attr_name, "t%s", attr_safe_name);
|
||||
GPU_vertformat_attr_add(format, attr_name, comp_type, 4, fetch_mode);
|
||||
GPU_vertformat_alias_add(format, "t");
|
||||
GPU_vertformat_alias_add(format, "at");
|
||||
|
|
|
@ -368,7 +368,7 @@ static void acf_generic_idblock_name(bAnimListElem *ale, char *name)
|
|||
|
||||
/* just copy the name... */
|
||||
if (id && name) {
|
||||
BLI_strncpy(name, id->name + 2, ANIM_CHAN_NAME_SIZE);
|
||||
BLI_strncpy_utf8(name, id->name + 2, ANIM_CHAN_NAME_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -476,7 +476,7 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi
|
|||
static void acf_summary_name(bAnimListElem *UNUSED(ale), char *name)
|
||||
{
|
||||
if (name) {
|
||||
BLI_strncpy(name, IFACE_("Summary"), ANIM_CHAN_NAME_SIZE);
|
||||
BLI_strncpy_utf8(name, IFACE_("Summary"), ANIM_CHAN_NAME_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1178,7 +1178,7 @@ static void acf_nla_controls_backdrop(bAnimContext *ac,
|
|||
/* name for nla controls expander entries */
|
||||
static void acf_nla_controls_name(bAnimListElem *UNUSED(ale), char *name)
|
||||
{
|
||||
BLI_strncpy(name, IFACE_("NLA Strip Controls"), ANIM_CHAN_NAME_SIZE);
|
||||
BLI_strncpy_utf8(name, IFACE_("NLA Strip Controls"), ANIM_CHAN_NAME_SIZE);
|
||||
}
|
||||
|
||||
/* check if some setting exists for this channel */
|
||||
|
@ -1393,7 +1393,7 @@ static int acf_filldrivers_icon(bAnimListElem *UNUSED(ale))
|
|||
|
||||
static void acf_filldrivers_name(bAnimListElem *UNUSED(ale), char *name)
|
||||
{
|
||||
BLI_strncpy(name, IFACE_("Drivers"), ANIM_CHAN_NAME_SIZE);
|
||||
BLI_strncpy_utf8(name, IFACE_("Drivers"), ANIM_CHAN_NAME_SIZE);
|
||||
}
|
||||
|
||||
/* check if some setting exists for this channel */
|
||||
|
@ -4468,6 +4468,10 @@ void ANIM_channel_draw(
|
|||
/* just skip - drawn as widget now */
|
||||
offset += ICON_WIDTH;
|
||||
}
|
||||
else {
|
||||
/* A bit of padding when there is no expand widget. */
|
||||
offset += (short)(0.2f * U.widget_unit);
|
||||
}
|
||||
|
||||
/* step 3) draw icon ............................................... */
|
||||
if (acf->icon) {
|
||||
|
@ -4522,10 +4526,6 @@ void ANIM_channel_draw(
|
|||
offset += ICON_WIDTH;
|
||||
}
|
||||
}
|
||||
else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
|
||||
/* just skip - drawn as widget now */
|
||||
offset += ICON_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
/* step 5) draw name ............................................... */
|
||||
|
@ -5252,11 +5252,6 @@ void ANIM_channel_draw_widgets(const bContext *C,
|
|||
offset += ICON_WIDTH;
|
||||
}
|
||||
}
|
||||
else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
|
||||
/* 'solo' setting for NLA Tracks */
|
||||
draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_SOLO);
|
||||
offset += ICON_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
/* step 4) draw text - check if renaming widget is in use... */
|
||||
|
@ -5338,6 +5333,13 @@ void ANIM_channel_draw_widgets(const bContext *C,
|
|||
/* check if there's enough space for the toggles if the sliders are drawn too */
|
||||
if (!(draw_sliders) || (BLI_rcti_size_x(&v2d->mask) > ANIM_UI_get_channel_button_width() / 2))
|
||||
{
|
||||
/* solo... */
|
||||
if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
|
||||
offset -= ICON_WIDTH;
|
||||
draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_SOLO);
|
||||
/* A touch of padding because the star icon is so wide. */
|
||||
offset -= (short)(0.2f * ICON_WIDTH);
|
||||
}
|
||||
/* protect... */
|
||||
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) {
|
||||
offset -= ICON_WIDTH;
|
||||
|
|
|
@ -327,6 +327,7 @@ void postEditBoneDuplicate(struct ListBase *editbones, Object *ob)
|
|||
if (!ebone_dst) {
|
||||
ebone_dst = ED_armature_ebone_get_mirrored(editbones, ebone_src);
|
||||
}
|
||||
|
||||
if (ebone_dst) {
|
||||
BLI_ghash_insert(name_map, ebone_src->name, ebone_dst->name);
|
||||
}
|
||||
|
@ -334,22 +335,28 @@ void postEditBoneDuplicate(struct ListBase *editbones, Object *ob)
|
|||
|
||||
LISTBASE_FOREACH (EditBone *, ebone_src, editbones) {
|
||||
EditBone *ebone_dst = ebone_src->temp.ebone;
|
||||
if (ebone_dst) {
|
||||
bPoseChannel *pchan_src = BKE_pose_channel_find_name(ob->pose, ebone_src->name);
|
||||
if (pchan_src) {
|
||||
bPoseChannel *pchan_dst = BKE_pose_channel_find_name(ob->pose, ebone_dst->name);
|
||||
if (pchan_dst) {
|
||||
if (pchan_src->custom_tx) {
|
||||
pchan_dst->custom_tx = pchan_duplicate_map(ob->pose, name_map, pchan_src->custom_tx);
|
||||
}
|
||||
if (pchan_src->bbone_prev) {
|
||||
pchan_dst->bbone_prev = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_prev);
|
||||
}
|
||||
if (pchan_src->bbone_next) {
|
||||
pchan_dst->bbone_next = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_next);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ebone_dst) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bPoseChannel *pchan_src = BKE_pose_channel_find_name(ob->pose, ebone_src->name);
|
||||
if (!pchan_src) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bPoseChannel *pchan_dst = BKE_pose_channel_find_name(ob->pose, ebone_dst->name);
|
||||
if (!pchan_dst) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pchan_src->custom_tx) {
|
||||
pchan_dst->custom_tx = pchan_duplicate_map(ob->pose, name_map, pchan_src->custom_tx);
|
||||
}
|
||||
if (pchan_src->bbone_prev) {
|
||||
pchan_dst->bbone_prev = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_prev);
|
||||
}
|
||||
if (pchan_src->bbone_next) {
|
||||
pchan_dst->bbone_next = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_next);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1120,71 +1127,80 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op)
|
|||
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||
scene, view_layer, CTX_wm_view3d(C), &objects_len);
|
||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||
Object *obedit = objects[ob_index];
|
||||
bArmature *arm = obedit->data;
|
||||
|
||||
EditBone *ebone_iter;
|
||||
/* The beginning of the duplicated mirrored bones in the edbo list */
|
||||
EditBone *ebone_first_dupe = NULL;
|
||||
|
||||
Object *obedit = objects[ob_index];
|
||||
bArmature *arm = obedit->data;
|
||||
|
||||
ED_armature_edit_sync_selection(arm->edbo); /* XXX why is this needed? */
|
||||
|
||||
preEditBoneDuplicate(arm->edbo);
|
||||
|
||||
/* Select mirrored bones */
|
||||
/* Deselect ebones depending on input axis and direction.
|
||||
* A symmetrizable selection contains selected ebones of the input direction
|
||||
* and unique selected bones with an unique flippable name.
|
||||
*
|
||||
* Storing temp ptrs to mirrored unselected ebones. */
|
||||
for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
|
||||
if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED)) {
|
||||
char name_flip[MAXBONENAME];
|
||||
if (!(EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED))) {
|
||||
/* Skipping invisible selected bones. */
|
||||
continue;
|
||||
}
|
||||
|
||||
BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip));
|
||||
char name_flip[MAXBONENAME];
|
||||
if (ebone_iter == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (STREQ(name_flip, ebone_iter->name)) {
|
||||
/* if the name matches, we don't have the potential to be mirrored, just skip */
|
||||
ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
|
||||
}
|
||||
else {
|
||||
EditBone *ebone = ED_armature_ebone_find_name(arm->edbo, name_flip);
|
||||
BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip));
|
||||
|
||||
if (ebone) {
|
||||
if ((ebone->flag & BONE_SELECTED) == 0) {
|
||||
/* simple case, we're selected, the other bone isn't! */
|
||||
ebone_iter->temp.ebone = ebone;
|
||||
}
|
||||
else {
|
||||
/* complicated - choose which direction to copy */
|
||||
float axis_delta;
|
||||
if (STREQ(name_flip, ebone_iter->name)) {
|
||||
/* Skipping ebones without flippable as they don't have the potential to be mirrored. */
|
||||
ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
|
||||
continue;
|
||||
}
|
||||
|
||||
axis_delta = ebone->head[axis] - ebone_iter->head[axis];
|
||||
if (axis_delta == 0.0f) {
|
||||
axis_delta = ebone->tail[axis] - ebone_iter->tail[axis];
|
||||
}
|
||||
EditBone *ebone = ED_armature_ebone_find_name(arm->edbo, name_flip);
|
||||
|
||||
if (axis_delta == 0.0f) {
|
||||
/* Both mirrored bones exist and point to each other and overlap exactly.
|
||||
*
|
||||
* in this case there's no well defined solution, so de-select both and skip.
|
||||
*/
|
||||
ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
|
||||
ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
|
||||
}
|
||||
else {
|
||||
EditBone *ebone_src, *ebone_dst;
|
||||
if (((axis_delta < 0.0f) ? -1 : 1) == direction) {
|
||||
ebone_src = ebone;
|
||||
ebone_dst = ebone_iter;
|
||||
}
|
||||
else {
|
||||
ebone_src = ebone_iter;
|
||||
ebone_dst = ebone;
|
||||
}
|
||||
if (!ebone) {
|
||||
/* The ebone_iter is unique and mirrorable. */
|
||||
continue;
|
||||
}
|
||||
|
||||
ebone_src->temp.ebone = ebone_dst;
|
||||
ebone_dst->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
|
||||
}
|
||||
}
|
||||
if (ebone->flag & BONE_SELECTED) {
|
||||
/* The mirrored ebone and the ebone_iter are selected.
|
||||
* Deselect based on the input direction and axis. */
|
||||
float axis_delta;
|
||||
|
||||
axis_delta = ebone->head[axis] - ebone_iter->head[axis];
|
||||
if (axis_delta == 0.0f) {
|
||||
/* The ebone heads are overlapping. */
|
||||
axis_delta = ebone->tail[axis] - ebone_iter->tail[axis];
|
||||
|
||||
if (axis_delta == 0.0f) {
|
||||
/* Both mirrored bones point to each other and overlap exactly.
|
||||
* In this case there's no well defined solution, so de-select both and skip. */
|
||||
ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
|
||||
ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Deselect depending on direction. */
|
||||
if (((axis_delta < 0.0f) ? -1 : 1) == direction) {
|
||||
/* Don't store temp ptr if the iter_bone gets deselected.
|
||||
* In this case, the ebone.temp should point to the ebone_iter. */
|
||||
ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
|
||||
continue;
|
||||
}
|
||||
|
||||
ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
|
||||
}
|
||||
|
||||
/* Set temp pointer to mirrored ebones */
|
||||
ebone_iter->temp.ebone = ebone;
|
||||
}
|
||||
|
||||
/* Find the selected bones and duplicate them as needed, with mirrored name. */
|
||||
|
@ -1206,11 +1222,12 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op)
|
|||
ebone_iter->temp.ebone->inherit_scale_mode = ebone_iter->inherit_scale_mode;
|
||||
continue;
|
||||
}
|
||||
|
||||
char name_flip[MAXBONENAME];
|
||||
|
||||
BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip));
|
||||
|
||||
/* bones must have a side-suffix */
|
||||
/* mirrored bones must have a side-suffix */
|
||||
if (!STREQ(name_flip, ebone_iter->name)) {
|
||||
EditBone *ebone;
|
||||
|
||||
|
@ -1254,8 +1271,8 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op)
|
|||
*/
|
||||
|
||||
if (ebone->head[axis] != 0.0f) {
|
||||
/* The mirrored bone doesn't start on the mirror axis, so assume that this one should
|
||||
* not be connected to the old parent */
|
||||
/* The mirrored bone doesn't start on the mirror axis, so assume that this one
|
||||
* should not be connected to the old parent */
|
||||
ebone->flag &= ~BONE_CONNECTED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3388,7 +3388,7 @@ void ED_gpencil_layer_merge(bGPdata *gpd,
|
|||
}
|
||||
}
|
||||
|
||||
static void gpencil_layer_new_name_get(bGPdata *gpd, char *rname)
|
||||
static void gpencil_layer_new_name_get(bGPdata *gpd, char *r_name, size_t name_maxncpy)
|
||||
{
|
||||
int index = 0;
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
|
@ -3398,12 +3398,10 @@ static void gpencil_layer_new_name_get(bGPdata *gpd, char *rname)
|
|||
}
|
||||
|
||||
if (index == 0) {
|
||||
BLI_strncpy(rname, "GP_Layer", 128);
|
||||
BLI_strncpy(r_name, "GP_Layer", name_maxncpy);
|
||||
return;
|
||||
}
|
||||
char *name = BLI_sprintfN("%.*s.%03d", 128, "GP_Layer", index);
|
||||
BLI_strncpy(rname, name, 128);
|
||||
MEM_freeN(name);
|
||||
BLI_snprintf(r_name, name_maxncpy, "GP_Layer.%03d", index);
|
||||
}
|
||||
|
||||
int ED_gpencil_new_layer_dialog(bContext *C, wmOperator *op)
|
||||
|
@ -3415,7 +3413,7 @@ int ED_gpencil_new_layer_dialog(bContext *C, wmOperator *op)
|
|||
if (!RNA_property_is_set(op->ptr, prop)) {
|
||||
char name[MAX_NAME];
|
||||
bGPdata *gpd = ob->data;
|
||||
gpencil_layer_new_name_get(gpd, name);
|
||||
gpencil_layer_new_name_get(gpd, name, sizeof(name));
|
||||
RNA_property_string_set(op->ptr, prop, name);
|
||||
return WM_operator_props_dialog_popup(C, op, 200);
|
||||
}
|
||||
|
|
|
@ -3937,11 +3937,11 @@ static void ui_but_update_ex(uiBut *but, const bool validate)
|
|||
(void)str; /* UNUSED */
|
||||
}
|
||||
else {
|
||||
STRNCPY(but->drawstr, IFACE_("Press a key"));
|
||||
STRNCPY_UTF8(but->drawstr, IFACE_("Press a key"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
STRNCPY(but->drawstr, but->str);
|
||||
STRNCPY_UTF8(but->drawstr, but->str);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
|
@ -2021,7 +2022,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op)
|
|||
BKE_nlatrack_add_strip(nlt, strip, is_liboverride);
|
||||
|
||||
/* Auto-name the strip, and give the track an interesting name. */
|
||||
STRNCPY(nlt->name, DATA_("SoundTrack"));
|
||||
STRNCPY_UTF8(nlt->name, DATA_("SoundTrack"));
|
||||
BKE_nlastrip_validate_name(adt, strip);
|
||||
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, nullptr);
|
||||
|
|
|
@ -779,6 +779,9 @@ static bConstraint *edit_constraint_property_get(bContext *C, wmOperator *op, Ob
|
|||
|
||||
if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
|
||||
list = ED_object_pose_constraint_list(C);
|
||||
if (!list) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
list = &ob->constraints;
|
||||
|
|
|
@ -758,23 +758,25 @@ void timeline_draw_cache(const SpaceAction *saction, const Object *ob, const Sce
|
|||
|
||||
y_offset += cache_draw_height;
|
||||
}
|
||||
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
|
||||
if (md->type != eModifierType_Nodes) {
|
||||
continue;
|
||||
if (saction->cache_display & TIME_CACHE_SIMULATION_NODES) {
|
||||
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
|
||||
if (md->type != eModifierType_Nodes) {
|
||||
continue;
|
||||
}
|
||||
const NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
|
||||
if (nmd->node_group == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (nmd->simulation_cache == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if ((nmd->node_group->runtime->runtime_flag & NTREE_RUNTIME_FLAG_HAS_SIMULATION_ZONE) == 0) {
|
||||
continue;
|
||||
}
|
||||
timeline_cache_draw_simulation_nodes(
|
||||
*scene, *nmd->simulation_cache, y_offset, cache_draw_height, pos_id);
|
||||
y_offset += cache_draw_height;
|
||||
}
|
||||
const NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
|
||||
if (nmd->node_group == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (nmd->simulation_cache == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if ((nmd->node_group->runtime->runtime_flag & NTREE_RUNTIME_FLAG_HAS_SIMULATION_ZONE) == 0) {
|
||||
continue;
|
||||
}
|
||||
timeline_cache_draw_simulation_nodes(
|
||||
*scene, *nmd->simulation_cache, y_offset, cache_draw_height, pos_id);
|
||||
y_offset += cache_draw_height;
|
||||
}
|
||||
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
|
|
|
@ -67,11 +67,9 @@ static SpaceLink *action_create(const ScrArea *area, const Scene *scene)
|
|||
|
||||
saction->ads.filterflag |= ADS_FILTER_SUMMARY;
|
||||
|
||||
/* enable all cache display */
|
||||
saction->cache_display |= TIME_CACHE_DISPLAY;
|
||||
saction->cache_display |= (TIME_CACHE_SOFTBODY | TIME_CACHE_PARTICLES);
|
||||
saction->cache_display |= (TIME_CACHE_CLOTH | TIME_CACHE_SMOKE | TIME_CACHE_DYNAMICPAINT);
|
||||
saction->cache_display |= TIME_CACHE_RIGIDBODY;
|
||||
saction->cache_display = TIME_CACHE_DISPLAY | TIME_CACHE_SOFTBODY | TIME_CACHE_PARTICLES |
|
||||
TIME_CACHE_CLOTH | TIME_CACHE_SMOKE | TIME_CACHE_DYNAMICPAINT |
|
||||
TIME_CACHE_RIGIDBODY | TIME_CACHE_SIMULATION_NODES;
|
||||
|
||||
/* header */
|
||||
region = MEM_cnew<ARegion>("header for action");
|
||||
|
|
|
@ -2841,7 +2841,7 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
|
|||
else if (!can_create_dir(params->dir)) {
|
||||
const char *lastdir = folderlist_peeklastdir(sfile->folders_prev);
|
||||
if (lastdir) {
|
||||
BLI_strncpy(params->dir, lastdir, sizeof(params->dir));
|
||||
STRNCPY(params->dir, lastdir);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -982,7 +982,7 @@ typedef struct tGaussOperatorData {
|
|||
|
||||
/* Store data to smooth an FCurve segment. */
|
||||
typedef struct tFCurveSegmentLink {
|
||||
struct tFCurveSegmentLink *prev, *next;
|
||||
struct tFCurveSegmentLink *next, *prev;
|
||||
FCurve *fcu;
|
||||
FCurveSegment *segment;
|
||||
float *samples; /* Array of y-values of the FCurve segment. */
|
||||
|
|
|
@ -249,7 +249,7 @@ static int unpack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
|
|||
}
|
||||
|
||||
if (count == 1) {
|
||||
STRNCPY(title, IFACE_("Unpack 1 File"));
|
||||
STRNCPY_UTF8(title, IFACE_("Unpack 1 File"));
|
||||
}
|
||||
else {
|
||||
SNPRINTF(title, IFACE_("Unpack %d Files"), count);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_timecode.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
|
@ -748,18 +749,18 @@ void ED_info_draw_stats(
|
|||
};
|
||||
char labels[MAX_LABELS_COUNT][64];
|
||||
|
||||
STRNCPY(labels[OBJ], IFACE_("Objects"));
|
||||
STRNCPY(labels[VERTS], IFACE_("Vertices"));
|
||||
STRNCPY(labels[EDGES], IFACE_("Edges"));
|
||||
STRNCPY(labels[FACES], IFACE_("Faces"));
|
||||
STRNCPY(labels[TRIS], IFACE_("Triangles"));
|
||||
STRNCPY(labels[JOINTS], IFACE_("Joints"));
|
||||
STRNCPY(labels[BONES], IFACE_("Bones"));
|
||||
STRNCPY(labels[LAYERS], IFACE_("Layers"));
|
||||
STRNCPY(labels[FRAMES], IFACE_("Frames"));
|
||||
STRNCPY(labels[STROKES], IFACE_("Strokes"));
|
||||
STRNCPY(labels[POINTS], IFACE_("Points"));
|
||||
STRNCPY(labels[LIGHTS], IFACE_("Lights"));
|
||||
STRNCPY_UTF8(labels[OBJ], IFACE_("Objects"));
|
||||
STRNCPY_UTF8(labels[VERTS], IFACE_("Vertices"));
|
||||
STRNCPY_UTF8(labels[EDGES], IFACE_("Edges"));
|
||||
STRNCPY_UTF8(labels[FACES], IFACE_("Faces"));
|
||||
STRNCPY_UTF8(labels[TRIS], IFACE_("Triangles"));
|
||||
STRNCPY_UTF8(labels[JOINTS], IFACE_("Joints"));
|
||||
STRNCPY_UTF8(labels[BONES], IFACE_("Bones"));
|
||||
STRNCPY_UTF8(labels[LAYERS], IFACE_("Layers"));
|
||||
STRNCPY_UTF8(labels[FRAMES], IFACE_("Frames"));
|
||||
STRNCPY_UTF8(labels[STROKES], IFACE_("Strokes"));
|
||||
STRNCPY_UTF8(labels[POINTS], IFACE_("Points"));
|
||||
STRNCPY_UTF8(labels[LIGHTS], IFACE_("Lights"));
|
||||
|
||||
int longest_label = 0;
|
||||
int i;
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include "BKE_workspace.h"
|
||||
|
||||
#include "BLI_set.hh"
|
||||
#include "BLI_string_utf8.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
@ -507,7 +509,7 @@ void ED_node_shader_default(const bContext *C, ID *id)
|
|||
ma->nodetree = ntreeCopyTree(bmain, ma_default->nodetree);
|
||||
ma->nodetree->owner_id = &ma->id;
|
||||
for (bNode *node_iter : ma->nodetree->all_nodes()) {
|
||||
STRNCPY(node_iter->name, DATA_(node_iter->name));
|
||||
STRNCPY_UTF8(node_iter->name, DATA_(node_iter->name));
|
||||
nodeUniqueName(ma->nodetree, node_iter);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "BLI_array.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
@ -474,14 +475,14 @@ static void ui_node_sock_name(const bNodeTree *ntree,
|
|||
name, UI_MAX_NAME_STR, "%s | %s", IFACE_(node_name), IFACE_(sock->link->fromsock->name));
|
||||
}
|
||||
else {
|
||||
BLI_strncpy(name, IFACE_(node_name), UI_MAX_NAME_STR);
|
||||
BLI_strncpy_utf8(name, IFACE_(node_name), UI_MAX_NAME_STR);
|
||||
}
|
||||
}
|
||||
else if (sock->type == SOCK_SHADER) {
|
||||
BLI_strncpy(name, IFACE_("None"), UI_MAX_NAME_STR);
|
||||
BLI_strncpy_utf8(name, IFACE_("None"), UI_MAX_NAME_STR);
|
||||
}
|
||||
else {
|
||||
BLI_strncpy(name, IFACE_("Default"), UI_MAX_NAME_STR);
|
||||
BLI_strncpy_utf8(name, IFACE_("Default"), UI_MAX_NAME_STR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -604,7 +605,7 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
|
|||
icon = ICON_BLANK1;
|
||||
}
|
||||
else {
|
||||
STRNCPY(name, IFACE_(item.node_name));
|
||||
STRNCPY_UTF8(name, IFACE_(item.node_name));
|
||||
icon = ICON_NONE;
|
||||
}
|
||||
|
||||
|
|
|
@ -726,13 +726,13 @@ static void tree_element_sequence_dup_activate(Scene *scene, TreeElement * /*te*
|
|||
#endif
|
||||
Sequence *p = static_cast<Sequence *>(ed->seqbasep->first);
|
||||
while (p) {
|
||||
if ((!p->strip) || (!p->strip->stripdata) || (p->strip->stripdata->name[0] == '\0')) {
|
||||
if ((!p->strip) || (!p->strip->stripdata) || (p->strip->stripdata->filename[0] == '\0')) {
|
||||
p = p->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) {
|
||||
if (STREQ(p->strip->stripdata->filename, seq->strip->stripdata->filename)) {
|
||||
select_single_seq(p, 0);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -69,7 +69,7 @@ SequenceAddOp TreeDisplaySequencer::need_add_seq_dup(Sequence *seq) const
|
|||
continue;
|
||||
}
|
||||
|
||||
if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) {
|
||||
if (STREQ(p->strip->stripdata->filename, seq->strip->stripdata->filename)) {
|
||||
return SEQUENCE_DUPLICATE_NOOP;
|
||||
}
|
||||
p = p->prev;
|
||||
|
@ -82,7 +82,7 @@ SequenceAddOp TreeDisplaySequencer::need_add_seq_dup(Sequence *seq) const
|
|||
continue;
|
||||
}
|
||||
|
||||
if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) {
|
||||
if (STREQ(p->strip->stripdata->filename, seq->strip->stripdata->filename)) {
|
||||
return SEQUENCE_DUPLICATE_ADD;
|
||||
}
|
||||
p = p->next;
|
||||
|
@ -95,12 +95,12 @@ void TreeDisplaySequencer::add_seq_dup(Sequence *seq, TreeElement *te, short ind
|
|||
{
|
||||
Sequence *p = seq;
|
||||
while (p) {
|
||||
if ((!p->strip) || (!p->strip->stripdata) || (p->strip->stripdata->name[0] == '\0')) {
|
||||
if ((!p->strip) || (!p->strip->stripdata) || (p->strip->stripdata->filename[0] == '\0')) {
|
||||
p = p->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) {
|
||||
if (STREQ(p->strip->stripdata->filename, seq->strip->stripdata->filename)) {
|
||||
outliner_add_element(&space_outliner_, &te->subtree, (void *)p, te, TSE_SEQUENCE, index);
|
||||
}
|
||||
p = p->next;
|
||||
|
|
|
@ -68,8 +68,8 @@ TreeElementSequenceStrip::TreeElementSequenceStrip(TreeElement &legacy_te, Strip
|
|||
{
|
||||
BLI_assert(legacy_te.store_elem->type == TSE_SEQ_STRIP);
|
||||
|
||||
if (strip.dir[0] != '\0') {
|
||||
legacy_te_.name = strip.dir;
|
||||
if (strip.dirpath[0] != '\0') {
|
||||
legacy_te_.name = strip.dirpath;
|
||||
}
|
||||
else {
|
||||
legacy_te_.name = IFACE_("Strip None");
|
||||
|
@ -86,7 +86,7 @@ TreeElementSequenceStripDuplicate::TreeElementSequenceStripDuplicate(TreeElement
|
|||
BLI_assert(legacy_te.store_elem->type == TSE_SEQUENCE_DUP);
|
||||
|
||||
legacy_te_.idcode = sequence.type;
|
||||
legacy_te_.name = sequence.strip->stripdata->name;
|
||||
legacy_te_.name = sequence.strip->stripdata->filename;
|
||||
}
|
||||
|
||||
Sequence &TreeElementSequenceStripDuplicate::getSequence() const
|
||||
|
|
|
@ -179,7 +179,7 @@ static void sequencer_generic_invoke_path__internal(bContext *C,
|
|||
if (last_seq && last_seq->strip && SEQ_HAS_PATH(last_seq)) {
|
||||
Main *bmain = CTX_data_main(C);
|
||||
char path[FILE_MAX];
|
||||
STRNCPY(path, last_seq->strip->dir);
|
||||
STRNCPY(path, last_seq->strip->dirpath);
|
||||
BLI_path_abs(path, BKE_main_blendfile_path(bmain));
|
||||
RNA_string_set(op->ptr, identifier, path);
|
||||
}
|
||||
|
@ -1254,7 +1254,7 @@ void sequencer_image_seq_reserve_frames(
|
|||
for (int i = 0; i < len; i++, se++) {
|
||||
STRNCPY(filename_stripped, filename);
|
||||
BLI_path_frame(filename_stripped, sizeof(filename_stripped), minframe + i, numdigits);
|
||||
SNPRINTF(se->name, "%s%s", filename_stripped, ext);
|
||||
SNPRINTF(se->filename, "%s%s", filename_stripped, ext);
|
||||
}
|
||||
|
||||
MEM_freeN(filename);
|
||||
|
@ -1282,10 +1282,9 @@ static void sequencer_add_image_strip_load_files(wmOperator *op,
|
|||
const int numdigits)
|
||||
{
|
||||
const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
|
||||
/* size of Strip->dir. */
|
||||
char directory[FILE_MAXDIR];
|
||||
BLI_path_split_dir_part(load_data->path, directory, sizeof(directory));
|
||||
SEQ_add_image_set_directory(seq, directory);
|
||||
char dirpath[sizeof(seq->strip->dirpath)];
|
||||
BLI_path_split_dir_part(load_data->path, dirpath, sizeof(dirpath));
|
||||
SEQ_add_image_set_directory(seq, dirpath);
|
||||
|
||||
if (use_placeholders) {
|
||||
sequencer_image_seq_reserve_frames(
|
||||
|
|
|
@ -806,7 +806,8 @@ static void draw_seq_text_get_source(Sequence *seq, char *r_source, size_t sourc
|
|||
switch (seq->type) {
|
||||
case SEQ_TYPE_IMAGE:
|
||||
case SEQ_TYPE_MOVIE: {
|
||||
BLI_path_join(r_source, source_maxncpy, seq->strip->dir, seq->strip->stripdata->name);
|
||||
BLI_path_join(
|
||||
r_source, source_maxncpy, seq->strip->dirpath, seq->strip->stripdata->filename);
|
||||
break;
|
||||
}
|
||||
case SEQ_TYPE_SOUND_RAM: {
|
||||
|
|
|
@ -1879,7 +1879,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
|
|||
/* Note this assume all elements (images) have the same dimension,
|
||||
* since we only copy the name here. */
|
||||
se_new = MEM_reallocN(strip_new->stripdata, sizeof(*se_new));
|
||||
STRNCPY(se_new->name, se->name);
|
||||
STRNCPY(se_new->filename, se->filename);
|
||||
strip_new->stripdata = se_new;
|
||||
|
||||
if (step > 1) {
|
||||
|
@ -2920,7 +2920,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
|
|||
* but look into changing after 2.60. */
|
||||
BLI_path_rel(directory, BKE_main_blendfile_path(bmain));
|
||||
}
|
||||
STRNCPY(seq->strip->dir, directory);
|
||||
STRNCPY(seq->strip->dirpath, directory);
|
||||
|
||||
if (seq->strip->stripdata) {
|
||||
MEM_freeN(seq->strip->stripdata);
|
||||
|
@ -2933,7 +2933,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
|
|||
else {
|
||||
RNA_BEGIN (op->ptr, itemptr, "files") {
|
||||
char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0, NULL);
|
||||
STRNCPY(se->name, filename);
|
||||
STRNCPY(se->filename, filename);
|
||||
MEM_freeN(filename);
|
||||
se++;
|
||||
}
|
||||
|
@ -2991,9 +2991,9 @@ static int sequencer_change_path_invoke(bContext *C, wmOperator *op, const wmEve
|
|||
Sequence *seq = SEQ_select_active_get(scene);
|
||||
char filepath[FILE_MAX];
|
||||
|
||||
BLI_path_join(filepath, sizeof(filepath), seq->strip->dir, seq->strip->stripdata->name);
|
||||
BLI_path_join(filepath, sizeof(filepath), seq->strip->dirpath, seq->strip->stripdata->filename);
|
||||
|
||||
RNA_string_set(op->ptr, "directory", seq->strip->dir);
|
||||
RNA_string_set(op->ptr, "directory", seq->strip->dirpath);
|
||||
RNA_string_set(op->ptr, "filepath", filepath);
|
||||
|
||||
/* Set default display depending on seq type. */
|
||||
|
|
|
@ -235,12 +235,12 @@ void ED_sequencer_select_sequence_single(Scene *scene, Sequence *seq, bool desel
|
|||
|
||||
if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE)) {
|
||||
if (seq->strip) {
|
||||
BLI_strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR);
|
||||
BLI_strncpy(ed->act_imagedir, seq->strip->dirpath, FILE_MAXDIR);
|
||||
}
|
||||
}
|
||||
else if (seq->type == SEQ_TYPE_SOUND_RAM) {
|
||||
if (seq->strip) {
|
||||
BLI_strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR);
|
||||
BLI_strncpy(ed->act_sounddir, seq->strip->dirpath, FILE_MAXDIR);
|
||||
}
|
||||
}
|
||||
seq->flag |= SELECT;
|
||||
|
@ -570,12 +570,12 @@ static void sequencer_select_set_active(Scene *scene, Sequence *seq)
|
|||
|
||||
if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE)) {
|
||||
if (seq->strip) {
|
||||
BLI_strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR);
|
||||
BLI_strncpy(ed->act_imagedir, seq->strip->dirpath, FILE_MAXDIR);
|
||||
}
|
||||
}
|
||||
else if (seq->type == SEQ_TYPE_SOUND_RAM) {
|
||||
if (seq->strip) {
|
||||
BLI_strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR);
|
||||
BLI_strncpy(ed->act_sounddir, seq->strip->dirpath, FILE_MAXDIR);
|
||||
}
|
||||
}
|
||||
recurs_sel_seq(seq);
|
||||
|
@ -1893,7 +1893,7 @@ static bool select_grouped_data(SeqCollection *strips,
|
|||
const int channel)
|
||||
{
|
||||
bool changed = false;
|
||||
const char *dir = actseq->strip ? actseq->strip->dir : NULL;
|
||||
const char *dirpath = actseq->strip ? actseq->strip->dirpath : NULL;
|
||||
|
||||
if (!SEQ_USE_DATA(actseq)) {
|
||||
return changed;
|
||||
|
@ -1901,10 +1901,10 @@ static bool select_grouped_data(SeqCollection *strips,
|
|||
|
||||
Sequence *seq;
|
||||
|
||||
if (SEQ_HAS_PATH(actseq) && dir) {
|
||||
if (SEQ_HAS_PATH(actseq) && dirpath) {
|
||||
SEQ_ITERATOR_FOREACH (seq, strips) {
|
||||
if (SEQ_CHANNEL_CHECK(seq, channel) && SEQ_HAS_PATH(seq) && seq->strip &&
|
||||
STREQ(seq->strip->dir, dir))
|
||||
STREQ(seq->strip->dirpath, dirpath))
|
||||
{
|
||||
seq->flag |= SELECT;
|
||||
changed = true;
|
||||
|
|
|
@ -1980,8 +1980,7 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
|
|||
Object *ob = base->object;
|
||||
/* if hidden but in edit mode, we still display, can happen with animation */
|
||||
if ((base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT) != 0 ||
|
||||
(ob->mode != OB_MODE_OBJECT))
|
||||
{
|
||||
(ob->mode != OB_MODE_OBJECT)) {
|
||||
CTX_data_id_pointer_set(result, &ob->id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1327,7 +1327,7 @@ void calculatePropRatio(TransInfo *t)
|
|||
}
|
||||
|
||||
if (pet_id) {
|
||||
STRNCPY(t->proptext, IFACE_(pet_id));
|
||||
STRNCPY_UTF8(t->proptext, IFACE_(pet_id));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -585,7 +585,7 @@ static void handle_armature_parent_orientation(Object *ob, float r_mat[3][3])
|
|||
bPoseChannel *active_pchan = BKE_pose_channel_active(ob, false);
|
||||
|
||||
/* Check if target bone is a child. */
|
||||
if (active_pchan->parent) {
|
||||
if (active_pchan && active_pchan->parent) {
|
||||
/* For child, show parent local regardless if "local location" is set for parent bone. */
|
||||
transform_orientations_create_from_axis(r_mat, UNPACK3(active_pchan->parent->pose_mat));
|
||||
return;
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_global.h"
|
||||
|
||||
#include "BLI_array.hh"
|
||||
#include "BLI_convexhull_2d.h"
|
||||
#include "BLI_linklist.h"
|
||||
|
@ -59,6 +61,7 @@
|
|||
#include "ED_image.h"
|
||||
#include "ED_mesh.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_undo.h"
|
||||
#include "ED_uvedit.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
|
@ -169,6 +172,14 @@ void blender::geometry::UVPackIsland_Params::setUDIMOffsetFromSpaceImage(const S
|
|||
}
|
||||
/** \} */
|
||||
|
||||
bool blender::geometry::UVPackIsland_Params::isCancelled() const
|
||||
{
|
||||
if (stop) {
|
||||
return *stop;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Parametrizer Conversion
|
||||
* \{ */
|
||||
|
@ -1141,6 +1152,7 @@ static bool island_has_pins(const Scene *scene,
|
|||
* This is needed to perform UV packing on objects that aren't in edit-mode.
|
||||
* \param udim_source_closest: UDIM source SpaceImage.
|
||||
* \param original_selection: Pack to original selection.
|
||||
* \param notify_wm: Notify the WM of any changes. (UI thread only.)
|
||||
* \param params: Parameters and options to pass to the packing engine.
|
||||
*/
|
||||
static void uvedit_pack_islands_multi(const Scene *scene,
|
||||
|
@ -1149,6 +1161,7 @@ static void uvedit_pack_islands_multi(const Scene *scene,
|
|||
BMesh **bmesh_override,
|
||||
const SpaceImage *udim_source_closest,
|
||||
const bool original_selection,
|
||||
const bool notify_wm,
|
||||
blender::geometry::UVPackIsland_Params *params)
|
||||
{
|
||||
blender::Vector<FaceIsland *> island_vector;
|
||||
|
@ -1271,6 +1284,7 @@ static void uvedit_pack_islands_multi(const Scene *scene,
|
|||
BLI_memarena_free(arena);
|
||||
|
||||
const float scale = pack_islands(pack_island_vector, *params);
|
||||
const bool is_cancelled = params->isCancelled();
|
||||
|
||||
float base_offset[2] = {0.0f, 0.0f};
|
||||
copy_v2_v2(base_offset, params->udim_base_offset);
|
||||
|
@ -1309,7 +1323,10 @@ static void uvedit_pack_islands_multi(const Scene *scene,
|
|||
float matrix[2][2];
|
||||
float matrix_inverse[2][2];
|
||||
float pre_translate[2];
|
||||
for (int64_t i : pack_island_vector.index_range()) {
|
||||
for (const int64_t i : pack_island_vector.index_range()) {
|
||||
if (is_cancelled) {
|
||||
continue;
|
||||
}
|
||||
blender::geometry::PackIsland *pack_island = pack_island_vector[i];
|
||||
FaceIsland *island = island_vector[pack_island->caller_index];
|
||||
const float island_scale = pack_island->can_scale_(*params) ? scale : 1.0f;
|
||||
|
@ -1339,16 +1356,21 @@ static void uvedit_pack_islands_multi(const Scene *scene,
|
|||
pre_translate[1] = selection_min_co[1] / rescale;
|
||||
island_uv_transform(island, matrix, pre_translate);
|
||||
}
|
||||
}
|
||||
|
||||
for (const int64_t i : pack_island_vector.index_range()) {
|
||||
blender::geometry::PackIsland *pack_island = pack_island_vector[i];
|
||||
/* Cleanup memory. */
|
||||
pack_island_vector[i] = nullptr;
|
||||
delete pack_island;
|
||||
}
|
||||
|
||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||
Object *obedit = objects[ob_index];
|
||||
DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_GEOMETRY);
|
||||
WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
|
||||
if (notify_wm && !is_cancelled) {
|
||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||
Object *obedit = objects[ob_index];
|
||||
DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_GEOMETRY);
|
||||
WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
|
||||
}
|
||||
}
|
||||
|
||||
for (FaceIsland *island : island_vector) {
|
||||
|
@ -1361,6 +1383,9 @@ static void uvedit_pack_islands_multi(const Scene *scene,
|
|||
/** \name Pack UV Islands Operator
|
||||
* \{ */
|
||||
|
||||
/* TODO: support this, interaction with the job-system needs to be handled carefully. */
|
||||
// #define USE_INTERACTIVE_PACK
|
||||
|
||||
/* Packing targets. */
|
||||
enum {
|
||||
PACK_UDIM_SRC_CLOSEST = 0,
|
||||
|
@ -1368,6 +1393,70 @@ enum {
|
|||
PACK_ORIGINAL_AABB,
|
||||
};
|
||||
|
||||
struct UVPackIslandsData {
|
||||
wmWindowManager *wm;
|
||||
|
||||
const Scene *scene;
|
||||
|
||||
Object **objects;
|
||||
uint objects_len;
|
||||
const SpaceImage *sima;
|
||||
int udim_source;
|
||||
|
||||
bContext *undo_context;
|
||||
const char *undo_str;
|
||||
bool use_job;
|
||||
|
||||
blender::geometry::UVPackIsland_Params pack_island_params;
|
||||
};
|
||||
|
||||
static void pack_islands_startjob(void *pidv, bool *stop, bool *do_update, float *progress)
|
||||
{
|
||||
*progress = 0.02f;
|
||||
|
||||
UVPackIslandsData *pid = static_cast<UVPackIslandsData *>(pidv);
|
||||
|
||||
pid->pack_island_params.stop = stop;
|
||||
pid->pack_island_params.do_update = do_update;
|
||||
pid->pack_island_params.progress = progress;
|
||||
|
||||
uvedit_pack_islands_multi(pid->scene,
|
||||
pid->objects,
|
||||
pid->objects_len,
|
||||
nullptr,
|
||||
(pid->udim_source == PACK_UDIM_SRC_CLOSEST) ? pid->sima : nullptr,
|
||||
(pid->udim_source == PACK_ORIGINAL_AABB),
|
||||
!pid->use_job,
|
||||
&pid->pack_island_params);
|
||||
|
||||
*progress = 0.99f;
|
||||
*do_update = true;
|
||||
}
|
||||
|
||||
static void pack_islands_endjob(void *pidv)
|
||||
{
|
||||
UVPackIslandsData *pid = static_cast<UVPackIslandsData *>(pidv);
|
||||
for (uint ob_index = 0; ob_index < pid->objects_len; ob_index++) {
|
||||
Object *obedit = pid->objects[ob_index];
|
||||
DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_GEOMETRY);
|
||||
WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
|
||||
}
|
||||
WM_main_add_notifier(NC_SPACE | ND_SPACE_IMAGE, NULL);
|
||||
|
||||
if (pid->undo_str) {
|
||||
ED_undo_push(pid->undo_context, pid->undo_str);
|
||||
}
|
||||
}
|
||||
|
||||
static void pack_islands_freejob(void *pidv)
|
||||
{
|
||||
WM_cursor_wait(false);
|
||||
UVPackIslandsData *pid = static_cast<UVPackIslandsData *>(pidv);
|
||||
MEM_freeN(pid->objects);
|
||||
WM_set_locked_interface(pid->wm, false);
|
||||
MEM_freeN(pid);
|
||||
}
|
||||
|
||||
static int pack_islands_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
|
@ -1400,7 +1489,23 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
|
|||
RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
|
||||
}
|
||||
|
||||
blender::geometry::UVPackIsland_Params pack_island_params;
|
||||
UVPackIslandsData *pid = static_cast<UVPackIslandsData *>(
|
||||
MEM_callocN(sizeof(UVPackIslandsData), "pack_islands_data"));
|
||||
pid->use_job = op->flag & OP_IS_INVOKE;
|
||||
pid->scene = scene;
|
||||
pid->objects = objects;
|
||||
pid->objects_len = objects_len;
|
||||
pid->sima = sima;
|
||||
pid->udim_source = udim_source;
|
||||
pid->wm = CTX_wm_manager(C);
|
||||
|
||||
blender::geometry::UVPackIsland_Params &pack_island_params = pid->pack_island_params;
|
||||
{
|
||||
/* Call default constructor and copy the defaults. */
|
||||
blender::geometry::UVPackIsland_Params default_params;
|
||||
pack_island_params = default_params;
|
||||
}
|
||||
|
||||
pack_island_params.setFromUnwrapOptions(options);
|
||||
pack_island_params.rotate = RNA_boolean_get(op->ptr, "rotate");
|
||||
pack_island_params.scale_to_fit = RNA_boolean_get(op->ptr, "scale");
|
||||
|
@ -1416,15 +1521,31 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
|
|||
pack_island_params.setUDIMOffsetFromSpaceImage(sima);
|
||||
}
|
||||
|
||||
uvedit_pack_islands_multi(scene,
|
||||
objects,
|
||||
objects_len,
|
||||
nullptr,
|
||||
(udim_source == PACK_UDIM_SRC_CLOSEST) ? sima : nullptr,
|
||||
(udim_source == PACK_ORIGINAL_AABB),
|
||||
&pack_island_params);
|
||||
if (pid->use_job) {
|
||||
/* Setup job. */
|
||||
if (pid->wm->op_undo_depth == 0) {
|
||||
/* The job must do it's own undo push. */
|
||||
pid->undo_context = C;
|
||||
pid->undo_str = op->type->name;
|
||||
}
|
||||
|
||||
MEM_freeN(objects);
|
||||
wmJob *wm_job = WM_jobs_get(
|
||||
pid->wm, CTX_wm_window(C), scene, "Packing UVs", WM_JOB_PROGRESS, WM_JOB_TYPE_UV_PACK);
|
||||
WM_jobs_customdata_set(wm_job, pid, pack_islands_freejob);
|
||||
WM_jobs_timer(wm_job, 0.1, 0, 0);
|
||||
WM_set_locked_interface(pid->wm, true);
|
||||
WM_jobs_callbacks(wm_job, pack_islands_startjob, nullptr, nullptr, pack_islands_endjob);
|
||||
|
||||
WM_cursor_wait(true);
|
||||
G.is_break = false;
|
||||
WM_jobs_start(CTX_wm_manager(C), wm_job);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
pack_islands_startjob(pid, nullptr, nullptr, nullptr);
|
||||
pack_islands_endjob(pid);
|
||||
|
||||
MEM_freeN(pid);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
@ -1452,7 +1573,7 @@ static const EnumPropertyItem pack_shape_method_items[] = {
|
|||
};
|
||||
|
||||
static const EnumPropertyItem pinned_islands_method_items[] = {
|
||||
{ED_UVPACK_PIN_NORMAL, "NORMAL", 0, "Normal", "Pin information is not used"},
|
||||
{ED_UVPACK_PIN_DEFAULT, "DEFAULT", 0, "Default", "Pin information is not used"},
|
||||
{ED_UVPACK_PIN_IGNORED, "IGNORED", 0, "Ignored", "Pinned islands are not packed"},
|
||||
{ED_UVPACK_PIN_LOCK_SCALE, "SCALE", 0, "Locked scale", "Pinned islands won't rescale"},
|
||||
{ED_UVPACK_PIN_LOCK_ROTATION, "ROTATION", 0, "Locked rotation", "Pinned islands won't rotate"},
|
||||
|
@ -1487,10 +1608,21 @@ void UV_OT_pack_islands(wmOperatorType *ot)
|
|||
ot->description =
|
||||
"Transform all islands so that they fill up the UV/UDIM space as much as possible";
|
||||
|
||||
#ifdef USE_INTERACTIVE_PACK
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
#else
|
||||
/* The operator will handle undo, so the job system can push() it after the job completes. */
|
||||
ot->flag = OPTYPE_REGISTER;
|
||||
#endif
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = pack_islands_exec;
|
||||
|
||||
#ifdef USE_INTERACTIVE_PACK
|
||||
ot->invoke = WM_operator_props_popup_call;
|
||||
#else
|
||||
ot->invoke = WM_operator_props_popup_confirm;
|
||||
#endif
|
||||
ot->poll = ED_operator_uvedit;
|
||||
|
||||
/* properties */
|
||||
|
@ -1510,7 +1642,7 @@ void UV_OT_pack_islands(wmOperatorType *ot)
|
|||
RNA_def_enum(ot->srna,
|
||||
"pin_method",
|
||||
pinned_islands_method_items,
|
||||
ED_UVPACK_PIN_NORMAL,
|
||||
ED_UVPACK_PIN_DEFAULT,
|
||||
"Pinned Islands",
|
||||
"");
|
||||
RNA_def_enum(ot->srna,
|
||||
|
@ -2234,7 +2366,7 @@ void ED_uvedit_live_unwrap(const Scene *scene, Object **objects, int objects_len
|
|||
pack_island_params.margin = scene->toolsettings->uvcalc_margin;
|
||||
|
||||
uvedit_pack_islands_multi(
|
||||
scene, objects, objects_len, nullptr, nullptr, false, &pack_island_params);
|
||||
scene, objects, objects_len, nullptr, nullptr, false, true, &pack_island_params);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2377,7 +2509,7 @@ static int unwrap_exec(bContext *C, wmOperator *op)
|
|||
pack_island_params.margin = RNA_float_get(op->ptr, "margin");
|
||||
|
||||
uvedit_pack_islands_multi(
|
||||
scene, objects, objects_len, nullptr, nullptr, false, &pack_island_params);
|
||||
scene, objects, objects_len, nullptr, nullptr, false, true, &pack_island_params);
|
||||
|
||||
MEM_freeN(objects);
|
||||
|
||||
|
@ -2759,7 +2891,7 @@ static int smart_project_exec(bContext *C, wmOperator *op)
|
|||
params.margin = RNA_float_get(op->ptr, "island_margin");
|
||||
|
||||
uvedit_pack_islands_multi(
|
||||
scene, objects_changed, object_changed_len, nullptr, nullptr, false, ¶ms);
|
||||
scene, objects_changed, object_changed_len, nullptr, nullptr, false, true, ¶ms);
|
||||
|
||||
/* #uvedit_pack_islands_multi only supports `per_face_aspect = false`. */
|
||||
const bool per_face_aspect = false;
|
||||
|
@ -3747,7 +3879,7 @@ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob)
|
|||
params.margin_method = ED_UVPACK_MARGIN_SCALED;
|
||||
params.margin = 0.001f;
|
||||
|
||||
uvedit_pack_islands_multi(scene, &ob, 1, &bm, nullptr, false, ¶ms);
|
||||
uvedit_pack_islands_multi(scene, &ob, 1, &bm, nullptr, false, true, ¶ms);
|
||||
|
||||
/* Write back from BMesh to Mesh. */
|
||||
BMeshToMeshParams bm_to_me_params{};
|
||||
|
|
|
@ -37,7 +37,7 @@ enum eUVPackIsland_ShapeMethod {
|
|||
|
||||
enum eUVPackIsland_PinMethod {
|
||||
ED_UVPACK_PIN_IGNORED = 0,
|
||||
ED_UVPACK_PIN_NORMAL,
|
||||
ED_UVPACK_PIN_DEFAULT,
|
||||
ED_UVPACK_PIN_LOCK_ROTATION,
|
||||
ED_UVPACK_PIN_LOCK_ROTATION_SCALE,
|
||||
ED_UVPACK_PIN_LOCK_SCALE,
|
||||
|
@ -55,6 +55,7 @@ class UVPackIsland_Params {
|
|||
|
||||
void setFromUnwrapOptions(const UnwrapOptions &options);
|
||||
void setUDIMOffsetFromSpaceImage(const SpaceImage *sima);
|
||||
bool isCancelled() const;
|
||||
|
||||
/** Islands can be rotated to improve packing. */
|
||||
bool rotate;
|
||||
|
@ -84,6 +85,12 @@ class UVPackIsland_Params {
|
|||
float target_aspect_y;
|
||||
/** Which shape to use when packing. */
|
||||
eUVPackIsland_ShapeMethod shape_method;
|
||||
|
||||
/** Abandon packing early when set by the job system. */
|
||||
bool *stop;
|
||||
bool *do_update;
|
||||
/** How much progress we have made. From wmJob. */
|
||||
float *progress;
|
||||
};
|
||||
|
||||
class uv_phi;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue