Add Vertex Crease operator to vertex context menu #109146
|
@ -79,6 +79,7 @@ typedef hiprtError(thiprtSetFuncTable)(hiprtContext context,
|
|||
hiprtFuncDataSet set);
|
||||
typedef hiprtError(thiprtDestroyFuncTable)(hiprtContext context,
|
||||
hiprtFuncTable funcTable);
|
||||
typedef void(thiprtSetLogLevel)( hiprtLogLevel level );
|
||||
|
||||
/* Function declarations. */
|
||||
extern thiprtCreateContext *hiprtCreateContext;
|
||||
|
@ -94,6 +95,7 @@ extern thiprtGetSceneBuildTemporaryBufferSize *hiprtGetSceneBuildTemporaryBuffer
|
|||
extern thiprtCreateFuncTable *hiprtCreateFuncTable;
|
||||
extern thiprtSetFuncTable *hiprtSetFuncTable;
|
||||
extern thiprtDestroyFuncTable *hiprtDestroyFuncTable;
|
||||
extern thiprtSetLogLevel *hiprtSetLogLevel;
|
||||
|
||||
/* HIPEW API. */
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ thiprtGetSceneBuildTemporaryBufferSize *hiprtGetSceneBuildTemporaryBufferSize;
|
|||
thiprtCreateFuncTable *hiprtCreateFuncTable;
|
||||
thiprtSetFuncTable *hiprtSetFuncTable;
|
||||
thiprtDestroyFuncTable *hiprtDestroyFuncTable;
|
||||
thiprtSetLogLevel *hiprtSetLogLevel;
|
||||
|
||||
static void hipewHipRtExit(void)
|
||||
{
|
||||
|
@ -89,6 +90,7 @@ bool hiprtewInit()
|
|||
HIPRT_LIBRARY_FIND(hiprtCreateFuncTable)
|
||||
HIPRT_LIBRARY_FIND(hiprtSetFuncTable)
|
||||
HIPRT_LIBRARY_FIND(hiprtDestroyFuncTable)
|
||||
HIPRT_LIBRARY_FIND(hiprtSetLogLevel)
|
||||
|
||||
result = true;
|
||||
#endif
|
||||
|
|
|
@ -464,8 +464,9 @@ static char *concat_string_list (char **t, int *bytes)
|
|||
break;
|
||||
if (!(t[n][0]))
|
||||
break;
|
||||
strcpy (s + l, t[n]);
|
||||
l += strlen (t[n]) + 1;
|
||||
int t_size = strlen (t[n]) + 1;
|
||||
memcpy (s + l, t[n], t_size);
|
||||
l += t_size;
|
||||
}
|
||||
*bytes = l;
|
||||
s[l] = '\0';
|
||||
|
|
|
@ -96,6 +96,8 @@ HIPRTDevice::HIPRTDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
|
|||
set_error(string_printf("Failed to create HIPRT Function Table"));
|
||||
return;
|
||||
}
|
||||
|
||||
hiprtSetLogLevel(hiprtLogLevelNone);
|
||||
}
|
||||
|
||||
HIPRTDevice::~HIPRTDevice()
|
||||
|
@ -261,8 +263,7 @@ string HIPRTDevice::compile_kernel(const uint kernel_features, const char *name,
|
|||
linker_options.append(" --offload-arch=").append(arch);
|
||||
linker_options.append(" -fgpu-rdc --hip-link --cuda-device-only ");
|
||||
string hiprt_ver(HIPRT_VERSION_STR);
|
||||
string hiprt_bc;
|
||||
hiprt_bc = hiprt_path + "\\hiprt" + hiprt_ver + "_amd_lib_win.bc";
|
||||
string hiprt_bc = hiprt_path + "\\dist\\bin\\Release\\hiprt" + hiprt_ver + "_amd_lib_win.bc";
|
||||
|
||||
string linker_command = string_printf("clang++ %s \"%s\" %s -o \"%s\"",
|
||||
linker_options.c_str(),
|
||||
|
|
|
@ -61,6 +61,8 @@ bool HIPRTDeviceQueue::enqueue(DeviceKernel kernel,
|
|||
0),
|
||||
"enqueue");
|
||||
|
||||
debug_enqueue_end();
|
||||
|
||||
return !(hiprt_device_->have_error());
|
||||
}
|
||||
|
||||
|
|
|
@ -46,11 +46,11 @@ ccl_device_intersect bool scene_intersect(KernelGlobals kg,
|
|||
GET_TRAVERSAL_STACK()
|
||||
|
||||
if (visibility & PATH_RAY_SHADOW_OPAQUE) {
|
||||
GET_TRAVERSAL_ANY_HIT(table_closest_intersect, 0)
|
||||
GET_TRAVERSAL_ANY_HIT(table_closest_intersect, 0, ray->time)
|
||||
hit = traversal.getNextHit();
|
||||
}
|
||||
else {
|
||||
GET_TRAVERSAL_CLOSEST_HIT(table_closest_intersect, 0)
|
||||
GET_TRAVERSAL_CLOSEST_HIT(table_closest_intersect, 0, ray->time)
|
||||
hit = traversal.getNextHit();
|
||||
}
|
||||
if (hit.hasHit()) {
|
||||
|
@ -157,13 +157,13 @@ ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals kg,
|
|||
payload.in_state = state;
|
||||
payload.max_hits = max_hits;
|
||||
payload.visibility = visibility;
|
||||
payload.prim_type = PRIMITIVE_TRIANGLE;
|
||||
payload.prim_type = PRIMITIVE_NONE;
|
||||
payload.ray_time = ray->time;
|
||||
payload.num_hits = 0;
|
||||
payload.r_num_recorded_hits = num_recorded_hits;
|
||||
payload.r_throughput = throughput;
|
||||
GET_TRAVERSAL_STACK()
|
||||
GET_TRAVERSAL_ANY_HIT(table_shadow_intersect, 1)
|
||||
GET_TRAVERSAL_ANY_HIT(table_shadow_intersect, 1, ray->time)
|
||||
hiprtHit hit = traversal.getNextHit();
|
||||
num_recorded_hits = payload.r_num_recorded_hits;
|
||||
throughput = payload.r_throughput;
|
||||
|
@ -201,7 +201,7 @@ ccl_device_intersect bool scene_intersect_volume(KernelGlobals kg,
|
|||
|
||||
GET_TRAVERSAL_STACK()
|
||||
|
||||
GET_TRAVERSAL_CLOSEST_HIT(table_volume_intersect, 3)
|
||||
GET_TRAVERSAL_CLOSEST_HIT(table_volume_intersect, 3, ray->time)
|
||||
hiprtHit hit = traversal.getNextHit();
|
||||
// return hit.hasHit();
|
||||
if (hit.hasHit()) {
|
||||
|
|
|
@ -53,7 +53,7 @@ struct LocalPayload {
|
|||
# endif
|
||||
|
||||
# ifdef HIPRT_SHARED_STACK
|
||||
# define GET_TRAVERSAL_ANY_HIT(FUNCTION_TABLE, RAY_TYPE) \
|
||||
# define GET_TRAVERSAL_ANY_HIT(FUNCTION_TABLE, RAY_TYPE, RAY_TIME) \
|
||||
hiprtSceneTraversalAnyHitCustomStack<Stack> traversal(kernel_data.device_bvh, \
|
||||
ray_hip, \
|
||||
stack, \
|
||||
|
@ -61,10 +61,10 @@ struct LocalPayload {
|
|||
hiprtTraversalHintDefault, \
|
||||
&payload, \
|
||||
kernel_params.FUNCTION_TABLE, \
|
||||
RAY_TYPE); \
|
||||
hiprtSceneTraversalAnyHitCustomStack<Stack> traversal_simple( \
|
||||
kernel_data.device_bvh, ray_hip, stack, visibility);
|
||||
# define GET_TRAVERSAL_CLOSEST_HIT(FUNCTION_TABLE, RAY_TYPE) \
|
||||
RAY_TYPE, \
|
||||
RAY_TIME);
|
||||
|
||||
# define GET_TRAVERSAL_CLOSEST_HIT(FUNCTION_TABLE, RAY_TYPE, RAY_TIME) \
|
||||
hiprtSceneTraversalClosestCustomStack<Stack> traversal(kernel_data.device_bvh, \
|
||||
ray_hip, \
|
||||
stack, \
|
||||
|
@ -72,9 +72,8 @@ struct LocalPayload {
|
|||
hiprtTraversalHintDefault, \
|
||||
&payload, \
|
||||
kernel_params.FUNCTION_TABLE, \
|
||||
RAY_TYPE); \
|
||||
hiprtSceneTraversalClosestCustomStack<Stack> traversal_simple( \
|
||||
kernel_data.device_bvh, ray_hip, stack, visibility);
|
||||
RAY_TYPE, \
|
||||
RAY_TIME);
|
||||
# else
|
||||
# define GET_TRAVERSAL_ANY_HIT(FUNCTION_TABLE) \
|
||||
hiprtSceneTraversalAnyHit traversal(kernel_data.device_bvh, \
|
||||
|
@ -82,16 +81,14 @@ struct LocalPayload {
|
|||
visibility, \
|
||||
FUNCTION_TABLE, \
|
||||
hiprtTraversalHintDefault, \
|
||||
&payload); \
|
||||
hiprtSceneTraversalAnyHit traversal_simple(kernel_data.device_bvh, ray_hip, visibility);
|
||||
&payload);
|
||||
# define GET_TRAVERSAL_CLOSEST_HIT(FUNCTION_TABLE) \
|
||||
hiprtSceneTraversalClosest traversal(kernel_data.device_bvh, \
|
||||
ray_hip, \
|
||||
visibility, \
|
||||
FUNCTION_TABLE, \
|
||||
hiprtTraversalHintDefault, \
|
||||
&payload); \
|
||||
hiprtSceneTraversalClosest traversal_simple(kernel_data.device_bvh, ray_hip, visibility);
|
||||
&payload);
|
||||
# endif
|
||||
|
||||
ccl_device_inline void set_intersect_point(KernelGlobals kg,
|
||||
|
|
|
@ -775,7 +775,9 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
|
|||
surface_shader_bsdf_eval(kg, state, sd, wo, throughput, ls->shader);
|
||||
|
||||
/* Update light sample with new position / direction and keep pdf in vertex area measure. */
|
||||
light_sample_update(kg, ls, vertices[vertex_count - 1].p);
|
||||
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
light_sample_update(
|
||||
kg, ls, vertices[vertex_count - 1].p, vertices[vertex_count - 1].n, path_flag);
|
||||
|
||||
/* Save state path bounce info in case a light path node is used in the refractive interface or
|
||||
* light shader graph. */
|
||||
|
|
|
@ -20,6 +20,8 @@ ccl_device_inline bool shadow_linking_light_sample_from_intersection(
|
|||
KernelGlobals kg,
|
||||
ccl_private const Intersection &ccl_restrict isect,
|
||||
ccl_private const Ray &ccl_restrict ray,
|
||||
const float3 N,
|
||||
const uint32_t path_flag,
|
||||
ccl_private LightSample *ccl_restrict ls)
|
||||
{
|
||||
const int lamp = isect.prim;
|
||||
|
@ -31,7 +33,7 @@ ccl_device_inline bool shadow_linking_light_sample_from_intersection(
|
|||
return distant_light_sample_from_intersection(kg, ray.D, lamp, ls);
|
||||
}
|
||||
|
||||
return light_sample_from_intersection(kg, &isect, ray.P, ray.D, ls);
|
||||
return light_sample_from_intersection(kg, &isect, ray.P, ray.D, N, path_flag, ls);
|
||||
}
|
||||
|
||||
ccl_device_inline float shadow_linking_light_sample_mis_weight(KernelGlobals kg,
|
||||
|
@ -88,8 +90,11 @@ ccl_device bool shadow_linking_shade_light(KernelGlobals kg,
|
|||
ccl_private float &mis_weight,
|
||||
ccl_private int &ccl_restrict light_group)
|
||||
{
|
||||
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
const float3 N = INTEGRATOR_STATE(state, path, mis_origin_n);
|
||||
LightSample ls ccl_optional_struct_init;
|
||||
const bool use_light_sample = shadow_linking_light_sample_from_intersection(kg, isect, ray, &ls);
|
||||
const bool use_light_sample = shadow_linking_light_sample_from_intersection(
|
||||
kg, isect, ray, N, path_flag, &ls);
|
||||
if (!use_light_sample) {
|
||||
/* No light to be sampled, so no direct light contribution either. */
|
||||
return false;
|
||||
|
@ -100,7 +105,6 @@ ccl_device bool shadow_linking_shade_light(KernelGlobals kg,
|
|||
return false;
|
||||
}
|
||||
|
||||
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
if (!is_light_shader_visible_to_path(ls.shader, path_flag)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -24,12 +24,15 @@ ccl_device_inline void integrate_light(KernelGlobals kg,
|
|||
float3 ray_P = INTEGRATOR_STATE(state, ray, P);
|
||||
const float3 ray_D = INTEGRATOR_STATE(state, ray, D);
|
||||
const float ray_time = INTEGRATOR_STATE(state, ray, time);
|
||||
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
const float3 N = INTEGRATOR_STATE(state, path, mis_origin_n);
|
||||
|
||||
/* Advance ray to new start distance. */
|
||||
INTEGRATOR_STATE_WRITE(state, ray, tmin) = intersection_t_offset(isect.t);
|
||||
|
||||
LightSample ls ccl_optional_struct_init;
|
||||
const bool use_light_sample = light_sample_from_intersection(kg, &isect, ray_P, ray_D, &ls);
|
||||
const bool use_light_sample = light_sample_from_intersection(
|
||||
kg, &isect, ray_P, ray_D, N, path_flag, &ls);
|
||||
|
||||
if (!use_light_sample) {
|
||||
return;
|
||||
|
@ -37,7 +40,6 @@ ccl_device_inline void integrate_light(KernelGlobals kg,
|
|||
|
||||
/* Use visibility flag to skip lights. */
|
||||
#ifdef __PASSES__
|
||||
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
if (!is_light_shader_visible_to_path(ls.shader, path_flag)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,9 @@ ccl_device_noinline bool light_distribution_sample(KernelGlobals kg,
|
|||
const float3 rand,
|
||||
const float time,
|
||||
const float3 P,
|
||||
const float3 N,
|
||||
const int object_receiver,
|
||||
const int shader_flags,
|
||||
const int bounce,
|
||||
const uint32_t path_flag,
|
||||
ccl_private LightSample *ls)
|
||||
|
@ -56,8 +58,19 @@ ccl_device_noinline bool light_distribution_sample(KernelGlobals kg,
|
|||
const int index = light_distribution_sample(kg, rand.z);
|
||||
const float pdf_selection = kernel_data.integrator.distribution_pdf_lights;
|
||||
const float2 rand_uv = float3_to_float2(rand);
|
||||
return light_sample<in_volume_segment>(
|
||||
kg, rand_uv, time, P, object_receiver, bounce, path_flag, index, 0, pdf_selection, ls);
|
||||
return light_sample<in_volume_segment>(kg,
|
||||
rand_uv,
|
||||
time,
|
||||
P,
|
||||
N,
|
||||
object_receiver,
|
||||
shader_flags,
|
||||
bounce,
|
||||
path_flag,
|
||||
index,
|
||||
0,
|
||||
pdf_selection,
|
||||
ls);
|
||||
}
|
||||
|
||||
ccl_device_inline float light_distribution_pdf_lamp(KernelGlobals kg)
|
||||
|
|
|
@ -96,6 +96,8 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
|
|||
const int lamp,
|
||||
const float2 rand,
|
||||
const float3 P,
|
||||
const float3 N,
|
||||
const int shader_flags,
|
||||
const uint32_t path_flag,
|
||||
ccl_private LightSample *ls)
|
||||
{
|
||||
|
@ -150,7 +152,7 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
|
|||
}
|
||||
}
|
||||
else if (type == LIGHT_POINT) {
|
||||
if (!point_light_sample<in_volume_segment>(klight, rand, P, ls)) {
|
||||
if (!point_light_sample(klight, rand, P, N, shader_flags, ls)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +173,9 @@ ccl_device_noinline bool light_sample(KernelGlobals kg,
|
|||
const float2 rand,
|
||||
const float time,
|
||||
const float3 P,
|
||||
const float3 N,
|
||||
const int object_receiver,
|
||||
const int shader_flags,
|
||||
const int bounce,
|
||||
const uint32_t path_flag,
|
||||
const int emitter_index,
|
||||
|
@ -233,7 +237,7 @@ ccl_device_noinline bool light_sample(KernelGlobals kg,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!light_sample<in_volume_segment>(kg, light, rand, P, path_flag, ls)) {
|
||||
if (!light_sample<in_volume_segment>(kg, light, rand, P, N, shader_flags, path_flag, ls)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -446,6 +450,8 @@ ccl_device bool light_sample_from_intersection(KernelGlobals kg,
|
|||
ccl_private const Intersection *ccl_restrict isect,
|
||||
const float3 ray_P,
|
||||
const float3 ray_D,
|
||||
const float3 N,
|
||||
const uint32_t path_flag,
|
||||
ccl_private LightSample *ccl_restrict ls)
|
||||
{
|
||||
const int lamp = isect->prim;
|
||||
|
@ -468,7 +474,7 @@ ccl_device bool light_sample_from_intersection(KernelGlobals kg,
|
|||
}
|
||||
}
|
||||
else if (type == LIGHT_POINT) {
|
||||
if (!point_light_sample_from_intersection(klight, isect, ray_P, ray_D, ls)) {
|
||||
if (!point_light_sample_from_intersection(klight, isect, ray_P, ray_D, N, path_flag, ls)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,68 +8,123 @@
|
|||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
template<bool in_volume_segment>
|
||||
ccl_device_inline bool point_light_sample(const ccl_global KernelLight *klight,
|
||||
const float2 rand,
|
||||
const float3 P,
|
||||
const float3 N,
|
||||
const int shader_flags,
|
||||
ccl_private LightSample *ls)
|
||||
{
|
||||
float3 center = klight->co;
|
||||
float radius = klight->spot.radius;
|
||||
/* disk oriented normal */
|
||||
const float3 lightN = normalize(P - center);
|
||||
ls->P = center;
|
||||
float3 lightN = P - klight->co;
|
||||
const float d_sq = len_squared(lightN);
|
||||
const float d = sqrtf(d_sq);
|
||||
lightN /= d;
|
||||
|
||||
if (radius > 0.0f) {
|
||||
ls->P += disk_light_sample(lightN, rand) * radius;
|
||||
const float r_sq = sqr(klight->spot.radius);
|
||||
|
||||
float cos_theta;
|
||||
if (d_sq > r_sq) {
|
||||
const float one_minus_cos = sin_sqr_to_one_minus_cos(r_sq / d_sq);
|
||||
sample_uniform_cone_concentric(-lightN, one_minus_cos, rand, &cos_theta, &ls->D, &ls->pdf);
|
||||
}
|
||||
else {
|
||||
const bool has_transmission = (shader_flags & SD_BSDF_HAS_TRANSMISSION);
|
||||
if (has_transmission) {
|
||||
ls->D = sample_uniform_sphere(rand);
|
||||
ls->pdf = M_1_2PI_F * 0.5f;
|
||||
}
|
||||
else {
|
||||
sample_cos_hemisphere(N, rand, &ls->D, &ls->pdf);
|
||||
}
|
||||
cos_theta = -dot(ls->D, lightN);
|
||||
}
|
||||
ls->pdf = klight->spot.invarea;
|
||||
|
||||
ls->D = normalize_len(ls->P - P, &ls->t);
|
||||
/* we set the light normal to the outgoing direction to support texturing */
|
||||
ls->Ng = -ls->D;
|
||||
/* Law of cosines. */
|
||||
ls->t = d * cos_theta - copysignf(safe_sqrtf(r_sq - d_sq + d_sq * sqr(cos_theta)), d_sq - r_sq);
|
||||
|
||||
ls->P = P + ls->D * ls->t;
|
||||
|
||||
ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
|
||||
if (r_sq == 0) {
|
||||
/* Use intensity instead of radiance for point light. */
|
||||
ls->eval_fac /= sqr(ls->t);
|
||||
/* `ls->Ng` is not well-defined for point light, so use the incoming direction instead. */
|
||||
ls->Ng = -ls->D;
|
||||
}
|
||||
else {
|
||||
ls->Ng = normalize(ls->P - klight->co);
|
||||
/* Remap sampled point onto the sphere to prevent precision issues with small radius. */
|
||||
ls->P = ls->Ng * klight->spot.radius + klight->co;
|
||||
}
|
||||
|
||||
const Transform itfm = klight->itfm;
|
||||
const float2 uv = map_to_sphere(transform_direction(&itfm, ls->Ng));
|
||||
/* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
|
||||
ls->u = uv.y;
|
||||
ls->v = 1.0f - uv.x - uv.y;
|
||||
|
||||
float2 uv = map_to_sphere(ls->Ng);
|
||||
ls->u = uv.x;
|
||||
ls->v = uv.y;
|
||||
ls->pdf *= lamp_light_pdf(lightN, -ls->D, ls->t);
|
||||
return true;
|
||||
}
|
||||
|
||||
ccl_device_forceinline float point_light_pdf(
|
||||
const float d_sq, const float r_sq, const float3 N, const float3 D, const uint32_t path_flag)
|
||||
{
|
||||
if (d_sq > r_sq) {
|
||||
return M_1_2PI_F / sin_sqr_to_one_minus_cos(r_sq / d_sq);
|
||||
}
|
||||
|
||||
const bool has_transmission = (path_flag & PATH_RAY_MIS_HAD_TRANSMISSION);
|
||||
return has_transmission ? M_1_2PI_F * 0.5f : pdf_cos_hemisphere(N, D);
|
||||
}
|
||||
|
||||
ccl_device_forceinline void point_light_mnee_sample_update(const ccl_global KernelLight *klight,
|
||||
ccl_private LightSample *ls,
|
||||
const float3 P)
|
||||
const float3 P,
|
||||
const float3 N,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
ls->D = normalize_len(ls->P - P, &ls->t);
|
||||
ls->Ng = -ls->D;
|
||||
|
||||
float2 uv = map_to_sphere(ls->Ng);
|
||||
ls->u = uv.x;
|
||||
ls->v = uv.y;
|
||||
const float radius = klight->spot.radius;
|
||||
|
||||
float invarea = klight->spot.invarea;
|
||||
ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
|
||||
/* NOTE : preserve pdf in area measure. */
|
||||
ls->pdf = invarea;
|
||||
if (radius > 0) {
|
||||
const float d_sq = len_squared(P - klight->co);
|
||||
const float r_sq = sqr(radius);
|
||||
const float t_sq = sqr(ls->t);
|
||||
|
||||
ls->pdf = point_light_pdf(d_sq, r_sq, N, ls->D, path_flag);
|
||||
|
||||
/* NOTE : preserve pdf in area measure. */
|
||||
ls->pdf *= 0.5f * fabsf(d_sq - r_sq - t_sq) / (radius * ls->t * t_sq);
|
||||
|
||||
ls->Ng = normalize(ls->P - klight->co);
|
||||
}
|
||||
else {
|
||||
ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
|
||||
|
||||
ls->Ng = -ls->D;
|
||||
|
||||
/* PDF does not change. */
|
||||
}
|
||||
|
||||
const Transform itfm = klight->itfm;
|
||||
const float2 uv = map_to_sphere(transform_direction(&itfm, ls->Ng));
|
||||
/* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
|
||||
ls->u = uv.y;
|
||||
ls->v = 1.0f - uv.x - uv.y;
|
||||
}
|
||||
|
||||
ccl_device_inline bool point_light_intersect(const ccl_global KernelLight *klight,
|
||||
const ccl_private Ray *ccl_restrict ray,
|
||||
ccl_private float *t)
|
||||
{
|
||||
/* Sphere light (aka, aligned disk light). */
|
||||
const float3 lightP = klight->co;
|
||||
const float radius = klight->spot.radius;
|
||||
if (radius == 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* disk oriented normal */
|
||||
const float3 lightN = normalize(ray->P - lightP);
|
||||
float3 P;
|
||||
return ray_disk_intersect(ray->P, ray->D, ray->tmin, ray->tmax, lightP, lightN, radius, &P, t);
|
||||
return ray_sphere_intersect(ray->P, ray->D, ray->tmin, ray->tmax, klight->co, radius, &P, t);
|
||||
}
|
||||
|
||||
ccl_device_inline bool point_light_sample_from_intersection(
|
||||
|
@ -77,27 +132,27 @@ ccl_device_inline bool point_light_sample_from_intersection(
|
|||
ccl_private const Intersection *ccl_restrict isect,
|
||||
const float3 ray_P,
|
||||
const float3 ray_D,
|
||||
const float3 N,
|
||||
const uint32_t path_flag,
|
||||
ccl_private LightSample *ccl_restrict ls)
|
||||
{
|
||||
const float3 lighN = normalize(ray_P - klight->co);
|
||||
ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
|
||||
|
||||
/* We set the light normal to the outgoing direction to support texturing. */
|
||||
ls->Ng = -ls->D;
|
||||
const float radius = klight->spot.radius;
|
||||
|
||||
float invarea = klight->spot.invarea;
|
||||
ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
|
||||
ls->pdf = invarea;
|
||||
ls->Ng = radius > 0 ? normalize(ls->P - klight->co) : -ray_D;
|
||||
|
||||
float2 uv = map_to_sphere(ls->Ng);
|
||||
ls->u = uv.x;
|
||||
ls->v = uv.y;
|
||||
const Transform itfm = klight->itfm;
|
||||
const float2 uv = map_to_sphere(transform_direction(&itfm, ls->Ng));
|
||||
/* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
|
||||
ls->u = uv.y;
|
||||
ls->v = 1.0f - uv.x - uv.y;
|
||||
|
||||
/* compute pdf */
|
||||
if (ls->t != FLT_MAX) {
|
||||
ls->pdf *= lamp_light_pdf(lighN, -ls->D, ls->t);
|
||||
if (ls->t == FLT_MAX) {
|
||||
ls->pdf = 0.0f;
|
||||
}
|
||||
else {
|
||||
ls->pdf = 0.f;
|
||||
ls->pdf = point_light_pdf(len_squared(ray_P - klight->co), sqr(radius), N, ray_D, path_flag);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -115,14 +170,22 @@ ccl_device_forceinline bool point_light_tree_parameters(const ccl_global KernelL
|
|||
cos_theta_u = 1.0f; /* Any value in [-1, 1], irrelevant since theta = 0 */
|
||||
return true;
|
||||
}
|
||||
float min_distance;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &min_distance);
|
||||
|
||||
float dist_point_to_centroid;
|
||||
point_to_centroid = safe_normalize_len(centroid - P, &dist_point_to_centroid);
|
||||
|
||||
const float radius = klight->spot.radius;
|
||||
const float hypotenus = sqrtf(sqr(radius) + sqr(min_distance));
|
||||
cos_theta_u = min_distance / hypotenus;
|
||||
|
||||
distance = make_float2(hypotenus, min_distance);
|
||||
if (dist_point_to_centroid > radius) {
|
||||
/* Equivalent to a disk light with the same angular span. */
|
||||
cos_theta_u = cos_from_sin(radius / dist_point_to_centroid);
|
||||
distance = dist_point_to_centroid * make_float2(1.0f / cos_theta_u, 1.0f);
|
||||
}
|
||||
else {
|
||||
/* Similar to background light. */
|
||||
cos_theta_u = -1.0f;
|
||||
/* HACK: pack radiance scaling in the distance. */
|
||||
distance = one_float2() * radius / M_SQRT2_F;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -338,7 +338,7 @@ ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
|
|||
#endif
|
||||
{
|
||||
return light_distribution_sample<true>(
|
||||
kg, rand, time, P, object_receiver, bounce, path_flag, ls);
|
||||
kg, rand, time, P, D, object_receiver, SD_BSDF_HAS_TRANSMISSION, bounce, path_flag, ls);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -363,7 +363,7 @@ ccl_device bool light_sample_from_position(KernelGlobals kg,
|
|||
#endif
|
||||
{
|
||||
return light_distribution_sample<false>(
|
||||
kg, rand, time, P, object_receiver, bounce, path_flag, ls);
|
||||
kg, rand, time, P, N, object_receiver, shader_flags, bounce, path_flag, ls);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,12 +371,14 @@ ccl_device bool light_sample_from_position(KernelGlobals kg,
|
|||
* except for directional light. */
|
||||
ccl_device_forceinline void light_sample_update(KernelGlobals kg,
|
||||
ccl_private LightSample *ls,
|
||||
const float3 P)
|
||||
const float3 P,
|
||||
const float3 N,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
const ccl_global KernelLight *klight = &kernel_data_fetch(lights, ls->lamp);
|
||||
|
||||
if (ls->type == LIGHT_POINT) {
|
||||
point_light_mnee_sample_update(klight, ls, P);
|
||||
point_light_mnee_sample_update(klight, ls, P, N, path_flag);
|
||||
}
|
||||
else if (ls->type == LIGHT_SPOT) {
|
||||
spot_light_mnee_sample_update(klight, ls, P);
|
||||
|
|
|
@ -761,7 +761,9 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
|
|||
float3_to_float2(rand),
|
||||
time,
|
||||
P,
|
||||
N_or_D,
|
||||
object_receiver,
|
||||
shader_flags,
|
||||
bounce,
|
||||
path_flag,
|
||||
selected_emitter,
|
||||
|
|
|
@ -19,6 +19,29 @@ ccl_device void to_unit_disk(ccl_private float2 *rand)
|
|||
rand->y = r * sinf(phi);
|
||||
}
|
||||
|
||||
/* Distribute 2D uniform random samples on [0, 1] over unit disk [-1, 1], with concentric mapping
|
||||
* to better preserve stratification for some RNG sequences. */
|
||||
ccl_device float2 concentric_sample_disk(const float2 rand)
|
||||
{
|
||||
float phi, r;
|
||||
float a = 2.0f * rand.x - 1.0f;
|
||||
float b = 2.0f * rand.y - 1.0f;
|
||||
|
||||
if (a == 0.0f && b == 0.0f) {
|
||||
return zero_float2();
|
||||
}
|
||||
else if (a * a > b * b) {
|
||||
r = a;
|
||||
phi = M_PI_4_F * (b / a);
|
||||
}
|
||||
else {
|
||||
r = b;
|
||||
phi = M_PI_2_F - M_PI_4_F * (a / b);
|
||||
}
|
||||
|
||||
return make_float2(r * cosf(phi), r * sinf(phi));
|
||||
}
|
||||
|
||||
/* return an orthogonal tangent and bitangent given a normal and tangent that
|
||||
* may not be exactly orthogonal */
|
||||
ccl_device void make_orthonormals_tangent(const float3 N,
|
||||
|
@ -45,6 +68,12 @@ ccl_device_inline void sample_cos_hemisphere(const float3 N,
|
|||
*pdf = costheta * M_1_PI_F;
|
||||
}
|
||||
|
||||
ccl_device_inline float pdf_cos_hemisphere(const float3 N, const float3 D)
|
||||
{
|
||||
const float cos_theta = dot(N, D);
|
||||
return cos_theta > 0 ? cos_theta * M_1_PI_F : 0.0f;
|
||||
}
|
||||
|
||||
/* sample direction uniformly distributed in hemisphere */
|
||||
ccl_device_inline void sample_uniform_hemisphere(const float3 N,
|
||||
const float2 rand,
|
||||
|
@ -91,6 +120,42 @@ ccl_device_inline float pdf_uniform_cone(const float3 N, float3 D, float angle)
|
|||
return 0.0f;
|
||||
}
|
||||
|
||||
/* Uniformly sample a direction in a cone of given angle around `N`. Use concentric mapping to
|
||||
* better preserve stratification. Return the angle between `N` and the sampled direction as
|
||||
* `cos_theta`.
|
||||
* Pass `1 - cos(angle)` as argument instead of `angle` to alleviate precision issues at small
|
||||
* angles (see sphere light for reference). */
|
||||
ccl_device_inline void sample_uniform_cone_concentric(const float3 N,
|
||||
const float one_minus_cos_angle,
|
||||
const float2 rand,
|
||||
ccl_private float *cos_theta,
|
||||
ccl_private float3 *wo,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
if (one_minus_cos_angle > 0) {
|
||||
/* Map random number from 2D to 1D. */
|
||||
float2 xy = concentric_sample_disk(rand);
|
||||
const float r2 = len_squared(xy);
|
||||
|
||||
/* Equivalent to `mix(cos_angle, 1.0f, 1.0f - r2)` */
|
||||
*cos_theta = 1.0f - r2 * one_minus_cos_angle;
|
||||
|
||||
/* Equivalent to `xy *= sin_theta / sqrt(r2); */
|
||||
xy *= safe_sqrtf(one_minus_cos_angle * (2.0f - one_minus_cos_angle * r2));
|
||||
|
||||
float3 T, B;
|
||||
make_orthonormals(N, &T, &B);
|
||||
|
||||
*wo = xy.x * T + xy.y * B + *cos_theta * N;
|
||||
*pdf = M_1_2PI_F / one_minus_cos_angle;
|
||||
}
|
||||
else {
|
||||
*cos_theta = 1.0f;
|
||||
*wo = N;
|
||||
*pdf = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* sample uniform point on the surface of a sphere */
|
||||
ccl_device float3 sample_uniform_sphere(const float2 rand)
|
||||
{
|
||||
|
@ -103,29 +168,6 @@ ccl_device float3 sample_uniform_sphere(const float2 rand)
|
|||
return make_float3(x, y, z);
|
||||
}
|
||||
|
||||
/* distribute uniform xy on [0,1] over unit disk [-1,1], with concentric mapping
|
||||
* to better preserve stratification for some RNG sequences */
|
||||
ccl_device float2 concentric_sample_disk(const float2 rand)
|
||||
{
|
||||
float phi, r;
|
||||
float a = 2.0f * rand.x - 1.0f;
|
||||
float b = 2.0f * rand.y - 1.0f;
|
||||
|
||||
if (a == 0.0f && b == 0.0f) {
|
||||
return zero_float2();
|
||||
}
|
||||
else if (a * a > b * b) {
|
||||
r = a;
|
||||
phi = M_PI_4_F * (b / a);
|
||||
}
|
||||
else {
|
||||
r = b;
|
||||
phi = M_PI_2_F - M_PI_4_F * (a / b);
|
||||
}
|
||||
|
||||
return make_float2(r * cosf(phi), r * sinf(phi));
|
||||
}
|
||||
|
||||
/* sample point in unit polygon with given number of corners and rotation */
|
||||
ccl_device float2 regular_polygon_sample(float corners, float rotation, const float2 rand)
|
||||
{
|
||||
|
|
|
@ -1214,6 +1214,9 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
|
|||
shader_id &= ~SHADER_AREA_LIGHT;
|
||||
|
||||
float radius = light->size;
|
||||
/* TODO: `invarea` was used for disk sampling, with the current solid angle sampling this
|
||||
* becomes unnecessary. We could store `eval_fac` instead, but currently it shares the same
|
||||
* #KernelSpotLight type with #LIGHT_SPOT, so keep it know until refactor for spot light. */
|
||||
float invarea = (light->normalize && radius > 0.0f) ? 1.0f / (M_PI_F * radius * radius) :
|
||||
1.0f;
|
||||
|
||||
|
|
|
@ -748,6 +748,12 @@ ccl_device_inline float cos_from_sin(const float s)
|
|||
return safe_sqrtf(1.0f - sqr(s));
|
||||
}
|
||||
|
||||
ccl_device_inline float sin_sqr_to_one_minus_cos(const float s_sq)
|
||||
{
|
||||
/* Using second-order Taylor expansion at small angles for better accuracy. */
|
||||
return s_sq > 0.0004f ? 1.0f - safe_sqrtf(1.0f - s_sq) : 0.5f * s_sq;
|
||||
}
|
||||
|
||||
ccl_device_inline float pow20(float a)
|
||||
{
|
||||
return sqr(sqr(sqr(sqr(a)) * a));
|
||||
|
|
|
@ -18,29 +18,32 @@ ccl_device bool ray_sphere_intersect(float3 ray_P,
|
|||
ccl_private float3 *isect_P,
|
||||
ccl_private float *isect_t)
|
||||
{
|
||||
const float3 d = sphere_P - ray_P;
|
||||
const float radiussq = sphere_radius * sphere_radius;
|
||||
const float tsq = dot(d, d);
|
||||
const float3 d_vec = sphere_P - ray_P;
|
||||
const float r_sq = sphere_radius * sphere_radius;
|
||||
const float d_sq = dot(d_vec, d_vec);
|
||||
const float d_cos_theta = dot(d_vec, ray_D);
|
||||
|
||||
if (tsq > radiussq) {
|
||||
/* Ray origin outside sphere. */
|
||||
const float tp = dot(d, ray_D);
|
||||
if (tp < 0.0f) {
|
||||
/* Ray points away from sphere. */
|
||||
return false;
|
||||
}
|
||||
const float dsq = tsq - tp * tp; /* Pythagoras. */
|
||||
if (dsq > radiussq) {
|
||||
/* Closest point on ray outside sphere. */
|
||||
return false;
|
||||
}
|
||||
const float t = tp - sqrtf(radiussq - dsq); /* pythagoras */
|
||||
if (t > ray_tmin && t < ray_tmax) {
|
||||
*isect_t = t;
|
||||
*isect_P = ray_P + ray_D * t;
|
||||
return true;
|
||||
}
|
||||
if (d_sq > r_sq && d_cos_theta < 0.0f) {
|
||||
/* Ray origin outside sphere and points away from sphere. */
|
||||
return false;
|
||||
}
|
||||
|
||||
const float d_sin_theta_sq = d_sq - d_cos_theta * d_cos_theta;
|
||||
|
||||
if (d_sin_theta_sq > r_sq) {
|
||||
/* Closest point on ray outside sphere. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Law of cosines. */
|
||||
const float t = d_cos_theta - copysignf(sqrtf(r_sq - d_sin_theta_sq), d_sq - r_sq);
|
||||
|
||||
if (t > ray_tmin && t < ray_tmax) {
|
||||
*isect_t = t;
|
||||
*isect_P = ray_P + ray_D * t;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -584,13 +584,14 @@ char *GHOST_GetTitle(GHOST_WindowHandle windowhandle)
|
|||
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
||||
std::string title = window->getTitle();
|
||||
|
||||
char *ctitle = (char *)malloc(title.size() + 1);
|
||||
const size_t ctitle_size = title.size() + 1;
|
||||
char *ctitle = (char *)malloc(ctitle_size);
|
||||
|
||||
if (ctitle == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
strcpy(ctitle, title.c_str());
|
||||
memcpy(ctitle, title.c_str(), ctitle_size);
|
||||
|
||||
return ctitle;
|
||||
}
|
||||
|
|
|
@ -270,10 +270,11 @@ void *GHOST_DropTargetWin32::getDropDataAsString(IDataObject *p_data_object)
|
|||
if (p_data_object->QueryGetData(&fmtetc) == S_OK) {
|
||||
if (p_data_object->GetData(&fmtetc, &stgmed) == S_OK) {
|
||||
char *str = (char *)::GlobalLock(stgmed.hGlobal);
|
||||
int str_size = ::strlen(str) + 1;
|
||||
|
||||
tmp_string = (char *)::malloc(::strlen(str) + 1);
|
||||
tmp_string = (char *)::malloc(str_size);
|
||||
if (tmp_string) {
|
||||
::strcpy(tmp_string, str);
|
||||
::memcpy(tmp_string, str, str_size);
|
||||
}
|
||||
/* Free memory. */
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
|
|
|
@ -2190,12 +2190,14 @@ char *GHOST_SystemX11::getClipboard(bool selection) const
|
|||
owner = XGetSelectionOwner(m_display, sseln);
|
||||
if (owner == win) {
|
||||
if (sseln == m_atom.CLIPBOARD) {
|
||||
sel_buf = (char *)malloc(strlen(txt_cut_buffer) + 1);
|
||||
strcpy(sel_buf, txt_cut_buffer);
|
||||
size_t sel_buf_size = strlen(txt_cut_buffer) + 1;
|
||||
sel_buf = (char *)malloc(sel_buf_size);
|
||||
memcpy(sel_buf, txt_cut_buffer, sel_buf_size);
|
||||
return sel_buf;
|
||||
}
|
||||
sel_buf = (char *)malloc(strlen(txt_select_buffer) + 1);
|
||||
strcpy(sel_buf, txt_select_buffer);
|
||||
size_t sel_buf_size = strlen(txt_select_buffer) + 1;
|
||||
sel_buf = (char *)malloc(sel_buf_size);
|
||||
memcpy(sel_buf, txt_select_buffer, sel_buf_size);
|
||||
return sel_buf;
|
||||
}
|
||||
if (owner == None) {
|
||||
|
@ -2289,8 +2291,9 @@ void GHOST_SystemX11::putClipboard(const char *buffer, bool selection) const
|
|||
free((void *)txt_cut_buffer);
|
||||
}
|
||||
|
||||
txt_cut_buffer = (char *)malloc(strlen(buffer) + 1);
|
||||
strcpy(txt_cut_buffer, buffer);
|
||||
size_t buffer_size = strlen(buffer) + 1;
|
||||
txt_cut_buffer = (char *)malloc(buffer_size);
|
||||
memcpy(txt_cut_buffer, buffer, buffer_size);
|
||||
}
|
||||
else {
|
||||
XSetSelectionOwner(m_display, m_atom.PRIMARY, m_window, CurrentTime);
|
||||
|
@ -2299,8 +2302,9 @@ void GHOST_SystemX11::putClipboard(const char *buffer, bool selection) const
|
|||
free((void *)txt_select_buffer);
|
||||
}
|
||||
|
||||
txt_select_buffer = (char *)malloc(strlen(buffer) + 1);
|
||||
strcpy(txt_select_buffer, buffer);
|
||||
size_t buffer_size = strlen(buffer) + 1;
|
||||
txt_select_buffer = (char *)malloc(buffer_size);
|
||||
memcpy(txt_select_buffer, buffer, buffer_size);
|
||||
}
|
||||
|
||||
if (owner != m_window) {
|
||||
|
|
|
@ -22,11 +22,10 @@ PERFORMANCE OF THIS SOFTWARE.
|
|||
** Audaspace; version 1.3.0 -- https://audaspace.github.io/
|
||||
** Cuda Wrangler; version cbf465b -- https://github.com/CudaWrangler/cuew
|
||||
** Draco; version 1.3.6 -- https://google.github.io/draco/
|
||||
** Embree; version 3.13.4 -- https://github.com/embree/embree
|
||||
** Intel(R) oneAPI DPC++ compiler; version 20221019 --
|
||||
** Embree; version 4.1.0 -- https://github.com/embree/embree
|
||||
** Intel(R) oneAPI DPC++ compiler; version 2022-12 --
|
||||
https://github.com/intel/llvm#oneapi-dpc-compiler
|
||||
** Intel® Open Path Guiding Library; version v0.4.1-beta --
|
||||
http://www.openpgl.org/
|
||||
** Intel® Open Path Guiding Library; version 0.5.0 -- http://www.openpgl.org/
|
||||
** Mantaflow; version 0.13 -- http://mantaflow.com/
|
||||
** materialX; version 1.38.6 --
|
||||
https://github.com/AcademySoftwareFoundation/MaterialX
|
||||
|
@ -40,6 +39,8 @@ https://software.intel.com/en-us/oneapi/onetbb
|
|||
** SDL Extension Wrangler; version 15edf8e --
|
||||
https://github.com/SDLWrangler/sdlew
|
||||
** ShaderC; version 2022.3 -- https://github.com/google/shaderc
|
||||
** SYCL Unified Runtime ; version fd711c920acc4434cb52ff18b078c082d9d7f44d --
|
||||
https://github.com/oneapi-src/unified-runtime
|
||||
** Vulkan Loader; version 1.2.198 --
|
||||
https://github.com/KhronosGroup/Vulkan-Loader
|
||||
|
||||
|
@ -279,6 +280,8 @@ limitations under the License.
|
|||
Copyright 2014 Blender Foundation
|
||||
* For ShaderC see also this required NOTICE:
|
||||
Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
* For SYCL Unified Runtime see also this required NOTICE:
|
||||
Copyright (C) 2022-2023 Intel Corporation
|
||||
* For Vulkan Loader see also this required NOTICE:
|
||||
Copyright (c) 2019 The Khronos Group Inc.
|
||||
Copyright (c) 2019 Valve Corporation
|
||||
|
@ -378,7 +381,7 @@ All rights reserved.
|
|||
** Google Logging; version 4.4.0 -- https://github.com/google/glog
|
||||
Copyright (c) 2006, Google Inc.
|
||||
All rights reserved.
|
||||
** Imath; version 3.1.5 -- https://github.com/AcademySoftwareFoundation/Imath
|
||||
** Imath; version 3.1.7 -- https://github.com/AcademySoftwareFoundation/Imath
|
||||
Copyright Contributors to the OpenEXR Project. All rights reserved.
|
||||
** ISPC; version 1.17.0 -- https://github.com/ispc/ispc
|
||||
Copyright Intel Corporation
|
||||
|
@ -395,10 +398,10 @@ Copyright Contributors to the Open Shading Language project.
|
|||
** OpenColorIO; version 2.2.0 --
|
||||
https://github.com/AcademySoftwareFoundation/OpenColorIO
|
||||
Copyright Contributors to the OpenColorIO Project.
|
||||
** OpenEXR; version 3.1.5 --
|
||||
** OpenEXR; version 3.1.7 --
|
||||
https://github.com/AcademySoftwareFoundation/openexr
|
||||
Copyright Contributors to the OpenEXR Project. All rights reserved.
|
||||
** OpenImageIO; version 2.4.9.0 -- http://www.openimageio.org
|
||||
** OpenImageIO; version 2.4.11.0 -- http://www.openimageio.org
|
||||
Copyright (c) 2008-present by Contributors to the OpenImageIO project. All
|
||||
Rights Reserved.
|
||||
** Pystring; version 1.1.3 -- https://github.com/imageworks/pystring
|
||||
|
@ -571,7 +574,7 @@ effect of CC0 on those rights.
|
|||
|
||||
------
|
||||
|
||||
** FLAC; version 1.3.4 -- https://xiph.org/flac/
|
||||
** FLAC; version 1.4.2 -- https://xiph.org/flac/
|
||||
Copyright (C) 2001-2009 Josh Coalson
|
||||
Copyright (C) 2011-2016 Xiph.Org Foundation
|
||||
** Potrace; version 1.16 -- http://potrace.sourceforge.net/
|
||||
|
@ -1242,7 +1245,7 @@ Copyright (C) 2003-2021 x264 project
|
|||
** miniLZO; version 2.08 -- http://www.oberhumer.com/opensource/lzo/
|
||||
LZO and miniLZO are Copyright (C) 1996-2014 Markus Franz Xaver Oberhumer
|
||||
All Rights Reserved.
|
||||
** The FreeType Project; version 2.12.1 --
|
||||
** The FreeType Project; version 2.13.0 --
|
||||
https://sourceforge.net/projects/freetype
|
||||
Copyright (C) 1996-2020 by David Turner, Robert Wilhelm, and Werner Lemberg.
|
||||
** X Drag and Drop; version 2000-08-08 --
|
||||
|
@ -2796,7 +2799,7 @@ That's all there is to it!
|
|||
|
||||
------
|
||||
|
||||
** FFmpeg; version 5.1.2 -- http://ffmpeg.org/
|
||||
** FFmpeg; version 6.0 -- http://ffmpeg.org/
|
||||
Copyright: The FFmpeg contributors
|
||||
https://github.com/FFmpeg/FFmpeg/blob/master/CREDITS
|
||||
** Libsndfile; version 1.1.0 -- http://libsndfile.github.io/libsndfile/
|
||||
|
@ -3425,7 +3428,35 @@ December 9, 2010
|
|||
|
||||
------
|
||||
|
||||
** {fmt}; version 8.0.0 -- https://github.com/fmtlib/fmt
|
||||
** vcintrinsics; version 782fbf7301dc73acaa049a4324c976ad94f587f7 --
|
||||
https://github.com/intel/vc-intrinsics
|
||||
Copyright (c) 2019 Intel Corporation
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Intel Corporation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
------
|
||||
|
||||
** {fmt}; version 9.1.0 -- https://github.com/fmtlib/fmt
|
||||
Copyright (c) 2012 - present, Victor Zverovich
|
||||
** Brotli; version 1.0.9 -- https://github.com/google/brotli
|
||||
Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors.
|
||||
|
@ -3454,11 +3485,11 @@ Copyright (c) 2006, 2008 Junio C Hamano
|
|||
Copyright © 2017-2018 Red Hat Inc.
|
||||
Copyright © 2012 Collabora, Ltd.
|
||||
Copyright © 2008 Kristian Høgsberg
|
||||
** Libxml2; version 2.10.3 -- http://xmlsoft.org/
|
||||
** Libxml2; version 2.10.4 -- http://xmlsoft.org/
|
||||
Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved.
|
||||
** Mesa 3D; version 21.1.5 -- https://www.mesa3d.org/
|
||||
Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
|
||||
** oneAPI Level Zero; version v1.8.5 --
|
||||
** oneAPI Level Zero; version v1.8.8 --
|
||||
https://github.com/oneapi-src/level-zero
|
||||
Copyright (C) 2019-2021 Intel Corporation
|
||||
** OPENCollada; version 1.6.68 -- https://github.com/KhronosGroup/OpenCOLLADA
|
||||
|
@ -3470,12 +3501,11 @@ Copyright (c) 2018 Jingwei Huang, Yichao Zhou, Matthias Niessner,
|
|||
Jonathan Shewchuk and Leonidas Guibas. All rights reserved.
|
||||
** robin-map; version 0.6.2 -- https://github.com/Tessil/robin-map
|
||||
Copyright (c) 2017 Thibaut Goetghebuer-Planchon <tessil@gmx.com>
|
||||
** sse2neon; version fe5ff00bb8d19b327714a3c290f3e2ce81ba3525 --
|
||||
https://github.com/DLTcollab/sse2neon
|
||||
** sse2neon; version 1.6.0 -- https://github.com/DLTcollab/sse2neon
|
||||
Copyright sse2neon contributors
|
||||
** TinyGLTF; version 2.5.0 -- https://github.com/syoyo/tinygltf
|
||||
Copyright (c) 2017 Syoyo Fujita, Aurélien Chatelain and many contributors
|
||||
** Wayland protocols; version 1.21 --
|
||||
** Wayland protocols; version 1.31 --
|
||||
https://gitlab.freedesktop.org/wayland/wayland-protocols
|
||||
Copyright © 2008-2013 Kristian Høgsberg
|
||||
Copyright © 2010-2013 Intel Corporation
|
||||
|
@ -3973,7 +4003,7 @@ the following restrictions:
|
|||
|
||||
------
|
||||
|
||||
** LibTIFF; version 4.4.0 -- http://www.libtiff.org/
|
||||
** LibTIFF; version 4.5.1 -- http://www.libtiff.org/
|
||||
Copyright (c) 1988-1997 Sam Leffler
|
||||
Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
|
||||
|
@ -4029,7 +4059,7 @@ Software.
|
|||
|
||||
** OpenSubdiv; version 3.5.0 -- http://graphics.pixar.com/opensubdiv
|
||||
Copyright 2013 Pixar
|
||||
** Universal Scene Description; version 22.11 -- http://www.openusd.org/
|
||||
** Universal Scene Description; version 23.05 -- http://www.openusd.org/
|
||||
Copyright 2016 Pixar
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "Apache License") with the
|
||||
|
@ -4215,7 +4245,7 @@ disclaims all warranties with regard to this software.
|
|||
|
||||
------
|
||||
|
||||
** Wayland; version 1.21.0 -- https://gitlab.freedesktop.org/wayland/wayland
|
||||
** Wayland; version 1.22.0 -- https://gitlab.freedesktop.org/wayland/wayland
|
||||
Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
|
||||
Copyright © 2011 Kristian Høgsberg
|
||||
Copyright © 2011 Benjamin Franzke
|
||||
|
@ -4240,7 +4270,7 @@ MIT Expat
|
|||
|
||||
------
|
||||
|
||||
** OpenSSL; version 1.1.1q -- https://www.openssl.org/
|
||||
** OpenSSL; version 3.1.1 -- https://www.openssl.org/
|
||||
Copyright (c) 1998-2021 The OpenSSL Project
|
||||
Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
|
||||
|
||||
|
@ -4363,7 +4393,7 @@ OpenSSL License
|
|||
|
||||
------
|
||||
|
||||
** Python; version 3.10.9 -- https://www.python.org
|
||||
** Python; version 3.10.12 -- https://www.python.org
|
||||
Copyright (c) 2001-2021 Python Software Foundation. All rights reserved.
|
||||
|
||||
A. HISTORY OF THE SOFTWARE
|
||||
|
|
|
@ -566,7 +566,7 @@ def _name_convention_attribute_remove(attributes, name):
|
|||
class Mesh(bpy_types.ID):
|
||||
__slots__ = ()
|
||||
|
||||
def from_pydata(self, vertices, edges, faces):
|
||||
def from_pydata(self, vertices, edges, faces, shade_flat=True):
|
||||
"""
|
||||
Make a mesh from a list of vertices/edges/faces
|
||||
Until we have a nicer way to make geometry, use this.
|
||||
|
@ -623,6 +623,9 @@ class Mesh(bpy_types.ID):
|
|||
self.polygons.foreach_set("loop_start", loop_starts)
|
||||
self.polygons.foreach_set("vertices", vertex_indices)
|
||||
|
||||
if shade_flat:
|
||||
self.shade_flat()
|
||||
|
||||
if edges_len or faces_len:
|
||||
self.update(
|
||||
# Needed to either:
|
||||
|
@ -663,6 +666,22 @@ class Mesh(bpy_types.ID):
|
|||
def edge_creases_remove(self):
|
||||
_name_convention_attribute_remove(self.attributes, "crease_edge")
|
||||
|
||||
def shade_flat(self):
|
||||
"""
|
||||
Render and display faces uniform, using face normals,
|
||||
setting the "sharp_face" attribute true for every face
|
||||
"""
|
||||
sharp_faces = _name_convention_attribute_ensure(self.attributes, "sharp_face", 'FACE', 'BOOLEAN')
|
||||
for value in sharp_faces.data:
|
||||
value.value = True
|
||||
|
||||
def shade_smooth(self):
|
||||
"""
|
||||
Render and display faces smooth, using interpolated vertex normals,
|
||||
removing the "sharp_face" attribute
|
||||
"""
|
||||
_name_convention_attribute_remove(self.attributes, "sharp_face")
|
||||
|
||||
|
||||
class MeshEdge(StructRNA):
|
||||
__slots__ = ()
|
||||
|
|
|
@ -246,6 +246,7 @@ class AddTorus(Operator, object_utils.AddObjectHelper):
|
|||
mesh.vertices.foreach_set("co", verts_loc)
|
||||
mesh.polygons.foreach_set("loop_start", range(0, nbr_loops, 4))
|
||||
mesh.loops.foreach_set("vertex_index", faces)
|
||||
mesh.shade_flat()
|
||||
|
||||
if self.generate_uvs:
|
||||
add_uvs(mesh, self.minor_segments, self.major_segments)
|
||||
|
|
|
@ -250,13 +250,10 @@ class NODE_OT_tree_path_parent(Operator):
|
|||
class NodePanelOperator():
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
snode = context.space_data
|
||||
if snode is None:
|
||||
space = context.space_data
|
||||
if not space or space.type != 'NODE_EDITOR' or not space.edit_tree:
|
||||
return False
|
||||
tree = snode.edit_tree
|
||||
if tree is None:
|
||||
return False
|
||||
if tree.is_embedded_data:
|
||||
if space.edit_tree.is_embedded_data:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
|
|
@ -398,7 +398,7 @@ def lightmap_uvpack(
|
|||
# Since the boxes are sized in powers of 2, we can neatly group them into bigger squares
|
||||
# this is done hierarchically, so that we may avoid running the pack function
|
||||
# on many thousands of boxes, (under 1k is best) because it would get slow.
|
||||
# Using an off and even dict us useful because they are packed differently
|
||||
# Using an odd and even dict is useful because they are packed differently
|
||||
# where w/h are the same, their packed in groups of 4
|
||||
# where they are different they are packed in pairs
|
||||
#
|
||||
|
|
|
@ -31,7 +31,7 @@ def draw_ui_list(
|
|||
context,
|
||||
class_name="UI_UL_list",
|
||||
*,
|
||||
unique_id="",
|
||||
unique_id,
|
||||
list_path,
|
||||
active_index_path,
|
||||
insertion_operators=True,
|
||||
|
@ -48,7 +48,7 @@ def draw_ui_list(
|
|||
:type context: :class:`Context`
|
||||
:arg class_name: Name of the UIList class to draw. The default is the UIList class that ships with Blender.
|
||||
:type class_name: str
|
||||
:arg unique_id: Optional identifier, in case wanting to draw multiple unique copies of a list.
|
||||
:arg unique_id: Unique identifier to differentiate this from other UI lists.
|
||||
:type unique_id: str
|
||||
:arg list_path: Data path of the list relative to context, eg. "object.vertex_groups".
|
||||
:type list_path: str
|
||||
|
|
|
@ -87,8 +87,12 @@ class SPREADSHEET_HT_header(bpy.types.Header):
|
|||
layout.label(text="Invalid id")
|
||||
elif ctx.type == 'MODIFIER':
|
||||
layout.label(text=ctx.modifier_name, icon='MODIFIER')
|
||||
elif ctx.type == 'NODE':
|
||||
layout.label(text=ctx.node_name, icon='NODE')
|
||||
elif ctx.type == 'GROUP_NODE':
|
||||
layout.label(text=ctx.ui_name, icon='NODE')
|
||||
elif ctx.type == 'SIMULATION_ZONE':
|
||||
layout.label(text="Simulation Zone")
|
||||
elif ctx.type == 'VIEWER_NODE':
|
||||
layout.label(text=ctx.ui_name)
|
||||
|
||||
def draw_spreadsheet_viewer_path_icon(self, layout, space, icon='RIGHTARROW_THIN'):
|
||||
layout.prop(space, "display_viewer_path_collapsed", icon_only=True, emboss=False, icon=icon)
|
||||
|
|
|
@ -2431,7 +2431,7 @@ class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
|
|||
({"property": "use_experimental_compositors"}, ("blender/blender/issues/88150", "#88150")),
|
||||
({"property": "enable_eevee_next"}, ("blender/blender/issues/93220", "#93220")),
|
||||
({"property": "enable_workbench_next"}, ("blender/blender/issues/101619", "#101619")),
|
||||
({"property": "use_grease_pencil_version3"}, ("blender/blender/projects/40", "Grease Pencil 3.0")),
|
||||
({"property": "use_grease_pencil_version3"}, ("blender/blender/projects/6", "Grease Pencil 3.0")),
|
||||
({"property": "enable_overlay_next"}, ("blender/blender/issues/102179", "#102179")),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -748,6 +748,14 @@ class VIEW3D_HT_header(Header):
|
|||
).domain = 'CURVE'
|
||||
|
||||
# Grease Pencil
|
||||
if obj and obj.type == 'GREASEPENCIL':
|
||||
# Select mode for Editing
|
||||
if object_mode == 'EDIT':
|
||||
row = layout.row(align=True)
|
||||
row.prop_enum(tool_settings, "gpencil_selectmode_edit", text="", value='POINT')
|
||||
row.prop_enum(tool_settings, "gpencil_selectmode_edit", text="", value='STROKE')
|
||||
|
||||
# Grease Pencil (legacy)
|
||||
if obj and obj.type == 'GPENCIL' and context.gpencil_data:
|
||||
gpd = context.gpencil_data
|
||||
|
||||
|
@ -2024,6 +2032,7 @@ class VIEW3D_MT_select_edit_gpencil(Menu):
|
|||
def draw(self, context):
|
||||
if not context.preferences.experimental.use_grease_pencil_version3:
|
||||
self.draw_legacy(context)
|
||||
return
|
||||
|
||||
layout = self.layout
|
||||
|
||||
|
@ -2034,6 +2043,7 @@ class VIEW3D_MT_select_edit_gpencil(Menu):
|
|||
layout.separator()
|
||||
|
||||
layout.operator("grease_pencil.select_linked", text="Linked")
|
||||
layout.operator("grease_pencil.select_random", text="Random")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
@ -3055,8 +3065,8 @@ class VIEW3D_MT_object_convert(Menu):
|
|||
def draw(self, context):
|
||||
layout = self.layout
|
||||
ob = context.active_object
|
||||
|
||||
if ob and ob.type == 'GPENCIL' and context.gpencil_data:
|
||||
|
||||
if ob and ob.type == 'GPENCIL' and context.gpencil_data and not context.preferences.experimental.use_grease_pencil_version3:
|
||||
layout.operator_enum("gpencil.convert", "type")
|
||||
else:
|
||||
layout.operator_enum("object.convert", "target")
|
||||
|
@ -3592,9 +3602,6 @@ class VIEW3D_MT_face_sets_init(Menu):
|
|||
props = layout.operator("sculpt.face_sets_init", text="By Sharp Edges")
|
||||
props.mode = 'SHARP_EDGES'
|
||||
|
||||
props = layout.operator("sculpt.face_sets_init", text="By Face Maps")
|
||||
props.mode = 'FACE_MAPS'
|
||||
|
||||
|
||||
class VIEW3D_MT_random_mask(Menu):
|
||||
bl_label = "Random Mask"
|
||||
|
|
|
@ -18,8 +18,9 @@ class MyPanel(bpy.types.Panel):
|
|||
draw_ui_list(
|
||||
layout,
|
||||
context,
|
||||
list_context_path="scene.my_list",
|
||||
active_index_context_path="scene.my_list_active_index"
|
||||
list_path="scene.my_list",
|
||||
active_index_path="scene.my_list_active_index",
|
||||
unique_id="my_list_id",
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -206,7 +206,7 @@ typedef struct GlyphBLF {
|
|||
|
||||
/**
|
||||
* X and Y bearing of the glyph.
|
||||
* The X bearing is from the origin to the glyph left bbox edge.
|
||||
* The X bearing is from the origin to the glyph left bounding-box edge.
|
||||
* The Y bearing is from the baseline to the top of the glyph edge.
|
||||
*/
|
||||
int pos[2];
|
||||
|
|
|
@ -559,7 +559,9 @@ void BKE_pchan_bbone_deform_segment_index(const struct bPoseChannel *pchan,
|
|||
|
||||
/* context.selected_pose_bones */
|
||||
#define FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN(_ob, _pchan) \
|
||||
for (bPoseChannel *_pchan = (_ob)->pose->chanbase.first; _pchan; _pchan = _pchan->next) { \
|
||||
for (bPoseChannel *_pchan = (bPoseChannel *)(_ob)->pose->chanbase.first; _pchan; \
|
||||
_pchan = _pchan->next) \
|
||||
{ \
|
||||
if (PBONE_VISIBLE(((bArmature *)(_ob)->data), (_pchan)->bone) && \
|
||||
((_pchan)->bone->flag & BONE_SELECTED)) \
|
||||
{
|
||||
|
|
|
@ -930,7 +930,7 @@ void gather_attributes(AttributeAccessor src_attributes,
|
|||
MutableAttributeAccessor dst_attributes);
|
||||
|
||||
/**
|
||||
* Copy attribute values from groups groups defined by \a src_offsets to groups defined by \a
|
||||
* Copy attribute values from groups defined by \a src_offsets to groups defined by \a
|
||||
* dst_offsets. The group indices are gathered to the result by \a selection. The size of each
|
||||
* source and result group must be the same.
|
||||
*/
|
||||
|
|
|
@ -59,4 +59,23 @@ class NodeGroupComputeContext : public ComputeContext {
|
|||
void print_current_in_line(std::ostream &stream) const override;
|
||||
};
|
||||
|
||||
class SimulationZoneComputeContext : public ComputeContext {
|
||||
private:
|
||||
static constexpr const char *s_static_type = "SIMULATION_ZONE";
|
||||
|
||||
int32_t output_node_id_;
|
||||
|
||||
public:
|
||||
SimulationZoneComputeContext(const ComputeContext *parent, int output_node_id);
|
||||
SimulationZoneComputeContext(const ComputeContext *parent, const bNode &node);
|
||||
|
||||
int32_t output_node_id() const
|
||||
{
|
||||
return output_node_id_;
|
||||
}
|
||||
|
||||
private:
|
||||
void print_current_in_line(std::ostream &stream) const override;
|
||||
};
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -71,8 +71,7 @@ class Layer;
|
|||
/**
|
||||
* A TreeNode represents one node in the layer tree.
|
||||
* It can either be a layer or a group. The node has zero children if it is a layer or zero or
|
||||
more
|
||||
* children if it is a group.
|
||||
* more children if it is a group.
|
||||
*/
|
||||
class TreeNode : public ::GreasePencilLayerTreeNode {
|
||||
public:
|
||||
|
|
|
@ -93,13 +93,15 @@ void normals_calc_poly_vert(Span<float3> vert_positions,
|
|||
* a regular #float3 format.
|
||||
*/
|
||||
struct CornerNormalSpace {
|
||||
/** Reference vector, orthogonal to corner normal. */
|
||||
/** The automatically computed face corner normal, not including influence of custom normals. */
|
||||
float3 vec_lnor;
|
||||
/** Reference vector, orthogonal to #vec_lnor. */
|
||||
float3 vec_ref;
|
||||
/** Third vector, orthogonal to corner normal and #vec_ref. */
|
||||
/** Third vector, orthogonal to #vec_lnor and #vec_ref. */
|
||||
float3 vec_ortho;
|
||||
/** Reference angle around #vec_ortho, in [0, pi] range (0.0 marks space as invalid). */
|
||||
float ref_alpha;
|
||||
/** Reference angle around corner normal, in [0, 2pi] range (0.0 marks space as invalid). */
|
||||
/** Reference angle around #vec_lnor, in [0, 2pi] range (0.0 marks space as invalid). */
|
||||
float ref_beta;
|
||||
};
|
||||
|
||||
|
@ -131,7 +133,6 @@ struct CornerNormalSpaceArray {
|
|||
};
|
||||
|
||||
void lnor_space_custom_normal_to_data(const CornerNormalSpace *lnor_space,
|
||||
float3 lnor_no_custom,
|
||||
const float custom_lnor[3],
|
||||
short r_clnor_data[2]);
|
||||
|
||||
|
|
|
@ -33,8 +33,8 @@ struct RelationsInNode;
|
|||
}
|
||||
namespace aal = anonymous_attribute_lifetime;
|
||||
} // namespace blender::nodes
|
||||
namespace blender::bke::node_tree_zones {
|
||||
class TreeZones;
|
||||
namespace blender::bke {
|
||||
class bNodeTreeZones;
|
||||
}
|
||||
namespace blender::bke::anonymous_attribute_inferencing {
|
||||
struct AnonymousAttributeInferencingResult;
|
||||
|
@ -149,7 +149,7 @@ class bNodeTreeRuntime : NonCopyable, NonMovable {
|
|||
mutable std::atomic<int> allow_use_dirty_topology_cache = 0;
|
||||
|
||||
CacheMutex tree_zones_cache_mutex;
|
||||
std::unique_ptr<node_tree_zones::TreeZones> tree_zones;
|
||||
std::unique_ptr<bNodeTreeZones> tree_zones;
|
||||
|
||||
/** Only valid when #topology_cache_is_dirty is false. */
|
||||
Vector<bNodeLink *> links;
|
||||
|
|
|
@ -12,10 +12,13 @@
|
|||
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
namespace blender::bke::node_tree_zones {
|
||||
namespace blender::bke {
|
||||
|
||||
struct TreeZone {
|
||||
TreeZones *owner = nullptr;
|
||||
class bNodeTreeZones;
|
||||
|
||||
class bNodeTreeZone {
|
||||
public:
|
||||
bNodeTreeZones *owner = nullptr;
|
||||
/** Index of the zone in the array of all zones in a node tree. */
|
||||
int index = -1;
|
||||
/** Zero for top level zones, one for a nested zone, and so on. */
|
||||
|
@ -25,22 +28,22 @@ struct TreeZone {
|
|||
/** Output node of the zone. */
|
||||
const bNode *output_node = nullptr;
|
||||
/** Direct parent of the zone. If this is null, this is a top level zone. */
|
||||
TreeZone *parent_zone = nullptr;
|
||||
bNodeTreeZone *parent_zone = nullptr;
|
||||
/** Direct children zones. Does not contain recursively nested zones. */
|
||||
Vector<TreeZone *> child_zones;
|
||||
Vector<bNodeTreeZone *> child_zones;
|
||||
/** Direct children nodes excluding nodes that belong to child zones. */
|
||||
Vector<const bNode *> child_nodes;
|
||||
/** Links that enter the zone through the zone border. */
|
||||
Vector<const bNodeLink *> border_links;
|
||||
|
||||
bool contains_node_recursively(const bNode &node) const;
|
||||
bool contains_zone_recursively(const TreeZone &other_zone) const;
|
||||
bool contains_zone_recursively(const bNodeTreeZone &other_zone) const;
|
||||
};
|
||||
|
||||
class TreeZones {
|
||||
class bNodeTreeZones {
|
||||
public:
|
||||
Vector<std::unique_ptr<TreeZone>> zones;
|
||||
Vector<TreeZone *> root_zones;
|
||||
Vector<std::unique_ptr<bNodeTreeZone>> zones;
|
||||
Vector<bNodeTreeZone *> root_zones;
|
||||
Vector<const bNode *> nodes_outside_zones;
|
||||
/**
|
||||
* Zone index by node. Nodes that are in no zone, are not included. Nodes that are at the border
|
||||
|
@ -52,9 +55,26 @@ class TreeZones {
|
|||
* Get the deepest zone that a socket is in. Note that the inputs of a Simulation Input node are
|
||||
* in a different zone than its output sockets.
|
||||
*/
|
||||
const TreeZone *get_zone_by_socket(const bNodeSocket &socket) const;
|
||||
const bNodeTreeZone *get_zone_by_socket(const bNodeSocket &socket) const;
|
||||
|
||||
/**
|
||||
* Get the deepest zone that the node is in. Note that the e.g. Simulation Input and Output nodes
|
||||
* are considered to be inside of the zone they create.
|
||||
*/
|
||||
const bNodeTreeZone *get_zone_by_node(const int32_t node_id) const;
|
||||
|
||||
/**
|
||||
* Get a sorted list of zones that the node is in. First comes the root zone and last the most
|
||||
* nested zone. For nodes that are at the root level, the returned list is empty.
|
||||
*/
|
||||
Vector<const bNodeTreeZone *> get_zone_stack_for_node(const int32_t node_id) const;
|
||||
};
|
||||
|
||||
const TreeZones *get_tree_zones(const bNodeTree &tree);
|
||||
const bNodeTreeZones *get_tree_zones(const bNodeTree &tree);
|
||||
|
||||
} // namespace blender::bke::node_tree_zones
|
||||
} // namespace blender::bke
|
||||
|
||||
inline const blender::bke::bNodeTreeZones *bNodeTree::zones() const
|
||||
{
|
||||
return blender::bke::get_tree_zones(*this);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,9 @@ void BKE_viewer_path_id_remap(ViewerPath *viewer_path, const struct IDRemapper *
|
|||
ViewerPathElem *BKE_viewer_path_elem_new(ViewerPathElemType type);
|
||||
IDViewerPathElem *BKE_viewer_path_elem_new_id(void);
|
||||
ModifierViewerPathElem *BKE_viewer_path_elem_new_modifier(void);
|
||||
NodeViewerPathElem *BKE_viewer_path_elem_new_node(void);
|
||||
GroupNodeViewerPathElem *BKE_viewer_path_elem_new_group_node(void);
|
||||
SimulationZoneViewerPathElem *BKE_viewer_path_elem_new_simulation_zone(void);
|
||||
ViewerNodeViewerPathElem *BKE_viewer_path_elem_new_viewer_node(void);
|
||||
ViewerPathElem *BKE_viewer_path_elem_copy(const ViewerPathElem *src);
|
||||
bool BKE_viewer_path_elem_equal(const ViewerPathElem *a, const ViewerPathElem *b);
|
||||
void BKE_viewer_path_elem_free(ViewerPathElem *elem);
|
||||
|
|
|
@ -39,7 +39,7 @@ typedef struct bMovieHandle {
|
|||
void (*end_movie)(void *context_v);
|
||||
|
||||
/* Optional function. */
|
||||
void (*get_movie_path)(char *filepath,
|
||||
void (*get_movie_path)(char filepath[/*FILE_MAX*/ 1024],
|
||||
const struct RenderData *rd,
|
||||
bool preview,
|
||||
const char *suffix);
|
||||
|
@ -53,7 +53,7 @@ bMovieHandle *BKE_movie_handle_get(char imtype);
|
|||
/**
|
||||
* \note Similar to #BKE_image_path_from_imformat()
|
||||
*/
|
||||
void BKE_movie_filepath_get(char *filepath,
|
||||
void BKE_movie_filepath_get(char filepath[/*FILE_MAX*/ 1024],
|
||||
const struct RenderData *rd,
|
||||
bool preview,
|
||||
const char *suffix);
|
||||
|
|
|
@ -65,7 +65,7 @@ int BKE_ffmpeg_append(void *context_v,
|
|||
int recty,
|
||||
const char *suffix,
|
||||
struct ReportList *reports);
|
||||
void BKE_ffmpeg_filepath_get(char *filepath,
|
||||
void BKE_ffmpeg_filepath_get(char filepath[/*FILE_MAX*/ 1024],
|
||||
const struct RenderData *rd,
|
||||
bool preview,
|
||||
const char *suffix);
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "BKE_action.h"
|
||||
|
||||
#include "DNA_action_types.h"
|
||||
|
@ -53,10 +55,10 @@ TEST(action_groups, ReconstructGroupsWithReordering)
|
|||
bActionGroup groupB = {nullptr};
|
||||
bActionGroup groupC = {nullptr};
|
||||
bActionGroup groupD = {nullptr};
|
||||
strcpy(groupA.name, "groupA");
|
||||
strcpy(groupB.name, "groupB");
|
||||
strcpy(groupC.name, "groupC");
|
||||
strcpy(groupD.name, "groupD");
|
||||
STRNCPY(groupA.name, "groupA");
|
||||
STRNCPY(groupB.name, "groupB");
|
||||
STRNCPY(groupC.name, "groupC");
|
||||
STRNCPY(groupD.name, "groupD");
|
||||
|
||||
BLI_addtail(&action.groups, &groupA);
|
||||
BLI_addtail(&action.groups, &groupB);
|
||||
|
|
|
@ -703,7 +703,7 @@ bool bone_autoside_name(
|
|||
{
|
||||
uint len;
|
||||
char basename[MAXBONENAME] = "";
|
||||
char extension[5] = "";
|
||||
const char *extension = NULL;
|
||||
|
||||
len = strlen(name);
|
||||
if (len == 0) {
|
||||
|
@ -723,18 +723,18 @@ bool bone_autoside_name(
|
|||
/* z-axis - vertical (top/bottom) */
|
||||
if (IS_EQF(head, 0.0f)) {
|
||||
if (tail < 0) {
|
||||
strcpy(extension, "Bot");
|
||||
extension = "Bot";
|
||||
}
|
||||
else if (tail > 0) {
|
||||
strcpy(extension, "Top");
|
||||
extension = "Top";
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (head < 0) {
|
||||
strcpy(extension, "Bot");
|
||||
extension = "Bot";
|
||||
}
|
||||
else {
|
||||
strcpy(extension, "Top");
|
||||
extension = "Top";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -742,18 +742,18 @@ bool bone_autoside_name(
|
|||
/* y-axis - depth (front/back) */
|
||||
if (IS_EQF(head, 0.0f)) {
|
||||
if (tail < 0) {
|
||||
strcpy(extension, "Fr");
|
||||
extension = "Fr";
|
||||
}
|
||||
else if (tail > 0) {
|
||||
strcpy(extension, "Bk");
|
||||
extension = "Bk";
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (head < 0) {
|
||||
strcpy(extension, "Fr");
|
||||
extension = "Fr";
|
||||
}
|
||||
else {
|
||||
strcpy(extension, "Bk");
|
||||
extension = "Bk";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -761,19 +761,19 @@ bool bone_autoside_name(
|
|||
/* x-axis - horizontal (left/right) */
|
||||
if (IS_EQF(head, 0.0f)) {
|
||||
if (tail < 0) {
|
||||
strcpy(extension, "R");
|
||||
extension = "R";
|
||||
}
|
||||
else if (tail > 0) {
|
||||
strcpy(extension, "L");
|
||||
extension = "L";
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (head < 0) {
|
||||
strcpy(extension, "R");
|
||||
extension = "R";
|
||||
/* XXX Shouldn't this be simple else, as for z and y axes? */
|
||||
}
|
||||
else if (head > 0) {
|
||||
strcpy(extension, "L");
|
||||
extension = "L";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -782,7 +782,7 @@ bool bone_autoside_name(
|
|||
* - truncate if there is an extension and it wouldn't be able to fit
|
||||
* - otherwise, just append to end
|
||||
*/
|
||||
if (extension[0]) {
|
||||
if (extension) {
|
||||
bool changed = true;
|
||||
|
||||
while (changed) { /* remove extensions */
|
||||
|
|
|
@ -355,9 +355,9 @@ class BKE_armature_find_selected_bones_test : public testing::Test {
|
|||
|
||||
void SetUp() override
|
||||
{
|
||||
strcpy(bone1.name, "bone1");
|
||||
strcpy(bone2.name, "bone2");
|
||||
strcpy(bone3.name, "bone3");
|
||||
STRNCPY(bone1.name, "bone1");
|
||||
STRNCPY(bone2.name, "bone2");
|
||||
STRNCPY(bone3.name, "bone3");
|
||||
|
||||
arm.bonebase = {nullptr, nullptr};
|
||||
bone1.childbase = {nullptr, nullptr};
|
||||
|
|
|
@ -147,7 +147,7 @@ void BKE_blender_globals_init(void)
|
|||
|
||||
BKE_blender_globals_main_replace(BKE_main_new());
|
||||
|
||||
strcpy(G.ima, "//");
|
||||
STRNCPY(G.ima, "//");
|
||||
|
||||
#ifndef WITH_PYTHON_SECURITY /* default */
|
||||
G.f |= G_FLAG_SCRIPT_AUTOEXEC;
|
||||
|
|
|
@ -219,11 +219,13 @@ static void setup_app_userdef(BlendFileData *bfd)
|
|||
}
|
||||
}
|
||||
|
||||
/** Helper struct to manage IDs that are re-used across blendfile loading (i.e. moved from the old
|
||||
* Main the the new one).
|
||||
/**
|
||||
* Helper struct to manage IDs that are re-used across blend-file loading (i.e. moved from the old
|
||||
* Main the new one).
|
||||
*
|
||||
* NOTE: this is only used when actually loading a real .blend file, loading of memfile undo steps
|
||||
* does not need it. */
|
||||
* NOTE: this is only used when actually loading a real `.blend` file,
|
||||
* loading of memfile undo steps does not need it.
|
||||
*/
|
||||
typedef struct ReuseOldBMainData {
|
||||
Main *new_bmain;
|
||||
Main *old_bmain;
|
||||
|
|
|
@ -1657,7 +1657,7 @@ BoidState *boid_new_state(BoidSettings *boids)
|
|||
SNPRINTF(state->name, "State %i", state->id);
|
||||
}
|
||||
else {
|
||||
strcpy(state->name, "State");
|
||||
STRNCPY(state->name, "State");
|
||||
}
|
||||
|
||||
state->rule_fuzziness = 0.5;
|
||||
|
|
|
@ -62,4 +62,30 @@ void NodeGroupComputeContext::print_current_in_line(std::ostream &stream) const
|
|||
stream << "Node ID: " << node_id_;
|
||||
}
|
||||
|
||||
SimulationZoneComputeContext::SimulationZoneComputeContext(const ComputeContext *parent,
|
||||
const int32_t output_node_id)
|
||||
: ComputeContext(s_static_type, parent), output_node_id_(output_node_id)
|
||||
{
|
||||
/* Mix static type and node id into a single buffer so that only a single call to #mix_in is
|
||||
* necessary. */
|
||||
const int type_size = strlen(s_static_type);
|
||||
const int buffer_size = type_size + 1 + sizeof(int32_t);
|
||||
DynamicStackBuffer<64, 8> buffer_owner(buffer_size, 8);
|
||||
char *buffer = static_cast<char *>(buffer_owner.buffer());
|
||||
memcpy(buffer, s_static_type, type_size + 1);
|
||||
memcpy(buffer + type_size + 1, &output_node_id_, sizeof(int32_t));
|
||||
hash_.mix_in(buffer, buffer_size);
|
||||
}
|
||||
|
||||
SimulationZoneComputeContext::SimulationZoneComputeContext(const ComputeContext *parent,
|
||||
const bNode &node)
|
||||
: SimulationZoneComputeContext(parent, node.identifier)
|
||||
{
|
||||
}
|
||||
|
||||
void SimulationZoneComputeContext::print_current_in_line(std::ostream &stream) const
|
||||
{
|
||||
stream << "Simulation Zone ID: " << output_node_id_;
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -99,7 +99,7 @@ static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *linese
|
|||
new_lineset->edge_types = lineset->edge_types;
|
||||
new_lineset->exclude_edge_types = lineset->exclude_edge_types;
|
||||
new_lineset->group = lineset->group;
|
||||
strcpy(new_lineset->name, lineset->name);
|
||||
STRNCPY(new_lineset->name, lineset->name);
|
||||
|
||||
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
|
||||
id_us_plus((ID *)new_lineset->linestyle);
|
||||
|
@ -187,7 +187,7 @@ FreestyleLineSet *BKE_freestyle_lineset_add(struct Main *bmain,
|
|||
SNPRINTF(lineset->name, "LineSet %i", lineset_index + 1);
|
||||
}
|
||||
else {
|
||||
strcpy(lineset->name, "LineSet");
|
||||
STRNCPY(lineset->name, "LineSet");
|
||||
}
|
||||
BKE_freestyle_lineset_unique_name(config, lineset);
|
||||
|
||||
|
|
|
@ -791,7 +791,7 @@ IDProperty *IDP_GetProperties(ID *id, const bool create_if_needed)
|
|||
/* NOTE(@ideasman42): Don't overwrite the data's name and type
|
||||
* some functions might need this if they
|
||||
* don't have a real ID, should be named elsewhere. */
|
||||
// strcpy(id->name, "top_level_group");
|
||||
// STRNCPY(id->name, "top_level_group");
|
||||
}
|
||||
return id->properties;
|
||||
}
|
||||
|
|
|
@ -1165,7 +1165,7 @@ static char *get_rna_access(ID *id,
|
|||
else if ((blocktype == ID_KE) && STREQ(actname, "Shape")) {
|
||||
/* Actionified "Shape" IPO's -
|
||||
* these are forced onto object level via the action container there... */
|
||||
strcpy(buf, "data.shape_keys");
|
||||
STRNCPY(buf, "data.shape_keys");
|
||||
}
|
||||
else {
|
||||
/* Pose-Channel */
|
||||
|
|
|
@ -40,7 +40,7 @@ static void test_lattice_deform_init(LatticeDeformTestContext *ctx,
|
|||
ctx->coords[index][2] = (rng->get_float() - 0.5f) * 10;
|
||||
}
|
||||
IDType_ID_LT.init_data(&ctx->lattice.id);
|
||||
strcpy(ctx->lattice.id.name, "LTLattice");
|
||||
STRNCPY(ctx->lattice.id.name, "LTLattice");
|
||||
IDType_ID_OB.init_data(&ctx->ob_lattice.id);
|
||||
ctx->ob_lattice.type = OB_LATTICE;
|
||||
ctx->ob_lattice.data = &ctx->lattice;
|
||||
|
|
|
@ -1620,7 +1620,7 @@ bool BKE_id_new_name_validate(
|
|||
|
||||
result = BKE_main_namemap_get_name(bmain, id, name);
|
||||
|
||||
strcpy(id->name + 2, name);
|
||||
BLI_strncpy(id->name + 2, name, sizeof(id->name) - 2);
|
||||
id_sort_by_name(lb, id, NULL);
|
||||
return result;
|
||||
}
|
||||
|
@ -2012,7 +2012,7 @@ void BKE_libblock_rename(Main *bmain, ID *id, const char *name)
|
|||
|
||||
void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const ID *id, char separator_char)
|
||||
{
|
||||
strcpy(name, id->name + 2);
|
||||
BLI_strncpy(name, id->name + 2, MAX_ID_FULL_NAME);
|
||||
|
||||
if (ID_IS_LINKED(id)) {
|
||||
const size_t idname_len = strlen(id->name + 2);
|
||||
|
@ -2020,7 +2020,7 @@ void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const ID *id, char separa
|
|||
|
||||
name[idname_len] = separator_char ? separator_char : ' ';
|
||||
name[idname_len + 1] = '[';
|
||||
strcpy(name + idname_len + 2, id->lib->id.name + 2);
|
||||
BLI_strncpy(name + idname_len + 2, id->lib->id.name + 2, MAX_ID_FULL_NAME - (idname_len + 2));
|
||||
name[idname_len + 2 + libname_len] = ']';
|
||||
name[idname_len + 2 + libname_len + 1] = '\0';
|
||||
}
|
||||
|
|
|
@ -336,12 +336,7 @@ MaskLayer *BKE_mask_layer_new(Mask *mask, const char *name)
|
|||
{
|
||||
MaskLayer *masklay = MEM_cnew<MaskLayer>(__func__);
|
||||
|
||||
if (name && name[0]) {
|
||||
STRNCPY(masklay->name, name);
|
||||
}
|
||||
else {
|
||||
strcpy(masklay->name, DATA_("MaskLayer"));
|
||||
}
|
||||
STRNCPY(masklay->name, name && name[0] ? name : DATA_("MaskLayer"));
|
||||
|
||||
BLI_addtail(&mask->masklayers, masklay);
|
||||
|
||||
|
@ -1011,12 +1006,7 @@ Mask *BKE_mask_new(Main *bmain, const char *name)
|
|||
Mask *mask;
|
||||
char mask_name[MAX_ID_NAME - 2];
|
||||
|
||||
if (name && name[0]) {
|
||||
STRNCPY(mask_name, name);
|
||||
}
|
||||
else {
|
||||
strcpy(mask_name, "Mask");
|
||||
}
|
||||
STRNCPY(mask_name, (name && name[0]) ? name : "Mask");
|
||||
|
||||
mask = mask_alloc(bmain, mask_name);
|
||||
|
||||
|
@ -2040,7 +2030,7 @@ void BKE_mask_clipboard_copy_from_layer(MaskLayer *mask_layer)
|
|||
if (!BLI_ghash_lookup(mask_clipboard.id_hash, point->parent.id)) {
|
||||
int len = strlen(point->parent.id->name);
|
||||
char *name_copy = static_cast<char *>(MEM_mallocN(len + 1, "mask clipboard ID name"));
|
||||
strcpy(name_copy, point->parent.id->name);
|
||||
memcpy(name_copy, point->parent.id->name, len + 1);
|
||||
BLI_ghash_insert(mask_clipboard.id_hash, point->parent.id, name_copy);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -432,15 +432,12 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
|||
mirrorj += result_polys[mirror_i].size() - (j - src_poly.start());
|
||||
}
|
||||
|
||||
const blender::float3 orig_normal = loop_normals[mirrorj];
|
||||
copy_v3_v3(loop_normals[mirrorj], loop_normals[j]);
|
||||
mul_m4_v3(mtx_nor, loop_normals[mirrorj]);
|
||||
|
||||
const int space_index = lnors_spacearr.corner_space_indices[mirrorj];
|
||||
blender::bke::mesh::lnor_space_custom_normal_to_data(&lnors_spacearr.spaces[space_index],
|
||||
orig_normal,
|
||||
loop_normals[mirrorj],
|
||||
clnors[mirrorj]);
|
||||
blender::bke::mesh::lnor_space_custom_normal_to_data(
|
||||
&lnors_spacearr.spaces[space_index], loop_normals[mirrorj], clnors[mirrorj]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -472,6 +472,8 @@ static void lnor_space_define(CornerNormalSpace *lnor_space,
|
|||
return;
|
||||
}
|
||||
|
||||
lnor_space->vec_lnor = lnor;
|
||||
|
||||
/* Compute ref alpha, average angle of all available edge vectors to lnor. */
|
||||
if (!edge_vectors.is_empty()) {
|
||||
float alpha = 0.0f;
|
||||
|
@ -526,7 +528,7 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space,
|
|||
using namespace blender::bke::mesh;
|
||||
CornerNormalSpace space{};
|
||||
lnor_space_define(&space, lnor, vec_ref, vec_other, edge_vectors);
|
||||
copy_v3_v3(lnor_space->vec_lnor, lnor);
|
||||
copy_v3_v3(lnor_space->vec_lnor, space.vec_lnor);
|
||||
copy_v3_v3(lnor_space->vec_ref, space.vec_ref);
|
||||
copy_v3_v3(lnor_space->vec_ortho, space.vec_ortho);
|
||||
lnor_space->ref_alpha = space.ref_alpha;
|
||||
|
@ -570,13 +572,12 @@ MINLINE short unit_float_to_short(const float val)
|
|||
|
||||
namespace blender::bke::mesh {
|
||||
static void lnor_space_custom_data_to_normal(const CornerNormalSpace *lnor_space,
|
||||
const float3 lnor_no_custom,
|
||||
const short clnor_data[2],
|
||||
float r_custom_lnor[3])
|
||||
{
|
||||
/* NOP custom normal data or invalid lnor space, return. */
|
||||
if (clnor_data[0] == 0 || lnor_space->ref_alpha == 0.0f || lnor_space->ref_beta == 0.0f) {
|
||||
copy_v3_v3(r_custom_lnor, lnor_no_custom);
|
||||
copy_v3_v3(r_custom_lnor, lnor_space->vec_lnor);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -589,7 +590,7 @@ static void lnor_space_custom_data_to_normal(const CornerNormalSpace *lnor_space
|
|||
alphafac;
|
||||
const float betafac = unit_short_to_float(clnor_data[1]);
|
||||
|
||||
mul_v3_v3fl(r_custom_lnor, lnor_no_custom, cosf(alpha));
|
||||
mul_v3_v3fl(r_custom_lnor, lnor_space->vec_lnor, cosf(alpha));
|
||||
|
||||
if (betafac == 0.0f) {
|
||||
madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ref, sinf(alpha));
|
||||
|
@ -611,29 +612,29 @@ void BKE_lnor_space_custom_data_to_normal(const MLoopNorSpace *lnor_space,
|
|||
{
|
||||
using namespace blender::bke::mesh;
|
||||
CornerNormalSpace space;
|
||||
space.vec_lnor = lnor_space->vec_lnor;
|
||||
space.vec_ref = lnor_space->vec_ref;
|
||||
space.vec_ortho = lnor_space->vec_ortho;
|
||||
space.ref_alpha = lnor_space->ref_alpha;
|
||||
space.ref_beta = lnor_space->ref_beta;
|
||||
lnor_space_custom_data_to_normal(&space, lnor_space->vec_lnor, clnor_data, r_custom_lnor);
|
||||
lnor_space_custom_data_to_normal(&space, clnor_data, r_custom_lnor);
|
||||
}
|
||||
|
||||
namespace blender::bke::mesh {
|
||||
void lnor_space_custom_normal_to_data(const CornerNormalSpace *lnor_space,
|
||||
const float3 lnor_no_custom,
|
||||
const float custom_lnor[3],
|
||||
short r_clnor_data[2])
|
||||
{
|
||||
/* We use nullptr vector as NOP custom normal (can be simpler than giving auto-computed `lnor`).
|
||||
*/
|
||||
if (is_zero_v3(custom_lnor) || compare_v3v3(lnor_no_custom, custom_lnor, 1e-4f)) {
|
||||
if (is_zero_v3(custom_lnor) || compare_v3v3(lnor_space->vec_lnor, custom_lnor, 1e-4f)) {
|
||||
r_clnor_data[0] = r_clnor_data[1] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
const float pi2 = float(M_PI * 2.0);
|
||||
const float cos_alpha = dot_v3v3(lnor_no_custom, custom_lnor);
|
||||
const float cos_alpha = dot_v3v3(lnor_space->vec_lnor, custom_lnor);
|
||||
float vec[3], cos_beta;
|
||||
float alpha;
|
||||
|
||||
|
@ -648,7 +649,7 @@ void lnor_space_custom_normal_to_data(const CornerNormalSpace *lnor_space,
|
|||
}
|
||||
|
||||
/* Project custom lnor on (vec_ref, vec_ortho) plane. */
|
||||
mul_v3_v3fl(vec, lnor_no_custom, -cos_alpha);
|
||||
mul_v3_v3fl(vec, lnor_space->vec_lnor, -cos_alpha);
|
||||
add_v3_v3(vec, custom_lnor);
|
||||
normalize_v3(vec);
|
||||
|
||||
|
@ -680,11 +681,12 @@ void BKE_lnor_space_custom_normal_to_data(const MLoopNorSpace *lnor_space,
|
|||
{
|
||||
using namespace blender::bke::mesh;
|
||||
CornerNormalSpace space;
|
||||
space.vec_lnor = lnor_space->vec_lnor;
|
||||
space.vec_ref = lnor_space->vec_ref;
|
||||
space.vec_ortho = lnor_space->vec_ortho;
|
||||
space.ref_alpha = lnor_space->ref_alpha;
|
||||
space.ref_beta = lnor_space->ref_beta;
|
||||
lnor_space_custom_normal_to_data(&space, lnor_space->vec_lnor, custom_lnor, r_clnor_data);
|
||||
lnor_space_custom_normal_to_data(&space, custom_lnor, r_clnor_data);
|
||||
}
|
||||
|
||||
namespace blender::bke::mesh {
|
||||
|
@ -901,10 +903,8 @@ static void lnor_space_for_single_fan(LoopSplitTaskDataCommon *common_data,
|
|||
lnors_spacearr->corner_space_indices[ml_curr_index] = space_index;
|
||||
|
||||
if (!clnors_data.is_empty()) {
|
||||
lnor_space_custom_data_to_normal(lnor_space,
|
||||
loop_normals[ml_curr_index],
|
||||
clnors_data[ml_curr_index],
|
||||
loop_normals[ml_curr_index]);
|
||||
lnor_space_custom_data_to_normal(
|
||||
lnor_space, clnors_data[ml_curr_index], loop_normals[ml_curr_index]);
|
||||
}
|
||||
|
||||
if (!lnors_spacearr->corners_by_space.is_empty()) {
|
||||
|
@ -1084,7 +1084,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
|||
/* Extra bonus: since small-stack is local to this function,
|
||||
* no more need to empty it at all cost! */
|
||||
|
||||
lnor_space_custom_data_to_normal(lnor_space, lnor, *clnor_ref, lnor);
|
||||
lnor_space_custom_data_to_normal(lnor_space, *clnor_ref, lnor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1600,8 +1600,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
float *nor = r_custom_loop_normals[nidx];
|
||||
|
||||
const int space_index = lnors_spacearr.corner_space_indices[i];
|
||||
lnor_space_custom_normal_to_data(
|
||||
&lnors_spacearr.spaces[space_index], loop_normals[i], nor, r_clnors_data[i]);
|
||||
lnor_space_custom_normal_to_data(&lnors_spacearr.spaces[space_index], nor, r_clnors_data[i]);
|
||||
done_loops[i].reset();
|
||||
}
|
||||
else {
|
||||
|
@ -1618,7 +1617,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
mul_v3_fl(avg_nor, 1.0f / float(fan_corners.size()));
|
||||
short2 clnor_data_tmp;
|
||||
lnor_space_custom_normal_to_data(
|
||||
&lnors_spacearr.spaces[space_index], loop_normals[i], avg_nor, clnor_data_tmp);
|
||||
&lnors_spacearr.spaces[space_index], avg_nor, clnor_data_tmp);
|
||||
|
||||
r_clnors_data.fill_indices(fan_corners, clnor_data_tmp);
|
||||
}
|
||||
|
|
|
@ -338,14 +338,16 @@ void BKE_mesh_calc_loop_tangent_step_0(const CustomData *loopData,
|
|||
*ract_uv_n = CustomData_get_active_layer(loopData, CD_PROP_FLOAT2);
|
||||
ract_uv_name[0] = 0;
|
||||
if (*ract_uv_n != -1) {
|
||||
strcpy(ract_uv_name, loopData->layers[*ract_uv_n + layer_index].name);
|
||||
BLI_strncpy(
|
||||
ract_uv_name, loopData->layers[*ract_uv_n + layer_index].name, MAX_CUSTOMDATA_LAYER_NAME);
|
||||
}
|
||||
|
||||
/* Active tangent in render */
|
||||
*rren_uv_n = CustomData_get_render_layer(loopData, CD_PROP_FLOAT2);
|
||||
rren_uv_name[0] = 0;
|
||||
if (*rren_uv_n != -1) {
|
||||
strcpy(rren_uv_name, loopData->layers[*rren_uv_n + layer_index].name);
|
||||
BLI_strncpy(
|
||||
rren_uv_name, loopData->layers[*rren_uv_n + layer_index].name, MAX_CUSTOMDATA_LAYER_NAME);
|
||||
}
|
||||
|
||||
/* If active tangent not in tangent_names we take it into account */
|
||||
|
|
|
@ -367,7 +367,7 @@ void BKE_nlatrack_insert_before(ListBase *nla_tracks,
|
|||
new_track->index = BLI_findindex(nla_tracks, new_track);
|
||||
|
||||
/* Must have unique name, but we need to seed this. */
|
||||
strcpy(new_track->name, "NlaTrack");
|
||||
STRNCPY(new_track->name, "NlaTrack");
|
||||
|
||||
BLI_uniquename(nla_tracks,
|
||||
new_track,
|
||||
|
|
|
@ -3653,9 +3653,6 @@ void ntreeLocalMerge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree)
|
|||
if (ntree->typeinfo->local_merge) {
|
||||
ntree->typeinfo->local_merge(bmain, localtree, ntree);
|
||||
}
|
||||
|
||||
ntreeFreeTree(localtree);
|
||||
MEM_freeN(localtree);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
#include "BLI_task.hh"
|
||||
#include "BLI_timeit.hh"
|
||||
|
||||
namespace blender::bke::node_tree_zones {
|
||||
namespace blender::bke {
|
||||
|
||||
static void update_zone_depths(TreeZone &zone)
|
||||
static void update_zone_depths(bNodeTreeZone &zone)
|
||||
{
|
||||
if (zone.depth >= 0) {
|
||||
return;
|
||||
|
@ -26,12 +26,14 @@ static void update_zone_depths(TreeZone &zone)
|
|||
zone.depth = zone.parent_zone->depth + 1;
|
||||
}
|
||||
|
||||
static Vector<std::unique_ptr<TreeZone>> find_zone_nodes(
|
||||
const bNodeTree &tree, TreeZones &owner, Map<const bNode *, TreeZone *> &r_zone_by_inout_node)
|
||||
static Vector<std::unique_ptr<bNodeTreeZone>> find_zone_nodes(
|
||||
const bNodeTree &tree,
|
||||
bNodeTreeZones &owner,
|
||||
Map<const bNode *, bNodeTreeZone *> &r_zone_by_inout_node)
|
||||
{
|
||||
Vector<std::unique_ptr<TreeZone>> zones;
|
||||
Vector<std::unique_ptr<bNodeTreeZone>> zones;
|
||||
for (const bNode *node : tree.nodes_by_type("GeometryNodeSimulationOutput")) {
|
||||
auto zone = std::make_unique<TreeZone>();
|
||||
auto zone = std::make_unique<bNodeTreeZone>();
|
||||
zone->owner = &owner;
|
||||
zone->index = zones.size();
|
||||
zone->output_node = node;
|
||||
|
@ -41,7 +43,7 @@ static Vector<std::unique_ptr<TreeZone>> find_zone_nodes(
|
|||
for (const bNode *node : tree.nodes_by_type("GeometryNodeSimulationInput")) {
|
||||
const auto &storage = *static_cast<NodeGeometrySimulationInput *>(node->storage);
|
||||
if (const bNode *sim_output_node = tree.node_by_id(storage.output_node_id)) {
|
||||
if (TreeZone *zone = r_zone_by_inout_node.lookup_default(sim_output_node, nullptr)) {
|
||||
if (bNodeTreeZone *zone = r_zone_by_inout_node.lookup_default(sim_output_node, nullptr)) {
|
||||
zone->input_node = node;
|
||||
r_zone_by_inout_node.add(node, zone);
|
||||
}
|
||||
|
@ -51,18 +53,18 @@ static Vector<std::unique_ptr<TreeZone>> find_zone_nodes(
|
|||
}
|
||||
|
||||
struct ZoneRelation {
|
||||
TreeZone *parent;
|
||||
TreeZone *child;
|
||||
bNodeTreeZone *parent;
|
||||
bNodeTreeZone *child;
|
||||
};
|
||||
|
||||
static Vector<ZoneRelation> get_direct_zone_relations(
|
||||
const Span<std::unique_ptr<TreeZone>> all_zones,
|
||||
const Span<std::unique_ptr<bNodeTreeZone>> all_zones,
|
||||
const BitGroupVector<> &depend_on_input_flag_array)
|
||||
{
|
||||
Vector<ZoneRelation> zone_relations;
|
||||
|
||||
/* Gather all relations, even the transitive once. */
|
||||
for (const std::unique_ptr<TreeZone> &zone : all_zones) {
|
||||
for (const std::unique_ptr<bNodeTreeZone> &zone : all_zones) {
|
||||
const int zone_i = zone->index;
|
||||
for (const bNode *node : {zone->output_node}) {
|
||||
if (node == nullptr) {
|
||||
|
@ -108,18 +110,18 @@ static Vector<ZoneRelation> get_direct_zone_relations(
|
|||
}
|
||||
|
||||
static void update_zone_per_node(const Span<const bNode *> all_nodes,
|
||||
const Span<std::unique_ptr<TreeZone>> all_zones,
|
||||
const Span<std::unique_ptr<bNodeTreeZone>> all_zones,
|
||||
const BitGroupVector<> &depend_on_input_flag_array,
|
||||
const Map<const bNode *, TreeZone *> &zone_by_inout_node,
|
||||
const Map<const bNode *, bNodeTreeZone *> &zone_by_inout_node,
|
||||
Map<int, int> &r_zone_by_node_id,
|
||||
Vector<const bNode *> &r_node_outside_zones)
|
||||
{
|
||||
for (const int node_i : all_nodes.index_range()) {
|
||||
const bNode &node = *all_nodes[node_i];
|
||||
const BoundedBitSpan depend_on_input_flags = depend_on_input_flag_array[node_i];
|
||||
TreeZone *parent_zone = nullptr;
|
||||
bNodeTreeZone *parent_zone = nullptr;
|
||||
bits::foreach_1_index(depend_on_input_flags, [&](const int parent_zone_i) {
|
||||
TreeZone *zone = all_zones[parent_zone_i].get();
|
||||
bNodeTreeZone *zone = all_zones[parent_zone_i].get();
|
||||
if (ELEM(&node, zone->input_node, zone->output_node)) {
|
||||
return;
|
||||
}
|
||||
|
@ -136,12 +138,12 @@ static void update_zone_per_node(const Span<const bNode *> all_nodes,
|
|||
r_zone_by_node_id.add(node.identifier, parent_zone->index);
|
||||
}
|
||||
}
|
||||
for (const MapItem<const bNode *, TreeZone *> item : zone_by_inout_node.items()) {
|
||||
for (const MapItem<const bNode *, bNodeTreeZone *> item : zone_by_inout_node.items()) {
|
||||
r_zone_by_node_id.add_overwrite(item.key->identifier, item.value->index);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_zone_border_links(const bNodeTree &tree, TreeZones &tree_zones)
|
||||
static void update_zone_border_links(const bNodeTree &tree, bNodeTreeZones &tree_zones)
|
||||
{
|
||||
for (const bNodeLink *link : tree.all_links()) {
|
||||
if (!link->is_available()) {
|
||||
|
@ -150,28 +152,30 @@ static void update_zone_border_links(const bNodeTree &tree, TreeZones &tree_zone
|
|||
if (link->is_muted()) {
|
||||
continue;
|
||||
}
|
||||
TreeZone *from_zone = const_cast<TreeZone *>(tree_zones.get_zone_by_socket(*link->fromsock));
|
||||
TreeZone *to_zone = const_cast<TreeZone *>(tree_zones.get_zone_by_socket(*link->tosock));
|
||||
bNodeTreeZone *from_zone = const_cast<bNodeTreeZone *>(
|
||||
tree_zones.get_zone_by_socket(*link->fromsock));
|
||||
bNodeTreeZone *to_zone = const_cast<bNodeTreeZone *>(
|
||||
tree_zones.get_zone_by_socket(*link->tosock));
|
||||
if (from_zone == to_zone) {
|
||||
continue;
|
||||
}
|
||||
BLI_assert(from_zone == nullptr || from_zone->contains_zone_recursively(*to_zone));
|
||||
for (TreeZone *zone = to_zone; zone != from_zone; zone = zone->parent_zone) {
|
||||
for (bNodeTreeZone *zone = to_zone; zone != from_zone; zone = zone->parent_zone) {
|
||||
zone->border_links.append(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::unique_ptr<TreeZones> discover_tree_zones(const bNodeTree &tree)
|
||||
static std::unique_ptr<bNodeTreeZones> discover_tree_zones(const bNodeTree &tree)
|
||||
{
|
||||
if (tree.has_available_link_cycle()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::unique_ptr<TreeZones> tree_zones = std::make_unique<TreeZones>();
|
||||
std::unique_ptr<bNodeTreeZones> tree_zones = std::make_unique<bNodeTreeZones>();
|
||||
|
||||
const Span<const bNode *> all_nodes = tree.all_nodes();
|
||||
Map<const bNode *, TreeZone *> zone_by_inout_node;
|
||||
Map<const bNode *, bNodeTreeZone *> zone_by_inout_node;
|
||||
tree_zones->zones = find_zone_nodes(tree, *tree_zones, zone_by_inout_node);
|
||||
|
||||
const int zones_num = tree_zones->zones.size();
|
||||
|
@ -203,13 +207,13 @@ static std::unique_ptr<TreeZones> discover_tree_zones(const bNodeTree &tree)
|
|||
}
|
||||
}
|
||||
if (node->type == GEO_NODE_SIMULATION_INPUT) {
|
||||
if (const TreeZone *zone = zone_by_inout_node.lookup_default(node, nullptr)) {
|
||||
if (const bNodeTreeZone *zone = zone_by_inout_node.lookup_default(node, nullptr)) {
|
||||
/* Now entering a zone, so set the corresponding bit. */
|
||||
depend_on_input_flags[zone->index].set();
|
||||
}
|
||||
}
|
||||
else if (node->type == GEO_NODE_SIMULATION_OUTPUT) {
|
||||
if (const TreeZone *zone = zone_by_inout_node.lookup_default(node, nullptr)) {
|
||||
if (const bNodeTreeZone *zone = zone_by_inout_node.lookup_default(node, nullptr)) {
|
||||
/* The output is implicitly linked to the input, so also propagate the bits from there. */
|
||||
if (const bNode *zone_input_node = zone->input_node) {
|
||||
const int input_node_i = zone_input_node->index();
|
||||
|
@ -239,11 +243,11 @@ static std::unique_ptr<TreeZones> discover_tree_zones(const bNodeTree &tree)
|
|||
}
|
||||
|
||||
/* Update depths. */
|
||||
for (std::unique_ptr<TreeZone> &zone : tree_zones->zones) {
|
||||
for (std::unique_ptr<bNodeTreeZone> &zone : tree_zones->zones) {
|
||||
update_zone_depths(*zone);
|
||||
}
|
||||
|
||||
for (std::unique_ptr<TreeZone> &zone : tree_zones->zones) {
|
||||
for (std::unique_ptr<bNodeTreeZone> &zone : tree_zones->zones) {
|
||||
if (zone->depth == 0) {
|
||||
tree_zones->root_zones.append(zone.get());
|
||||
}
|
||||
|
@ -262,7 +266,7 @@ static std::unique_ptr<TreeZones> discover_tree_zones(const bNodeTree &tree)
|
|||
if (zone_i == -1) {
|
||||
continue;
|
||||
}
|
||||
const TreeZone &zone = *tree_zones->zones[zone_i];
|
||||
const bNodeTreeZone &zone = *tree_zones->zones[zone_i];
|
||||
if (ELEM(node, zone.input_node, zone.output_node)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -274,21 +278,21 @@ static std::unique_ptr<TreeZones> discover_tree_zones(const bNodeTree &tree)
|
|||
return tree_zones;
|
||||
}
|
||||
|
||||
const TreeZones *get_tree_zones(const bNodeTree &tree)
|
||||
const bNodeTreeZones *get_tree_zones(const bNodeTree &tree)
|
||||
{
|
||||
tree.runtime->tree_zones_cache_mutex.ensure(
|
||||
[&]() { tree.runtime->tree_zones = discover_tree_zones(tree); });
|
||||
return tree.runtime->tree_zones.get();
|
||||
}
|
||||
|
||||
bool TreeZone::contains_node_recursively(const bNode &node) const
|
||||
bool bNodeTreeZone::contains_node_recursively(const bNode &node) const
|
||||
{
|
||||
const TreeZones *zones = this->owner;
|
||||
const bNodeTreeZones *zones = this->owner;
|
||||
const int zone_i = zones->zone_by_node_id.lookup_default(node.identifier, -1);
|
||||
if (zone_i == -1) {
|
||||
return false;
|
||||
}
|
||||
for (const TreeZone *zone = zones->zones[zone_i].get(); zone; zone = zone->parent_zone) {
|
||||
for (const bNodeTreeZone *zone = zones->zones[zone_i].get(); zone; zone = zone->parent_zone) {
|
||||
if (zone == this) {
|
||||
return true;
|
||||
}
|
||||
|
@ -296,9 +300,9 @@ bool TreeZone::contains_node_recursively(const bNode &node) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool TreeZone::contains_zone_recursively(const TreeZone &other_zone) const
|
||||
bool bNodeTreeZone::contains_zone_recursively(const bNodeTreeZone &other_zone) const
|
||||
{
|
||||
for (const TreeZone *zone = other_zone.parent_zone; zone; zone = zone->parent_zone) {
|
||||
for (const bNodeTreeZone *zone = other_zone.parent_zone; zone; zone = zone->parent_zone) {
|
||||
if (zone == this) {
|
||||
return true;
|
||||
}
|
||||
|
@ -306,25 +310,47 @@ bool TreeZone::contains_zone_recursively(const TreeZone &other_zone) const
|
|||
return false;
|
||||
}
|
||||
|
||||
const TreeZone *TreeZones::get_zone_by_socket(const bNodeSocket &socket) const
|
||||
const bNodeTreeZone *bNodeTreeZones::get_zone_by_socket(const bNodeSocket &socket) const
|
||||
{
|
||||
const bNode &node = socket.owner_node();
|
||||
const int zone_i = this->zone_by_node_id.lookup_default(node.identifier, -1);
|
||||
const bNodeTreeZone *zone = this->get_zone_by_node(node.identifier);
|
||||
if (zone == nullptr) {
|
||||
return zone;
|
||||
}
|
||||
if (zone->input_node == &node) {
|
||||
if (socket.is_input()) {
|
||||
return zone->parent_zone;
|
||||
}
|
||||
}
|
||||
if (zone->output_node == &node) {
|
||||
if (socket.is_output()) {
|
||||
return zone->parent_zone;
|
||||
}
|
||||
}
|
||||
return zone;
|
||||
}
|
||||
|
||||
const bNodeTreeZone *bNodeTreeZones::get_zone_by_node(const int32_t node_id) const
|
||||
{
|
||||
const int zone_i = this->zone_by_node_id.lookup_default(node_id, -1);
|
||||
if (zone_i == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
const TreeZone &zone = *this->zones[zone_i];
|
||||
if (zone.input_node == &node) {
|
||||
if (socket.is_input()) {
|
||||
return zone.parent_zone;
|
||||
}
|
||||
}
|
||||
if (zone.output_node == &node) {
|
||||
if (socket.is_output()) {
|
||||
return zone.parent_zone;
|
||||
}
|
||||
}
|
||||
return &zone;
|
||||
return this->zones[zone_i].get();
|
||||
}
|
||||
|
||||
} // namespace blender::bke::node_tree_zones
|
||||
Vector<const bNodeTreeZone *> bNodeTreeZones::get_zone_stack_for_node(const int node_id) const
|
||||
{
|
||||
const bNodeTreeZone *zone = this->get_zone_by_node(node_id);
|
||||
if (zone == nullptr) {
|
||||
return {};
|
||||
}
|
||||
Vector<const bNodeTreeZone *> zone_stack;
|
||||
for (; zone; zone = zone->parent_zone) {
|
||||
zone_stack.append(zone);
|
||||
}
|
||||
std::reverse(zone_stack.begin(), zone_stack.end());
|
||||
return zone_stack;
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -1424,14 +1424,15 @@ static int ptcache_filepath(PTCacheID *pid,
|
|||
idname = (pid->owner_id->name + 2);
|
||||
/* convert chars to hex so they are always a valid filename */
|
||||
while ('\0' != *idname) {
|
||||
BLI_snprintf(newname, MAX_PTCACHE_FILE - len, "%02X", (uint)(*idname++));
|
||||
newname += 2;
|
||||
len += 2;
|
||||
/* Always 2 unless there isn't enough room in the string. */
|
||||
const int temp = BLI_snprintf_rlen(
|
||||
newname, MAX_PTCACHE_FILE - len, "%02X", (uint)(*idname++));
|
||||
newname += temp;
|
||||
len += temp;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int temp = (int)strlen(pid->cache->name);
|
||||
strcpy(newname, pid->cache->name);
|
||||
int temp = BLI_strncpy_rlen(newname, pid->cache->name, MAX_PTCACHE_FILE - len);
|
||||
newname += temp;
|
||||
len += temp;
|
||||
}
|
||||
|
|
|
@ -462,8 +462,7 @@ bSound *BKE_sound_new_buffer(Main *bmain, bSound *source)
|
|||
bSound *sound = NULL;
|
||||
|
||||
char name[MAX_ID_NAME + 5];
|
||||
strcpy(name, "buf_");
|
||||
strcpy(name + 4, source->id.name);
|
||||
BLI_string_join(name, sizeof(name), "buf_", source->id.name);
|
||||
|
||||
sound = BKE_libblock_alloc(bmain, ID_SO, name);
|
||||
|
||||
|
@ -480,8 +479,7 @@ bSound *BKE_sound_new_limiter(Main *bmain, bSound *source, float start, float en
|
|||
bSound *sound = NULL;
|
||||
|
||||
char name[MAX_ID_NAME + 5];
|
||||
strcpy(name, "lim_");
|
||||
strcpy(name + 4, source->id.name);
|
||||
BLI_string_join(name, sizeof(name), "lim_", source->id.name);
|
||||
|
||||
sound = BKE_libblock_alloc(bmain, ID_SO, name);
|
||||
|
||||
|
|
|
@ -499,7 +499,7 @@ MovieTrackingTrack *BKE_tracking_track_add_empty(MovieTracking *tracking, ListBa
|
|||
const MovieTrackingSettings *settings = &tracking->settings;
|
||||
|
||||
MovieTrackingTrack *track = MEM_cnew<MovieTrackingTrack>("add_marker_exec track");
|
||||
strcpy(track->name, "Track");
|
||||
STRNCPY(track->name, "Track");
|
||||
|
||||
/* Fill track's settings from default settings. */
|
||||
track->motion_model = settings->default_motion_model;
|
||||
|
@ -1579,7 +1579,7 @@ MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(MovieTracking *tracking,
|
|||
plane_track = MEM_cnew<MovieTrackingPlaneTrack>("new plane track");
|
||||
|
||||
/* Use some default name. */
|
||||
strcpy(plane_track->name, "Plane Track");
|
||||
STRNCPY(plane_track->name, "Plane Track");
|
||||
|
||||
plane_track->image_opacity = 1.0f;
|
||||
|
||||
|
|
|
@ -295,7 +295,7 @@ static VFontData *vfont_get_data(VFont *vfont)
|
|||
/* DON'T DO THIS
|
||||
* missing file shouldn't modify path! - campbell */
|
||||
#if 0
|
||||
strcpy(vfont->filepath, FO_BUILTIN_NAME);
|
||||
STRNCPY(vfont->filepath, FO_BUILTIN_NAME);
|
||||
#endif
|
||||
pf = get_builtin_packedfile();
|
||||
}
|
||||
|
|
|
@ -73,13 +73,23 @@ void BKE_viewer_path_blend_write(BlendWriter *writer, const ViewerPath *viewer_p
|
|||
BLO_write_string(writer, typed_elem->modifier_name);
|
||||
break;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_NODE: {
|
||||
const auto *typed_elem = reinterpret_cast<NodeViewerPathElem *>(elem);
|
||||
BLO_write_struct(writer, NodeViewerPathElem, typed_elem);
|
||||
BLO_write_string(writer, typed_elem->node_name);
|
||||
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE: {
|
||||
const auto *typed_elem = reinterpret_cast<GroupNodeViewerPathElem *>(elem);
|
||||
BLO_write_struct(writer, GroupNodeViewerPathElem, typed_elem);
|
||||
break;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: {
|
||||
const auto *typed_elem = reinterpret_cast<SimulationZoneViewerPathElem *>(elem);
|
||||
BLO_write_struct(writer, SimulationZoneViewerPathElem, typed_elem);
|
||||
break;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: {
|
||||
const auto *typed_elem = reinterpret_cast<ViewerNodeViewerPathElem *>(elem);
|
||||
BLO_write_struct(writer, ViewerNodeViewerPathElem, typed_elem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
BLO_write_string(writer, elem->ui_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +97,11 @@ void BKE_viewer_path_blend_read_data(BlendDataReader *reader, ViewerPath *viewer
|
|||
{
|
||||
BLO_read_list(reader, &viewer_path->path);
|
||||
LISTBASE_FOREACH (ViewerPathElem *, elem, &viewer_path->path) {
|
||||
BLO_read_data_address(reader, &elem->ui_name);
|
||||
switch (ViewerPathElemType(elem->type)) {
|
||||
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE:
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_ID: {
|
||||
break;
|
||||
}
|
||||
|
@ -96,11 +110,6 @@ void BKE_viewer_path_blend_read_data(BlendDataReader *reader, ViewerPath *viewer
|
|||
BLO_read_data_address(reader, &typed_elem->modifier_name);
|
||||
break;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_NODE: {
|
||||
auto *typed_elem = reinterpret_cast<NodeViewerPathElem *>(elem);
|
||||
BLO_read_data_address(reader, &typed_elem->node_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +124,9 @@ void BKE_viewer_path_blend_read_lib(BlendLibReader *reader, ID *self_id, ViewerP
|
|||
break;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_MODIFIER:
|
||||
case VIEWER_PATH_ELEM_TYPE_NODE: {
|
||||
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE:
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +143,9 @@ void BKE_viewer_path_foreach_id(LibraryForeachIDData *data, ViewerPath *viewer_p
|
|||
break;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_MODIFIER:
|
||||
case VIEWER_PATH_ELEM_TYPE_NODE: {
|
||||
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE:
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -149,30 +162,39 @@ void BKE_viewer_path_id_remap(ViewerPath *viewer_path, const IDRemapper *mapping
|
|||
break;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_MODIFIER:
|
||||
case VIEWER_PATH_ELEM_TYPE_NODE: {
|
||||
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE:
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> static T *make_elem(const ViewerPathElemType type)
|
||||
{
|
||||
T *elem = MEM_cnew<T>(__func__);
|
||||
elem->base.type = type;
|
||||
return elem;
|
||||
}
|
||||
|
||||
ViewerPathElem *BKE_viewer_path_elem_new(const ViewerPathElemType type)
|
||||
{
|
||||
switch (type) {
|
||||
case VIEWER_PATH_ELEM_TYPE_ID: {
|
||||
IDViewerPathElem *elem = MEM_cnew<IDViewerPathElem>(__func__);
|
||||
elem->base.type = type;
|
||||
return &elem->base;
|
||||
return &make_elem<IDViewerPathElem>(type)->base;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_MODIFIER: {
|
||||
ModifierViewerPathElem *elem = MEM_cnew<ModifierViewerPathElem>(__func__);
|
||||
elem->base.type = type;
|
||||
return &elem->base;
|
||||
return &make_elem<ModifierViewerPathElem>(type)->base;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_NODE: {
|
||||
NodeViewerPathElem *elem = MEM_cnew<NodeViewerPathElem>(__func__);
|
||||
elem->base.type = type;
|
||||
return &elem->base;
|
||||
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE: {
|
||||
return &make_elem<GroupNodeViewerPathElem>(type)->base;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: {
|
||||
return &make_elem<SimulationZoneViewerPathElem>(type)->base;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: {
|
||||
return &make_elem<ViewerNodeViewerPathElem>(type)->base;
|
||||
}
|
||||
}
|
||||
BLI_assert_unreachable();
|
||||
|
@ -190,15 +212,30 @@ ModifierViewerPathElem *BKE_viewer_path_elem_new_modifier()
|
|||
BKE_viewer_path_elem_new(VIEWER_PATH_ELEM_TYPE_MODIFIER));
|
||||
}
|
||||
|
||||
NodeViewerPathElem *BKE_viewer_path_elem_new_node()
|
||||
GroupNodeViewerPathElem *BKE_viewer_path_elem_new_group_node()
|
||||
{
|
||||
return reinterpret_cast<NodeViewerPathElem *>(
|
||||
BKE_viewer_path_elem_new(VIEWER_PATH_ELEM_TYPE_NODE));
|
||||
return reinterpret_cast<GroupNodeViewerPathElem *>(
|
||||
BKE_viewer_path_elem_new(VIEWER_PATH_ELEM_TYPE_GROUP_NODE));
|
||||
}
|
||||
|
||||
SimulationZoneViewerPathElem *BKE_viewer_path_elem_new_simulation_zone()
|
||||
{
|
||||
return reinterpret_cast<SimulationZoneViewerPathElem *>(
|
||||
BKE_viewer_path_elem_new(VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE));
|
||||
}
|
||||
|
||||
ViewerNodeViewerPathElem *BKE_viewer_path_elem_new_viewer_node()
|
||||
{
|
||||
return reinterpret_cast<ViewerNodeViewerPathElem *>(
|
||||
BKE_viewer_path_elem_new(VIEWER_PATH_ELEM_TYPE_VIEWER_NODE));
|
||||
}
|
||||
|
||||
ViewerPathElem *BKE_viewer_path_elem_copy(const ViewerPathElem *src)
|
||||
{
|
||||
ViewerPathElem *dst = BKE_viewer_path_elem_new(ViewerPathElemType(src->type));
|
||||
if (src->ui_name) {
|
||||
dst->ui_name = BLI_strdup(src->ui_name);
|
||||
}
|
||||
switch (ViewerPathElemType(src->type)) {
|
||||
case VIEWER_PATH_ELEM_TYPE_ID: {
|
||||
const auto *old_elem = reinterpret_cast<const IDViewerPathElem *>(src);
|
||||
|
@ -214,13 +251,22 @@ ViewerPathElem *BKE_viewer_path_elem_copy(const ViewerPathElem *src)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_NODE: {
|
||||
const auto *old_elem = reinterpret_cast<const NodeViewerPathElem *>(src);
|
||||
auto *new_elem = reinterpret_cast<NodeViewerPathElem *>(dst);
|
||||
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE: {
|
||||
const auto *old_elem = reinterpret_cast<const GroupNodeViewerPathElem *>(src);
|
||||
auto *new_elem = reinterpret_cast<GroupNodeViewerPathElem *>(dst);
|
||||
new_elem->node_id = old_elem->node_id;
|
||||
break;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: {
|
||||
const auto *old_elem = reinterpret_cast<const SimulationZoneViewerPathElem *>(src);
|
||||
auto *new_elem = reinterpret_cast<SimulationZoneViewerPathElem *>(dst);
|
||||
new_elem->sim_output_node_id = old_elem->sim_output_node_id;
|
||||
break;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: {
|
||||
const auto *old_elem = reinterpret_cast<const ViewerNodeViewerPathElem *>(src);
|
||||
auto *new_elem = reinterpret_cast<ViewerNodeViewerPathElem *>(dst);
|
||||
new_elem->node_id = old_elem->node_id;
|
||||
if (old_elem->node_name != nullptr) {
|
||||
new_elem->node_name = BLI_strdup(old_elem->node_name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -243,9 +289,19 @@ bool BKE_viewer_path_elem_equal(const ViewerPathElem *a, const ViewerPathElem *b
|
|||
const auto *b_elem = reinterpret_cast<const ModifierViewerPathElem *>(b);
|
||||
return StringRef(a_elem->modifier_name) == StringRef(b_elem->modifier_name);
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_NODE: {
|
||||
const auto *a_elem = reinterpret_cast<const NodeViewerPathElem *>(a);
|
||||
const auto *b_elem = reinterpret_cast<const NodeViewerPathElem *>(b);
|
||||
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE: {
|
||||
const auto *a_elem = reinterpret_cast<const GroupNodeViewerPathElem *>(a);
|
||||
const auto *b_elem = reinterpret_cast<const GroupNodeViewerPathElem *>(b);
|
||||
return a_elem->node_id == b_elem->node_id;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: {
|
||||
const auto *a_elem = reinterpret_cast<const SimulationZoneViewerPathElem *>(a);
|
||||
const auto *b_elem = reinterpret_cast<const SimulationZoneViewerPathElem *>(b);
|
||||
return a_elem->sim_output_node_id == b_elem->sim_output_node_id;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: {
|
||||
const auto *a_elem = reinterpret_cast<const ViewerNodeViewerPathElem *>(a);
|
||||
const auto *b_elem = reinterpret_cast<const ViewerNodeViewerPathElem *>(b);
|
||||
return a_elem->node_id == b_elem->node_id;
|
||||
}
|
||||
}
|
||||
|
@ -255,7 +311,10 @@ bool BKE_viewer_path_elem_equal(const ViewerPathElem *a, const ViewerPathElem *b
|
|||
void BKE_viewer_path_elem_free(ViewerPathElem *elem)
|
||||
{
|
||||
switch (ViewerPathElemType(elem->type)) {
|
||||
case VIEWER_PATH_ELEM_TYPE_ID: {
|
||||
case VIEWER_PATH_ELEM_TYPE_ID:
|
||||
case VIEWER_PATH_ELEM_TYPE_GROUP_NODE:
|
||||
case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE:
|
||||
case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: {
|
||||
break;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_MODIFIER: {
|
||||
|
@ -263,11 +322,9 @@ void BKE_viewer_path_elem_free(ViewerPathElem *elem)
|
|||
MEM_SAFE_FREE(typed_elem->modifier_name);
|
||||
break;
|
||||
}
|
||||
case VIEWER_PATH_ELEM_TYPE_NODE: {
|
||||
auto *typed_elem = reinterpret_cast<NodeViewerPathElem *>(elem);
|
||||
MEM_SAFE_FREE(typed_elem->node_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (elem->ui_name) {
|
||||
MEM_freeN(elem->ui_name);
|
||||
}
|
||||
MEM_freeN(elem);
|
||||
}
|
||||
|
|
|
@ -83,7 +83,10 @@ static int append_avi(void *context_v,
|
|||
int recty,
|
||||
const char *suffix,
|
||||
ReportList *reports);
|
||||
static void filepath_avi(char *string, const RenderData *rd, bool preview, const char *suffix);
|
||||
static void filepath_avi(char filepath[FILE_MAX],
|
||||
const RenderData *rd,
|
||||
bool preview,
|
||||
const char *suffix);
|
||||
static void *context_create_avi(void);
|
||||
static void context_free_avi(void *context_v);
|
||||
#endif /* WITH_AVI */
|
||||
|
@ -141,7 +144,10 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
|
|||
|
||||
#ifdef WITH_AVI
|
||||
|
||||
static void filepath_avi(char *filepath, const RenderData *rd, bool preview, const char *suffix)
|
||||
static void filepath_avi(char filepath[FILE_MAX],
|
||||
const RenderData *rd,
|
||||
bool preview,
|
||||
const char *suffix)
|
||||
{
|
||||
int sfra, efra;
|
||||
|
||||
|
@ -158,7 +164,7 @@ static void filepath_avi(char *filepath, const RenderData *rd, bool preview, con
|
|||
efra = rd->efra;
|
||||
}
|
||||
|
||||
strcpy(filepath, rd->pic);
|
||||
BLI_strncpy(filepath, rd->pic, FILE_MAX);
|
||||
BLI_path_abs(filepath, BKE_main_blendfile_path_from_global());
|
||||
|
||||
BLI_file_ensure_parent_dir_exists(filepath);
|
||||
|
@ -188,13 +194,13 @@ static int start_avi(void *context_v,
|
|||
const char *suffix)
|
||||
{
|
||||
int x, y;
|
||||
char name[256];
|
||||
char filepath[FILE_MAX];
|
||||
AviFormat format;
|
||||
int quality;
|
||||
double framerate;
|
||||
AviMovie *avi = context_v;
|
||||
|
||||
filepath_avi(name, rd, preview, suffix);
|
||||
filepath_avi(filepath, rd, preview, suffix);
|
||||
|
||||
x = rectx;
|
||||
y = recty;
|
||||
|
@ -209,7 +215,7 @@ static int start_avi(void *context_v,
|
|||
format = AVI_FORMAT_MJPEG;
|
||||
}
|
||||
|
||||
if (AVI_open_compress(name, avi, 1, format) != AVI_ERROR_NONE) {
|
||||
if (AVI_open_compress(filepath, avi, 1, format) != AVI_ERROR_NONE) {
|
||||
BKE_report(reports, RPT_ERROR, "Cannot open or start AVI movie file");
|
||||
return 0;
|
||||
}
|
||||
|
@ -222,7 +228,7 @@ static int start_avi(void *context_v,
|
|||
avi->interlace = 0;
|
||||
avi->odd_fields = 0;
|
||||
|
||||
printf("Created avi: %s\n", name);
|
||||
printf("Created avi: %s\n", filepath);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -298,7 +304,10 @@ static void context_free_avi(void *context_v)
|
|||
|
||||
#endif /* WITH_AVI */
|
||||
|
||||
void BKE_movie_filepath_get(char *filepath, const RenderData *rd, bool preview, const char *suffix)
|
||||
void BKE_movie_filepath_get(char filepath[/*FILE_MAX*/ 1024],
|
||||
const RenderData *rd,
|
||||
bool preview,
|
||||
const char *suffix)
|
||||
{
|
||||
bMovieHandle *mh = BKE_movie_handle_get(rd->im_format.imtype);
|
||||
if (mh && mh->get_movie_path) {
|
||||
|
|
|
@ -1428,7 +1428,7 @@ static void ffmpeg_filepath_get(FFMpegContext *context,
|
|||
BLI_path_suffix(filepath, FILE_MAX, suffix, "");
|
||||
}
|
||||
|
||||
void BKE_ffmpeg_filepath_get(char *filepath,
|
||||
void BKE_ffmpeg_filepath_get(char filepath[/*FILE_MAX*/ 1024],
|
||||
const RenderData *rd,
|
||||
bool preview,
|
||||
const char *suffix)
|
||||
|
|
|
@ -599,7 +599,8 @@ template<typename T> class MutableSpan {
|
|||
|
||||
constexpr T &operator[](const int64_t index) const
|
||||
{
|
||||
BLI_assert(index < this->size());
|
||||
BLI_assert(index >= 0);
|
||||
BLI_assert(index < size_);
|
||||
return data_[index];
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
# include <dirent.h>
|
||||
#endif
|
||||
|
||||
#include <string.h> /* #strcpy etc. */
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
|
@ -320,7 +320,7 @@ void BLI_filelist_entry_owner_to_string(const struct stat *st,
|
|||
{
|
||||
#ifdef WIN32
|
||||
UNUSED_VARS(st);
|
||||
strcpy(r_owner, "unknown");
|
||||
BLI_strncpy(r_owner, "unknown", FILELIST_DIRENTRY_OWNER_LEN);
|
||||
#else
|
||||
struct passwd *pwuser = getpwuid(st->st_uid);
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ int BLI_path_sequence_decode(const char *path,
|
|||
if (head) {
|
||||
/* Name_end points to last character of head,
|
||||
* make it +1 so null-terminator is nicely placed. */
|
||||
BLI_strncpy(head, path, name_end + 1);
|
||||
BLI_strncpy(head, path, MIN2(head_maxncpy, name_end + 1));
|
||||
}
|
||||
if (r_digits_len) {
|
||||
*r_digits_len = 0;
|
||||
|
@ -196,8 +196,8 @@ static int path_normalize_impl(char *path, bool check_blend_relative_prefix)
|
|||
/* NOTE(@ideasman42):
|
||||
* `memmove(start, eind, strlen(eind) + 1);`
|
||||
* is the same as
|
||||
* `strcpy(start, eind);`
|
||||
* except `strcpy` should not be used because there is overlap,
|
||||
* `BLI_strncpy(start, eind, ...);`
|
||||
* except string-copy should not be used because there is overlap,
|
||||
* so use `memmove` 's slightly more obscure syntax. */
|
||||
|
||||
/* Inline replacement:
|
||||
|
@ -793,7 +793,7 @@ void BLI_path_rel(char path[FILE_MAX], const char *basepath)
|
|||
#ifdef WIN32
|
||||
BLI_str_replace_char(res + 2, '/', '\\');
|
||||
#endif
|
||||
strcpy(path, res);
|
||||
BLI_strncpy(path, res, FILE_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -825,10 +825,10 @@ bool BLI_rcti_clamp(rcti *rect, const rcti *rect_bounds, int r_xy[2])
|
|||
|
||||
bool BLI_rctf_compare(const rctf *rect_a, const rctf *rect_b, const float limit)
|
||||
{
|
||||
if (fabsf(rect_a->xmin - rect_b->xmin) < limit) {
|
||||
if (fabsf(rect_a->xmax - rect_b->xmax) < limit) {
|
||||
if (fabsf(rect_a->ymin - rect_b->ymin) < limit) {
|
||||
if (fabsf(rect_a->ymax - rect_b->ymax) < limit) {
|
||||
if (fabsf(rect_a->xmin - rect_b->xmin) <= limit) {
|
||||
if (fabsf(rect_a->xmax - rect_b->xmax) <= limit) {
|
||||
if (fabsf(rect_a->ymin - rect_b->ymin) <= limit) {
|
||||
if (fabsf(rect_a->ymax - rect_b->ymax) <= limit) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1086,9 +1086,8 @@ uint BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float n
|
|||
for (a = 0; a < poly; a++, pf++) {
|
||||
for (c = (ushort)(a + 1); c < poly; c++) {
|
||||
|
||||
/* if 'a' inside 'c': join (bbox too)
|
||||
* Careful: 'a' can also be inside another poly.
|
||||
*/
|
||||
/* If 'a' inside 'c': join (bounding-box too)
|
||||
* Careful: 'a' can also be inside another poly. */
|
||||
if (boundisect(pf, pflist + c)) {
|
||||
*pc = c;
|
||||
pc++;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h> /* `strcpy` etc. */
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
# include "BLI_string_utf8.h"
|
||||
|
@ -145,16 +145,17 @@ double BLI_dir_free_space(const char *dir)
|
|||
return -1;
|
||||
}
|
||||
|
||||
strcpy(dirname, dir);
|
||||
memcpy(dirname, dir, len + 1);
|
||||
|
||||
if (len) {
|
||||
slash = strrchr(dirname, '/');
|
||||
if (slash) {
|
||||
slash[1] = 0;
|
||||
slash[1] = '\0';
|
||||
}
|
||||
}
|
||||
else {
|
||||
strcpy(dirname, "/");
|
||||
dirname[0] = '/';
|
||||
dirname[1] = '\0';
|
||||
}
|
||||
|
||||
# if defined(USE_STATFS_STATVFS)
|
||||
|
|
|
@ -133,14 +133,14 @@ size_t BLI_string_flip_side_name(char *name_dst,
|
|||
BLI_string_debug_size(name_dst, name_dst_maxncpy);
|
||||
|
||||
size_t len;
|
||||
char *prefix = alloca(name_dst_maxncpy); /* The part before the facing */
|
||||
char *suffix = alloca(name_dst_maxncpy); /* The part after the facing */
|
||||
char *replace = alloca(name_dst_maxncpy); /* The replacement string */
|
||||
char *number = alloca(name_dst_maxncpy); /* The number extension string */
|
||||
char *prefix = alloca(name_dst_maxncpy); /* The part before the facing */
|
||||
char *suffix = alloca(name_dst_maxncpy); /* The part after the facing */
|
||||
char *number = alloca(name_dst_maxncpy); /* The number extension string */
|
||||
const char *replace = NULL;
|
||||
char *index = NULL;
|
||||
bool is_set = false;
|
||||
|
||||
*prefix = *suffix = *replace = *number = '\0';
|
||||
*prefix = *suffix = *number = '\0';
|
||||
|
||||
/* always copy the name, since this can be called with an uninitialized string */
|
||||
len = BLI_strncpy_rlen(name_dst, name_src, name_dst_maxncpy);
|
||||
|
@ -169,19 +169,19 @@ size_t BLI_string_flip_side_name(char *name_dst,
|
|||
switch (name_dst[len - 1]) {
|
||||
case 'l':
|
||||
prefix[len - 1] = 0;
|
||||
strcpy(replace, "r");
|
||||
replace = "r";
|
||||
break;
|
||||
case 'r':
|
||||
prefix[len - 1] = 0;
|
||||
strcpy(replace, "l");
|
||||
replace = "l";
|
||||
break;
|
||||
case 'L':
|
||||
prefix[len - 1] = 0;
|
||||
strcpy(replace, "R");
|
||||
replace = "R";
|
||||
break;
|
||||
case 'R':
|
||||
prefix[len - 1] = 0;
|
||||
strcpy(replace, "L");
|
||||
replace = "L";
|
||||
break;
|
||||
default:
|
||||
is_set = false;
|
||||
|
@ -193,22 +193,22 @@ size_t BLI_string_flip_side_name(char *name_dst,
|
|||
is_set = true;
|
||||
switch (name_dst[0]) {
|
||||
case 'l':
|
||||
strcpy(replace, "r");
|
||||
replace = "r";
|
||||
BLI_strncpy(suffix, name_dst + 1, name_dst_maxncpy);
|
||||
prefix[0] = 0;
|
||||
break;
|
||||
case 'r':
|
||||
strcpy(replace, "l");
|
||||
replace = "l";
|
||||
BLI_strncpy(suffix, name_dst + 1, name_dst_maxncpy);
|
||||
prefix[0] = 0;
|
||||
break;
|
||||
case 'L':
|
||||
strcpy(replace, "R");
|
||||
replace = "R";
|
||||
BLI_strncpy(suffix, name_dst + 1, name_dst_maxncpy);
|
||||
prefix[0] = 0;
|
||||
break;
|
||||
case 'R':
|
||||
strcpy(replace, "L");
|
||||
replace = "L";
|
||||
BLI_strncpy(suffix, name_dst + 1, name_dst_maxncpy);
|
||||
prefix[0] = 0;
|
||||
break;
|
||||
|
@ -222,10 +222,10 @@ size_t BLI_string_flip_side_name(char *name_dst,
|
|||
if (((index = BLI_strcasestr(prefix, "right")) == prefix) || (index == prefix + len - 5)) {
|
||||
is_set = true;
|
||||
if (index[0] == 'r') {
|
||||
strcpy(replace, "left");
|
||||
replace = "left";
|
||||
}
|
||||
else {
|
||||
strcpy(replace, (index[1] == 'I') ? "LEFT" : "Left");
|
||||
replace = (index[1] == 'I' ? "LEFT" : "Left");
|
||||
}
|
||||
*index = 0;
|
||||
BLI_strncpy(suffix, index + 5, name_dst_maxncpy);
|
||||
|
@ -233,10 +233,10 @@ size_t BLI_string_flip_side_name(char *name_dst,
|
|||
else if (((index = BLI_strcasestr(prefix, "left")) == prefix) || (index == prefix + len - 4)) {
|
||||
is_set = true;
|
||||
if (index[0] == 'l') {
|
||||
strcpy(replace, "right");
|
||||
replace = "right";
|
||||
}
|
||||
else {
|
||||
strcpy(replace, (index[1] == 'E') ? "RIGHT" : "Right");
|
||||
replace = (index[1] == 'E' ? "RIGHT" : "Right");
|
||||
}
|
||||
*index = 0;
|
||||
BLI_strncpy(suffix, index + 4, name_dst_maxncpy);
|
||||
|
@ -244,7 +244,7 @@ size_t BLI_string_flip_side_name(char *name_dst,
|
|||
}
|
||||
|
||||
return BLI_snprintf_rlen(
|
||||
name_dst, name_dst_maxncpy, "%s%s%s%s", prefix, replace, suffix, number);
|
||||
name_dst, name_dst_maxncpy, "%s%s%s%s", prefix, replace ? replace : "", suffix, number);
|
||||
}
|
||||
|
||||
/* Unique name utils. */
|
||||
|
|
|
@ -204,6 +204,8 @@ void BLO_blendfiledata_free(BlendFileData *bfd);
|
|||
typedef struct BLODataBlockInfo {
|
||||
char name[64]; /* MAX_NAME */
|
||||
struct AssetMetaData *asset_data;
|
||||
/** Ownership over #asset_data above can be "stolen out" of this struct, for more permanent
|
||||
* storage. In that case, set this to false to avoid double freeing of the stolen data. */
|
||||
bool free_asset_data;
|
||||
/**
|
||||
* Optimization: Tag data-blocks for which we know there is no preview.
|
||||
|
|
|
@ -716,7 +716,7 @@ void blo_do_versions_250(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
*/
|
||||
for (ma = bmain->materials.first; ma; ma = ma->id.next) {
|
||||
if (ma->nodetree && ma->nodetree->id.name[0] == '\0') {
|
||||
strcpy(ma->nodetree->id.name, "NTShader Nodetree");
|
||||
STRNCPY(ma->nodetree->id.name, "NTShader Nodetree");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -724,7 +724,7 @@ void blo_do_versions_250(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
for (sce = bmain->scenes.first; sce; sce = sce->id.next) {
|
||||
enum { R_PANORAMA = (1 << 10) };
|
||||
if (sce->nodetree && sce->nodetree->id.name[0] == '\0') {
|
||||
strcpy(sce->nodetree->id.name, "NTCompositing Nodetree");
|
||||
STRNCPY(sce->nodetree->id.name, "NTCompositing Nodetree");
|
||||
}
|
||||
|
||||
/* move to cameras */
|
||||
|
@ -748,7 +748,7 @@ void blo_do_versions_250(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
|
||||
if (tx->nodetree) {
|
||||
if (tx->nodetree->id.name[0] == '\0') {
|
||||
strcpy(tx->nodetree->id.name, "NTTexture Nodetree");
|
||||
STRNCPY(tx->nodetree->id.name, "NTTexture Nodetree");
|
||||
}
|
||||
|
||||
/* which_output 0 is now "not specified" */
|
||||
|
@ -2315,7 +2315,7 @@ static void lib_node_do_versions_group_indices(bNode *gnode)
|
|||
|
||||
for (link = ngroup->links.first; link; link = link->next) {
|
||||
if (link->tonode == NULL && link->fromsock->own_index == old_index) {
|
||||
strcpy(sock->identifier, link->fromsock->identifier);
|
||||
STRNCPY(sock->identifier, link->fromsock->identifier);
|
||||
/* deprecated */
|
||||
sock->own_index = link->fromsock->own_index;
|
||||
sock->to_index = 0;
|
||||
|
@ -2327,7 +2327,7 @@ static void lib_node_do_versions_group_indices(bNode *gnode)
|
|||
|
||||
for (link = ngroup->links.first; link; link = link->next) {
|
||||
if (link->fromnode == NULL && link->tosock->own_index == old_index) {
|
||||
strcpy(sock->identifier, link->tosock->identifier);
|
||||
STRNCPY(sock->identifier, link->tosock->identifier);
|
||||
/* deprecated */
|
||||
sock->own_index = link->tosock->own_index;
|
||||
sock->to_index = 0;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1363,7 +1363,7 @@ static void version_switch_node_input_prefix(Main *bmain)
|
|||
if (socket == node->inputs.first) {
|
||||
continue;
|
||||
}
|
||||
strcpy(socket->name, socket->name[0] == 'A' ? "False" : "True");
|
||||
STRNCPY(socket->name, socket->name[0] == 'A' ? "False" : "True");
|
||||
|
||||
/* Replace "A" and "B", but keep the unique number suffix at the end. */
|
||||
char number_suffix[8];
|
||||
|
@ -1940,7 +1940,7 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
|
|||
NodeCombSepColor *storage = (NodeCombSepColor *)MEM_callocN(sizeof(NodeCombSepColor),
|
||||
__func__);
|
||||
storage->mode = NODE_COMBSEP_COLOR_RGB;
|
||||
strcpy(node->idname, "FunctionNodeCombineColor");
|
||||
STRNCPY(node->idname, "FunctionNodeCombineColor");
|
||||
node->storage = storage;
|
||||
break;
|
||||
}
|
||||
|
@ -1949,7 +1949,7 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
|
|||
NodeCombSepColor *storage = (NodeCombSepColor *)MEM_callocN(sizeof(NodeCombSepColor),
|
||||
__func__);
|
||||
storage->mode = NODE_COMBSEP_COLOR_RGB;
|
||||
strcpy(node->idname, "FunctionNodeSeparateColor");
|
||||
STRNCPY(node->idname, "FunctionNodeSeparateColor");
|
||||
node->storage = storage;
|
||||
break;
|
||||
}
|
||||
|
@ -2007,7 +2007,7 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
|
|||
NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)MEM_callocN(
|
||||
sizeof(NodeCMPCombSepColor), __func__);
|
||||
storage->mode = CMP_NODE_COMBSEP_COLOR_RGB;
|
||||
strcpy(node->idname, "CompositorNodeCombineColor");
|
||||
STRNCPY(node->idname, "CompositorNodeCombineColor");
|
||||
node->storage = storage;
|
||||
break;
|
||||
}
|
||||
|
@ -2016,7 +2016,7 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
|
|||
NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)MEM_callocN(
|
||||
sizeof(NodeCMPCombSepColor), __func__);
|
||||
storage->mode = CMP_NODE_COMBSEP_COLOR_HSV;
|
||||
strcpy(node->idname, "CompositorNodeCombineColor");
|
||||
STRNCPY(node->idname, "CompositorNodeCombineColor");
|
||||
node->storage = storage;
|
||||
break;
|
||||
}
|
||||
|
@ -2026,7 +2026,7 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
|
|||
sizeof(NodeCMPCombSepColor), __func__);
|
||||
storage->mode = CMP_NODE_COMBSEP_COLOR_YCC;
|
||||
storage->ycc_mode = node->custom1;
|
||||
strcpy(node->idname, "CompositorNodeCombineColor");
|
||||
STRNCPY(node->idname, "CompositorNodeCombineColor");
|
||||
node->storage = storage;
|
||||
break;
|
||||
}
|
||||
|
@ -2035,7 +2035,7 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
|
|||
NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)MEM_callocN(
|
||||
sizeof(NodeCMPCombSepColor), __func__);
|
||||
storage->mode = CMP_NODE_COMBSEP_COLOR_YUV;
|
||||
strcpy(node->idname, "CompositorNodeCombineColor");
|
||||
STRNCPY(node->idname, "CompositorNodeCombineColor");
|
||||
node->storage = storage;
|
||||
break;
|
||||
}
|
||||
|
@ -2044,7 +2044,7 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
|
|||
NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)MEM_callocN(
|
||||
sizeof(NodeCMPCombSepColor), __func__);
|
||||
storage->mode = CMP_NODE_COMBSEP_COLOR_RGB;
|
||||
strcpy(node->idname, "CompositorNodeSeparateColor");
|
||||
STRNCPY(node->idname, "CompositorNodeSeparateColor");
|
||||
node->storage = storage;
|
||||
break;
|
||||
}
|
||||
|
@ -2053,7 +2053,7 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
|
|||
NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)MEM_callocN(
|
||||
sizeof(NodeCMPCombSepColor), __func__);
|
||||
storage->mode = CMP_NODE_COMBSEP_COLOR_HSV;
|
||||
strcpy(node->idname, "CompositorNodeSeparateColor");
|
||||
STRNCPY(node->idname, "CompositorNodeSeparateColor");
|
||||
node->storage = storage;
|
||||
break;
|
||||
}
|
||||
|
@ -2063,7 +2063,7 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
|
|||
sizeof(NodeCMPCombSepColor), __func__);
|
||||
storage->mode = CMP_NODE_COMBSEP_COLOR_YCC;
|
||||
storage->ycc_mode = node->custom1;
|
||||
strcpy(node->idname, "CompositorNodeSeparateColor");
|
||||
STRNCPY(node->idname, "CompositorNodeSeparateColor");
|
||||
node->storage = storage;
|
||||
break;
|
||||
}
|
||||
|
@ -2072,7 +2072,7 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
|
|||
NodeCMPCombSepColor *storage = (NodeCMPCombSepColor *)MEM_callocN(
|
||||
sizeof(NodeCMPCombSepColor), __func__);
|
||||
storage->mode = CMP_NODE_COMBSEP_COLOR_YUV;
|
||||
strcpy(node->idname, "CompositorNodeSeparateColor");
|
||||
STRNCPY(node->idname, "CompositorNodeSeparateColor");
|
||||
node->storage = storage;
|
||||
break;
|
||||
}
|
||||
|
@ -2087,13 +2087,13 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
|
|||
case TEX_NODE_COMPOSE_LEGACY: {
|
||||
node->type = TEX_NODE_COMBINE_COLOR;
|
||||
node->custom1 = NODE_COMBSEP_COLOR_RGB;
|
||||
strcpy(node->idname, "TextureNodeCombineColor");
|
||||
STRNCPY(node->idname, "TextureNodeCombineColor");
|
||||
break;
|
||||
}
|
||||
case TEX_NODE_DECOMPOSE_LEGACY: {
|
||||
node->type = TEX_NODE_SEPARATE_COLOR;
|
||||
node->custom1 = NODE_COMBSEP_COLOR_RGB;
|
||||
strcpy(node->idname, "TextureNodeSeparateColor");
|
||||
STRNCPY(node->idname, "TextureNodeSeparateColor");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2127,7 +2127,7 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
|
|||
NodeCombSepColor *storage = (NodeCombSepColor *)MEM_callocN(sizeof(NodeCombSepColor),
|
||||
__func__);
|
||||
storage->mode = NODE_COMBSEP_COLOR_RGB;
|
||||
strcpy(node->idname, "ShaderNodeCombineColor");
|
||||
STRNCPY(node->idname, "ShaderNodeCombineColor");
|
||||
node->storage = storage;
|
||||
break;
|
||||
}
|
||||
|
@ -2136,7 +2136,7 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
|
|||
NodeCombSepColor *storage = (NodeCombSepColor *)MEM_callocN(sizeof(NodeCombSepColor),
|
||||
__func__);
|
||||
storage->mode = NODE_COMBSEP_COLOR_HSV;
|
||||
strcpy(node->idname, "ShaderNodeCombineColor");
|
||||
STRNCPY(node->idname, "ShaderNodeCombineColor");
|
||||
node->storage = storage;
|
||||
break;
|
||||
}
|
||||
|
@ -2145,7 +2145,7 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
|
|||
NodeCombSepColor *storage = (NodeCombSepColor *)MEM_callocN(sizeof(NodeCombSepColor),
|
||||
__func__);
|
||||
storage->mode = NODE_COMBSEP_COLOR_RGB;
|
||||
strcpy(node->idname, "ShaderNodeSeparateColor");
|
||||
STRNCPY(node->idname, "ShaderNodeSeparateColor");
|
||||
node->storage = storage;
|
||||
break;
|
||||
}
|
||||
|
@ -2154,7 +2154,7 @@ static void versioning_replace_legacy_combined_and_separate_color_nodes(bNodeTre
|
|||
NodeCombSepColor *storage = (NodeCombSepColor *)MEM_callocN(sizeof(NodeCombSepColor),
|
||||
__func__);
|
||||
storage->mode = NODE_COMBSEP_COLOR_HSV;
|
||||
strcpy(node->idname, "ShaderNodeSeparateColor");
|
||||
STRNCPY(node->idname, "ShaderNodeSeparateColor");
|
||||
node->storage = storage;
|
||||
break;
|
||||
}
|
||||
|
@ -2171,7 +2171,7 @@ static void versioning_replace_legacy_mix_rgb_node(bNodeTree *ntree)
|
|||
version_node_output_socket_name(ntree, SH_NODE_MIX_RGB_LEGACY, "Color", "Result_Color");
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type == SH_NODE_MIX_RGB_LEGACY) {
|
||||
strcpy(node->idname, "ShaderNodeMix");
|
||||
STRNCPY(node->idname, "ShaderNodeMix");
|
||||
node->type = SH_NODE_MIX;
|
||||
NodeShaderMix *data = (NodeShaderMix *)MEM_callocN(sizeof(NodeShaderMix), __func__);
|
||||
data->blend_type = node->custom1;
|
||||
|
@ -2570,7 +2570,7 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
if (ntree->type == NTREE_GEOMETRY) {
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type == GEO_NODE_SUBDIVIDE_MESH) {
|
||||
strcpy(node->idname, "GeometryNodeMeshSubdivide");
|
||||
STRNCPY(node->idname, "GeometryNodeMeshSubdivide");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3266,7 +3266,7 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
sizeof(NodeFunctionCompare), __func__);
|
||||
data->data_type = SOCK_FLOAT;
|
||||
data->operation = node->custom1;
|
||||
strcpy(node->idname, "FunctionNodeCompare");
|
||||
STRNCPY(node->idname, "FunctionNodeCompare");
|
||||
node->storage = data;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ static void versioning_replace_legacy_glossy_node(bNodeTree *ntree)
|
|||
{
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type == SH_NODE_BSDF_GLOSSY_LEGACY) {
|
||||
strcpy(node->idname, "ShaderNodeBsdfAnisotropic");
|
||||
STRNCPY(node->idname, "ShaderNodeBsdfAnisotropic");
|
||||
node->type = SH_NODE_BSDF_GLOSSY;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ void version_node_id(bNodeTree *ntree, const int node_type, const char *new_name
|
|||
for (bNode *node : ntree->all_nodes()) {
|
||||
if (node->type == node_type) {
|
||||
if (!STREQ(node->idname, new_name)) {
|
||||
strcpy(node->idname, new_name);
|
||||
STRNCPY(node->idname, new_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1040,8 +1040,8 @@ static void update_voronoi_node_fac_output(bNodeTree *ntree)
|
|||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type == SH_NODE_TEX_VORONOI) {
|
||||
bNodeSocket *facOutput = BLI_findlink(&node->outputs, 1);
|
||||
strcpy(facOutput->identifier, "Distance");
|
||||
strcpy(facOutput->name, "Distance");
|
||||
STRNCPY(facOutput->identifier, "Distance");
|
||||
STRNCPY(facOutput->name, "Distance");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -324,7 +324,7 @@ static void customdata_version_242(Mesh *me)
|
|||
if (layer->type == CD_MTFACE) {
|
||||
if (layer->name[0] == 0) {
|
||||
if (mtfacen == 0) {
|
||||
strcpy(layer->name, "UVMap");
|
||||
STRNCPY(layer->name, "UVMap");
|
||||
}
|
||||
else {
|
||||
SNPRINTF(layer->name, "UVMap.%.3d", mtfacen);
|
||||
|
@ -335,7 +335,7 @@ static void customdata_version_242(Mesh *me)
|
|||
else if (layer->type == CD_MCOL) {
|
||||
if (layer->name[0] == 0) {
|
||||
if (mcoln == 0) {
|
||||
strcpy(layer->name, "Col");
|
||||
STRNCPY(layer->name, "Col");
|
||||
}
|
||||
else {
|
||||
SNPRINTF(layer->name, "Col.%.3d", mcoln);
|
||||
|
@ -843,7 +843,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
|
|||
VFont *vf;
|
||||
for (vf = bmain->fonts.first; vf; vf = vf->id.next) {
|
||||
if (BLI_str_endswith(vf->filepath, ".Bfont")) {
|
||||
strcpy(vf->filepath, FO_BUILTIN_NAME);
|
||||
STRNCPY(vf->filepath, FO_BUILTIN_NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1476,7 +1476,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
|
|||
for (kb = key->block.first; kb; kb = kb->next) {
|
||||
if (kb == key->refkey) {
|
||||
if (kb->name[0] == 0) {
|
||||
strcpy(kb->name, "Basis");
|
||||
STRNCPY(kb->name, "Basis");
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1611,8 +1611,8 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
|
|||
Image *ima;
|
||||
for (ima = bmain->images.first; ima; ima = ima->id.next) {
|
||||
if (STREQ(ima->filepath, "Compositor")) {
|
||||
strcpy(ima->id.name + 2, "Viewer Node");
|
||||
strcpy(ima->filepath, "Viewer Node");
|
||||
BLI_strncpy(ima->id.name + 2, "Viewer Node", sizeof(ima->id.name) - 2);
|
||||
STRNCPY(ima->filepath, "Viewer Node");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -237,7 +237,7 @@ void blo_do_versions_userdef(UserDef *userdef)
|
|||
}
|
||||
|
||||
if (!USER_VERSION_ATLEAST(192, 0)) {
|
||||
strcpy(userdef->sounddir, "/");
|
||||
STRNCPY(userdef->sounddir, "/");
|
||||
}
|
||||
|
||||
/* patch to set Dupli Armature */
|
||||
|
@ -311,52 +311,52 @@ void blo_do_versions_userdef(UserDef *userdef)
|
|||
|
||||
for (km = userdef->user_keymaps.first; km; km = km->next) {
|
||||
if (STREQ(km->idname, "Armature_Sketch")) {
|
||||
strcpy(km->idname, "Armature Sketch");
|
||||
STRNCPY(km->idname, "Armature Sketch");
|
||||
}
|
||||
else if (STREQ(km->idname, "View3D")) {
|
||||
strcpy(km->idname, "3D View");
|
||||
STRNCPY(km->idname, "3D View");
|
||||
}
|
||||
else if (STREQ(km->idname, "View3D Generic")) {
|
||||
strcpy(km->idname, "3D View Generic");
|
||||
STRNCPY(km->idname, "3D View Generic");
|
||||
}
|
||||
else if (STREQ(km->idname, "EditMesh")) {
|
||||
strcpy(km->idname, "Mesh");
|
||||
STRNCPY(km->idname, "Mesh");
|
||||
}
|
||||
else if (STREQ(km->idname, "UVEdit")) {
|
||||
strcpy(km->idname, "UV Editor");
|
||||
STRNCPY(km->idname, "UV Editor");
|
||||
}
|
||||
else if (STREQ(km->idname, "Animation_Channels")) {
|
||||
strcpy(km->idname, "Animation Channels");
|
||||
STRNCPY(km->idname, "Animation Channels");
|
||||
}
|
||||
else if (STREQ(km->idname, "GraphEdit Keys")) {
|
||||
strcpy(km->idname, "Graph Editor");
|
||||
STRNCPY(km->idname, "Graph Editor");
|
||||
}
|
||||
else if (STREQ(km->idname, "GraphEdit Generic")) {
|
||||
strcpy(km->idname, "Graph Editor Generic");
|
||||
STRNCPY(km->idname, "Graph Editor Generic");
|
||||
}
|
||||
else if (STREQ(km->idname, "Action_Keys")) {
|
||||
strcpy(km->idname, "Dopesheet");
|
||||
STRNCPY(km->idname, "Dopesheet");
|
||||
}
|
||||
else if (STREQ(km->idname, "NLA Data")) {
|
||||
strcpy(km->idname, "NLA Editor");
|
||||
STRNCPY(km->idname, "NLA Editor");
|
||||
}
|
||||
else if (STREQ(km->idname, "Node Generic")) {
|
||||
strcpy(km->idname, "Node Editor");
|
||||
STRNCPY(km->idname, "Node Editor");
|
||||
}
|
||||
else if (STREQ(km->idname, "Logic Generic")) {
|
||||
strcpy(km->idname, "Logic Editor");
|
||||
STRNCPY(km->idname, "Logic Editor");
|
||||
}
|
||||
else if (STREQ(km->idname, "File")) {
|
||||
strcpy(km->idname, "File Browser");
|
||||
STRNCPY(km->idname, "File Browser");
|
||||
}
|
||||
else if (STREQ(km->idname, "FileMain")) {
|
||||
strcpy(km->idname, "File Browser Main");
|
||||
STRNCPY(km->idname, "File Browser Main");
|
||||
}
|
||||
else if (STREQ(km->idname, "FileButtons")) {
|
||||
strcpy(km->idname, "File Browser Buttons");
|
||||
STRNCPY(km->idname, "File Browser Buttons");
|
||||
}
|
||||
else if (STREQ(km->idname, "Buttons Generic")) {
|
||||
strcpy(km->idname, "Property Editor");
|
||||
STRNCPY(km->idname, "Property Editor");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,8 +54,8 @@
|
|||
* - write #BLO_CODE_GLOB (#FileGlobal struct) (some global vars).
|
||||
* - write #BLO_CODE_DNA1 (#SDNA struct)
|
||||
* - write #BLO_CODE_USER (#UserDef struct) for file paths:
|
||||
- #BLENDER_STARTUP_FILE (on UNIX `~/.config/blender/X.X/config/startup.blend`).
|
||||
- #BLENDER_USERPREF_FILE (on UNIX `~/.config/blender/X.X/config/userpref.blend`).
|
||||
* - #BLENDER_STARTUP_FILE (on UNIX `~/.config/blender/X.X/config/startup.blend`).
|
||||
* - #BLENDER_USERPREF_FILE (on UNIX `~/.config/blender/X.X/config/userpref.blend`).
|
||||
*/
|
||||
|
||||
#include <cerrno>
|
||||
|
|
|
@ -440,7 +440,7 @@ BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l)
|
|||
{
|
||||
BMLoop *l_other;
|
||||
|
||||
// BLI_assert(BM_edge_is_manifold(e)); // TOO strict, just check if we have another radial face
|
||||
// BLI_assert(BM_edge_is_manifold(e)); /* Too strict, just check there is another radial face. */
|
||||
BLI_assert(e->l && e->l->radial_next != e->l);
|
||||
BLI_assert(BM_vert_in_edge(e, l->v));
|
||||
|
||||
|
|
|
@ -112,6 +112,7 @@ set(GLSL_SRC
|
|||
shaders/compositor_blur_variable_size.glsl
|
||||
shaders/compositor_bokeh_image.glsl
|
||||
shaders/compositor_box_mask.glsl
|
||||
shaders/compositor_compute_preview.glsl
|
||||
shaders/compositor_convert.glsl
|
||||
shaders/compositor_despeckle.glsl
|
||||
shaders/compositor_directional_blur.glsl
|
||||
|
@ -226,6 +227,7 @@ set(SRC_SHADER_CREATE_INFOS
|
|||
shaders/infos/compositor_blur_variable_size_info.hh
|
||||
shaders/infos/compositor_bokeh_image_info.hh
|
||||
shaders/infos/compositor_box_mask_info.hh
|
||||
shaders/infos/compositor_compute_preview_info.hh
|
||||
shaders/infos/compositor_convert_info.hh
|
||||
shaders/infos/compositor_despeckle_info.hh
|
||||
shaders/infos/compositor_directional_blur_info.hh
|
||||
|
|
|
@ -42,6 +42,9 @@ class Context {
|
|||
public:
|
||||
Context(TexturePool &texture_pool);
|
||||
|
||||
/* Get the compositing scene. */
|
||||
virtual const Scene &get_scene() const = 0;
|
||||
|
||||
/* Get the node tree used for compositing. */
|
||||
virtual const bNodeTree &get_node_tree() const = 0;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "COM_context.hh"
|
||||
#include "COM_operation.hh"
|
||||
#include "COM_result.hh"
|
||||
#include "COM_scheduler.hh"
|
||||
|
||||
namespace blender::realtime_compositor {
|
||||
|
@ -44,6 +45,12 @@ class NodeOperation : public Operation {
|
|||
void compute_results_reference_counts(const Schedule &schedule);
|
||||
|
||||
protected:
|
||||
/* Compute a preview for the operation and set to the bNodePreview of the node. This is only done
|
||||
* for nodes which enables previews, are not hidden, and are part of the active node context. The
|
||||
* preview is computed as a lower resolution version of the output of the get_preview_result
|
||||
* method. */
|
||||
void compute_preview() override;
|
||||
|
||||
/* Returns a reference to the derived node that this operation represents. */
|
||||
const DNode &node() const;
|
||||
|
||||
|
@ -53,6 +60,17 @@ class NodeOperation : public Operation {
|
|||
/* Returns true if the output identified by the given identifier is needed and should be
|
||||
* computed, otherwise returns false. */
|
||||
bool should_compute_output(StringRef identifier);
|
||||
|
||||
private:
|
||||
/* Get the result which will be previewed in the node, this is chosen as the first linked output
|
||||
* of the node, if no outputs exist, then the first allocated input will be chosen. Nullptr is
|
||||
* guaranteed not to be returned, since the node will always either have a linked output or an
|
||||
* allocated input. */
|
||||
Result *get_preview_result();
|
||||
|
||||
/* Resize the give input result to the given preview size and set it to the preview buffer after
|
||||
* applying the necessary color management processor.*/
|
||||
void write_preview_from_result(bNodePreview &preview, Result &input_result);
|
||||
};
|
||||
|
||||
} // namespace blender::realtime_compositor
|
||||
|
|
|
@ -130,6 +130,10 @@ class Operation {
|
|||
* output results. */
|
||||
virtual void execute() = 0;
|
||||
|
||||
/* Compute and set a preview of the operation if needed. This method defaults to an empty
|
||||
* implementation and should be implemented by operations which can have previews. */
|
||||
virtual void compute_preview();
|
||||
|
||||
/* Get a reference to the result connected to the input identified by the given identifier. */
|
||||
Result &get_input(StringRef identifier) const;
|
||||
|
||||
|
|
|
@ -4,15 +4,29 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
#include "BLI_assert.h"
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_math_base.h"
|
||||
#include "BLI_math_base.hh"
|
||||
#include "BLI_math_color.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_task.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_texture.h"
|
||||
|
||||
#include "IMB_colormanagement.h"
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
|
||||
#include "NOD_derived_node_tree.hh"
|
||||
#include "NOD_node_declaration.hh"
|
||||
|
||||
#include "BKE_node.h"
|
||||
|
||||
#include "COM_context.hh"
|
||||
#include "COM_input_descriptor.hh"
|
||||
#include "COM_node_operation.hh"
|
||||
|
@ -39,6 +53,126 @@ NodeOperation::NodeOperation(Context &context, DNode node) : Operation(context),
|
|||
}
|
||||
}
|
||||
|
||||
/* Given the size of a result, compute a lower resolution size for a preview. The greater dimension
|
||||
* will be assigned an arbitrarily chosen size of 128, while the other dimension will get the size
|
||||
* that maintains the same aspect ratio. */
|
||||
static int2 compute_preview_size(int2 size)
|
||||
{
|
||||
const int greater_dimension_size = 128;
|
||||
if (size.x > size.y) {
|
||||
return int2(greater_dimension_size, int(greater_dimension_size * (float(size.y) / size.x)));
|
||||
}
|
||||
else {
|
||||
return int2(int(greater_dimension_size * (float(size.x) / size.y)), greater_dimension_size);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeOperation::compute_preview()
|
||||
{
|
||||
if (!(node()->flag & NODE_PREVIEW)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node()->flag & NODE_HIDDEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only compute previews for nodes in the active context. */
|
||||
if (node().context()->instance_key().value !=
|
||||
node().context()->derived_tree().active_context().instance_key().value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize node tree previews if not already initialized. */
|
||||
bNodeTree *root_tree = const_cast<bNodeTree *>(
|
||||
&node().context()->derived_tree().root_context().btree());
|
||||
if (!root_tree->previews) {
|
||||
root_tree->previews = BKE_node_instance_hash_new("node previews");
|
||||
}
|
||||
|
||||
Result *preview_result = get_preview_result();
|
||||
const int2 preview_size = compute_preview_size(preview_result->domain().size);
|
||||
node()->runtime->preview_xsize = preview_size.x;
|
||||
node()->runtime->preview_ysize = preview_size.y;
|
||||
|
||||
bNodePreview *preview = bke::node_preview_verify(
|
||||
root_tree->previews, node().instance_key(), preview_size.x, preview_size.y, true);
|
||||
|
||||
write_preview_from_result(*preview, *preview_result);
|
||||
}
|
||||
|
||||
Result *NodeOperation::get_preview_result()
|
||||
{
|
||||
/* Find the first linked output. */
|
||||
for (const bNodeSocket *output : node()->output_sockets()) {
|
||||
Result &output_result = get_result(output->identifier);
|
||||
if (output_result.should_compute()) {
|
||||
return &output_result;
|
||||
}
|
||||
}
|
||||
|
||||
/* No linked outputs, find the first allocated input. */
|
||||
for (const bNodeSocket *input : node()->input_sockets()) {
|
||||
Result &input_result = get_input(input->identifier);
|
||||
if (input_result.is_allocated()) {
|
||||
return &input_result;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void NodeOperation::write_preview_from_result(bNodePreview &preview, Result &input_result)
|
||||
{
|
||||
GPUShader *shader = shader_manager().get("compositor_compute_preview");
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
if (input_result.type() == ResultType::Float) {
|
||||
GPU_texture_swizzle_set(input_result.texture(), "rrr1");
|
||||
}
|
||||
|
||||
input_result.bind_as_texture(shader, "input_tx");
|
||||
|
||||
const int2 preview_size = int2(preview.xsize, preview.ysize);
|
||||
Result preview_result = Result::Temporary(ResultType::Color, texture_pool());
|
||||
preview_result.allocate_texture(Domain(preview_size));
|
||||
preview_result.bind_as_image(shader, "preview_img");
|
||||
|
||||
compute_dispatch_threads_at_least(shader, preview_size);
|
||||
|
||||
input_result.unbind_as_texture();
|
||||
preview_result.unbind_as_image();
|
||||
GPU_shader_unbind();
|
||||
|
||||
GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH);
|
||||
float *preview_pixels = static_cast<float *>(
|
||||
GPU_texture_read(preview_result.texture(), GPU_DATA_FLOAT, 0));
|
||||
preview_result.release();
|
||||
|
||||
ColormanageProcessor *color_processor = IMB_colormanagement_display_processor_new(
|
||||
&context().get_scene().view_settings, &context().get_scene().display_settings);
|
||||
|
||||
threading::parallel_for(IndexRange(preview_size.y), 1, [&](const IndexRange sub_y_range) {
|
||||
for (const int64_t y : sub_y_range) {
|
||||
for (const int64_t x : IndexRange(preview_size.x)) {
|
||||
const int index = (y * preview_size.x + x) * 4;
|
||||
IMB_colormanagement_processor_apply_v4(color_processor, preview_pixels + index);
|
||||
rgba_float_to_uchar(preview.rect + index, preview_pixels + index);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* Restore original swizzle mask set above. */
|
||||
if (input_result.type() == ResultType::Float) {
|
||||
GPU_texture_swizzle_set(input_result.texture(), "rgba");
|
||||
}
|
||||
|
||||
IMB_colormanagement_processor_free(color_processor);
|
||||
MEM_freeN(preview_pixels);
|
||||
}
|
||||
|
||||
void NodeOperation::compute_results_reference_counts(const Schedule &schedule)
|
||||
{
|
||||
for (const bNodeSocket *output : this->node()->output_sockets()) {
|
||||
|
|
|
@ -35,6 +35,8 @@ void Operation::evaluate()
|
|||
|
||||
execute();
|
||||
|
||||
compute_preview();
|
||||
|
||||
release_inputs();
|
||||
|
||||
release_unneeded_results();
|
||||
|
@ -136,6 +138,8 @@ void Operation::add_and_evaluate_input_processor(StringRef identifier, SimpleOpe
|
|||
processor->evaluate();
|
||||
}
|
||||
|
||||
void Operation::compute_preview(){};
|
||||
|
||||
Result &Operation::get_input(StringRef identifier) const
|
||||
{
|
||||
return *results_mapped_to_inputs_.lookup(identifier);
|
||||
|
|
|
@ -21,58 +21,6 @@ namespace blender::realtime_compositor {
|
|||
|
||||
using namespace nodes::derived_node_tree_types;
|
||||
|
||||
/* Find the active context from the given context and its descendants contexts. The active context
|
||||
* is the one whose node instance key matches the active_viewer_key stored in the root node tree.
|
||||
* The instance key of each context is computed by calling BKE_node_instance_key given the key of
|
||||
* the parent as well as the group node making the context. */
|
||||
static const DTreeContext *find_active_context_recursive(const DTreeContext *context,
|
||||
bNodeInstanceKey key)
|
||||
{
|
||||
/* The instance key of the given context matches the active viewer instance key, so this is the
|
||||
* active context, return it. */
|
||||
if (key.value == context->derived_tree().root_context().btree().active_viewer_key.value) {
|
||||
return context;
|
||||
}
|
||||
|
||||
/* For each of the group nodes, compute their instance key and contexts and call this function
|
||||
* recursively. */
|
||||
for (const bNode *group_node : context->btree().group_nodes()) {
|
||||
const bNodeInstanceKey child_key = BKE_node_instance_key(key, &context->btree(), group_node);
|
||||
const DTreeContext *child_context = context->child_context(*group_node);
|
||||
const DTreeContext *found_context = find_active_context_recursive(child_context, child_key);
|
||||
|
||||
/* If the found context is null, that means neither the child context nor one of its descendant
|
||||
* contexts is active. */
|
||||
if (!found_context) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Otherwise, we have found our active context, return it. */
|
||||
return found_context;
|
||||
}
|
||||
|
||||
/* Neither the given context nor one of its descendant contexts is active, so return null. */
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Find the active context for the given node tree. The active context represents the node tree
|
||||
* currently being edited. In most cases, that would be the top level node tree itself, but in the
|
||||
* case where the user is editing the node tree of a node group, the active context would be a
|
||||
* representation of the node tree of that node group. Note that the context also stores the group
|
||||
* node that the user selected to edit the node tree, so the context fully represents a particular
|
||||
* instance of the node group. */
|
||||
static const DTreeContext *find_active_context(const DerivedNodeTree &tree)
|
||||
{
|
||||
/* If the active viewer key is NODE_INSTANCE_KEY_NONE, that means it is not yet initialized and
|
||||
* we return the root context in that case. See the find_active_context_recursive function. */
|
||||
if (tree.root_context().btree().active_viewer_key.value == NODE_INSTANCE_KEY_NONE.value) {
|
||||
return &tree.root_context();
|
||||
}
|
||||
|
||||
/* The root context has an instance key of NODE_INSTANCE_KEY_BASE by definition. */
|
||||
return find_active_context_recursive(&tree.root_context(), NODE_INSTANCE_KEY_BASE);
|
||||
}
|
||||
|
||||
/* Add the viewer node which is marked as NODE_DO_OUTPUT in the given context to the given stack.
|
||||
* If multiple types of viewer nodes are marked, then the preference will be CMP_NODE_VIEWER >
|
||||
* CMP_NODE_SPLITVIEWER. If no viewer nodes were found, composite nodes can be added as a fallback
|
||||
|
@ -114,7 +62,8 @@ static bool add_viewer_nodes_in_context(const DTreeContext *context, Stack<DNode
|
|||
* Output, Composite, and Viewer nodes. Viewer nodes are a special case, as only the nodes that
|
||||
* satisfies the requirements in the add_viewer_nodes_in_context function are added. First, the
|
||||
* active context is searched for viewer nodes, if non were found, the root context is searched.
|
||||
* For more information on what contexts mean here, see the find_active_context function. */
|
||||
* For more information on what contexts mean here, see the DerivedNodeTree::active_context()
|
||||
* function. */
|
||||
static void add_output_nodes(const Context &context,
|
||||
const DerivedNodeTree &tree,
|
||||
Stack<DNode> &node_stack)
|
||||
|
@ -139,8 +88,8 @@ static void add_output_nodes(const Context &context,
|
|||
}
|
||||
}
|
||||
|
||||
const DTreeContext *active_context = find_active_context(tree);
|
||||
const bool viewer_was_added = add_viewer_nodes_in_context(active_context, node_stack);
|
||||
const DTreeContext &active_context = tree.active_context();
|
||||
const bool viewer_was_added = add_viewer_nodes_in_context(&active_context, node_stack);
|
||||
|
||||
/* An active viewer was added, no need to search further. */
|
||||
if (viewer_was_added) {
|
||||
|
@ -149,7 +98,7 @@ static void add_output_nodes(const Context &context,
|
|||
|
||||
/* If the active context is the root one and no viewer nodes were found, we consider this node
|
||||
* tree to have no viewer nodes, even if one of the non-active descendants have viewer nodes. */
|
||||
if (active_context->is_root()) {
|
||||
if (active_context.is_root()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -394,7 +343,8 @@ Schedule compute_schedule(const Context &context, const DerivedNodeTree &tree)
|
|||
int insertion_position = 0;
|
||||
for (int i = 0; i < sorted_dependency_nodes.size(); i++) {
|
||||
if (needed_buffers.lookup(doutput.node()) >
|
||||
needed_buffers.lookup(sorted_dependency_nodes[i])) {
|
||||
needed_buffers.lookup(sorted_dependency_nodes[i]))
|
||||
{
|
||||
insertion_position++;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
void main()
|
||||
{
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
vec2 coordinates = (vec2(texel) + vec2(0.5)) / vec2(imageSize(preview_img));
|
||||
imageStore(preview_img, texel, texture(input_tx, coordinates));
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_compute_preview)
|
||||
.local_group_size(16, 16)
|
||||
.sampler(0, ImageType::FLOAT_2D, "input_tx")
|
||||
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img")
|
||||
.compute_source("compositor_compute_preview.glsl")
|
||||
.do_static_compilation(true);
|
|
@ -36,17 +36,6 @@
|
|||
/* -------------------------------------------------------------------- */
|
||||
/* Utility functions */
|
||||
|
||||
static int path_ensure_slash(char *path)
|
||||
{
|
||||
int len = strlen(path);
|
||||
if (len == 0 || path[len - 1] != SEP) {
|
||||
path[len] = SEP;
|
||||
path[len + 1] = '\0';
|
||||
return len + 1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static bool path_test_extension(const char *filepath, const char *ext)
|
||||
{
|
||||
const size_t a = strlen(filepath);
|
||||
|
@ -81,6 +70,25 @@ static const char *path_basename(const char *path)
|
|||
return filename ? filename + 1 : path;
|
||||
}
|
||||
|
||||
static bool path_join(char *filepath,
|
||||
size_t filepath_maxncpy,
|
||||
const char *dirpath,
|
||||
const char *filename)
|
||||
{
|
||||
int dirpath_len = strlen(dirpath);
|
||||
if (dirpath_len && dirpath[dirpath_len - 1] == SEP) {
|
||||
dirpath_len--;
|
||||
}
|
||||
const int filename_len = strlen(filename);
|
||||
if (dirpath_len + 1 + filename_len + 1 > filepath_maxncpy) {
|
||||
return false;
|
||||
}
|
||||
memcpy(filepath, dirpath, dirpath_len);
|
||||
filepath[dirpath_len] = SEP;
|
||||
memcpy(filepath + dirpath_len + 1, filename, filename_len + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Write a PNG from RGBA pixels */
|
||||
|
||||
|
@ -392,8 +400,6 @@ static bool icondir_to_png(const char *path_src, const char *file_dst)
|
|||
DIR *dir;
|
||||
const struct dirent *fname;
|
||||
char filepath[1024];
|
||||
char *filename;
|
||||
int path_str_len;
|
||||
int found = 0, fail = 0;
|
||||
|
||||
struct IconMergeContext context;
|
||||
|
@ -411,15 +417,12 @@ static bool icondir_to_png(const char *path_src, const char *file_dst)
|
|||
return false;
|
||||
}
|
||||
|
||||
strcpy(filepath, path_src);
|
||||
path_str_len = path_ensure_slash(filepath);
|
||||
filename = &filepath[path_str_len];
|
||||
|
||||
while ((fname = readdir(dir)) != NULL) {
|
||||
if (path_test_extension(fname->d_name, ".dat")) {
|
||||
|
||||
strcpy(filename, fname->d_name);
|
||||
|
||||
if (!path_join(filepath, sizeof(filepath), path_src, fname->d_name)) {
|
||||
printf("%s: path is too long (%s, %s)\n", __func__, path_src, fname->d_name);
|
||||
return false;
|
||||
}
|
||||
if (icon_merge(&context, filepath, &pixels_canvas, &canvas_w, &canvas_h)) {
|
||||
found++;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ void ObjectRuntimeBackup::init_from_object(Object *object)
|
|||
light_linking_runtime = object->light_linking->runtime;
|
||||
}
|
||||
BKE_object_runtime_reset(object);
|
||||
/* Keep bbox (for now at least). */
|
||||
/* Keep bounding-box (for now at least). */
|
||||
object->runtime.bb = runtime.bb;
|
||||
/* Object update will override actual object->data to an evaluated version.
|
||||
* Need to make sure we don't have data set to evaluated one before free
|
||||
|
|
|
@ -58,6 +58,11 @@ class Context : public realtime_compositor::Context {
|
|||
{
|
||||
}
|
||||
|
||||
const Scene &get_scene() const override
|
||||
{
|
||||
return *DRW_context_state_get()->scene;
|
||||
}
|
||||
|
||||
const bNodeTree &get_node_tree() const override
|
||||
{
|
||||
return *DRW_context_state_get()->scene->nodetree;
|
||||
|
|
|
@ -86,8 +86,7 @@ static float light_shape_radiance_get(const Light *la, const EEVEE_Light *evli)
|
|||
case LA_LOCAL: {
|
||||
/* Sphere area. */
|
||||
float area = 4.0f * (float)M_PI * square_f(evli->radius);
|
||||
/* NOTE: Presence of a factor of PI here to match Cycles. But it should be missing to be
|
||||
* consistent with the other cases. */
|
||||
/* Convert radiant flux to radiance. */
|
||||
return 1.0f / (area * (float)M_PI);
|
||||
}
|
||||
default:
|
||||
|
@ -128,10 +127,9 @@ static float light_volume_radiance_factor_get(const Light *la,
|
|||
}
|
||||
case LA_SPOT:
|
||||
case LA_LOCAL: {
|
||||
/* Sphere solid angle. */
|
||||
float area = 4.0f * (float)M_PI;
|
||||
/* NOTE: Missing a factor of PI here to match Cycles. */
|
||||
power *= 1.0f / area;
|
||||
/* Convert radiant flux to intensity. */
|
||||
/* Inverse of sphere solid angle. */
|
||||
power *= 0.25f * (float)M_1_PI;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue