Compare commits
50 Commits
ui-asset-v
...
spreadshee
Author | SHA1 | Date | |
---|---|---|---|
83ccca8675 | |||
77c8070b11 | |||
1db976521e | |||
b00727950c | |||
f053bc2ddf | |||
51b4162fed | |||
1bdceb813c | |||
4a7736ce1d | |||
2a5c0c3491 | |||
26071531d0 | |||
131550dac1 | |||
328b39335e | |||
fa50edc999 | |||
0ffbcc4416 | |||
496df39e6f | |||
e1b2cf887f | |||
d5cefc1844 | |||
8a144b73c0 | |||
3f24cfb958 | |||
![]() |
a4260ac219 | ||
c859e1afa0 | |||
![]() |
b30cc7071b | ||
64538532d4 | |||
7bcd0e01af | |||
d6fcecc471 | |||
e945564068 | |||
1598d57663 | |||
42a40f4e7c | |||
80865399a8 | |||
d904271d09 | |||
7faf5b0e02 | |||
9ed2a7e680 | |||
546fa9a759 | |||
6fe2d6b8c8 | |||
3af1903ac7 | |||
214a49aae4 | |||
45aa341dd4 | |||
e0aab87f54 | |||
fca8d0f91f | |||
a9fc5be5fa | |||
ab652c2c90 | |||
4b595de5e6 | |||
d5c6485372 | |||
93972c8910 | |||
a641e08227 | |||
8262c2577e | |||
993e8af943 | |||
a535c07417 | |||
5cbecde9c7 | |||
4472178094 |
@@ -2,7 +2,7 @@
|
||||
# Configuration of clang-format
|
||||
# =============================
|
||||
#
|
||||
# Tested to work with versions: 6 to 8.
|
||||
# Tested to work with versions: 8 to 11.
|
||||
|
||||
# This causes parameters on continuations to align to the opening brace.
|
||||
#
|
||||
@@ -263,8 +263,5 @@ ForEachMacros:
|
||||
- MAP_SLOT_PROBING_BEGIN
|
||||
- VECTOR_SET_SLOT_PROBING_BEGIN
|
||||
|
||||
# Use once we bump the minimum version to version 8.
|
||||
# # Without this string literals that in-line 'STRINGIFY' behave strangely (a bug?).
|
||||
# StatementMacros:
|
||||
# - PyObject_VAR_HEAD
|
||||
# - STRINGIFY
|
||||
StatementMacros:
|
||||
- PyObject_VAR_HEAD
|
||||
|
@@ -1409,15 +1409,15 @@ class CYCLES_LIGHT_PT_nodes(CyclesButtonsPanel, Panel):
|
||||
panel_node_draw(layout, light, 'OUTPUT_LIGHT', 'Surface')
|
||||
|
||||
|
||||
class CYCLES_LIGHT_PT_spot(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Spot Shape"
|
||||
class CYCLES_LIGHT_PT_beam_shape(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Beam Shape"
|
||||
bl_parent_id = "CYCLES_LIGHT_PT_light"
|
||||
bl_context = "data"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
light = context.light
|
||||
return (light and light.type == 'SPOT') and CyclesButtonsPanel.poll(context)
|
||||
if context.light.type in {'SPOT', 'AREA'}:
|
||||
return context.light and CyclesButtonsPanel.poll(context)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -1425,9 +1425,12 @@ class CYCLES_LIGHT_PT_spot(CyclesButtonsPanel, Panel):
|
||||
layout.use_property_split = True
|
||||
|
||||
col = layout.column()
|
||||
col.prop(light, "spot_size", text="Size")
|
||||
col.prop(light, "spot_blend", text="Blend", slider=True)
|
||||
col.prop(light, "show_cone")
|
||||
if light.type == 'SPOT':
|
||||
col.prop(light, "spot_size", text="Spot Size")
|
||||
col.prop(light, "spot_blend", text="Blend", slider=True)
|
||||
col.prop(light, "show_cone")
|
||||
elif light.type == 'AREA':
|
||||
col.prop(light, "spread", text="Spread")
|
||||
|
||||
|
||||
class CYCLES_WORLD_PT_preview(CyclesButtonsPanel, Panel):
|
||||
@@ -2284,7 +2287,7 @@ classes = (
|
||||
CYCLES_LIGHT_PT_preview,
|
||||
CYCLES_LIGHT_PT_light,
|
||||
CYCLES_LIGHT_PT_nodes,
|
||||
CYCLES_LIGHT_PT_spot,
|
||||
CYCLES_LIGHT_PT_beam_shape,
|
||||
CYCLES_WORLD_PT_preview,
|
||||
CYCLES_WORLD_PT_surface,
|
||||
CYCLES_WORLD_PT_volume,
|
||||
@@ -2314,7 +2317,7 @@ classes = (
|
||||
node_panel(CYCLES_WORLD_PT_settings_surface),
|
||||
node_panel(CYCLES_WORLD_PT_settings_volume),
|
||||
node_panel(CYCLES_LIGHT_PT_light),
|
||||
node_panel(CYCLES_LIGHT_PT_spot),
|
||||
node_panel(CYCLES_LIGHT_PT_beam_shape)
|
||||
)
|
||||
|
||||
|
||||
|
@@ -82,6 +82,7 @@ void BlenderSync::sync_light(BL::Object &b_parent,
|
||||
light->set_axisu(transform_get_column(&tfm, 0));
|
||||
light->set_axisv(transform_get_column(&tfm, 1));
|
||||
light->set_sizeu(b_area_light.size());
|
||||
light->set_spread(b_area_light.spread());
|
||||
switch (b_area_light.shape()) {
|
||||
case BL::AreaLight::shape_SQUARE:
|
||||
light->set_sizev(light->get_sizeu());
|
||||
|
@@ -119,11 +119,11 @@ ccl_device_inline bool lamp_light_sample(
|
||||
klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
|
||||
float3 axisv = make_float3(
|
||||
klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
|
||||
float3 D = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
|
||||
float3 Ng = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
|
||||
float invarea = fabsf(klight->area.invarea);
|
||||
bool is_round = (klight->area.invarea < 0.0f);
|
||||
|
||||
if (dot(ls->P - P, D) > 0.0f) {
|
||||
if (dot(ls->P - P, Ng) > 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -135,20 +135,37 @@ ccl_device_inline bool lamp_light_sample(
|
||||
ls->pdf = invarea;
|
||||
}
|
||||
else {
|
||||
float3 sample_axisu = axisu;
|
||||
float3 sample_axisv = axisv;
|
||||
|
||||
if (klight->area.tan_spread > 0.0f) {
|
||||
if (!light_spread_clamp_area_light(
|
||||
P, Ng, &ls->P, &sample_axisu, &sample_axisv, klight->area.tan_spread)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inplane = ls->P;
|
||||
ls->pdf = rect_light_sample(P, &ls->P, axisu, axisv, randu, randv, true);
|
||||
ls->pdf = rect_light_sample(P, &ls->P, sample_axisu, sample_axisv, randu, randv, true);
|
||||
inplane = ls->P - inplane;
|
||||
}
|
||||
|
||||
ls->u = dot(inplane, axisu) * (1.0f / dot(axisu, axisu)) + 0.5f;
|
||||
ls->v = dot(inplane, axisv) * (1.0f / dot(axisv, axisv)) + 0.5f;
|
||||
|
||||
ls->Ng = D;
|
||||
ls->Ng = Ng;
|
||||
ls->D = normalize_len(ls->P - P, &ls->t);
|
||||
|
||||
ls->eval_fac = 0.25f * invarea;
|
||||
|
||||
if (klight->area.tan_spread > 0.0f) {
|
||||
/* Area Light spread angle attenuation */
|
||||
ls->eval_fac *= light_spread_attenuation(
|
||||
ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread);
|
||||
}
|
||||
|
||||
if (is_round) {
|
||||
ls->pdf *= lamp_light_pdf(kg, D, -ls->D, ls->t);
|
||||
ls->pdf *= lamp_light_pdf(kg, Ng, -ls->D, ls->t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -283,9 +300,28 @@ ccl_device bool lamp_light_eval(
|
||||
ls->pdf = invarea * lamp_light_pdf(kg, Ng, -D, ls->t);
|
||||
}
|
||||
else {
|
||||
ls->pdf = rect_light_sample(P, &light_P, axisu, axisv, 0, 0, false);
|
||||
float3 sample_axisu = axisu;
|
||||
float3 sample_axisv = axisv;
|
||||
|
||||
if (klight->area.tan_spread > 0.0f) {
|
||||
if (!light_spread_clamp_area_light(
|
||||
P, Ng, &light_P, &sample_axisu, &sample_axisv, klight->area.tan_spread)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ls->pdf = rect_light_sample(P, &light_P, sample_axisu, sample_axisv, 0, 0, false);
|
||||
}
|
||||
ls->eval_fac = 0.25f * invarea;
|
||||
|
||||
if (klight->area.tan_spread > 0.0f) {
|
||||
/* Area Light spread angle attenuation */
|
||||
ls->eval_fac *= light_spread_attenuation(
|
||||
ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread);
|
||||
if (ls->eval_fac == 0.0f) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
|
@@ -146,6 +146,70 @@ ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot
|
||||
return attenuation;
|
||||
}
|
||||
|
||||
ccl_device float light_spread_attenuation(const float3 D,
|
||||
const float3 lightNg,
|
||||
const float tan_spread,
|
||||
const float normalize_spread)
|
||||
{
|
||||
/* Model a soft-box grid, computing the ratio of light not hidden by the
|
||||
* slats of the grid at a given angle. (see D10594). */
|
||||
const float cos_a = -dot(D, lightNg);
|
||||
const float sin_a = safe_sqrtf(1.0f - sqr(cos_a));
|
||||
const float tan_a = sin_a / cos_a;
|
||||
return max((1.0f - (tan_spread * tan_a)) * normalize_spread, 0.0f);
|
||||
}
|
||||
|
||||
/* Compute subset of area light that actually has an influence on the shading point, to
|
||||
* reduce noise with low spread. */
|
||||
ccl_device bool light_spread_clamp_area_light(const float3 P,
|
||||
const float3 lightNg,
|
||||
float3 *lightP,
|
||||
float3 *axisu,
|
||||
float3 *axisv,
|
||||
const float tan_spread)
|
||||
{
|
||||
/* Closest point in area light plane and distance to that plane. */
|
||||
const float3 closest_P = P - dot(lightNg, P - *lightP) * lightNg;
|
||||
const float t = len(closest_P - P);
|
||||
|
||||
/* Radius of circle on area light that actually affects the shading point. */
|
||||
const float radius = t / tan_spread;
|
||||
|
||||
/* TODO: would be faster to store as normalized vector + length, also in rect_light_sample. */
|
||||
float len_u, len_v;
|
||||
const float3 u = normalize_len(*axisu, &len_u);
|
||||
const float3 v = normalize_len(*axisv, &len_v);
|
||||
|
||||
/* Local uv coordinates of closest point. */
|
||||
const float closest_u = dot(u, closest_P - *lightP);
|
||||
const float closest_v = dot(v, closest_P - *lightP);
|
||||
|
||||
/* Compute rectangle encompassing the circle that affects the shading point,
|
||||
* clamped to the bounds of the area light. */
|
||||
const float min_u = max(closest_u - radius, -len_u * 0.5f);
|
||||
const float max_u = min(closest_u + radius, len_u * 0.5f);
|
||||
const float min_v = max(closest_v - radius, -len_v * 0.5f);
|
||||
const float max_v = min(closest_v + radius, len_v * 0.5f);
|
||||
|
||||
/* Skip if rectangle is empty. */
|
||||
if (min_u >= max_u || min_v >= max_v) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Compute new area light center position and axes from rectangle in local
|
||||
* uv coordinates. */
|
||||
const float new_center_u = 0.5f * (min_u + max_u);
|
||||
const float new_center_v = 0.5f * (min_v + max_v);
|
||||
const float new_len_u = 0.5f * (max_u - min_u);
|
||||
const float new_len_v = 0.5f * (max_v - min_v);
|
||||
|
||||
*lightP = *lightP + new_center_u * u + new_center_v * v;
|
||||
*axisu = u * new_len_u * 2.0f;
|
||||
*axisv = v * new_len_v * 2.0f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t)
|
||||
{
|
||||
float cos_pi = dot(Ng, I);
|
||||
|
@@ -1501,9 +1501,9 @@ typedef struct KernelAreaLight {
|
||||
float axisu[3];
|
||||
float invarea;
|
||||
float axisv[3];
|
||||
float pad1;
|
||||
float tan_spread;
|
||||
float dir[3];
|
||||
float pad2;
|
||||
float normalize_spread;
|
||||
} KernelAreaLight;
|
||||
|
||||
typedef struct KernelDistantLight {
|
||||
|
@@ -179,9 +179,13 @@ bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMet
|
||||
metadata.transform_3d = transform_inverse(index_to_object * texture_to_index);
|
||||
metadata.use_transform_3d = true;
|
||||
|
||||
# ifndef WITH_NANOVDB
|
||||
(void)features;
|
||||
# endif
|
||||
return true;
|
||||
#else
|
||||
(void)metadata;
|
||||
(void)features;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
@@ -129,6 +129,7 @@ NODE_DEFINE(Light)
|
||||
SOCKET_VECTOR(axisv, "Axis V", zero_float3());
|
||||
SOCKET_FLOAT(sizev, "Size V", 1.0f);
|
||||
SOCKET_BOOLEAN(round, "Round", false);
|
||||
SOCKET_FLOAT(spread, "Spread", M_PI_F);
|
||||
|
||||
SOCKET_INT(map_resolution, "Map Resolution", 0);
|
||||
|
||||
@@ -858,6 +859,15 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
|
||||
float invarea = (area != 0.0f) ? 1.0f / area : 1.0f;
|
||||
float3 dir = light->dir;
|
||||
|
||||
/* Convert from spread angle 0..180 to 90..0, clamping to a minimum
|
||||
* angle to avoid excessive noise. */
|
||||
const float min_spread_angle = 1.0f * M_PI_F / 180.0f;
|
||||
const float spread_angle = 0.5f * (M_PI_F - max(light->spread, min_spread_angle));
|
||||
/* Normalization computed using:
|
||||
* integrate cos(x) (1 - tan(x) * tan(a)) * sin(x) from x = a to pi/2. */
|
||||
const float tan_spread = tanf(spread_angle);
|
||||
const float normalize_spread = 2.0f / (2.0f + (2.0f * spread_angle - M_PI_F) * tan_spread);
|
||||
|
||||
dir = safe_normalize(dir);
|
||||
|
||||
if (light->use_mis && area != 0.0f)
|
||||
@@ -877,6 +887,8 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
|
||||
klights[light_index].area.dir[0] = dir.x;
|
||||
klights[light_index].area.dir[1] = dir.y;
|
||||
klights[light_index].area.dir[2] = dir.z;
|
||||
klights[light_index].area.tan_spread = tan_spread;
|
||||
klights[light_index].area.normalize_spread = normalize_spread;
|
||||
}
|
||||
else if (light->light_type == LIGHT_SPOT) {
|
||||
shader_id &= ~SHADER_AREA_LIGHT;
|
||||
|
@@ -58,6 +58,7 @@ class Light : public Node {
|
||||
NODE_SOCKET_API(float3, axisv)
|
||||
NODE_SOCKET_API(float, sizev)
|
||||
NODE_SOCKET_API(bool, round)
|
||||
NODE_SOCKET_API(float, spread)
|
||||
|
||||
NODE_SOCKET_API(Transform, tfm)
|
||||
|
||||
|
@@ -18,6 +18,7 @@
|
||||
|
||||
#define TEST_CATEGORY_NAME util_avx2
|
||||
|
||||
#if defined(i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
|
||||
#if (defined(i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)) && \
|
||||
defined(__AVX2__)
|
||||
# include "util_avxf_test.h"
|
||||
#endif
|
||||
|
@@ -18,6 +18,7 @@
|
||||
|
||||
#define TEST_CATEGORY_NAME util_avx
|
||||
|
||||
#if defined(i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
|
||||
#if (defined(i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)) && \
|
||||
defined(__AVX__)
|
||||
# include "util_avxf_test.h"
|
||||
#endif
|
||||
|
2
intern/libmv/third_party/.clang-format
vendored
Normal file
2
intern/libmv/third_party/.clang-format
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
DisableFormat: true
|
||||
SortIncludes: false
|
@@ -108,7 +108,7 @@ void BKE_curve_transform(struct Curve *cu,
|
||||
const bool do_props);
|
||||
void BKE_curve_translate(struct Curve *cu, const float offset[3], const bool do_keys);
|
||||
void BKE_curve_material_index_remove(struct Curve *cu, int index);
|
||||
bool BKE_curve_material_index_used(struct Curve *cu, int index);
|
||||
bool BKE_curve_material_index_used(const struct Curve *cu, int index);
|
||||
void BKE_curve_material_index_clear(struct Curve *cu);
|
||||
bool BKE_curve_material_index_validate(struct Curve *cu);
|
||||
void BKE_curve_material_remap(struct Curve *cu, const unsigned int *remap, unsigned int remap_len);
|
||||
@@ -125,8 +125,10 @@ void BKE_curve_nurb_vert_active_set(struct Curve *cu, const struct Nurb *nu, con
|
||||
bool BKE_curve_nurb_vert_active_get(struct Curve *cu, struct Nurb **r_nu, void **r_vert);
|
||||
void BKE_curve_nurb_vert_active_validate(struct Curve *cu);
|
||||
|
||||
float (*BKE_curve_nurbs_vert_coords_alloc(struct ListBase *lb, int *r_vert_len))[3];
|
||||
void BKE_curve_nurbs_vert_coords_get(struct ListBase *lb, float (*vert_coords)[3], int vert_len);
|
||||
float (*BKE_curve_nurbs_vert_coords_alloc(const struct ListBase *lb, int *r_vert_len))[3];
|
||||
void BKE_curve_nurbs_vert_coords_get(const struct ListBase *lb,
|
||||
float (*vert_coords)[3],
|
||||
int vert_len);
|
||||
|
||||
void BKE_curve_nurbs_vert_coords_apply_with_mat4(struct ListBase *lb,
|
||||
const float (*vert_coords)[3],
|
||||
@@ -137,7 +139,7 @@ void BKE_curve_nurbs_vert_coords_apply(struct ListBase *lb,
|
||||
const float (*vert_coords)[3],
|
||||
const bool constrain_2d);
|
||||
|
||||
float (*BKE_curve_nurbs_key_vert_coords_alloc(struct ListBase *lb,
|
||||
float (*BKE_curve_nurbs_key_vert_coords_alloc(const struct ListBase *lb,
|
||||
float *key,
|
||||
int *r_vert_len))[3];
|
||||
void BKE_curve_nurbs_key_vert_tilts_apply(struct ListBase *lb, const float *key);
|
||||
@@ -166,8 +168,8 @@ void BKE_curve_correct_bezpart(const float v1[2], float v2[2], float v3[2], cons
|
||||
|
||||
bool BKE_nurbList_index_get_co(struct ListBase *editnurb, const int index, float r_co[3]);
|
||||
|
||||
int BKE_nurbList_verts_count(struct ListBase *nurb);
|
||||
int BKE_nurbList_verts_count_without_handles(struct ListBase *nurb);
|
||||
int BKE_nurbList_verts_count(const struct ListBase *nurb);
|
||||
int BKE_nurbList_verts_count_without_handles(const struct ListBase *nurb);
|
||||
|
||||
void BKE_nurbList_free(struct ListBase *lb);
|
||||
void BKE_nurbList_duplicate(struct ListBase *lb1, const struct ListBase *lb2);
|
||||
@@ -185,7 +187,7 @@ struct Nurb *BKE_nurb_duplicate(const struct Nurb *nu);
|
||||
struct Nurb *BKE_nurb_copy(struct Nurb *src, int pntsu, int pntsv);
|
||||
|
||||
void BKE_nurb_test_2d(struct Nurb *nu);
|
||||
void BKE_nurb_minmax(struct Nurb *nu, bool use_radius, float min[3], float max[3]);
|
||||
void BKE_nurb_minmax(const struct Nurb *nu, bool use_radius, float min[3], float max[3]);
|
||||
float BKE_nurb_calc_length(const struct Nurb *nu, int resolution);
|
||||
|
||||
void BKE_nurb_makeFaces(
|
||||
|
@@ -77,29 +77,29 @@ typedef struct DispList {
|
||||
int totindex; /* indexed array drawing surfaces */
|
||||
} DispList;
|
||||
|
||||
void BKE_displist_copy(struct ListBase *lbn, struct ListBase *lb);
|
||||
void BKE_displist_copy(struct ListBase *lbn, const struct ListBase *lb);
|
||||
void BKE_displist_elem_free(DispList *dl);
|
||||
DispList *BKE_displist_find_or_create(struct ListBase *lb, int type);
|
||||
DispList *BKE_displist_find(struct ListBase *lb, int type);
|
||||
void BKE_displist_normals_add(struct ListBase *lb);
|
||||
void BKE_displist_count(struct ListBase *lb, int *totvert, int *totface, int *tottri);
|
||||
void BKE_displist_count(const struct ListBase *lb, int *totvert, int *totface, int *tottri);
|
||||
void BKE_displist_free(struct ListBase *lb);
|
||||
bool BKE_displist_has_faces(struct ListBase *lb);
|
||||
bool BKE_displist_has_faces(const struct ListBase *lb);
|
||||
|
||||
void BKE_displist_make_surf(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
const struct Scene *scene,
|
||||
struct Object *ob,
|
||||
struct ListBase *dispbase,
|
||||
struct Mesh **r_final,
|
||||
const bool for_render,
|
||||
const bool for_orco);
|
||||
void BKE_displist_make_curveTypes(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
const struct Scene *scene,
|
||||
struct Object *ob,
|
||||
const bool for_render,
|
||||
const bool for_orco);
|
||||
void BKE_displist_make_curveTypes_forRender(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
const struct Scene *scene,
|
||||
struct Object *ob,
|
||||
struct ListBase *dispbase,
|
||||
struct Mesh **r_final,
|
||||
@@ -111,22 +111,26 @@ void BKE_displist_make_mball_forRender(struct Depsgraph *depsgraph,
|
||||
struct ListBase *dispbase);
|
||||
|
||||
bool BKE_curve_calc_modifiers_pre(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
const struct Scene *scene,
|
||||
struct Object *ob,
|
||||
struct ListBase *source_nurb,
|
||||
struct ListBase *target_nurb,
|
||||
const bool for_render);
|
||||
bool BKE_displist_surfindex_get(
|
||||
const struct DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4);
|
||||
|
||||
bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4);
|
||||
void BKE_displist_fill(const struct ListBase *dispbase,
|
||||
struct ListBase *to,
|
||||
const float normal_proj[3],
|
||||
const bool flip_normal);
|
||||
|
||||
float BKE_displist_calc_taper(
|
||||
struct Depsgraph *depsgraph, struct Scene *scene, struct Object *taperobj, int cur, int tot);
|
||||
float BKE_displist_calc_taper(struct Depsgraph *depsgraph,
|
||||
const struct Scene *scene,
|
||||
struct Object *taperobj,
|
||||
int cur,
|
||||
int tot);
|
||||
|
||||
void BKE_displist_minmax(struct ListBase *dispbase, float min[3], float max[3]);
|
||||
void BKE_displist_minmax(const struct ListBase *dispbase, float min[3], float max[3]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -141,6 +141,12 @@ class GeometryComponent {
|
||||
/* The returned component should be of the same type as the type this is called on. */
|
||||
virtual GeometryComponent *copy() const = 0;
|
||||
|
||||
/* Direct data is everything except for instances of objects/collections.
|
||||
* If this returns true, the geometry set can be cached and is still valid after e.g. modifier
|
||||
* evaluation ends. Instances can only be valid as long as the data they instance is valid. */
|
||||
virtual bool owns_direct_data() const = 0;
|
||||
virtual void ensure_owns_direct_data() = 0;
|
||||
|
||||
void user_add() const;
|
||||
void user_remove() const;
|
||||
bool is_mutable() const;
|
||||
@@ -315,6 +321,8 @@ struct GeometrySet {
|
||||
|
||||
void clear();
|
||||
|
||||
void ensure_owns_direct_data();
|
||||
|
||||
/* Utility methods for creation. */
|
||||
static GeometrySet create_with_mesh(
|
||||
Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
|
||||
@@ -374,6 +382,9 @@ class MeshComponent : public GeometryComponent {
|
||||
|
||||
bool is_empty() const final;
|
||||
|
||||
bool owns_direct_data() const override;
|
||||
void ensure_owns_direct_data() override;
|
||||
|
||||
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_MESH;
|
||||
|
||||
private:
|
||||
@@ -404,6 +415,9 @@ class PointCloudComponent : public GeometryComponent {
|
||||
|
||||
bool is_empty() const final;
|
||||
|
||||
bool owns_direct_data() const override;
|
||||
void ensure_owns_direct_data() override;
|
||||
|
||||
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_POINT_CLOUD;
|
||||
|
||||
private:
|
||||
@@ -444,6 +458,9 @@ class InstancesComponent : public GeometryComponent {
|
||||
|
||||
bool is_empty() const final;
|
||||
|
||||
bool owns_direct_data() const override;
|
||||
void ensure_owns_direct_data() override;
|
||||
|
||||
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_INSTANCES;
|
||||
};
|
||||
|
||||
@@ -466,5 +483,8 @@ class VolumeComponent : public GeometryComponent {
|
||||
const Volume *get_for_read() const;
|
||||
Volume *get_for_write();
|
||||
|
||||
bool owns_direct_data() const override;
|
||||
void ensure_owns_direct_data() override;
|
||||
|
||||
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_VOLUME;
|
||||
};
|
||||
|
@@ -34,6 +34,7 @@ struct Base;
|
||||
struct BoundBox;
|
||||
struct Curve;
|
||||
struct Depsgraph;
|
||||
struct GeometrySet;
|
||||
struct GpencilModifierData;
|
||||
struct HookGpencilModifierData;
|
||||
struct HookModifierData;
|
||||
@@ -69,6 +70,8 @@ void BKE_object_free_curve_cache(struct Object *ob);
|
||||
void BKE_object_free_derived_caches(struct Object *ob);
|
||||
void BKE_object_free_caches(struct Object *object);
|
||||
|
||||
void BKE_object_preview_geometry_set(struct Object *ob, struct GeometrySet *geometry_set);
|
||||
|
||||
void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData *hmd);
|
||||
void BKE_object_modifier_gpencil_hook_reset(struct Object *ob,
|
||||
struct HookGpencilModifierData *hmd);
|
||||
|
@@ -596,11 +596,11 @@ bool BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3])
|
||||
return false;
|
||||
}
|
||||
|
||||
int BKE_nurbList_verts_count(ListBase *nurb)
|
||||
int BKE_nurbList_verts_count(const ListBase *nurb)
|
||||
{
|
||||
int tot = 0;
|
||||
|
||||
LISTBASE_FOREACH (Nurb *, nu, nurb) {
|
||||
LISTBASE_FOREACH (const Nurb *, nu, nurb) {
|
||||
if (nu->bezt) {
|
||||
tot += 3 * nu->pntsu;
|
||||
}
|
||||
@@ -612,7 +612,7 @@ int BKE_nurbList_verts_count(ListBase *nurb)
|
||||
return tot;
|
||||
}
|
||||
|
||||
int BKE_nurbList_verts_count_without_handles(ListBase *nurb)
|
||||
int BKE_nurbList_verts_count_without_handles(const ListBase *nurb)
|
||||
{
|
||||
int tot = 0;
|
||||
|
||||
@@ -779,7 +779,7 @@ void BKE_nurb_test_2d(Nurb *nu)
|
||||
* if use_radius is truth, minmax will take points' radius into account,
|
||||
* which will make boundbox closer to beveled curve.
|
||||
*/
|
||||
void BKE_nurb_minmax(Nurb *nu, bool use_radius, float min[3], float max[3])
|
||||
void BKE_nurb_minmax(const Nurb *nu, bool use_radius, float min[3], float max[3])
|
||||
{
|
||||
BezTriple *bezt;
|
||||
BPoint *bp;
|
||||
@@ -1928,7 +1928,7 @@ static int cu_isectLL(const float v1[3],
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool bevelinside(BevList *bl1, BevList *bl2)
|
||||
static bool bevelinside(const BevList *bl1, const BevList *bl2)
|
||||
{
|
||||
/* is bl2 INSIDE bl1 ? with left-right method and "lambda's" */
|
||||
/* returns '1' if correct hole */
|
||||
@@ -2052,8 +2052,8 @@ static void calc_bevel_sin_cos(
|
||||
*r_cosa = x3 / t02;
|
||||
}
|
||||
|
||||
static void tilt_bezpart(BezTriple *prevbezt,
|
||||
BezTriple *bezt,
|
||||
static void tilt_bezpart(const BezTriple *prevbezt,
|
||||
const BezTriple *bezt,
|
||||
Nurb *nu,
|
||||
float *tilt_array,
|
||||
float *radius_array,
|
||||
@@ -2061,7 +2061,7 @@ static void tilt_bezpart(BezTriple *prevbezt,
|
||||
int resolu,
|
||||
int stride)
|
||||
{
|
||||
BezTriple *pprev, *next, *last;
|
||||
const BezTriple *pprev, *next, *last;
|
||||
float fac, dfac, t[4];
|
||||
int a;
|
||||
|
||||
@@ -4664,12 +4664,12 @@ void BKE_nurb_direction_switch(Nurb *nu)
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_curve_nurbs_vert_coords_get(ListBase *lb, float (*vert_coords)[3], int vert_len)
|
||||
void BKE_curve_nurbs_vert_coords_get(const ListBase *lb, float (*vert_coords)[3], int vert_len)
|
||||
{
|
||||
float *co = vert_coords[0];
|
||||
LISTBASE_FOREACH (Nurb *, nu, lb) {
|
||||
LISTBASE_FOREACH (const Nurb *, nu, lb) {
|
||||
if (nu->type == CU_BEZIER) {
|
||||
BezTriple *bezt = nu->bezt;
|
||||
const BezTriple *bezt = nu->bezt;
|
||||
for (int i = 0; i < nu->pntsu; i++, bezt++) {
|
||||
copy_v3_v3(co, bezt->vec[0]);
|
||||
co += 3;
|
||||
@@ -4680,7 +4680,7 @@ void BKE_curve_nurbs_vert_coords_get(ListBase *lb, float (*vert_coords)[3], int
|
||||
}
|
||||
}
|
||||
else {
|
||||
BPoint *bp = nu->bp;
|
||||
const BPoint *bp = nu->bp;
|
||||
for (int i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) {
|
||||
copy_v3_v3(co, bp->vec);
|
||||
co += 3;
|
||||
@@ -4691,7 +4691,7 @@ void BKE_curve_nurbs_vert_coords_get(ListBase *lb, float (*vert_coords)[3], int
|
||||
UNUSED_VARS_NDEBUG(vert_len);
|
||||
}
|
||||
|
||||
float (*BKE_curve_nurbs_vert_coords_alloc(ListBase *lb, int *r_vert_len))[3]
|
||||
float (*BKE_curve_nurbs_vert_coords_alloc(const ListBase *lb, int *r_vert_len))[3]
|
||||
{
|
||||
const int vert_len = BKE_nurbList_verts_count(lb);
|
||||
float(*vert_coords)[3] = MEM_malloc_arrayN(vert_len, sizeof(*vert_coords), __func__);
|
||||
@@ -4777,15 +4777,15 @@ void BKE_curve_nurbs_vert_coords_apply(ListBase *lb,
|
||||
}
|
||||
}
|
||||
|
||||
float (*BKE_curve_nurbs_key_vert_coords_alloc(ListBase *lb, float *key, int *r_vert_len))[3]
|
||||
float (*BKE_curve_nurbs_key_vert_coords_alloc(const ListBase *lb, float *key, int *r_vert_len))[3]
|
||||
{
|
||||
int vert_len = BKE_nurbList_verts_count(lb);
|
||||
float(*cos)[3] = MEM_malloc_arrayN(vert_len, sizeof(*cos), __func__);
|
||||
|
||||
float *co = cos[0];
|
||||
LISTBASE_FOREACH (Nurb *, nu, lb) {
|
||||
LISTBASE_FOREACH (const Nurb *, nu, lb) {
|
||||
if (nu->type == CU_BEZIER) {
|
||||
BezTriple *bezt = nu->bezt;
|
||||
const BezTriple *bezt = nu->bezt;
|
||||
|
||||
for (int i = 0; i < nu->pntsu; i++, bezt++) {
|
||||
copy_v3_v3(co, &key[0]);
|
||||
@@ -4798,7 +4798,7 @@ float (*BKE_curve_nurbs_key_vert_coords_alloc(ListBase *lb, float *key, int *r_v
|
||||
}
|
||||
}
|
||||
else {
|
||||
BPoint *bp = nu->bp;
|
||||
const BPoint *bp = nu->bp;
|
||||
|
||||
for (int i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) {
|
||||
copy_v3_v3(co, key);
|
||||
@@ -5216,7 +5216,7 @@ bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3])
|
||||
use_radius = false;
|
||||
}
|
||||
/* Do bounding box based on splines. */
|
||||
LISTBASE_FOREACH (Nurb *, nu, nurb_lb) {
|
||||
LISTBASE_FOREACH (const Nurb *, nu, nurb_lb) {
|
||||
BKE_nurb_minmax(nu, use_radius, min, max);
|
||||
}
|
||||
const bool result = (BLI_listbase_is_empty(nurb_lb) == false);
|
||||
@@ -5412,12 +5412,12 @@ void BKE_curve_material_index_remove(Curve *cu, int index)
|
||||
}
|
||||
}
|
||||
|
||||
bool BKE_curve_material_index_used(Curve *cu, int index)
|
||||
bool BKE_curve_material_index_used(const Curve *cu, int index)
|
||||
{
|
||||
const int curvetype = BKE_curve_type_get(cu);
|
||||
|
||||
if (curvetype == OB_FONT) {
|
||||
struct CharInfo *info = cu->strinfo;
|
||||
const struct CharInfo *info = cu->strinfo;
|
||||
for (int i = cu->len_char32 - 1; i >= 0; i--, info++) {
|
||||
if (info->mat_nr == index) {
|
||||
return true;
|
||||
@@ -5425,7 +5425,7 @@ bool BKE_curve_material_index_used(Curve *cu, int index)
|
||||
}
|
||||
}
|
||||
else {
|
||||
LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
|
||||
LISTBASE_FOREACH (const Nurb *, nu, &cu->nurb) {
|
||||
if (nu->mat_nr == index) {
|
||||
return true;
|
||||
}
|
||||
|
@@ -113,9 +113,9 @@ DispList *BKE_displist_find(ListBase *lb, int type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool BKE_displist_has_faces(ListBase *lb)
|
||||
bool BKE_displist_has_faces(const ListBase *lb)
|
||||
{
|
||||
LISTBASE_FOREACH (DispList *, dl, lb) {
|
||||
LISTBASE_FOREACH (const DispList *, dl, lb) {
|
||||
if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
|
||||
return true;
|
||||
}
|
||||
@@ -124,7 +124,7 @@ bool BKE_displist_has_faces(ListBase *lb)
|
||||
return false;
|
||||
}
|
||||
|
||||
void BKE_displist_copy(ListBase *lbn, ListBase *lb)
|
||||
void BKE_displist_copy(ListBase *lbn, const ListBase *lb)
|
||||
{
|
||||
BKE_displist_free(lbn);
|
||||
|
||||
@@ -208,9 +208,9 @@ void BKE_displist_normals_add(ListBase *lb)
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_displist_count(ListBase *lb, int *totvert, int *totface, int *tottri)
|
||||
void BKE_displist_count(const ListBase *lb, int *totvert, int *totface, int *tottri)
|
||||
{
|
||||
LISTBASE_FOREACH (DispList *, dl, lb) {
|
||||
LISTBASE_FOREACH (const DispList *, dl, lb) {
|
||||
int vert_tot = 0;
|
||||
int face_tot = 0;
|
||||
int tri_tot = 0;
|
||||
@@ -251,7 +251,8 @@ void BKE_displist_count(ListBase *lb, int *totvert, int *totface, int *tottri)
|
||||
}
|
||||
}
|
||||
|
||||
bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4)
|
||||
bool BKE_displist_surfindex_get(
|
||||
const DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4)
|
||||
{
|
||||
if ((dl->flag & DL_CYCL_V) == 0 && a == (dl->parts) - 1) {
|
||||
return false;
|
||||
@@ -608,7 +609,7 @@ static void bevels_to_filledpoly(const Curve *cu, ListBase *dispbase)
|
||||
BKE_displist_fill(dispbase, dispbase, z_up, false);
|
||||
}
|
||||
|
||||
static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dispbase)
|
||||
static void curve_to_filledpoly(const Curve *cu, ListBase *dispbase)
|
||||
{
|
||||
if (!CU_DO_2DFILL(cu)) {
|
||||
return;
|
||||
@@ -628,7 +629,10 @@ static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dis
|
||||
* - first point left, last point right
|
||||
* - based on subdivided points in original curve, not on points in taper curve (still)
|
||||
*/
|
||||
static float displist_calc_taper(Depsgraph *depsgraph, Scene *scene, Object *taperobj, float fac)
|
||||
static float displist_calc_taper(Depsgraph *depsgraph,
|
||||
const Scene *scene,
|
||||
Object *taperobj,
|
||||
float fac)
|
||||
{
|
||||
DispList *dl;
|
||||
|
||||
@@ -671,7 +675,7 @@ static float displist_calc_taper(Depsgraph *depsgraph, Scene *scene, Object *tap
|
||||
}
|
||||
|
||||
float BKE_displist_calc_taper(
|
||||
Depsgraph *depsgraph, Scene *scene, Object *taperobj, int cur, int tot)
|
||||
Depsgraph *depsgraph, const Scene *scene, Object *taperobj, int cur, int tot)
|
||||
{
|
||||
float fac = ((float)cur) / (float)(tot - 1);
|
||||
|
||||
@@ -713,8 +717,8 @@ void BKE_displist_make_mball_forRender(Depsgraph *depsgraph,
|
||||
object_deform_mball(ob, dispbase);
|
||||
}
|
||||
|
||||
static ModifierData *curve_get_tessellate_point(Scene *scene,
|
||||
Object *ob,
|
||||
static ModifierData *curve_get_tessellate_point(const Scene *scene,
|
||||
const Object *ob,
|
||||
const bool for_render,
|
||||
const bool editmode)
|
||||
{
|
||||
@@ -764,7 +768,7 @@ static ModifierData *curve_get_tessellate_point(Scene *scene,
|
||||
|
||||
/* Return true if any modifier was applied. */
|
||||
bool BKE_curve_calc_modifiers_pre(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
const Scene *scene,
|
||||
Object *ob,
|
||||
ListBase *source_nurb,
|
||||
ListBase *target_nurb,
|
||||
@@ -876,7 +880,7 @@ static float (*displist_vert_coords_alloc(ListBase *dispbase, int *r_vert_len))[
|
||||
return allverts;
|
||||
}
|
||||
|
||||
static void displist_vert_coords_apply(ListBase *dispbase, float (*allverts)[3])
|
||||
static void displist_vert_coords_apply(ListBase *dispbase, const float (*allverts)[3])
|
||||
{
|
||||
const float *fp;
|
||||
|
||||
@@ -889,9 +893,8 @@ static void displist_vert_coords_apply(ListBase *dispbase, float (*allverts)[3])
|
||||
}
|
||||
|
||||
static void curve_calc_modifiers_post(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
const Scene *scene,
|
||||
Object *ob,
|
||||
ListBase *nurb,
|
||||
ListBase *dispbase,
|
||||
Mesh **r_final,
|
||||
const bool for_render,
|
||||
@@ -900,7 +903,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
|
||||
VirtualModifierData virtualModifierData;
|
||||
ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData);
|
||||
ModifierData *pretessellatePoint;
|
||||
Curve *cu = ob->data;
|
||||
const Curve *cu = ob->data;
|
||||
int required_mode = 0, totvert = 0;
|
||||
const bool editmode = (!for_render && (cu->editnurb || cu->editfont));
|
||||
Mesh *modified = NULL, *mesh_applied;
|
||||
@@ -952,7 +955,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
|
||||
}
|
||||
|
||||
if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) {
|
||||
curve_to_filledpoly(cu, nurb, dispbase);
|
||||
curve_to_filledpoly(cu, dispbase);
|
||||
}
|
||||
|
||||
modified = BKE_mesh_new_nomain_from_curve_displist(ob, dispbase);
|
||||
@@ -1001,7 +1004,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
|
||||
}
|
||||
|
||||
if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) {
|
||||
curve_to_filledpoly(cu, nurb, dispbase);
|
||||
curve_to_filledpoly(cu, dispbase);
|
||||
}
|
||||
|
||||
modified = BKE_mesh_new_nomain_from_curve_displist(ob, dispbase);
|
||||
@@ -1126,7 +1129,7 @@ static void displist_surf_indices(DispList *dl)
|
||||
}
|
||||
|
||||
void BKE_displist_make_surf(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
const Scene *scene,
|
||||
Object *ob,
|
||||
ListBase *dispbase,
|
||||
Mesh **r_final,
|
||||
@@ -1230,7 +1233,7 @@ void BKE_displist_make_surf(Depsgraph *depsgraph,
|
||||
if (!for_orco) {
|
||||
BKE_nurbList_duplicate(&ob->runtime.curve_cache->deformed_nurbs, &nubase);
|
||||
curve_calc_modifiers_post(
|
||||
depsgraph, scene, ob, &nubase, dispbase, r_final, for_render, force_mesh_conversion);
|
||||
depsgraph, scene, ob, dispbase, r_final, for_render, force_mesh_conversion);
|
||||
}
|
||||
|
||||
BKE_nurbList_free(&nubase);
|
||||
@@ -1297,7 +1300,10 @@ static void rotateBevelPiece(const Curve *cu,
|
||||
*r_data = data;
|
||||
}
|
||||
|
||||
static void fillBevelCap(Nurb *nu, DispList *dlb, float *prev_fp, ListBase *dispbase)
|
||||
static void fillBevelCap(const Nurb *nu,
|
||||
const DispList *dlb,
|
||||
const float *prev_fp,
|
||||
ListBase *dispbase)
|
||||
{
|
||||
DispList *dl;
|
||||
|
||||
@@ -1320,7 +1326,7 @@ static void fillBevelCap(Nurb *nu, DispList *dlb, float *prev_fp, ListBase *disp
|
||||
}
|
||||
|
||||
static void calc_bevfac_segment_mapping(
|
||||
BevList *bl, float bevfac, float spline_length, int *r_bev, float *r_blend)
|
||||
const BevList *bl, float bevfac, float spline_length, int *r_bev, float *r_blend)
|
||||
{
|
||||
float normlen, normsum = 0.0f;
|
||||
float *seglen = bl->seglen;
|
||||
@@ -1346,7 +1352,7 @@ static void calc_bevfac_segment_mapping(
|
||||
}
|
||||
|
||||
static void calc_bevfac_spline_mapping(
|
||||
BevList *bl, float bevfac, float spline_length, int *r_bev, float *r_blend)
|
||||
const BevList *bl, float bevfac, float spline_length, int *r_bev, float *r_blend)
|
||||
{
|
||||
const float len_target = bevfac * spline_length;
|
||||
BevPoint *bevp = bl->bevpoints;
|
||||
@@ -1368,7 +1374,7 @@ static void calc_bevfac_spline_mapping(
|
||||
}
|
||||
|
||||
static void calc_bevfac_mapping_default(
|
||||
BevList *bl, int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend)
|
||||
const BevList *bl, int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend)
|
||||
{
|
||||
*r_start = 0;
|
||||
*r_steps = bl->nr;
|
||||
@@ -1376,9 +1382,9 @@ static void calc_bevfac_mapping_default(
|
||||
*r_lastblend = 1.0f;
|
||||
}
|
||||
|
||||
static void calc_bevfac_mapping(Curve *cu,
|
||||
BevList *bl,
|
||||
Nurb *nu,
|
||||
static void calc_bevfac_mapping(const Curve *cu,
|
||||
const BevList *bl,
|
||||
const Nurb *nu,
|
||||
int *r_start,
|
||||
float *r_firstblend,
|
||||
int *r_steps,
|
||||
@@ -1456,7 +1462,7 @@ static void calc_bevfac_mapping(Curve *cu,
|
||||
}
|
||||
|
||||
static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
const Scene *scene,
|
||||
Object *ob,
|
||||
ListBase *dispbase,
|
||||
const bool for_render,
|
||||
@@ -1691,7 +1697,7 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
|
||||
}
|
||||
|
||||
if (!(cu->flag & CU_DEFORM_FILL)) {
|
||||
curve_to_filledpoly(cu, &nubase, dispbase);
|
||||
curve_to_filledpoly(cu, dispbase);
|
||||
}
|
||||
|
||||
if (!for_orco) {
|
||||
@@ -1702,19 +1708,22 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
|
||||
|
||||
BKE_nurbList_duplicate(&ob->runtime.curve_cache->deformed_nurbs, &nubase);
|
||||
curve_calc_modifiers_post(
|
||||
depsgraph, scene, ob, &nubase, dispbase, r_final, for_render, force_mesh_conversion);
|
||||
depsgraph, scene, ob, dispbase, r_final, for_render, force_mesh_conversion);
|
||||
}
|
||||
|
||||
if (cu->flag & CU_DEFORM_FILL && !ob->runtime.data_eval) {
|
||||
curve_to_filledpoly(cu, &nubase, dispbase);
|
||||
curve_to_filledpoly(cu, dispbase);
|
||||
}
|
||||
|
||||
BKE_nurbList_free(&nubase);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_displist_make_curveTypes(
|
||||
Depsgraph *depsgraph, Scene *scene, Object *ob, const bool for_render, const bool for_orco)
|
||||
void BKE_displist_make_curveTypes(Depsgraph *depsgraph,
|
||||
const Scene *scene,
|
||||
Object *ob,
|
||||
const bool for_render,
|
||||
const bool for_orco)
|
||||
{
|
||||
ListBase *dispbase;
|
||||
|
||||
@@ -1744,7 +1753,7 @@ void BKE_displist_make_curveTypes(
|
||||
}
|
||||
|
||||
void BKE_displist_make_curveTypes_forRender(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
const Scene *scene,
|
||||
Object *ob,
|
||||
ListBase *dispbase,
|
||||
Mesh **r_final,
|
||||
@@ -1757,13 +1766,13 @@ void BKE_displist_make_curveTypes_forRender(Depsgraph *depsgraph,
|
||||
do_makeDispListCurveTypes(depsgraph, scene, ob, dispbase, true, for_orco, r_final);
|
||||
}
|
||||
|
||||
void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3])
|
||||
void BKE_displist_minmax(const ListBase *dispbase, float min[3], float max[3])
|
||||
{
|
||||
const float *vert;
|
||||
int a, tot = 0;
|
||||
int doit = 0;
|
||||
|
||||
LISTBASE_FOREACH (DispList *, dl, dispbase) {
|
||||
LISTBASE_FOREACH (const DispList *, dl, dispbase) {
|
||||
tot = (dl->type == DL_INDEX3) ? dl->nr : dl->nr * dl->parts;
|
||||
vert = dl->verts;
|
||||
for (a = 0; a < tot; a++, vert += 3) {
|
||||
|
@@ -108,6 +108,16 @@ bool InstancesComponent::is_empty() const
|
||||
return transforms_.size() == 0;
|
||||
}
|
||||
|
||||
bool InstancesComponent::owns_direct_data() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void InstancesComponent::ensure_owns_direct_data()
|
||||
{
|
||||
BLI_assert(this->is_mutable());
|
||||
}
|
||||
|
||||
static blender::Array<int> generate_unique_instance_ids(Span<int> original_ids)
|
||||
{
|
||||
using namespace blender;
|
||||
|
@@ -157,6 +157,20 @@ bool MeshComponent::is_empty() const
|
||||
return mesh_ == nullptr;
|
||||
}
|
||||
|
||||
bool MeshComponent::owns_direct_data() const
|
||||
{
|
||||
return ownership_ == GeometryOwnershipType::Owned;
|
||||
}
|
||||
|
||||
void MeshComponent::ensure_owns_direct_data()
|
||||
{
|
||||
BLI_assert(this->is_mutable());
|
||||
if (ownership_ != GeometryOwnershipType::Owned) {
|
||||
mesh_ = BKE_mesh_copy_for_eval(mesh_, false);
|
||||
ownership_ = GeometryOwnershipType::Owned;
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@@ -107,6 +107,20 @@ bool PointCloudComponent::is_empty() const
|
||||
return pointcloud_ == nullptr;
|
||||
}
|
||||
|
||||
bool PointCloudComponent::owns_direct_data() const
|
||||
{
|
||||
return ownership_ == GeometryOwnershipType::Owned;
|
||||
}
|
||||
|
||||
void PointCloudComponent::ensure_owns_direct_data()
|
||||
{
|
||||
BLI_assert(this->is_mutable());
|
||||
if (ownership_ != GeometryOwnershipType::Owned) {
|
||||
pointcloud_ = BKE_pointcloud_copy_for_eval(pointcloud_, false);
|
||||
ownership_ = GeometryOwnershipType::Owned;
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@@ -97,4 +97,18 @@ Volume *VolumeComponent::get_for_write()
|
||||
return volume_;
|
||||
}
|
||||
|
||||
bool VolumeComponent::owns_direct_data() const
|
||||
{
|
||||
return ownership_ == GeometryOwnershipType::Owned;
|
||||
}
|
||||
|
||||
void VolumeComponent::ensure_owns_direct_data()
|
||||
{
|
||||
BLI_assert(this->is_mutable());
|
||||
if (ownership_ != GeometryOwnershipType::Owned) {
|
||||
volume_ = BKE_volume_copy_for_eval(volume_, false);
|
||||
ownership_ = GeometryOwnershipType::Owned;
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@@ -211,6 +211,19 @@ void GeometrySet::clear()
|
||||
components_.clear();
|
||||
}
|
||||
|
||||
/* Make sure that the geometry can be cached. This does not ensure ownership of object/collection
|
||||
* instances. */
|
||||
void GeometrySet::ensure_owns_direct_data()
|
||||
{
|
||||
for (GeometryComponentType type : components_.keys()) {
|
||||
const GeometryComponent *component = this->get_component_for_read(type);
|
||||
if (!component->owns_direct_data()) {
|
||||
GeometryComponent &component_for_write = this->get_component_for_write(type);
|
||||
component_for_write.ensure_owns_direct_data();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns a read-only mesh or null. */
|
||||
const Mesh *GeometrySet::get_mesh_for_read() const
|
||||
{
|
||||
|
@@ -94,6 +94,7 @@ static void lattice_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const i
|
||||
}
|
||||
|
||||
lattice_dst->editlatt = NULL;
|
||||
lattice_dst->batch_cache = NULL;
|
||||
}
|
||||
|
||||
static void lattice_free_data(ID *id)
|
||||
|
@@ -1756,6 +1756,10 @@ void BKE_object_free_derived_caches(Object *ob)
|
||||
BKE_geometry_set_free(ob->runtime.geometry_set_eval);
|
||||
ob->runtime.geometry_set_eval = NULL;
|
||||
}
|
||||
if (ob->runtime.geometry_set_preview != NULL) {
|
||||
BKE_geometry_set_free(ob->runtime.geometry_set_preview);
|
||||
ob->runtime.geometry_set_preview = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_object_free_caches(Object *object)
|
||||
@@ -1806,6 +1810,18 @@ void BKE_object_free_caches(Object *object)
|
||||
}
|
||||
}
|
||||
|
||||
/* Can be called from multiple threads. */
|
||||
void BKE_object_preview_geometry_set(Object *ob, struct GeometrySet *geometry_set)
|
||||
{
|
||||
static ThreadMutex mutex = BLI_MUTEX_INITIALIZER;
|
||||
BLI_mutex_lock(&mutex);
|
||||
if (ob->runtime.geometry_set_preview != NULL) {
|
||||
BKE_geometry_set_free(ob->runtime.geometry_set_preview);
|
||||
}
|
||||
ob->runtime.geometry_set_preview = geometry_set;
|
||||
BLI_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actual check for internal data, not context or flags.
|
||||
*/
|
||||
|
@@ -16,6 +16,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
@@ -139,6 +140,29 @@ template<typename Ret, typename... Params> class FunctionRef<Ret(Params...)> {
|
||||
return callback_(callable_, std::forward<Params>(params)...);
|
||||
}
|
||||
|
||||
using OptionalReturnValue = std::conditional_t<std::is_void_v<Ret>, void, std::optional<Ret>>;
|
||||
|
||||
/**
|
||||
* Calls the referenced function if it is available.
|
||||
* The return value is of type `std::optional<Ret>` if `Ret` is not `void`.
|
||||
* Otherwise the return type is `void`.
|
||||
*/
|
||||
OptionalReturnValue call_safe(Params... params) const
|
||||
{
|
||||
if constexpr (std::is_void_v<Ret>) {
|
||||
if (callback_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
callback_(callable_, std::forward<Params>(params)...);
|
||||
}
|
||||
else {
|
||||
if (callback_ == nullptr) {
|
||||
return {};
|
||||
}
|
||||
return callback_(callable_, std::forward<Params>(params)...);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, when the `FunctionRef` references a function currently.
|
||||
* If this returns false, the `FunctionRef` must not be called.
|
||||
|
@@ -133,6 +133,9 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya
|
||||
*/
|
||||
template<typename T> MutableSpan<T> construct_array_copy(Span<T> src)
|
||||
{
|
||||
if (src.is_empty()) {
|
||||
return {};
|
||||
}
|
||||
MutableSpan<T> dst = this->allocate_array<T>(src.size());
|
||||
uninitialized_copy_n(src.data(), src.size(), dst.data());
|
||||
return dst;
|
||||
|
@@ -266,6 +266,9 @@ void orthogonalize_m4(float R[4][4], int axis);
|
||||
void orthogonalize_m3_stable(float R[3][3], int axis, bool normalize);
|
||||
void orthogonalize_m4_stable(float R[4][4], int axis, bool normalize);
|
||||
|
||||
bool orthogonalize_m3_zero_axes(float R[3][3], const float unit_length);
|
||||
bool orthogonalize_m4_zero_axes(float R[4][4], const float unit_length);
|
||||
|
||||
bool is_orthogonal_m3(const float mat[3][3]);
|
||||
bool is_orthogonal_m4(const float mat[4][4]);
|
||||
bool is_orthonormal_m3(const float mat[3][3]);
|
||||
|
@@ -17,13 +17,13 @@
|
||||
/** \file
|
||||
* \ingroup bli
|
||||
*
|
||||
* Common implementation of linked-list a non-recursive mergesort.
|
||||
* Common implementation of linked-list a non-recursive merge-sort.
|
||||
*
|
||||
* Originally from Mono's eglib, adapted for portable inclusion.
|
||||
* Originally from Mono's `eglib`, adapted for portable inclusion.
|
||||
* This file is to be directly included in C-source,
|
||||
* with defines to control its use.
|
||||
*
|
||||
* This code requires a typedef named `SORT_IMPL_LINKTYPE` for the list node.
|
||||
* This code requires a `typedef` named `SORT_IMPL_LINKTYPE` for the list node.
|
||||
* It is assumed that the list type is the type of a pointer to a list
|
||||
* node, and that the node has a field named 'next' that implements to
|
||||
* the linked list. No additional invariant is maintained
|
||||
|
@@ -1700,6 +1700,89 @@ void orthogonalize_m4_stable(float R[4][4], int axis, bool normalize)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Orthogonalize Matrix Zeroed Axes
|
||||
*
|
||||
* Set any zeroed axes to an orthogonal vector in relation to the other axes.
|
||||
*
|
||||
* Typically used so matrix inversion can be performed.
|
||||
*
|
||||
* \note If an object has a zero scaled axis, this function can be used to "clean" the matrix
|
||||
* to behave as if the scale on that axis was `unit_length`. So it can be inverted
|
||||
* or used in matrix multiply without creating degenerate matrices, see: T50103
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* \return true if any axis needed to be modified.
|
||||
*/
|
||||
static bool orthogonalize_m3_zero_axes_impl(float *mat[3], const float unit_length)
|
||||
{
|
||||
enum { X = 1 << 0, Y = 1 << 1, Z = 1 << 2 };
|
||||
int flag = 0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
flag |= (len_squared_v3(mat[i]) == 0.0f) ? (1 << i) : 0;
|
||||
}
|
||||
|
||||
/* Either all or none are zero, either way we can't properly resolve this
|
||||
* since we need to fill invalid axes from valid ones. */
|
||||
if (ELEM(flag, 0, X | Y | Z)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (flag) {
|
||||
case X | Y: {
|
||||
ortho_v3_v3(mat[1], mat[2]);
|
||||
ATTR_FALLTHROUGH;
|
||||
}
|
||||
case X: {
|
||||
cross_v3_v3v3(mat[0], mat[1], mat[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
case Y | Z: {
|
||||
ortho_v3_v3(mat[2], mat[0]);
|
||||
ATTR_FALLTHROUGH;
|
||||
}
|
||||
case Y: {
|
||||
cross_v3_v3v3(mat[1], mat[0], mat[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
case Z | X: {
|
||||
ortho_v3_v3(mat[0], mat[1]);
|
||||
ATTR_FALLTHROUGH;
|
||||
}
|
||||
case Z: {
|
||||
cross_v3_v3v3(mat[2], mat[0], mat[1]);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
BLI_assert(0); /* Unreachable! */
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (flag & (1 << i)) {
|
||||
if (UNLIKELY(normalize_v3_length(mat[i], unit_length) == 0.0f)) {
|
||||
mat[i][i] = unit_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool orthogonalize_m3_zero_axes(float m[3][3], const float unit_length)
|
||||
{
|
||||
return orthogonalize_m3_zero_axes_impl((float *[3]){UNPACK3(m)}, unit_length);
|
||||
}
|
||||
bool orthogonalize_m4_zero_axes(float m[4][4], const float unit_length)
|
||||
{
|
||||
return orthogonalize_m3_zero_axes_impl((float *[3]){UNPACK3(m)}, unit_length);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
bool is_orthogonal_m3(const float m[3][3])
|
||||
{
|
||||
int i, j;
|
||||
@@ -3195,68 +3278,6 @@ void invert_m4_m4_safe(float Ainv[4][4], const float A[4][4])
|
||||
* where we want to specify the length of the degenerate axes.
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Return true if invert should be attempted again.
|
||||
*
|
||||
* \note Takes an array of points to be usable from 3x3 and 4x4 matrices.
|
||||
*/
|
||||
static bool invert_m3_m3_safe_ortho_prepare(float *mat[3])
|
||||
{
|
||||
enum { X = 1 << 0, Y = 1 << 1, Z = 1 << 2 };
|
||||
int flag = 0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
flag |= (len_squared_v3(mat[i]) == 0.0f) ? (1 << i) : 0;
|
||||
}
|
||||
|
||||
/* Either all or none are zero, either way we can't properly resolve this
|
||||
* since we need to fill invalid axes from valid ones. */
|
||||
if (ELEM(flag, 0, X | Y | Z)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (flag) {
|
||||
case X | Y: {
|
||||
ortho_v3_v3(mat[1], mat[2]);
|
||||
ATTR_FALLTHROUGH;
|
||||
}
|
||||
case X: {
|
||||
cross_v3_v3v3(mat[0], mat[1], mat[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
case Y | Z: {
|
||||
ortho_v3_v3(mat[2], mat[0]);
|
||||
ATTR_FALLTHROUGH;
|
||||
}
|
||||
case Y: {
|
||||
cross_v3_v3v3(mat[1], mat[0], mat[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
case Z | X: {
|
||||
ortho_v3_v3(mat[0], mat[1]);
|
||||
ATTR_FALLTHROUGH;
|
||||
}
|
||||
case Z: {
|
||||
cross_v3_v3v3(mat[2], mat[0], mat[1]);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
BLI_assert(0); /* Unreachable! */
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (flag & (1 << i)) {
|
||||
if (UNLIKELY(normalize_v3(mat[i]) == 0.0f)) {
|
||||
mat[i][i] = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A safe version of invert that uses valid axes, calculating the zero'd axis
|
||||
* based on the non-zero ones.
|
||||
@@ -3268,8 +3289,7 @@ void invert_m4_m4_safe_ortho(float Ainv[4][4], const float A[4][4])
|
||||
if (UNLIKELY(!invert_m4_m4(Ainv, A))) {
|
||||
float Atemp[4][4];
|
||||
copy_m4_m4(Atemp, A);
|
||||
if (UNLIKELY(!(invert_m3_m3_safe_ortho_prepare((float *[3]){UNPACK3(Atemp)}) &&
|
||||
invert_m4_m4(Ainv, Atemp)))) {
|
||||
if (UNLIKELY(!(orthogonalize_m4_zero_axes(Atemp, 1.0f) && invert_m4_m4(Ainv, Atemp)))) {
|
||||
unit_m4(Ainv);
|
||||
}
|
||||
}
|
||||
@@ -3280,8 +3300,7 @@ void invert_m3_m3_safe_ortho(float Ainv[3][3], const float A[3][3])
|
||||
if (UNLIKELY(!invert_m3_m3(Ainv, A))) {
|
||||
float Atemp[3][3];
|
||||
copy_m3_m3(Atemp, A);
|
||||
if (UNLIKELY(!(invert_m3_m3_safe_ortho_prepare((float *[3]){UNPACK3(Atemp)}) &&
|
||||
invert_m3_m3(Ainv, Atemp)))) {
|
||||
if (UNLIKELY(!(orthogonalize_m3_zero_axes(Atemp, 1.0f) && invert_m3_m3(Ainv, Atemp)))) {
|
||||
unit_m3(Ainv);
|
||||
}
|
||||
}
|
||||
|
@@ -1121,7 +1121,7 @@ static float voronoi_CrS(float x, float y, float z)
|
||||
/** \name Cell-Noise Implementation
|
||||
* \{ */
|
||||
|
||||
/* returns unsigned cellnoise */
|
||||
/** Returns unsigned cell-noise. */
|
||||
static float BLI_cellNoiseU(float x, float y, float z)
|
||||
{
|
||||
/* avoid precision issues on unit coordinates */
|
||||
@@ -1166,7 +1166,9 @@ void BLI_noise_cell_v3(float x, float y, float z, float ca[3])
|
||||
/** \name Public API's
|
||||
* \{ */
|
||||
|
||||
/* newnoise: generic noise function for use with different noisebases */
|
||||
/**
|
||||
* newnoise: generic noise function for use with different `noisebasis`.
|
||||
*/
|
||||
float BLI_noise_generic_noise(
|
||||
float noisesize, float x, float y, float z, bool hard, int noisebasis)
|
||||
{
|
||||
|
@@ -1044,17 +1044,17 @@ bool BLI_path_abs(char *path, const char *basepath)
|
||||
#else
|
||||
BLI_strncpy(tmp, path, sizeof(tmp));
|
||||
|
||||
/* Check for loading a windows path on a posix system
|
||||
* in this case, there is no use in trying C:/ since it
|
||||
* will never exist on a unix os.
|
||||
/* Check for loading a MS-Windows path on a POSIX system
|
||||
* in this case, there is no use in trying `C:/` since it
|
||||
* will never exist on a Unix system.
|
||||
*
|
||||
* Add a '/' prefix and lowercase the drive-letter, remove the ':'.
|
||||
* C:\foo.JPG -> /c/foo.JPG */
|
||||
* Add a `/` prefix and lowercase the drive-letter, remove the `:`.
|
||||
* `C:\foo.JPG` -> `/c/foo.JPG` */
|
||||
|
||||
if (isalpha(tmp[0]) && (tmp[1] == ':') && ELEM(tmp[2], '\\', '/')) {
|
||||
tmp[1] = tolower(tmp[0]); /* Replace ':' with drive-letter. */
|
||||
tmp[0] = '/';
|
||||
/* '\' the slash will be converted later */
|
||||
/* `\` the slash will be converted later. */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -99,4 +99,29 @@ TEST(function_ref, ReferenceAnotherFunctionRef)
|
||||
EXPECT_EQ(y(), 2);
|
||||
}
|
||||
|
||||
TEST(function_ref, CallSafe)
|
||||
{
|
||||
FunctionRef<int()> f;
|
||||
EXPECT_FALSE(f.call_safe().has_value());
|
||||
auto func = []() { return 10; };
|
||||
f = func;
|
||||
EXPECT_TRUE(f.call_safe().has_value());
|
||||
EXPECT_EQ(*f.call_safe(), 10);
|
||||
f = {};
|
||||
EXPECT_FALSE(f.call_safe().has_value());
|
||||
BLI_STATIC_ASSERT((std::is_same_v<decltype(f.call_safe()), std::optional<int>>), "");
|
||||
}
|
||||
|
||||
TEST(function_ref, CallSafeVoid)
|
||||
{
|
||||
FunctionRef<void()> f;
|
||||
BLI_STATIC_ASSERT((std::is_same_v<decltype(f.call_safe()), void>), "");
|
||||
f.call_safe();
|
||||
int value = 0;
|
||||
auto func = [&]() { value++; };
|
||||
f = func;
|
||||
f.call_safe();
|
||||
EXPECT_EQ(value, 1);
|
||||
}
|
||||
|
||||
} // namespace blender::tests
|
||||
|
@@ -1814,7 +1814,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 280, 1)) {
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "bleedexp")) {
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "bleedexp")) {
|
||||
for (Light *la = bmain->lights.first; la; la = la->id.next) {
|
||||
la->bleedexp = 2.5f;
|
||||
}
|
||||
@@ -1840,7 +1840,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 280, 2)) {
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "cascade_max_dist")) {
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "cascade_max_dist")) {
|
||||
for (Light *la = bmain->lights.first; la; la = la->id.next) {
|
||||
la->cascade_max_dist = 1000.0f;
|
||||
la->cascade_count = 4;
|
||||
@@ -1849,7 +1849,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
}
|
||||
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "contact_dist")) {
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "contact_dist")) {
|
||||
for (Light *la = bmain->lights.first; la; la = la->id.next) {
|
||||
la->contact_dist = 0.2f;
|
||||
la->contact_bias = 0.03f;
|
||||
@@ -2185,7 +2185,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 280, 13)) {
|
||||
/* Initialize specular factor. */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "spec_fac")) {
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "spec_fac")) {
|
||||
for (Light *la = bmain->lights.first; la; la = la->id.next) {
|
||||
la->spec_fac = 1.0f;
|
||||
}
|
||||
@@ -3135,7 +3135,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
}
|
||||
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "att_dist")) {
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "att_dist")) {
|
||||
for (Light *la = bmain->lights.first; la; la = la->id.next) {
|
||||
la->att_dist = la->clipend;
|
||||
}
|
||||
@@ -4051,7 +4051,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
|
||||
/* Initializes sun lights with the new angular diameter property */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "sun_angle")) {
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "sun_angle")) {
|
||||
LISTBASE_FOREACH (Light *, light, &bmain->lights) {
|
||||
light->sun_angle = 2.0f * atanf(light->area_size);
|
||||
}
|
||||
|
@@ -1908,7 +1908,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 293, 14)) {
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "diff_fac")) {
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "diff_fac")) {
|
||||
LISTBASE_FOREACH (Light *, light, &bmain->lights) {
|
||||
light->diff_fac = 1.0f;
|
||||
light->volume_fac = 1.0f;
|
||||
@@ -1963,5 +1963,25 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
arm->axes_position = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the spread parameter for area lights*/
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "area_spread")) {
|
||||
LISTBASE_FOREACH (Light *, la, &bmain->lights) {
|
||||
la->area_spread = DEG2RADF(180.0f);
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
|
||||
if (sl->spacetype == SPACE_NODE) {
|
||||
SpaceNode *snode = (SpaceNode *)sl;
|
||||
LISTBASE_FOREACH (bNodeTreePath *, path, &snode->treepath) {
|
||||
STRNCPY(path->display_name, path->node_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -121,11 +121,9 @@ NodeOperation *ExecutionGroup::getOutputOperation() const
|
||||
->m_operations[0]; /* the first operation of the group is always the output operation. */
|
||||
}
|
||||
|
||||
void ExecutionGroup::initExecution()
|
||||
void ExecutionGroup::init_work_packages()
|
||||
{
|
||||
m_work_packages.clear();
|
||||
determineNumberOfChunks();
|
||||
|
||||
if (this->m_chunks_len != 0) {
|
||||
m_work_packages.resize(this->m_chunks_len);
|
||||
for (unsigned int index = 0; index < m_chunks_len; index++) {
|
||||
@@ -135,9 +133,11 @@ void ExecutionGroup::initExecution()
|
||||
determineChunkRect(&m_work_packages[index].rect, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExecutionGroup::init_read_buffer_operations()
|
||||
{
|
||||
unsigned int max_offset = 0;
|
||||
|
||||
for (NodeOperation *operation : m_operations) {
|
||||
if (operation->get_flags().is_read_buffer_operation) {
|
||||
ReadBufferOperation *readOperation = static_cast<ReadBufferOperation *>(operation);
|
||||
@@ -149,6 +149,13 @@ void ExecutionGroup::initExecution()
|
||||
this->m_max_read_buffer_offset = max_offset;
|
||||
}
|
||||
|
||||
void ExecutionGroup::initExecution()
|
||||
{
|
||||
init_number_of_chunks();
|
||||
init_work_packages();
|
||||
init_read_buffer_operations();
|
||||
}
|
||||
|
||||
void ExecutionGroup::deinitExecution()
|
||||
{
|
||||
m_work_packages.clear();
|
||||
@@ -158,6 +165,7 @@ void ExecutionGroup::deinitExecution()
|
||||
this->m_read_operations.clear();
|
||||
this->m_bTree = nullptr;
|
||||
}
|
||||
|
||||
void ExecutionGroup::determineResolution(unsigned int resolution[2])
|
||||
{
|
||||
NodeOperation *operation = this->getOutputOperation();
|
||||
@@ -167,7 +175,7 @@ void ExecutionGroup::determineResolution(unsigned int resolution[2])
|
||||
BLI_rcti_init(&this->m_viewerBorder, 0, this->m_width, 0, this->m_height);
|
||||
}
|
||||
|
||||
void ExecutionGroup::determineNumberOfChunks()
|
||||
void ExecutionGroup::init_number_of_chunks()
|
||||
{
|
||||
if (this->m_flags.single_threaded) {
|
||||
this->m_x_chunks_len = 1;
|
||||
@@ -184,7 +192,7 @@ void ExecutionGroup::determineNumberOfChunks()
|
||||
}
|
||||
}
|
||||
|
||||
blender::Array<unsigned int> ExecutionGroup::determine_chunk_execution_order() const
|
||||
blender::Array<unsigned int> ExecutionGroup::get_execution_order() const
|
||||
{
|
||||
blender::Array<unsigned int> chunk_order(m_chunks_len);
|
||||
for (int chunk_index = 0; chunk_index < this->m_chunks_len; chunk_index++) {
|
||||
@@ -302,7 +310,7 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
|
||||
this->m_chunks_finished = 0;
|
||||
this->m_bTree = bTree;
|
||||
|
||||
blender::Array<unsigned int> chunk_order = determine_chunk_execution_order();
|
||||
blender::Array<unsigned int> chunk_order = get_execution_order();
|
||||
|
||||
DebugInfo::execution_group_started(this);
|
||||
DebugInfo::graphviz(graph);
|
||||
|
@@ -178,7 +178,7 @@ class ExecutionGroup {
|
||||
* \brief determine the number of chunks, based on the chunkSize, width and height.
|
||||
* \note The result are stored in the fields numberOfChunks, numberOfXChunks, numberOfYChunks
|
||||
*/
|
||||
void determineNumberOfChunks();
|
||||
void init_number_of_chunks();
|
||||
|
||||
/**
|
||||
* \brief try to schedule a specific chunk.
|
||||
@@ -225,7 +225,10 @@ class ExecutionGroup {
|
||||
/**
|
||||
* Return the execution order of the user visible chunks.
|
||||
*/
|
||||
blender::Array<unsigned int> determine_chunk_execution_order() const;
|
||||
blender::Array<unsigned int> get_execution_order() const;
|
||||
|
||||
void init_read_buffer_operations();
|
||||
void init_work_packages();
|
||||
|
||||
public:
|
||||
// constructors
|
||||
|
@@ -63,12 +63,12 @@ class Node {
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief the list of actual inputsockets \see NodeInput
|
||||
* \brief the list of actual input-sockets \see NodeInput
|
||||
*/
|
||||
blender::Vector<NodeInput *> inputs;
|
||||
|
||||
/**
|
||||
* \brief the list of actual outputsockets \see NodeOutput
|
||||
* \brief the list of actual output-sockets \see NodeOutput
|
||||
*/
|
||||
blender::Vector<NodeOutput *> outputs;
|
||||
|
||||
@@ -184,7 +184,7 @@ class Node {
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief add an NodeInput to the collection of inputsockets
|
||||
* \brief add an NodeInput to the collection of input-sockets
|
||||
* \note may only be called in an constructor
|
||||
* \param socket: the NodeInput to add
|
||||
*/
|
||||
@@ -192,7 +192,7 @@ class Node {
|
||||
void addInputSocket(DataType datatype, bNodeSocket *socket);
|
||||
|
||||
/**
|
||||
* \brief add an NodeOutput to the collection of outputsockets
|
||||
* \brief add an NodeOutput to the collection of output-sockets
|
||||
* \note may only be called in an constructor
|
||||
* \param socket: the NodeOutput to add
|
||||
*/
|
||||
|
@@ -4863,6 +4863,11 @@ static int userpref_show_exec(bContext *C, wmOperator *op)
|
||||
region->flag |= RGN_FLAG_HIDDEN;
|
||||
ED_region_visibility_change_update(C, area, region);
|
||||
|
||||
/* And also show the region with "Load & Save" buttons. */
|
||||
region = BKE_area_find_region_type(area, RGN_TYPE_EXECUTE);
|
||||
region->flag &= ~RGN_FLAG_HIDDEN;
|
||||
ED_region_visibility_change_update(C, area, region);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
BKE_report(op->reports, RPT_ERROR, "Failed to open window!");
|
||||
|
@@ -648,6 +648,19 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static char *actkeys_paste_description(bContext *UNUSED(C),
|
||||
wmOperatorType *UNUSED(op),
|
||||
PointerRNA *ptr)
|
||||
{
|
||||
/* Custom description if the 'flipped' option is used. */
|
||||
if (RNA_boolean_get(ptr, "flipped")) {
|
||||
return BLI_strdup("Paste keyframes from mirrored bones if they exist");
|
||||
}
|
||||
|
||||
/* Use the default description in the other cases. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ACTION_OT_paste(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
@@ -660,6 +673,7 @@ void ACTION_OT_paste(wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
// ot->invoke = WM_operator_props_popup; // better wait for action redo panel
|
||||
ot->get_description = actkeys_paste_description;
|
||||
ot->exec = actkeys_paste_exec;
|
||||
ot->poll = ED_operator_action_active;
|
||||
|
||||
|
@@ -578,6 +578,19 @@ static int graphkeys_paste_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static char *graphkeys_paste_description(bContext *UNUSED(C),
|
||||
wmOperatorType *UNUSED(op),
|
||||
PointerRNA *ptr)
|
||||
{
|
||||
/* Custom description if the 'flipped' option is used. */
|
||||
if (RNA_boolean_get(ptr, "flipped")) {
|
||||
return BLI_strdup("Paste keyframes from mirrored bones if they exist");
|
||||
}
|
||||
|
||||
/* Use the default description in the other cases. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GRAPH_OT_paste(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
@@ -592,6 +605,7 @@ void GRAPH_OT_paste(wmOperatorType *ot)
|
||||
/* API callbacks */
|
||||
|
||||
// ot->invoke = WM_operator_props_popup; /* better wait for graph redo panel */
|
||||
ot->get_description = graphkeys_paste_description;
|
||||
ot->exec = graphkeys_paste_exec;
|
||||
ot->poll = graphop_editable_keyframes_poll;
|
||||
|
||||
|
@@ -1959,8 +1959,8 @@ void node_draw_space(const bContext *C, ARegion *region)
|
||||
ID *name_id = (path->nodetree && path->nodetree != snode->nodetree) ? &path->nodetree->id :
|
||||
snode->id;
|
||||
|
||||
if (name_id && UNLIKELY(!STREQ(path->node_name, name_id->name + 2))) {
|
||||
BLI_strncpy(path->node_name, name_id->name + 2, sizeof(path->node_name));
|
||||
if (name_id && UNLIKELY(!STREQ(path->display_name, name_id->name + 2))) {
|
||||
BLI_strncpy(path->display_name, name_id->name + 2, sizeof(path->display_name));
|
||||
}
|
||||
|
||||
/* Current View2D center, will be set temporarily for parent node trees. */
|
||||
|
@@ -41,6 +41,7 @@
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_workspace.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_build.h"
|
||||
@@ -670,6 +671,21 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti
|
||||
|
||||
nodeSetActive(ntree, node);
|
||||
|
||||
/* Tag for update, so that dependend objects are reevaluated. This is necessary when a
|
||||
* spreadsheet editor displays data from a node. */
|
||||
LISTBASE_FOREACH (wmWindow *, window, &((wmWindowManager *)bmain->wm.first)->windows) {
|
||||
bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
if (area->spacetype == SPACE_SPREADSHEET) {
|
||||
SpaceSpreadsheet *sspreadsheet = area->spacedata.first;
|
||||
if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_NODE) {
|
||||
DEG_id_tag_update(&ntree->id, ID_RECALC_COPY_ON_WRITE);
|
||||
ED_area_tag_redraw(area);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node->type != NODE_GROUP) {
|
||||
const bool was_output = (node->flag & NODE_DO_OUTPUT) != 0;
|
||||
bool do_update = false;
|
||||
|
@@ -74,7 +74,7 @@ void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from)
|
||||
copy_v2_v2(path->view_center, ntree->view_center);
|
||||
|
||||
if (id) {
|
||||
BLI_strncpy(path->node_name, id->name + 2, sizeof(path->node_name));
|
||||
BLI_strncpy(path->display_name, id->name + 2, sizeof(path->display_name));
|
||||
}
|
||||
|
||||
BLI_addtail(&snode->treepath, path);
|
||||
@@ -111,6 +111,7 @@ void ED_node_tree_push(SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
|
||||
}
|
||||
|
||||
BLI_strncpy(path->node_name, gnode->name, sizeof(path->node_name));
|
||||
BLI_strncpy(path->display_name, gnode->name, sizeof(path->display_name));
|
||||
}
|
||||
else {
|
||||
path->parent_key = NODE_INSTANCE_KEY_BASE;
|
||||
@@ -175,7 +176,7 @@ int ED_node_tree_path_length(SpaceNode *snode)
|
||||
int length = 0;
|
||||
int i = 0;
|
||||
LISTBASE_FOREACH_INDEX (bNodeTreePath *, path, &snode->treepath, i) {
|
||||
length += strlen(path->node_name);
|
||||
length += strlen(path->display_name);
|
||||
if (i > 0) {
|
||||
length += 1; /* for separator char */
|
||||
}
|
||||
@@ -190,12 +191,12 @@ void ED_node_tree_path_get(SpaceNode *snode, char *value)
|
||||
value[0] = '\0';
|
||||
LISTBASE_FOREACH_INDEX (bNodeTreePath *, path, &snode->treepath, i) {
|
||||
if (i == 0) {
|
||||
strcpy(value, path->node_name);
|
||||
value += strlen(path->node_name);
|
||||
strcpy(value, path->display_name);
|
||||
value += strlen(path->display_name);
|
||||
}
|
||||
else {
|
||||
sprintf(value, "/%s", path->node_name);
|
||||
value += strlen(path->node_name) + 1;
|
||||
sprintf(value, "/%s", path->display_name);
|
||||
value += strlen(path->display_name) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -208,10 +209,10 @@ void ED_node_tree_path_get_fixedbuf(SpaceNode *snode, char *value, int max_lengt
|
||||
int i = 0;
|
||||
LISTBASE_FOREACH_INDEX (bNodeTreePath *, path, &snode->treepath, i) {
|
||||
if (i == 0) {
|
||||
size = BLI_strncpy_rlen(value, path->node_name, max_length);
|
||||
size = BLI_strncpy_rlen(value, path->display_name, max_length);
|
||||
}
|
||||
else {
|
||||
size = BLI_snprintf_rlen(value, max_length, "/%s", path->node_name);
|
||||
size = BLI_snprintf_rlen(value, max_length, "/%s", path->display_name);
|
||||
}
|
||||
max_length -= size;
|
||||
if (max_length <= 0) {
|
||||
|
@@ -1104,7 +1104,7 @@ static bool collection_drop_init(bContext *C,
|
||||
const wmEvent *event,
|
||||
CollectionDrop *data)
|
||||
{
|
||||
/* Get collection to drop into. */
|
||||
/* Get collection to drop into. */
|
||||
TreeElementInsertType insert_type;
|
||||
TreeElement *te = outliner_drop_insert_collection_find(C, event, &insert_type);
|
||||
if (!te) {
|
||||
|
@@ -200,25 +200,7 @@ static GeometrySet get_display_geometry_set(SpaceSpreadsheet *sspreadsheet,
|
||||
const GeometryComponentType used_component_type)
|
||||
{
|
||||
GeometrySet geometry_set;
|
||||
if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_FINAL) {
|
||||
if (used_component_type == GEO_COMPONENT_TYPE_MESH && object_eval->mode == OB_MODE_EDIT) {
|
||||
Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(object_eval, false);
|
||||
if (mesh == nullptr) {
|
||||
return geometry_set;
|
||||
}
|
||||
BKE_mesh_wrapper_ensure_mdata(mesh);
|
||||
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
|
||||
mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly);
|
||||
mesh_component.copy_vertex_group_names_from_object(*object_eval);
|
||||
}
|
||||
else {
|
||||
if (object_eval->runtime.geometry_set_eval != nullptr) {
|
||||
/* This does not copy the geometry data itself. */
|
||||
geometry_set = *object_eval->runtime.geometry_set_eval;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL) {
|
||||
Object *object_orig = DEG_get_original_object(object_eval);
|
||||
if (object_orig->type == OB_MESH) {
|
||||
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
|
||||
@@ -247,6 +229,30 @@ static GeometrySet get_display_geometry_set(SpaceSpreadsheet *sspreadsheet,
|
||||
pointcloud_component.replace(pointcloud, GeometryOwnershipType::ReadOnly);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (used_component_type == GEO_COMPONENT_TYPE_MESH && object_eval->mode == OB_MODE_EDIT) {
|
||||
Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(object_eval, false);
|
||||
if (mesh == nullptr) {
|
||||
return geometry_set;
|
||||
}
|
||||
BKE_mesh_wrapper_ensure_mdata(mesh);
|
||||
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
|
||||
mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly);
|
||||
mesh_component.copy_vertex_group_names_from_object(*object_eval);
|
||||
}
|
||||
else {
|
||||
if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_NODE) {
|
||||
if (object_eval->runtime.geometry_set_preview != nullptr) {
|
||||
geometry_set = *object_eval->runtime.geometry_set_preview;
|
||||
}
|
||||
}
|
||||
else if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_FINAL) {
|
||||
if (object_eval->runtime.geometry_set_eval != nullptr) {
|
||||
geometry_set = *object_eval->runtime.geometry_set_eval;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return geometry_set;
|
||||
}
|
||||
|
||||
@@ -377,7 +383,7 @@ static Span<int64_t> filter_mesh_elements_by_selection(const bContext *C,
|
||||
static GeometryComponentType get_display_component_type(const bContext *C, Object *object_eval)
|
||||
{
|
||||
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
|
||||
if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_FINAL) {
|
||||
if (sspreadsheet->object_eval_state != SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL) {
|
||||
return (GeometryComponentType)sspreadsheet->geometry_component_type;
|
||||
}
|
||||
if (object_eval->type == OB_POINTCLOUD) {
|
||||
|
@@ -79,7 +79,7 @@ static SpaceLink *userpref_create(const ScrArea *area, const Scene *UNUSED(scene
|
||||
BLI_addtail(&spref->regionbase, region);
|
||||
region->regiontype = RGN_TYPE_EXECUTE;
|
||||
region->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
|
||||
region->flag |= RGN_FLAG_DYNAMIC_SIZE;
|
||||
region->flag |= RGN_FLAG_DYNAMIC_SIZE | RGN_FLAG_HIDDEN;
|
||||
|
||||
/* main region */
|
||||
region = MEM_callocN(sizeof(ARegion), "main region for userpref");
|
||||
@@ -251,6 +251,7 @@ void ED_spacetype_userpref(void)
|
||||
/* regions: execution window */
|
||||
art = MEM_callocN(sizeof(ARegionType), "spacetype userpref region");
|
||||
art->regionid = RGN_TYPE_EXECUTE;
|
||||
art->prefsizey = HEADERY;
|
||||
art->init = userpref_execute_region_init;
|
||||
art->layout = ED_region_panels_layout;
|
||||
art->draw = ED_region_panels_draw;
|
||||
|
@@ -282,9 +282,17 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
|
||||
*/
|
||||
BKE_object_to_mat3(ob, obmtx);
|
||||
copy_m3_m4(totmat, ob->obmat);
|
||||
invert_m3_m3(obinv, totmat);
|
||||
|
||||
/* If the object scale is zero on any axis, this might result in a zero matrix.
|
||||
* In this case, the transformation would not do anything, see: T50103. */
|
||||
orthogonalize_m3_zero_axes(obmtx, 1.0f);
|
||||
orthogonalize_m3_zero_axes(totmat, 1.0f);
|
||||
|
||||
/* Use safe invert even though the input matrices have had zero axes set to unit length,
|
||||
* in the unlikely case of failure (float precision for eg) this uses unit matrix fallback. */
|
||||
invert_m3_m3_safe_ortho(obinv, totmat);
|
||||
mul_m3_m3m3(td->smtx, obmtx, obinv);
|
||||
invert_m3_m3(td->mtx, td->smtx);
|
||||
invert_m3_m3_safe_ortho(td->mtx, td->smtx);
|
||||
}
|
||||
else {
|
||||
/* no conversion to/from dataspace */
|
||||
|
@@ -103,7 +103,6 @@ static void generate_strokes_actual(
|
||||
lmd->transparency_mask,
|
||||
lmd->thickness,
|
||||
lmd->opacity,
|
||||
lmd->resample_length,
|
||||
lmd->source_vertex_group,
|
||||
lmd->vgname,
|
||||
lmd->flags);
|
||||
@@ -381,8 +380,6 @@ static void chaining_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
||||
|
||||
uiItemR(layout, ptr, "chaining_image_threshold", 0, NULL, ICON_NONE);
|
||||
|
||||
uiItemR(layout, ptr, "resample_length", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
|
||||
|
||||
uiItemR(layout, ptr, "split_angle", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
|
||||
}
|
||||
|
||||
@@ -411,8 +408,6 @@ static void vgroup_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
||||
uiItemPointerR(
|
||||
col, ptr, "vertex_group", &ob_ptr, "vertex_groups", IFACE_("Target"), ICON_NONE);
|
||||
}
|
||||
|
||||
uiItemR(col, ptr, "use_soft_selection", 0, NULL, ICON_NONE);
|
||||
}
|
||||
|
||||
static void baking_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
||||
|
@@ -560,7 +560,6 @@ void MOD_lineart_gpencil_generate(LineartRenderBuffer *rb,
|
||||
unsigned char transparency_mask,
|
||||
short thickness,
|
||||
float opacity,
|
||||
float resample_length,
|
||||
const char *source_vgname,
|
||||
const char *vgname,
|
||||
int modifier_flags);
|
||||
|
@@ -3768,7 +3768,6 @@ static void lineart_gpencil_generate(LineartRenderBuffer *rb,
|
||||
uchar transparency_mask,
|
||||
short thickness,
|
||||
float opacity,
|
||||
float resample_length,
|
||||
const char *source_vgname,
|
||||
const char *vgname,
|
||||
int modifier_flags)
|
||||
@@ -3802,7 +3801,6 @@ static void lineart_gpencil_generate(LineartRenderBuffer *rb,
|
||||
int enabled_types = lineart_rb_edge_types(rb);
|
||||
bool invert_input = modifier_flags & LRT_GPENCIL_INVERT_SOURCE_VGROUP;
|
||||
bool match_output = modifier_flags & LRT_GPENCIL_MATCH_OUTPUT_VGROUP;
|
||||
bool preserve_weight = modifier_flags & LRT_GPENCIL_SOFT_SELECTION;
|
||||
|
||||
LISTBASE_FOREACH (LineartLineChain *, rlc, &rb->chains) {
|
||||
|
||||
@@ -3886,18 +3884,13 @@ static void lineart_gpencil_generate(LineartRenderBuffer *rb,
|
||||
}
|
||||
MDeformWeight *mdw = BKE_defvert_ensure_index(&me->dvert[vindex], dindex);
|
||||
MDeformWeight *gdw = BKE_defvert_ensure_index(&gps->dvert[sindex], gpdg);
|
||||
if (preserve_weight) {
|
||||
float use_weight = mdw->weight;
|
||||
if (invert_input) {
|
||||
use_weight = 1 - use_weight;
|
||||
}
|
||||
gdw->weight = MAX2(use_weight, gdw->weight);
|
||||
}
|
||||
else {
|
||||
if (mdw->weight > 0.999f) {
|
||||
gdw->weight = 1.0f;
|
||||
}
|
||||
|
||||
float use_weight = mdw->weight;
|
||||
if (invert_input) {
|
||||
use_weight = 1 - use_weight;
|
||||
}
|
||||
gdw->weight = MAX2(use_weight, gdw->weight);
|
||||
|
||||
sindex++;
|
||||
}
|
||||
}
|
||||
@@ -3908,9 +3901,6 @@ static void lineart_gpencil_generate(LineartRenderBuffer *rb,
|
||||
}
|
||||
}
|
||||
|
||||
if (resample_length > 0.0001) {
|
||||
BKE_gpencil_stroke_sample(gpencil_object->data, gps, resample_length, false);
|
||||
}
|
||||
if (G.debug_value == 4000) {
|
||||
BKE_gpencil_stroke_set_random_color(gps);
|
||||
}
|
||||
@@ -3941,7 +3931,6 @@ void MOD_lineart_gpencil_generate(LineartRenderBuffer *rb,
|
||||
uchar transparency_mask,
|
||||
short thickness,
|
||||
float opacity,
|
||||
float resample_length,
|
||||
const char *source_vgname,
|
||||
const char *vgname,
|
||||
int modifier_flags)
|
||||
@@ -3991,7 +3980,6 @@ void MOD_lineart_gpencil_generate(LineartRenderBuffer *rb,
|
||||
transparency_mask,
|
||||
thickness,
|
||||
opacity,
|
||||
resample_length,
|
||||
source_vgname,
|
||||
vgname,
|
||||
modifier_flags);
|
||||
|
@@ -131,7 +131,6 @@ static bool bake_strokes(Object *ob, Depsgraph *dg, GpencilModifierData *md, int
|
||||
lmd->transparency_mask,
|
||||
lmd->thickness,
|
||||
lmd->opacity,
|
||||
lmd->resample_length,
|
||||
lmd->source_vertex_group,
|
||||
lmd->vgname,
|
||||
lmd->flags);
|
||||
|
@@ -1140,6 +1140,7 @@ static int ffmpeg_generic_seek_workaround(struct anim *anim, int64_t requested_p
|
||||
* small. */
|
||||
for (int offset = 5; offset < 25; offset++) {
|
||||
current_pos = requested_pos - ((int64_t)(offset)*AV_TIME_BASE / frame_rate);
|
||||
current_pos = max_ii(current_pos, 0);
|
||||
|
||||
/* Seek to timestamp. */
|
||||
if (av_seek_frame(anim->pFormatCtx, -1, current_pos, AVSEEK_FLAG_BACKWARD) < 0) {
|
||||
@@ -1218,8 +1219,7 @@ static void ffmpeg_seek_and_decode(struct anim *anim, int position, struct anim_
|
||||
|
||||
AVFormatContext *format_ctx = anim->pFormatCtx;
|
||||
|
||||
/* Condition based on av_seek_frame() code. */
|
||||
if (format_ctx->iformat->read_seek2 && !format_ctx->iformat->read_seek) {
|
||||
if (format_ctx->iformat->read_seek2 || format_ctx->iformat->read_seek) {
|
||||
ret = av_seek_frame(anim->pFormatCtx, -1, pos, AVSEEK_FLAG_BACKWARD);
|
||||
}
|
||||
else {
|
||||
|
@@ -288,7 +288,7 @@
|
||||
.edge_types = LRT_EDGE_FLAG_ALL_TYPE, \
|
||||
.thickness = 25, \
|
||||
.opacity = 1.0f, \
|
||||
.flags = LRT_GPENCIL_MATCH_OUTPUT_VGROUP | LRT_GPENCIL_SOFT_SELECTION, \
|
||||
.flags = LRT_GPENCIL_MATCH_OUTPUT_VGROUP, \
|
||||
.crease_threshold = DEG2RAD(140.0f), \
|
||||
.calculation_flags = LRT_ALLOW_DUPLI_OBJECTS | LRT_ALLOW_CLIPPING_BOUNDARIES, \
|
||||
.angle_splitting_threshold = DEG2RAD(60.0f), \
|
||||
|
@@ -819,7 +819,7 @@ typedef enum eLineartGpencilModifierSource {
|
||||
typedef enum eLineArtGPencilModifierFlags {
|
||||
LRT_GPENCIL_INVERT_SOURCE_VGROUP = (1 << 0),
|
||||
LRT_GPENCIL_MATCH_OUTPUT_VGROUP = (1 << 1),
|
||||
LRT_GPENCIL_SOFT_SELECTION = (1 << 2),
|
||||
LRT_GPENCIL_BINARY_WEIGHTS = (1 << 2) /* Deprecated, this is removed for lack of use case. */,
|
||||
LRT_GPENCIL_IS_BAKED = (1 << 3),
|
||||
} eLineArtGPencilModifierFlags;
|
||||
|
||||
@@ -868,7 +868,7 @@ typedef struct LineartGpencilModifierData {
|
||||
/* CPU mode */
|
||||
float chaining_image_threshold;
|
||||
|
||||
float resample_length;
|
||||
int _pad;
|
||||
|
||||
/* Ported from SceneLineArt flags. */
|
||||
int calculation_flags;
|
||||
|
@@ -68,6 +68,7 @@
|
||||
.volume_fac = 1.0f, \
|
||||
.att_dist = 40.0f, \
|
||||
.sun_angle = DEG2RADF(0.526f), \
|
||||
.area_spread = DEG2RADF(180.0f), \
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@@ -70,9 +70,9 @@ typedef struct Light {
|
||||
|
||||
short area_shape;
|
||||
float area_size, area_sizey, area_sizez;
|
||||
float area_spread;
|
||||
|
||||
float sun_angle;
|
||||
char _pad3[4];
|
||||
|
||||
/* texact is for buttons */
|
||||
short texact, shadhalostep;
|
||||
|
@@ -168,6 +168,11 @@ typedef struct Object_Runtime {
|
||||
*/
|
||||
struct GeometrySet *geometry_set_eval;
|
||||
|
||||
/**
|
||||
* Data from this geometry set is previewed in the spreadsheet editor.
|
||||
*/
|
||||
struct GeometrySet *geometry_set_preview;
|
||||
|
||||
/**
|
||||
* Mesh structure created during object evaluation.
|
||||
* It has deformation only modifiers applied on it.
|
||||
|
@@ -1520,6 +1520,7 @@ typedef struct bNodeTreePath {
|
||||
|
||||
/** MAX_NAME. */
|
||||
char node_name[64];
|
||||
char display_name[64];
|
||||
} bNodeTreePath;
|
||||
|
||||
typedef struct SpaceNode {
|
||||
@@ -1885,6 +1886,7 @@ typedef enum eSpaceSpreadsheet_FilterFlag {
|
||||
typedef enum eSpaceSpreadsheet_ObjectEvalState {
|
||||
SPREADSHEET_OBJECT_EVAL_STATE_FINAL = 0,
|
||||
SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL = 1,
|
||||
SPREADSHEET_OBJECT_EVAL_STATE_NODE = 2,
|
||||
} eSpaceSpreadsheet_Context;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@@ -2501,12 +2501,6 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Match Output", "Match output vertex group based on name");
|
||||
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_soft_selection", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", LRT_GPENCIL_SOFT_SELECTION);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Clip", "Preserve original vertex weight instead of clipping to 0/1");
|
||||
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "is_baked", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", LRT_GPENCIL_IS_BAKED);
|
||||
RNA_def_property_ui_text(prop, "Is Baked", "This modifier has baked data");
|
||||
@@ -2524,15 +2518,6 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "resample_length", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Resample Length",
|
||||
"Resample the strokes so that the stroke points have the specified "
|
||||
"length between them. Zero length disables the resampling");
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.01f, 2);
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_transparency", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "transparency_flags", LRT_GPENCIL_TRANSPARENCY_ENABLE);
|
||||
RNA_def_property_ui_text(
|
||||
|
@@ -480,6 +480,15 @@ static void rna_def_area_light(BlenderRNA *brna)
|
||||
"Size Y",
|
||||
"Size of the area of the area light in the Y direction for rectangle shapes");
|
||||
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
|
||||
|
||||
prop = RNA_def_property(srna, "spread", PROP_FLOAT, PROP_ANGLE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "area_spread");
|
||||
RNA_def_property_range(prop, DEG2RADF(1.0f), DEG2RADF(180.0f));
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Spread",
|
||||
"How widely the emitted light fans out, as in the case of a gridded softbox");
|
||||
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
|
||||
}
|
||||
|
||||
static void rna_def_spot_light(BlenderRNA *brna)
|
||||
|
@@ -7344,6 +7344,11 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna)
|
||||
ICON_NONE,
|
||||
"Original",
|
||||
"Use data from original object without any modifiers applied"},
|
||||
{SPREADSHEET_OBJECT_EVAL_STATE_NODE,
|
||||
"NODE",
|
||||
ICON_NONE,
|
||||
"Node",
|
||||
"Use data from the first geometry output of the active node"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
|
@@ -43,17 +43,22 @@
|
||||
#include "DNA_pointcloud_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_lib_query.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_node_ui_storage.hh"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_pointcloud.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_simulation.h"
|
||||
#include "BKE_workspace.h"
|
||||
|
||||
#include "BLO_read_write.h"
|
||||
|
||||
@@ -89,6 +94,7 @@ using blender::bke::PersistentCollectionHandle;
|
||||
using blender::bke::PersistentDataHandleMap;
|
||||
using blender::bke::PersistentObjectHandle;
|
||||
using blender::fn::GMutablePointer;
|
||||
using blender::fn::GPointer;
|
||||
using blender::fn::GValueMap;
|
||||
using blender::nodes::GeoNodeExecParams;
|
||||
using namespace blender::fn::multi_function_types;
|
||||
@@ -253,6 +259,9 @@ static bool isDisabled(const struct Scene *UNUSED(scene),
|
||||
}
|
||||
|
||||
class GeometryNodesEvaluator {
|
||||
public:
|
||||
using LogSocketValueFn = std::function<void(DSocket, Span<GPointer>)>;
|
||||
|
||||
private:
|
||||
blender::LinearAllocator<> allocator_;
|
||||
Map<std::pair<DInputSocket, DOutputSocket>, GMutablePointer> value_by_input_;
|
||||
@@ -263,6 +272,7 @@ class GeometryNodesEvaluator {
|
||||
const Object *self_object_;
|
||||
const ModifierData *modifier_;
|
||||
Depsgraph *depsgraph_;
|
||||
LogSocketValueFn log_socket_value_fn_;
|
||||
|
||||
public:
|
||||
GeometryNodesEvaluator(const Map<DOutputSocket, GMutablePointer> &group_input_data,
|
||||
@@ -271,16 +281,19 @@ class GeometryNodesEvaluator {
|
||||
const PersistentDataHandleMap &handle_map,
|
||||
const Object *self_object,
|
||||
const ModifierData *modifier,
|
||||
Depsgraph *depsgraph)
|
||||
Depsgraph *depsgraph,
|
||||
LogSocketValueFn log_socket_value_fn)
|
||||
: group_outputs_(std::move(group_outputs)),
|
||||
mf_by_node_(mf_by_node),
|
||||
conversions_(blender::nodes::get_implicit_type_conversions()),
|
||||
handle_map_(handle_map),
|
||||
self_object_(self_object),
|
||||
modifier_(modifier),
|
||||
depsgraph_(depsgraph)
|
||||
depsgraph_(depsgraph),
|
||||
log_socket_value_fn_(std::move(log_socket_value_fn))
|
||||
{
|
||||
for (auto item : group_input_data.items()) {
|
||||
this->log_socket_value(item.key, item.value);
|
||||
this->forward_to_inputs(item.key, item.value);
|
||||
}
|
||||
}
|
||||
@@ -290,6 +303,7 @@ class GeometryNodesEvaluator {
|
||||
Vector<GMutablePointer> results;
|
||||
for (const DInputSocket &group_output : group_outputs_) {
|
||||
Vector<GMutablePointer> result = this->get_input_values(group_output);
|
||||
this->log_socket_value(group_output, result);
|
||||
results.append(result[0]);
|
||||
}
|
||||
for (GMutablePointer value : value_by_input_.values()) {
|
||||
@@ -384,7 +398,9 @@ class GeometryNodesEvaluator {
|
||||
GValueMap<StringRef> node_inputs_map{allocator_};
|
||||
for (const InputSocketRef *input_socket : node->inputs()) {
|
||||
if (input_socket->is_available()) {
|
||||
Vector<GMutablePointer> values = this->get_input_values({node.context(), input_socket});
|
||||
DInputSocket dsocket{node.context(), input_socket};
|
||||
Vector<GMutablePointer> values = this->get_input_values(dsocket);
|
||||
this->log_socket_value(dsocket, values);
|
||||
for (int i = 0; i < values.size(); ++i) {
|
||||
/* Values from Multi Input Sockets are stored in input map with the format
|
||||
* <identifier>[<index>]. */
|
||||
@@ -404,12 +420,31 @@ class GeometryNodesEvaluator {
|
||||
/* Forward computed outputs to linked input sockets. */
|
||||
for (const OutputSocketRef *output_socket : node->outputs()) {
|
||||
if (output_socket->is_available()) {
|
||||
const DOutputSocket dsocket{node.context(), output_socket};
|
||||
GMutablePointer value = node_outputs_map.extract(output_socket->identifier());
|
||||
this->forward_to_inputs({node.context(), output_socket}, value);
|
||||
this->log_socket_value(dsocket, value);
|
||||
this->forward_to_inputs(dsocket, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void log_socket_value(const DSocket socket, Span<GPointer> values)
|
||||
{
|
||||
if (log_socket_value_fn_) {
|
||||
log_socket_value_fn_(socket, values);
|
||||
}
|
||||
}
|
||||
|
||||
void log_socket_value(const DSocket socket, Span<GMutablePointer> values)
|
||||
{
|
||||
this->log_socket_value(socket, values.cast<GPointer>());
|
||||
}
|
||||
|
||||
void log_socket_value(const DSocket socket, GPointer value)
|
||||
{
|
||||
this->log_socket_value(socket, Span<GPointer>(&value, 1));
|
||||
}
|
||||
|
||||
void execute_node(const DNode node, GeoNodeExecParams params)
|
||||
{
|
||||
const bNode &bnode = params.node();
|
||||
@@ -523,8 +558,15 @@ class GeometryNodesEvaluator {
|
||||
{
|
||||
/* For all sockets that are linked with the from_socket push the value to their node. */
|
||||
Vector<DInputSocket> to_sockets_all;
|
||||
from_socket.foreach_target_socket(
|
||||
[&](DInputSocket to_socket) { to_sockets_all.append_non_duplicates(to_socket); });
|
||||
|
||||
auto handle_target_socket_fn = [&](DInputSocket to_socket) {
|
||||
to_sockets_all.append_non_duplicates(to_socket);
|
||||
};
|
||||
auto handle_skipped_socket_fn = [&, this](DSocket socket) {
|
||||
this->log_socket_value(socket, value_to_forward);
|
||||
};
|
||||
|
||||
from_socket.foreach_target_socket(handle_target_socket_fn, handle_skipped_socket_fn);
|
||||
|
||||
const CPPType &from_type = *value_to_forward.type();
|
||||
Vector<DInputSocket> to_sockets_same_type;
|
||||
@@ -1051,6 +1093,71 @@ static void reset_tree_ui_storage(Span<const blender::nodes::NodeTreeRef *> tree
|
||||
}
|
||||
}
|
||||
|
||||
static DNode find_matching_active_derived_node(const SpaceNode &snode, const DerivedNodeTree &tree)
|
||||
{
|
||||
const DTreeContext &root_context = tree.root_context();
|
||||
bNodeTree *root_tree_eval = root_context.tree().btree();
|
||||
bNodeTree *root_tree_orig = (bNodeTree *)DEG_get_original_id(&root_tree_eval->id);
|
||||
if (snode.nodetree != root_tree_orig) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const DTreeContext *current_context = &root_context;
|
||||
bool is_first = true;
|
||||
LISTBASE_FOREACH (const bNodeTreePath *, path, &snode.treepath) {
|
||||
if (is_first) {
|
||||
is_first = false;
|
||||
continue;
|
||||
}
|
||||
StringRef parent_node_name = path->node_name;
|
||||
const NodeTreeRef &tree_ref = current_context->tree();
|
||||
const NodeRef *parent_node_ref = nullptr;
|
||||
for (const NodeRef *node_ref : tree_ref.nodes()) {
|
||||
if (node_ref->name() == parent_node_name) {
|
||||
parent_node_ref = node_ref;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (parent_node_ref == nullptr) {
|
||||
return {};
|
||||
}
|
||||
current_context = current_context->child_context(*parent_node_ref);
|
||||
if (current_context == nullptr) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
const NodeTreeRef &tree_ref = current_context->tree();
|
||||
for (const NodeRef *node_ref : tree_ref.nodes()) {
|
||||
if (node_ref->bnode()->flag & NODE_ACTIVE) {
|
||||
return {current_context, node_ref};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static DNode find_matching_active_derived_node(Depsgraph *depsgraph, const DerivedNodeTree &tree)
|
||||
{
|
||||
Main *bmain = DEG_get_bmain(depsgraph);
|
||||
wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
|
||||
LISTBASE_FOREACH (wmWindow *, window, &wm->windows) {
|
||||
bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
SpaceLink *sl = (SpaceLink *)area->spacedata.first;
|
||||
if (sl->spacetype != SPACE_NODE) {
|
||||
continue;
|
||||
}
|
||||
SpaceNode *snode = (SpaceNode *)sl;
|
||||
DNode active_node = find_matching_active_derived_node(*snode, tree);
|
||||
if (!active_node) {
|
||||
continue;
|
||||
}
|
||||
return active_node;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a node group to compute the output geometry.
|
||||
* Currently, this uses a fairly basic and inefficient algorithm that might compute things more
|
||||
@@ -1106,13 +1213,36 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree,
|
||||
Vector<DInputSocket> group_outputs;
|
||||
group_outputs.append({root_context, &socket_to_compute});
|
||||
|
||||
const DNode active_node = find_matching_active_derived_node(ctx->depsgraph, tree);
|
||||
|
||||
auto log_socket_value = [&](const DSocket socket, const Span<GPointer> values) {
|
||||
const DNode node = socket.node();
|
||||
if (node != active_node) {
|
||||
return;
|
||||
}
|
||||
if (socket->is_input() && !node->outputs().is_empty()) {
|
||||
return;
|
||||
}
|
||||
if (values.size() != 1) {
|
||||
return;
|
||||
}
|
||||
const GPointer value = values[0];
|
||||
if (*value.type() != CPPType::get<GeometrySet>()) {
|
||||
return;
|
||||
}
|
||||
GeometrySet geometry_set = *(const GeometrySet *)value.get();
|
||||
geometry_set.ensure_owns_direct_data();
|
||||
BKE_object_preview_geometry_set(ctx->object, new GeometrySet(std::move(geometry_set)));
|
||||
};
|
||||
|
||||
GeometryNodesEvaluator evaluator{group_inputs,
|
||||
group_outputs,
|
||||
mf_by_node,
|
||||
handle_map,
|
||||
ctx->object,
|
||||
(ModifierData *)nmd,
|
||||
ctx->depsgraph};
|
||||
ctx->depsgraph,
|
||||
log_socket_value};
|
||||
|
||||
Vector<GMutablePointer> results = evaluator.execute();
|
||||
BLI_assert(results.size() == 1);
|
||||
|
@@ -59,6 +59,7 @@ class DTreeContext {
|
||||
const NodeTreeRef *tree_;
|
||||
/* All the children contexts of this context. */
|
||||
Map<const NodeRef *, DTreeContext *> children_;
|
||||
DerivedNodeTree *derived_tree_;
|
||||
|
||||
friend DerivedNodeTree;
|
||||
|
||||
@@ -67,6 +68,7 @@ class DTreeContext {
|
||||
const DTreeContext *parent_context() const;
|
||||
const NodeRef *parent_node() const;
|
||||
const DTreeContext *child_context(const NodeRef &node) const;
|
||||
const DerivedNodeTree &derived_tree() const;
|
||||
bool is_root() const;
|
||||
};
|
||||
|
||||
@@ -117,6 +119,8 @@ class DSocket {
|
||||
operator bool() const;
|
||||
|
||||
uint64_t hash() const;
|
||||
|
||||
DNode node() const;
|
||||
};
|
||||
|
||||
/* A (nullable) reference to an input socket and the context it is in. */
|
||||
@@ -132,7 +136,7 @@ class DInputSocket : public DSocket {
|
||||
DOutputSocket get_corresponding_group_node_output() const;
|
||||
Vector<DOutputSocket, 4> get_corresponding_group_input_sockets() const;
|
||||
|
||||
void foreach_origin_socket(FunctionRef<void(DSocket)> callback) const;
|
||||
void foreach_origin_socket(FunctionRef<void(DSocket)> origin_fn) const;
|
||||
};
|
||||
|
||||
/* A (nullable) reference to an output socket and the context it is in. */
|
||||
@@ -148,7 +152,8 @@ class DOutputSocket : public DSocket {
|
||||
DInputSocket get_corresponding_group_node_input() const;
|
||||
DInputSocket get_active_corresponding_group_output_socket() const;
|
||||
|
||||
void foreach_target_socket(FunctionRef<void(DInputSocket)> callback) const;
|
||||
void foreach_target_socket(FunctionRef<void(DInputSocket)> target_fn,
|
||||
FunctionRef<void(DSocket)> skipped_fn) const;
|
||||
};
|
||||
|
||||
class DerivedNodeTree {
|
||||
@@ -214,6 +219,11 @@ inline const DTreeContext *DTreeContext::child_context(const NodeRef &node) cons
|
||||
return children_.lookup_default(&node, nullptr);
|
||||
}
|
||||
|
||||
inline const DerivedNodeTree &DTreeContext::derived_tree() const
|
||||
{
|
||||
return *derived_tree_;
|
||||
}
|
||||
|
||||
inline bool DTreeContext::is_root() const
|
||||
{
|
||||
return parent_context_ == nullptr;
|
||||
@@ -319,6 +329,12 @@ inline uint64_t DSocket::hash() const
|
||||
return get_default_hash_2(context_, socket_ref_);
|
||||
}
|
||||
|
||||
inline DNode DSocket::node() const
|
||||
{
|
||||
BLI_assert(socket_ref_ != nullptr);
|
||||
return {context_, &socket_ref_->node()};
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* DInputSocket inline methods.
|
||||
*/
|
||||
|
@@ -81,15 +81,19 @@ class SocketRef : NonCopyable, NonMovable {
|
||||
Vector<LinkRef *> directly_linked_links_;
|
||||
|
||||
/* These sockets are linked directly, i.e. with a single link in between. */
|
||||
MutableSpan<SocketRef *> directly_linked_sockets_;
|
||||
MutableSpan<const SocketRef *> directly_linked_sockets_;
|
||||
/* These sockets are linked when reroutes, muted links and muted nodes have been taken into
|
||||
* account. */
|
||||
MutableSpan<SocketRef *> logically_linked_sockets_;
|
||||
MutableSpan<const SocketRef *> logically_linked_sockets_;
|
||||
/* These are the sockets that have been skipped when searching for logically linked sockets.
|
||||
* That includes for example the input and output socket of an intermediate reroute node. */
|
||||
MutableSpan<const SocketRef *> logically_linked_skipped_sockets_;
|
||||
|
||||
friend NodeTreeRef;
|
||||
|
||||
public:
|
||||
Span<const SocketRef *> logically_linked_sockets() const;
|
||||
Span<const SocketRef *> logically_linked_skipped_sockets() const;
|
||||
Span<const SocketRef *> directly_linked_sockets() const;
|
||||
Span<const LinkRef *> directly_linked_links() const;
|
||||
|
||||
@@ -132,12 +136,19 @@ class InputSocketRef final : public SocketRef {
|
||||
Span<const OutputSocketRef *> directly_linked_sockets() const;
|
||||
|
||||
bool is_multi_input_socket() const;
|
||||
|
||||
void foreach_logical_origin(FunctionRef<void(const OutputSocketRef &)> origin_fn,
|
||||
FunctionRef<void(const SocketRef &)> skipped_fn,
|
||||
bool only_follow_first_input_link = false) const;
|
||||
};
|
||||
|
||||
class OutputSocketRef final : public SocketRef {
|
||||
public:
|
||||
Span<const InputSocketRef *> logically_linked_sockets() const;
|
||||
Span<const InputSocketRef *> directly_linked_sockets() const;
|
||||
|
||||
void foreach_logical_target(FunctionRef<void(const InputSocketRef &)> target_fn,
|
||||
FunctionRef<void(const SocketRef &)> skipped_fn) const;
|
||||
};
|
||||
|
||||
class NodeRef : NonCopyable, NonMovable {
|
||||
@@ -257,12 +268,6 @@ class NodeTreeRef : NonCopyable, NonMovable {
|
||||
bNodeSocket *bsocket);
|
||||
|
||||
void create_linked_socket_caches();
|
||||
|
||||
void foreach_logical_origin(InputSocketRef &socket,
|
||||
FunctionRef<void(OutputSocketRef &)> callback,
|
||||
bool only_follow_first_input_link = false);
|
||||
void foreach_logical_target(OutputSocketRef &socket,
|
||||
FunctionRef<void(InputSocketRef &)> callback);
|
||||
};
|
||||
|
||||
using NodeTreeRefMap = Map<bNodeTree *, std::unique_ptr<const NodeTreeRef>>;
|
||||
@@ -287,6 +292,11 @@ inline Span<const SocketRef *> SocketRef::logically_linked_sockets() const
|
||||
return logically_linked_sockets_;
|
||||
}
|
||||
|
||||
inline Span<const SocketRef *> SocketRef::logically_linked_skipped_sockets() const
|
||||
{
|
||||
return logically_linked_skipped_sockets_;
|
||||
}
|
||||
|
||||
inline Span<const SocketRef *> SocketRef::directly_linked_sockets() const
|
||||
{
|
||||
return directly_linked_sockets_;
|
||||
|
@@ -40,6 +40,7 @@ DTreeContext &DerivedNodeTree::construct_context_recursively(DTreeContext *paren
|
||||
DTreeContext &context = *allocator_.construct<DTreeContext>().release();
|
||||
context.parent_context_ = parent_context;
|
||||
context.parent_node_ = parent_node;
|
||||
context.derived_tree_ = this;
|
||||
context.tree_ = &get_tree_ref_from_map(node_tree_refs, btree);
|
||||
used_node_tree_refs_.add(context.tree_);
|
||||
|
||||
@@ -167,10 +168,10 @@ DInputSocket DOutputSocket::get_active_corresponding_group_output_socket() const
|
||||
return {};
|
||||
}
|
||||
|
||||
/* Call the given callback for every "real" origin socket. "Real" means that reroutes, muted nodes
|
||||
/* Call `origin_fn` for every "real" origin socket. "Real" means that reroutes, muted nodes
|
||||
* and node groups are handled by this function. Origin sockets are ones where a node gets its
|
||||
* inputs from. */
|
||||
void DInputSocket::foreach_origin_socket(FunctionRef<void(DSocket)> callback) const
|
||||
void DInputSocket::foreach_origin_socket(FunctionRef<void(DSocket)> origin_fn) const
|
||||
{
|
||||
BLI_assert(*this);
|
||||
for (const OutputSocketRef *linked_socket : socket_ref_->as_input().logically_linked_sockets()) {
|
||||
@@ -180,18 +181,18 @@ void DInputSocket::foreach_origin_socket(FunctionRef<void(DSocket)> callback) co
|
||||
if (linked_node.is_group_input_node()) {
|
||||
if (context_->is_root()) {
|
||||
/* This is a group input in the root node group. */
|
||||
callback(linked_dsocket);
|
||||
origin_fn(linked_dsocket);
|
||||
}
|
||||
else {
|
||||
DInputSocket socket_in_parent_group = linked_dsocket.get_corresponding_group_node_input();
|
||||
if (socket_in_parent_group->is_logically_linked()) {
|
||||
/* Follow the links coming into the corresponding socket on the parent group node. */
|
||||
socket_in_parent_group.foreach_origin_socket(callback);
|
||||
socket_in_parent_group.foreach_origin_socket(origin_fn);
|
||||
}
|
||||
else {
|
||||
/* The corresponding input on the parent group node is not connected. Therefore, we use
|
||||
* the value of that input socket directly. */
|
||||
callback(socket_in_parent_group);
|
||||
origin_fn(socket_in_parent_group);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -200,27 +201,32 @@ void DInputSocket::foreach_origin_socket(FunctionRef<void(DSocket)> callback) co
|
||||
if (socket_in_group) {
|
||||
if (socket_in_group->is_logically_linked()) {
|
||||
/* Follow the links coming into the group output node of the child node group. */
|
||||
socket_in_group.foreach_origin_socket(callback);
|
||||
socket_in_group.foreach_origin_socket(origin_fn);
|
||||
}
|
||||
else {
|
||||
/* The output of the child node group is not connected, so we have to get the value from
|
||||
* that socket. */
|
||||
callback(socket_in_group);
|
||||
origin_fn(socket_in_group);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* The normal case: just use the value of a linked output socket. */
|
||||
callback(linked_dsocket);
|
||||
origin_fn(linked_dsocket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Calls the given callback for every "real" target socket. "Real" means that reroutes, muted nodes
|
||||
/* Calls `target_fn` for every "real" target socket. "Real" means that reroutes, muted nodes
|
||||
* and node groups are handled by this function. Target sockets are on the nodes that use the value
|
||||
* from this socket. */
|
||||
void DOutputSocket::foreach_target_socket(FunctionRef<void(DInputSocket)> callback) const
|
||||
* from this socket. The `skipped_fn` function is called for sockets that have been skipped during
|
||||
* the search for target sockets (e.g. reroutes). */
|
||||
void DOutputSocket::foreach_target_socket(FunctionRef<void(DInputSocket)> target_fn,
|
||||
FunctionRef<void(DSocket)> skipped_fn) const
|
||||
{
|
||||
for (const SocketRef *skipped_socket : socket_ref_->logically_linked_skipped_sockets()) {
|
||||
skipped_fn.call_safe({context_, skipped_socket});
|
||||
}
|
||||
for (const InputSocketRef *linked_socket : socket_ref_->as_output().logically_linked_sockets()) {
|
||||
const NodeRef &linked_node = linked_socket->node();
|
||||
DInputSocket linked_dsocket{context_, linked_socket};
|
||||
@@ -228,26 +234,30 @@ void DOutputSocket::foreach_target_socket(FunctionRef<void(DInputSocket)> callba
|
||||
if (linked_node.is_group_output_node()) {
|
||||
if (context_->is_root()) {
|
||||
/* This is a group output in the root node group. */
|
||||
callback(linked_dsocket);
|
||||
target_fn(linked_dsocket);
|
||||
}
|
||||
else {
|
||||
/* Follow the links going out of the group node in the parent node group. */
|
||||
DOutputSocket socket_in_parent_group =
|
||||
linked_dsocket.get_corresponding_group_node_output();
|
||||
socket_in_parent_group.foreach_target_socket(callback);
|
||||
skipped_fn.call_safe(linked_dsocket);
|
||||
skipped_fn.call_safe(socket_in_parent_group);
|
||||
socket_in_parent_group.foreach_target_socket(target_fn, skipped_fn);
|
||||
}
|
||||
}
|
||||
else if (linked_node.is_group_node()) {
|
||||
/* Follow the links within the nested node group. */
|
||||
Vector<DOutputSocket> sockets_in_group =
|
||||
linked_dsocket.get_corresponding_group_input_sockets();
|
||||
skipped_fn.call_safe(linked_dsocket);
|
||||
for (DOutputSocket socket_in_group : sockets_in_group) {
|
||||
socket_in_group.foreach_target_socket(callback);
|
||||
skipped_fn.call_safe(socket_in_group);
|
||||
socket_in_group.foreach_target_socket(target_fn, skipped_fn);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* The normal case: just use the linked input socket as target. */
|
||||
callback(linked_dsocket);
|
||||
target_fn(linked_dsocket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -163,7 +163,7 @@ void NodeTreeRef::create_linked_socket_caches()
|
||||
{
|
||||
for (InputSocketRef *socket : input_sockets_) {
|
||||
/* Find directly linked socket based on incident links. */
|
||||
Vector<SocketRef *> directly_linked_sockets;
|
||||
Vector<const SocketRef *> directly_linked_sockets;
|
||||
for (LinkRef *link : socket->directly_linked_links_) {
|
||||
directly_linked_sockets.append(link->from_);
|
||||
}
|
||||
@@ -171,9 +171,11 @@ void NodeTreeRef::create_linked_socket_caches()
|
||||
directly_linked_sockets.as_span());
|
||||
|
||||
/* Find logically linked sockets. */
|
||||
Vector<SocketRef *> logically_linked_sockets;
|
||||
this->foreach_logical_origin(
|
||||
*socket, [&](OutputSocketRef &origin) { logically_linked_sockets.append(&origin); });
|
||||
Vector<const SocketRef *> logically_linked_sockets;
|
||||
Vector<const SocketRef *> logically_linked_skipped_sockets;
|
||||
socket->foreach_logical_origin(
|
||||
[&](const OutputSocketRef &origin) { logically_linked_sockets.append(&origin); },
|
||||
[&](const SocketRef &socket) { logically_linked_skipped_sockets.append(&socket); });
|
||||
if (logically_linked_sockets == directly_linked_sockets) {
|
||||
socket->logically_linked_sockets_ = socket->directly_linked_sockets_;
|
||||
}
|
||||
@@ -181,11 +183,13 @@ void NodeTreeRef::create_linked_socket_caches()
|
||||
socket->logically_linked_sockets_ = allocator_.construct_array_copy(
|
||||
logically_linked_sockets.as_span());
|
||||
}
|
||||
socket->logically_linked_skipped_sockets_ = allocator_.construct_array_copy(
|
||||
logically_linked_skipped_sockets.as_span());
|
||||
}
|
||||
|
||||
for (OutputSocketRef *socket : output_sockets_) {
|
||||
/* Find directly linked socket based on incident links. */
|
||||
Vector<SocketRef *> directly_linked_sockets;
|
||||
Vector<const SocketRef *> directly_linked_sockets;
|
||||
for (LinkRef *link : socket->directly_linked_links_) {
|
||||
directly_linked_sockets.append(link->to_);
|
||||
}
|
||||
@@ -193,9 +197,11 @@ void NodeTreeRef::create_linked_socket_caches()
|
||||
directly_linked_sockets.as_span());
|
||||
|
||||
/* Find logically linked sockets. */
|
||||
Vector<SocketRef *> logically_linked_sockets;
|
||||
this->foreach_logical_target(
|
||||
*socket, [&](InputSocketRef &target) { logically_linked_sockets.append(&target); });
|
||||
Vector<const SocketRef *> logically_linked_sockets;
|
||||
Vector<const SocketRef *> logically_linked_skipped_sockets;
|
||||
socket->foreach_logical_target(
|
||||
[&](const InputSocketRef &target) { logically_linked_sockets.append(&target); },
|
||||
[&](const SocketRef &socket) { logically_linked_skipped_sockets.append(&socket); });
|
||||
if (logically_linked_sockets == directly_linked_sockets) {
|
||||
socket->logically_linked_sockets_ = socket->directly_linked_sockets_;
|
||||
}
|
||||
@@ -203,61 +209,77 @@ void NodeTreeRef::create_linked_socket_caches()
|
||||
socket->logically_linked_sockets_ = allocator_.construct_array_copy(
|
||||
logically_linked_sockets.as_span());
|
||||
}
|
||||
socket->logically_linked_skipped_sockets_ = allocator_.construct_array_copy(
|
||||
logically_linked_skipped_sockets.as_span());
|
||||
}
|
||||
}
|
||||
|
||||
void NodeTreeRef::foreach_logical_origin(InputSocketRef &socket,
|
||||
FunctionRef<void(OutputSocketRef &)> callback,
|
||||
bool only_follow_first_input_link)
|
||||
void InputSocketRef::foreach_logical_origin(FunctionRef<void(const OutputSocketRef &)> origin_fn,
|
||||
FunctionRef<void(const SocketRef &)> skipped_fn,
|
||||
bool only_follow_first_input_link) const
|
||||
{
|
||||
Span<LinkRef *> links_to_check = socket.directly_linked_links_;
|
||||
Span<const LinkRef *> links_to_check = this->directly_linked_links();
|
||||
if (only_follow_first_input_link) {
|
||||
links_to_check = links_to_check.take_front(1);
|
||||
}
|
||||
for (LinkRef *link : links_to_check) {
|
||||
for (const LinkRef *link : links_to_check) {
|
||||
if (link->is_muted()) {
|
||||
continue;
|
||||
}
|
||||
OutputSocketRef *origin = link->from_;
|
||||
NodeRef *origin_node = origin->node_;
|
||||
if (origin_node->is_reroute_node()) {
|
||||
this->foreach_logical_origin(*origin_node->inputs_[0], callback, false);
|
||||
const OutputSocketRef &origin = link->from();
|
||||
const NodeRef &origin_node = origin.node();
|
||||
if (origin_node.is_reroute_node()) {
|
||||
const InputSocketRef &reroute_input = origin_node.input(0);
|
||||
const OutputSocketRef &reroute_output = origin_node.output(0);
|
||||
skipped_fn.call_safe(reroute_input);
|
||||
skipped_fn.call_safe(reroute_output);
|
||||
reroute_input.foreach_logical_origin(origin_fn, skipped_fn, false);
|
||||
}
|
||||
else if (origin_node->is_muted()) {
|
||||
for (InternalLinkRef *internal_link : origin_node->internal_links_) {
|
||||
if (internal_link->to_ == origin) {
|
||||
this->foreach_logical_origin(*internal_link->from_, callback, true);
|
||||
else if (origin_node.is_muted()) {
|
||||
for (const InternalLinkRef *internal_link : origin_node.internal_links()) {
|
||||
if (&internal_link->to() == &origin) {
|
||||
const InputSocketRef &mute_input = internal_link->from();
|
||||
skipped_fn.call_safe(origin);
|
||||
skipped_fn.call_safe(mute_input);
|
||||
mute_input.foreach_logical_origin(origin_fn, skipped_fn, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
callback(*origin);
|
||||
origin_fn(origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeTreeRef::foreach_logical_target(OutputSocketRef &socket,
|
||||
FunctionRef<void(InputSocketRef &)> callback)
|
||||
void OutputSocketRef::foreach_logical_target(FunctionRef<void(const InputSocketRef &)> target_fn,
|
||||
FunctionRef<void(const SocketRef &)> skipped_fn) const
|
||||
{
|
||||
for (LinkRef *link : socket.directly_linked_links_) {
|
||||
for (const LinkRef *link : this->directly_linked_links()) {
|
||||
if (link->is_muted()) {
|
||||
continue;
|
||||
}
|
||||
InputSocketRef *target = link->to_;
|
||||
NodeRef *target_node = target->node_;
|
||||
if (target_node->is_reroute_node()) {
|
||||
this->foreach_logical_target(*target_node->outputs_[0], callback);
|
||||
const InputSocketRef &target = link->to();
|
||||
const NodeRef &target_node = target.node();
|
||||
if (target_node.is_reroute_node()) {
|
||||
const OutputSocketRef &reroute_output = target_node.output(0);
|
||||
skipped_fn.call_safe(target);
|
||||
skipped_fn.call_safe(reroute_output);
|
||||
reroute_output.foreach_logical_target(target_fn, skipped_fn);
|
||||
}
|
||||
else if (target_node->is_muted()) {
|
||||
for (InternalLinkRef *internal_link : target_node->internal_links_) {
|
||||
if (internal_link->from_ == target) {
|
||||
this->foreach_logical_target(*internal_link->to_, callback);
|
||||
else if (target_node.is_muted()) {
|
||||
skipped_fn.call_safe(target);
|
||||
for (const InternalLinkRef *internal_link : target_node.internal_links()) {
|
||||
if (&internal_link->from() == &target) {
|
||||
const OutputSocketRef &mute_output = internal_link->to();
|
||||
skipped_fn.call_safe(target);
|
||||
skipped_fn.call_safe(mute_output);
|
||||
mute_output.foreach_logical_target(target_fn, skipped_fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
callback(*target);
|
||||
target_fn(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -53,38 +53,45 @@ extern PyTypeObject BPy_BMIter_Type;
|
||||
|
||||
/* cast from _any_ bmesh type - they all have BMesh first */
|
||||
typedef struct BPy_BMGeneric {
|
||||
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
|
||||
PyObject_VAR_HEAD
|
||||
struct BMesh *bm; /* keep first */
|
||||
} BPy_BMGeneric;
|
||||
|
||||
/* BPy_BMVert/BPy_BMEdge/BPy_BMFace/BPy_BMLoop can cast to this */
|
||||
typedef struct BPy_BMElem {
|
||||
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
|
||||
PyObject_VAR_HEAD
|
||||
struct BMesh *bm; /* keep first */
|
||||
struct BMElem *ele;
|
||||
} BPy_BMElem;
|
||||
|
||||
typedef struct BPy_BMesh {
|
||||
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
|
||||
PyObject_VAR_HEAD
|
||||
struct BMesh *bm; /* keep first */
|
||||
int flag;
|
||||
} BPy_BMesh;
|
||||
|
||||
/* element types */
|
||||
typedef struct BPy_BMVert {
|
||||
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
|
||||
PyObject_VAR_HEAD
|
||||
struct BMesh *bm; /* keep first */
|
||||
struct BMVert *v;
|
||||
} BPy_BMVert;
|
||||
|
||||
typedef struct BPy_BMEdge {
|
||||
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
|
||||
PyObject_VAR_HEAD
|
||||
struct BMesh *bm; /* keep first */
|
||||
struct BMEdge *e;
|
||||
} BPy_BMEdge;
|
||||
|
||||
typedef struct BPy_BMFace {
|
||||
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
|
||||
PyObject_VAR_HEAD
|
||||
struct BMesh *bm; /* keep first */
|
||||
struct BMFace *f;
|
||||
} BPy_BMFace;
|
||||
|
||||
typedef struct BPy_BMLoop {
|
||||
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
|
||||
PyObject_VAR_HEAD
|
||||
struct BMesh *bm; /* keep first */
|
||||
struct BMLoop *l;
|
||||
} BPy_BMLoop;
|
||||
|
||||
@@ -98,7 +105,8 @@ typedef struct BPy_BMLoop {
|
||||
* - BPy_BMLoopSeq_Type
|
||||
*/
|
||||
typedef struct BPy_BMElemSeq {
|
||||
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
|
||||
PyObject_VAR_HEAD
|
||||
struct BMesh *bm; /* keep first */
|
||||
|
||||
/* if this is a sequence on an existing element,
|
||||
* loops of faces for eg.
|
||||
@@ -114,7 +122,8 @@ typedef struct BPy_BMElemSeq {
|
||||
} BPy_BMElemSeq;
|
||||
|
||||
typedef struct BPy_BMIter {
|
||||
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
|
||||
PyObject_VAR_HEAD
|
||||
struct BMesh *bm; /* keep first */
|
||||
BMIter iter;
|
||||
} BPy_BMIter;
|
||||
|
||||
|
@@ -38,20 +38,23 @@ extern PyTypeObject BPy_BMLayerItem_Type;
|
||||
|
||||
/* all layers for vert/edge/face/loop */
|
||||
typedef struct BPy_BMLayerAccess {
|
||||
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
|
||||
PyObject_VAR_HEAD
|
||||
struct BMesh *bm; /* keep first */
|
||||
char htype;
|
||||
} BPy_BMLayerAccess;
|
||||
|
||||
/* access different layer types deform/uv/vertexcolor */
|
||||
typedef struct BPy_BMLayerCollection {
|
||||
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
|
||||
PyObject_VAR_HEAD
|
||||
struct BMesh *bm; /* keep first */
|
||||
char htype;
|
||||
int type; /* customdata type - CD_XXX */
|
||||
} BPy_BMLayerCollection;
|
||||
|
||||
/* access a specific layer directly */
|
||||
typedef struct BPy_BMLayerItem {
|
||||
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
|
||||
PyObject_VAR_HEAD
|
||||
struct BMesh *bm; /* keep first */
|
||||
char htype;
|
||||
int type; /* customdata type - CD_XXX */
|
||||
int index; /* index of this layer type */
|
||||
|
@@ -48,7 +48,8 @@
|
||||
#define BPy_BMLoopUV_Check(v) (Py_TYPE(v) == &BPy_BMLoopUV_Type)
|
||||
|
||||
typedef struct BPy_BMLoopUV {
|
||||
PyObject_VAR_HEAD MLoopUV *data;
|
||||
PyObject_VAR_HEAD
|
||||
MLoopUV *data;
|
||||
} BPy_BMLoopUV;
|
||||
|
||||
PyDoc_STRVAR(bpy_bmloopuv_uv_doc,
|
||||
@@ -155,7 +156,8 @@ PyObject *BPy_BMLoopUV_CreatePyObject(struct MLoopUV *mloopuv)
|
||||
#define BPy_BMVertSkin_Check(v) (Py_TYPE(v) == &BPy_BMVertSkin_Type)
|
||||
|
||||
typedef struct BPy_BMVertSkin {
|
||||
PyObject_VAR_HEAD MVertSkin *data;
|
||||
PyObject_VAR_HEAD
|
||||
MVertSkin *data;
|
||||
} BPy_BMVertSkin;
|
||||
|
||||
PyDoc_STRVAR(bpy_bmvertskin_radius_doc,
|
||||
@@ -392,7 +394,8 @@ PyObject *BPy_BMLoopColor_CreatePyObject(struct MLoopCol *mloopcol)
|
||||
#define BPy_BMDeformVert_Check(v) (Py_TYPE(v) == &BPy_BMDeformVert_Type)
|
||||
|
||||
typedef struct BPy_BMDeformVert {
|
||||
PyObject_VAR_HEAD MDeformVert *data;
|
||||
PyObject_VAR_HEAD
|
||||
MDeformVert *data;
|
||||
} BPy_BMDeformVert;
|
||||
|
||||
/* Mapping Protocols
|
||||
|
@@ -29,7 +29,8 @@ extern PyTypeObject BPy_BMDeformVert_Type;
|
||||
#define BPy_BMLoopUV_Check(v) (Py_TYPE(v) == &BPy_BMLoopUV_Type)
|
||||
|
||||
typedef struct BPy_BMGenericMeshData {
|
||||
PyObject_VAR_HEAD void *data;
|
||||
PyObject_VAR_HEAD
|
||||
void *data;
|
||||
} BPy_BMGenericMeshData;
|
||||
|
||||
struct MDeformVert;
|
||||
|
@@ -32,11 +32,13 @@ extern PyTypeObject BPy_BMEditSelIter_Type;
|
||||
#define BPy_BMSelectHistoryIter_Check(v) (Py_TYPE(v) == &BPy_BMEditSelIter_Type)
|
||||
|
||||
typedef struct BPy_BMEditSelSeq {
|
||||
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
|
||||
PyObject_VAR_HEAD
|
||||
struct BMesh *bm; /* keep first */
|
||||
} BPy_BMEditSelSeq;
|
||||
|
||||
typedef struct BPy_BMEditSelIter {
|
||||
PyObject_VAR_HEAD struct BMesh *bm; /* keep first */
|
||||
PyObject_VAR_HEAD
|
||||
struct BMesh *bm; /* keep first */
|
||||
struct BMEditSelection *ese;
|
||||
} BPy_BMEditSelIter;
|
||||
|
||||
|
@@ -32,7 +32,8 @@ int BGL_typeSize(int type);
|
||||
* For Python access to OpenGL functions requiring a pointer.
|
||||
*/
|
||||
typedef struct _Buffer {
|
||||
PyObject_VAR_HEAD PyObject *parent;
|
||||
PyObject_VAR_HEAD
|
||||
PyObject *parent;
|
||||
|
||||
int type; /* GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT */
|
||||
int ndimensions;
|
||||
|
@@ -36,19 +36,22 @@ extern PyTypeObject BPy_IDGroup_Type;
|
||||
#define BPy_IDGroup_CheckExact(v) (Py_TYPE(v) == &BPy_IDGroup_Type)
|
||||
|
||||
typedef struct BPy_IDProperty {
|
||||
PyObject_VAR_HEAD struct ID *id; /* can be NULL */
|
||||
struct IDProperty *prop; /* must be second member */
|
||||
PyObject_VAR_HEAD
|
||||
struct ID *id; /* can be NULL */
|
||||
struct IDProperty *prop; /* must be second member */
|
||||
struct IDProperty *parent;
|
||||
PyObject *data_wrap;
|
||||
} BPy_IDProperty;
|
||||
|
||||
typedef struct BPy_IDArray {
|
||||
PyObject_VAR_HEAD struct ID *id; /* can be NULL */
|
||||
struct IDProperty *prop; /* must be second member */
|
||||
PyObject_VAR_HEAD
|
||||
struct ID *id; /* can be NULL */
|
||||
struct IDProperty *prop; /* must be second member */
|
||||
} BPy_IDArray;
|
||||
|
||||
typedef struct BPy_IDGroup_Iter {
|
||||
PyObject_VAR_HEAD BPy_IDProperty *group;
|
||||
PyObject_VAR_HEAD
|
||||
BPy_IDProperty *group;
|
||||
struct IDProperty *cur;
|
||||
int mode;
|
||||
} BPy_IDGroup_Iter;
|
||||
|
@@ -50,8 +50,8 @@ static PyObject *Py_ImBuf_CreatePyObject(ImBuf *ibuf);
|
||||
|
||||
typedef struct Py_ImBuf {
|
||||
PyObject_VAR_HEAD
|
||||
/* can be NULL */
|
||||
ImBuf *ibuf;
|
||||
/* can be NULL */
|
||||
ImBuf *ibuf;
|
||||
} Py_ImBuf;
|
||||
|
||||
static int py_imbuf_valid_check(Py_ImBuf *self)
|
||||
|
@@ -30,8 +30,8 @@ extern PyTypeObject BPyGPUBatch_Type;
|
||||
|
||||
typedef struct BPyGPUBatch {
|
||||
PyObject_VAR_HEAD
|
||||
/* The batch is owned, we may support thin wrapped batches later. */
|
||||
struct GPUBatch *batch;
|
||||
/* The batch is owned, we may support thin wrapped batches later. */
|
||||
struct GPUBatch *batch;
|
||||
#ifdef USE_GPU_PY_REFERENCES
|
||||
/* Just to keep a user to prevent freeing buf's we're using */
|
||||
PyObject *references;
|
||||
|
@@ -30,7 +30,8 @@ extern PyTypeObject BPyGPU_BufferType;
|
||||
* For Python access to GPU functions requiring a pointer.
|
||||
*/
|
||||
typedef struct BPyGPUBuffer {
|
||||
PyObject_VAR_HEAD PyObject *parent;
|
||||
PyObject_VAR_HEAD
|
||||
PyObject *parent;
|
||||
|
||||
int format;
|
||||
int shape_len;
|
||||
|
@@ -25,7 +25,8 @@ extern PyTypeObject BPyGPUIndexBuf_Type;
|
||||
#define BPyGPUIndexBuf_Check(v) (Py_TYPE(v) == &BPyGPUIndexBuf_Type)
|
||||
|
||||
typedef struct BPyGPUIndexBuf {
|
||||
PyObject_VAR_HEAD struct GPUIndexBuf *elem;
|
||||
PyObject_VAR_HEAD
|
||||
struct GPUIndexBuf *elem;
|
||||
} BPyGPUIndexBuf;
|
||||
|
||||
PyObject *BPyGPUIndexBuf_CreatePyObject(struct GPUIndexBuf *elem);
|
||||
|
@@ -25,7 +25,8 @@ extern PyTypeObject BPyGPUShader_Type;
|
||||
#define BPyGPUShader_Check(v) (Py_TYPE(v) == &BPyGPUShader_Type)
|
||||
|
||||
typedef struct BPyGPUShader {
|
||||
PyObject_VAR_HEAD struct GPUShader *shader;
|
||||
PyObject_VAR_HEAD
|
||||
struct GPUShader *shader;
|
||||
bool is_builtin;
|
||||
} BPyGPUShader;
|
||||
|
||||
|
@@ -28,8 +28,8 @@ extern PyTypeObject BPyGPUVertBuf_Type;
|
||||
|
||||
typedef struct BPyGPUVertBuf {
|
||||
PyObject_VAR_HEAD
|
||||
/* The buf is owned, we may support thin wrapped batches later. */
|
||||
struct GPUVertBuf *buf;
|
||||
/* The buf is owned, we may support thin wrapped batches later. */
|
||||
struct GPUVertBuf *buf;
|
||||
} BPyGPUVertBuf;
|
||||
|
||||
PyObject *BPyGPUVertBuf_CreatePyObject(struct GPUVertBuf *buf) ATTR_NONNULL(1);
|
||||
|
@@ -27,7 +27,8 @@ extern PyTypeObject BPyGPUVertFormat_Type;
|
||||
#define BPyGPUVertFormat_Check(v) (Py_TYPE(v) == &BPyGPUVertFormat_Type)
|
||||
|
||||
typedef struct BPyGPUVertFormat {
|
||||
PyObject_VAR_HEAD struct GPUVertFormat fmt;
|
||||
PyObject_VAR_HEAD
|
||||
struct GPUVertFormat fmt;
|
||||
} BPyGPUVertFormat;
|
||||
|
||||
PyObject *BPyGPUVertFormat_CreatePyObject(struct GPUVertFormat *fmt);
|
||||
|
@@ -52,7 +52,8 @@ enum {
|
||||
|
||||
#define BASE_MATH_MEMBERS(_data) \
|
||||
/** Array of data (alias), wrapped status depends on wrapped status. */ \
|
||||
PyObject_VAR_HEAD float *_data; \
|
||||
PyObject_VAR_HEAD \
|
||||
float *_data; \
|
||||
/** If this vector references another object, otherwise NULL, *Note* this owns its reference */ \
|
||||
PyObject *cb_user; \
|
||||
/** Which user funcs do we adhere to, RNA, etc */ \
|
||||
|
Reference in New Issue
Block a user