forked from bartvdbraak/blender
Merge branch 'master' into blender2.8
This commit is contained in:
commit
9567529b8f
@ -21,6 +21,9 @@ CCL_NAMESPACE_BEGIN
|
||||
* BSDF evaluation result, split per BSDF type. This is used to accumulate
|
||||
* render passes separately. */
|
||||
|
||||
ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg,
|
||||
const ShaderData *sd);
|
||||
|
||||
ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 value, int use_light_pass)
|
||||
{
|
||||
#ifdef __PASSES__
|
||||
@ -223,6 +226,7 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
|
||||
L->shadow_background_color = make_float3(0.0f, 0.0f, 0.0f);
|
||||
L->shadow_radiance_sum = make_float3(0.0f, 0.0f, 0.0f);
|
||||
L->shadow_throughput = 0.0f;
|
||||
L->shadow_transparency = 1.0f;
|
||||
#endif
|
||||
|
||||
#ifdef __DENOISING_FEATURES__
|
||||
@ -398,10 +402,11 @@ ccl_device_inline void path_radiance_accum_total_light(
|
||||
#endif
|
||||
}
|
||||
|
||||
ccl_device_inline void path_radiance_accum_background(PathRadiance *L,
|
||||
ccl_addr_space PathState *state,
|
||||
float3 throughput,
|
||||
float3 value)
|
||||
ccl_device_inline void path_radiance_accum_background(
|
||||
PathRadiance *L,
|
||||
ccl_addr_space PathState *state,
|
||||
float3 throughput,
|
||||
float3 value)
|
||||
{
|
||||
#ifdef __PASSES__
|
||||
if(L->use_light_pass) {
|
||||
@ -421,9 +426,7 @@ ccl_device_inline void path_radiance_accum_background(PathRadiance *L,
|
||||
#ifdef __SHADOW_TRICKS__
|
||||
if(state->flag & PATH_RAY_STORE_SHADOW_INFO) {
|
||||
L->path_total += throughput * value;
|
||||
if(state->flag & PATH_RAY_SHADOW_CATCHER_ONLY) {
|
||||
L->path_total_shaded += throughput * value;
|
||||
}
|
||||
L->path_total_shaded += throughput * value * L->shadow_transparency;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -671,7 +674,7 @@ ccl_device_inline float path_radiance_sum_shadow(const PathRadiance *L)
|
||||
if(path_total != 0.0f) {
|
||||
return path_total_shaded / path_total;
|
||||
}
|
||||
return 1.0f;
|
||||
return L->shadow_transparency;
|
||||
}
|
||||
|
||||
/* Calculate final light sum and transparency for shadow catcher object. */
|
||||
|
@ -320,8 +320,12 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
|
||||
#endif /* __BRANCHED_PATH__ */
|
||||
|
||||
#ifdef __SHADOW_TRICKS__
|
||||
if(!(sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) {
|
||||
state->flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
|
||||
if(!(sd->object_flag & SD_OBJECT_SHADOW_CATCHER) &&
|
||||
(state->flag & PATH_RAY_SHADOW_CATCHER))
|
||||
{
|
||||
/* Only update transparency after shadow catcher bounce. */
|
||||
L->shadow_transparency *=
|
||||
average(shader_bsdf_transparency(kg, sd));
|
||||
}
|
||||
#endif /* __SHADOW_TRICKS__ */
|
||||
|
||||
@ -647,7 +651,6 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
|
||||
if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) {
|
||||
if(state.flag & PATH_RAY_CAMERA) {
|
||||
state.flag |= (PATH_RAY_SHADOW_CATCHER |
|
||||
PATH_RAY_SHADOW_CATCHER_ONLY |
|
||||
PATH_RAY_STORE_SHADOW_INFO);
|
||||
if(!kernel_data.background.transparent) {
|
||||
L->shadow_background_color =
|
||||
@ -657,8 +660,10 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
|
||||
L->shadow_throughput = average(throughput);
|
||||
}
|
||||
}
|
||||
else {
|
||||
state.flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
|
||||
else if(state.flag & PATH_RAY_SHADOW_CATCHER) {
|
||||
/* Only update transparency after shadow catcher bounce. */
|
||||
L->shadow_transparency *=
|
||||
average(shader_bsdf_transparency(kg, &sd));
|
||||
}
|
||||
#endif /* __SHADOW_TRICKS__ */
|
||||
|
||||
|
@ -119,6 +119,9 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba
|
||||
PathState ps = *state;
|
||||
float3 tp = throughput;
|
||||
Ray bsdf_ray;
|
||||
#ifdef __SHADOW_TRICKS__
|
||||
float shadow_transparency = L->shadow_transparency;
|
||||
#endif
|
||||
|
||||
if(!kernel_branched_path_surface_bounce(kg,
|
||||
&bsdf_rng,
|
||||
@ -149,6 +152,10 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba
|
||||
* for the next samples */
|
||||
path_radiance_sum_indirect(L);
|
||||
path_radiance_reset_indirect(L);
|
||||
|
||||
#ifdef __SHADOW_TRICKS__
|
||||
L->shadow_transparency = shadow_transparency;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -500,7 +507,6 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
|
||||
#ifdef __SHADOW_TRICKS__
|
||||
if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) {
|
||||
state.flag |= (PATH_RAY_SHADOW_CATCHER |
|
||||
PATH_RAY_SHADOW_CATCHER_ONLY |
|
||||
PATH_RAY_STORE_SHADOW_INFO);
|
||||
if(!kernel_data.background.transparent) {
|
||||
L->shadow_background_color =
|
||||
@ -509,8 +515,10 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
|
||||
L->shadow_radiance_sum = path_radiance_clamp_and_sum(kg, L);
|
||||
L->shadow_throughput = average(throughput);
|
||||
}
|
||||
else {
|
||||
state.flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
|
||||
else if(state.flag & PATH_RAY_SHADOW_CATCHER) {
|
||||
/* Only update transparency after shadow catcher bounce. */
|
||||
L->shadow_transparency *=
|
||||
average(shader_bsdf_transparency(kg, &sd));
|
||||
}
|
||||
#endif /* __SHADOW_TRICKS__ */
|
||||
|
||||
|
@ -669,7 +669,7 @@ ccl_device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughn
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
|
||||
ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, const ShaderData *sd)
|
||||
{
|
||||
if(sd->flag & SD_HAS_ONLY_VOLUME)
|
||||
return make_float3(1.0f, 1.0f, 1.0f);
|
||||
@ -677,7 +677,7 @@ ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
|
||||
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
for(int i = 0; i < sd->num_closure; i++) {
|
||||
ShaderClosure *sc = &sd->closure[i];
|
||||
const ShaderClosure *sc = &sd->closure[i];
|
||||
|
||||
if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) // todo: make this work for osl
|
||||
eval += sc->weight;
|
||||
|
@ -351,8 +351,7 @@ enum PathRayFlag {
|
||||
PATH_RAY_DIFFUSE_ANCESTOR = (1 << 16),
|
||||
PATH_RAY_SINGLE_PASS_DONE = (1 << 17),
|
||||
PATH_RAY_SHADOW_CATCHER = (1 << 18),
|
||||
PATH_RAY_SHADOW_CATCHER_ONLY = (1 << 19),
|
||||
PATH_RAY_STORE_SHADOW_INFO = (1 << 20),
|
||||
PATH_RAY_STORE_SHADOW_INFO = (1 << 19),
|
||||
};
|
||||
|
||||
/* Closure Label */
|
||||
@ -529,6 +528,9 @@ typedef ccl_addr_space struct PathRadiance {
|
||||
*/
|
||||
float3 shadow_radiance_sum;
|
||||
float shadow_throughput;
|
||||
|
||||
/* Accumulated transparency along the path after shadow catcher bounce. */
|
||||
float shadow_transparency;
|
||||
#endif
|
||||
|
||||
#ifdef __DENOISING_FEATURES__
|
||||
|
@ -127,7 +127,6 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
|
||||
if(state->flag & PATH_RAY_CAMERA) {
|
||||
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
|
||||
state->flag |= (PATH_RAY_SHADOW_CATCHER |
|
||||
PATH_RAY_SHADOW_CATCHER_ONLY |
|
||||
PATH_RAY_STORE_SHADOW_INFO);
|
||||
if(!kernel_data.background.transparent) {
|
||||
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
|
||||
@ -141,8 +140,10 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
|
||||
L->shadow_throughput = average(throughput);
|
||||
}
|
||||
}
|
||||
else {
|
||||
state->flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
|
||||
else if(state->flag & PATH_RAY_SHADOW_CATCHER) {
|
||||
/* Only update transparency after shadow catcher bounce. */
|
||||
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
|
||||
L->shadow_transparency *= average(shader_bsdf_transparency(kg, sd));
|
||||
}
|
||||
#endif /* __SHADOW_TRICKS__ */
|
||||
|
||||
|
@ -79,7 +79,7 @@ class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
|
||||
|
||||
col = split.column()
|
||||
|
||||
if obj.type in {'MESH', 'LATTICE', 'CURVE'}:
|
||||
if obj.type in {'MESH', 'LATTICE', 'CURVE', 'SURFACE', 'FONT'}:
|
||||
physics_add(self, col, context.soft_body, "Soft Body", 'SOFT_BODY', 'MOD_SOFT', True)
|
||||
|
||||
if obj.type == 'MESH':
|
||||
|
@ -26,6 +26,9 @@ from bl_ui.properties_physics_common import (
|
||||
)
|
||||
|
||||
|
||||
COMPAT_OB_TYPES = {'MESH', 'LATTICE', 'CURVE', 'SURFACE', 'FONT'}
|
||||
|
||||
|
||||
def softbody_panel_enabled(md):
|
||||
return (md.point_cache.is_baked is False)
|
||||
|
||||
@ -39,7 +42,7 @@ class PhysicButtonsPanel:
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
rd = context.scene.render
|
||||
return (ob and (ob.type == 'MESH' or ob.type == 'LATTICE'or ob.type == 'CURVE')) and (rd.engine in cls.COMPAT_ENGINES) and (context.soft_body)
|
||||
return ob and ob.type in COMPAT_OB_TYPES and rd.engine in cls.COMPAT_ENGINES and context.soft_body
|
||||
|
||||
|
||||
class PHYSICS_PT_softbody(PhysicButtonsPanel, Panel):
|
||||
|
@ -94,8 +94,8 @@ void BKE_curve_texspace_get(struct Curve *cu, float r_loc[3], float r_rot[3], fl
|
||||
bool BKE_curve_minmax(struct Curve *cu, bool use_radius, float min[3], float max[3]);
|
||||
bool BKE_curve_center_median(struct Curve *cu, float cent[3]);
|
||||
bool BKE_curve_center_bounds(struct Curve *cu, float cent[3]);
|
||||
void BKE_curve_transform_ex(struct Curve *cu, float mat[4][4], const bool do_keys, const float unit_scale);
|
||||
void BKE_curve_transform(struct Curve *cu, float mat[4][4], const bool do_keys);
|
||||
void BKE_curve_transform_ex(struct Curve *cu, float mat[4][4], const bool do_keys, const bool do_props, const float unit_scale);
|
||||
void BKE_curve_transform(struct Curve *cu, float mat[4][4], const bool do_keys, const bool do_props);
|
||||
void BKE_curve_translate(struct Curve *cu, float offset[3], const bool do_keys);
|
||||
void BKE_curve_material_index_remove(struct Curve *cu, int index);
|
||||
void BKE_curve_material_index_clear(struct Curve *cu);
|
||||
|
@ -60,7 +60,7 @@ bool BKE_mball_minmax_ex(struct MetaBall *mb, float min[3], float max[3],
|
||||
float obmat[4][4], const short flag);
|
||||
bool BKE_mball_center_median(struct MetaBall *mb, float r_cent[3]);
|
||||
bool BKE_mball_center_bounds(struct MetaBall *mb, float r_cent[3]);
|
||||
void BKE_mball_transform(struct MetaBall *mb, float mat[4][4]);
|
||||
void BKE_mball_transform(struct MetaBall *mb, float mat[4][4], const bool do_props);
|
||||
void BKE_mball_translate(struct MetaBall *mb, const float offset[3]);
|
||||
|
||||
struct MetaElem *BKE_mball_element_add(struct MetaBall *mb, const int type);
|
||||
|
@ -4446,7 +4446,9 @@ bool BKE_curve_center_bounds(Curve *cu, float cent[3])
|
||||
}
|
||||
|
||||
|
||||
void BKE_curve_transform_ex(Curve *cu, float mat[4][4], const bool do_keys, const float unit_scale)
|
||||
void BKE_curve_transform_ex(
|
||||
Curve *cu, float mat[4][4],
|
||||
const bool do_keys, const bool do_props, const float unit_scale)
|
||||
{
|
||||
Nurb *nu;
|
||||
BPoint *bp;
|
||||
@ -4460,7 +4462,9 @@ void BKE_curve_transform_ex(Curve *cu, float mat[4][4], const bool do_keys, cons
|
||||
mul_m4_v3(mat, bezt->vec[0]);
|
||||
mul_m4_v3(mat, bezt->vec[1]);
|
||||
mul_m4_v3(mat, bezt->vec[2]);
|
||||
bezt->radius *= unit_scale;
|
||||
if (do_props) {
|
||||
bezt->radius *= unit_scale;
|
||||
}
|
||||
}
|
||||
BKE_nurb_handles_calc(nu);
|
||||
}
|
||||
@ -4468,7 +4472,9 @@ void BKE_curve_transform_ex(Curve *cu, float mat[4][4], const bool do_keys, cons
|
||||
i = nu->pntsu * nu->pntsv;
|
||||
for (bp = nu->bp; i--; bp++) {
|
||||
mul_m4_v3(mat, bp->vec);
|
||||
bp->radius *= unit_scale;
|
||||
if (do_props) {
|
||||
bp->radius *= unit_scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4484,10 +4490,12 @@ void BKE_curve_transform_ex(Curve *cu, float mat[4][4], const bool do_keys, cons
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_curve_transform(Curve *cu, float mat[4][4], const bool do_keys)
|
||||
void BKE_curve_transform(
|
||||
Curve *cu, float mat[4][4],
|
||||
const bool do_keys, const bool do_props)
|
||||
{
|
||||
float unit_scale = mat4_to_scale(mat);
|
||||
BKE_curve_transform_ex(cu, mat, do_keys, unit_scale);
|
||||
BKE_curve_transform_ex(cu, mat, do_keys, do_props, unit_scale);
|
||||
}
|
||||
|
||||
void BKE_curve_translate(Curve *cu, float offset[3], const bool do_keys)
|
||||
|
@ -472,7 +472,7 @@ bool BKE_mball_center_bounds(MetaBall *mb, float r_cent[3])
|
||||
return false;
|
||||
}
|
||||
|
||||
void BKE_mball_transform(MetaBall *mb, float mat[4][4])
|
||||
void BKE_mball_transform(MetaBall *mb, float mat[4][4], const bool do_props)
|
||||
{
|
||||
MetaElem *me;
|
||||
float quat[4];
|
||||
@ -484,14 +484,17 @@ void BKE_mball_transform(MetaBall *mb, float mat[4][4])
|
||||
for (me = mb->elems.first; me; me = me->next) {
|
||||
mul_m4_v3(mat, &me->x);
|
||||
mul_qt_qtqt(me->quat, quat, me->quat);
|
||||
me->rad *= scale;
|
||||
/* hrmf, probably elems shouldn't be
|
||||
* treating scale differently - campbell */
|
||||
if (!MB_TYPE_SIZE_SQUARED(me->type)) {
|
||||
mul_v3_fl(&me->expx, scale);
|
||||
}
|
||||
else {
|
||||
mul_v3_fl(&me->expx, scale_sqrt);
|
||||
|
||||
if (do_props) {
|
||||
me->rad *= scale;
|
||||
/* hrmf, probably elems shouldn't be
|
||||
* treating scale differently - campbell */
|
||||
if (!MB_TYPE_SIZE_SQUARED(me->type)) {
|
||||
mul_v3_fl(&me->expx, scale);
|
||||
}
|
||||
else {
|
||||
mul_v3_fl(&me->expx, scale_sqrt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2280,7 +2280,7 @@ StructRNA *ntreeInterfaceTypeGet(bNodeTree *ntree, int create)
|
||||
|
||||
/* rename the RNA type */
|
||||
RNA_def_struct_free_pointers(srna);
|
||||
RNA_def_struct_identifier(srna, identifier);
|
||||
RNA_def_struct_identifier(&BLENDER_RNA, srna, identifier);
|
||||
RNA_def_struct_ui_text(srna, name, description);
|
||||
RNA_def_struct_duplicate_pointers(srna);
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ extern "C" {
|
||||
#ifndef GHASH_INTERNAL_API
|
||||
# ifdef __GNUC__
|
||||
# undef _GHASH_INTERNAL_ATTR
|
||||
# define _GHASH_INTERNAL_ATTR __attribute__ ((deprecated))
|
||||
# define _GHASH_INTERNAL_ATTR __attribute__ ((deprecated)) /* not deprecated, just private. */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -4531,53 +4531,198 @@ static void set_profile_spacing(BevelParams *bp)
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate and return an offset that is the lesser of the current
|
||||
* Assume we have a situation like:
|
||||
*
|
||||
* a d
|
||||
* \ /
|
||||
* A \ / C
|
||||
* \ th1 th2/
|
||||
* b---------c
|
||||
* B
|
||||
*
|
||||
* where edges are A, B, and C,
|
||||
* following a face around vertices a, b, c, d;
|
||||
* th1 is angle abc and th2 is angle bcd;
|
||||
* and the argument EdgeHalf eb is B, going from b to c.
|
||||
* In general case, edge offset specs for A, B, C have
|
||||
* the form ka*t, kb*t, kc*t where ka, kb, kc are some factors
|
||||
* (may be 0) and t is the current bp->offset.
|
||||
* We want to calculate t at which the clone of B parallel
|
||||
* to it collapses. This can be calculated using trig.
|
||||
* Another case of geometry collision that can happen is
|
||||
* When B slides along A because A is unbeveled.
|
||||
* Then it might collide with a. Similarly for B sliding along C.
|
||||
*/
|
||||
static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
|
||||
{
|
||||
EdgeHalf *ea, *ec, *ebother;
|
||||
BevVert *bvc;
|
||||
BMLoop *lb;
|
||||
BMVert *va, *vb, *vc, *vd;
|
||||
float ka, kb, kc, g, h, t, den, no_collide_offset, th1, th2, sin1, sin2, tan1, tan2, limit;
|
||||
|
||||
limit = no_collide_offset = bp->offset + 1e6;
|
||||
if (bp->offset == 0.0f)
|
||||
return no_collide_offset;
|
||||
kb = eb->offset_l_spec;
|
||||
ea = eb->next; /* note: this is in direction b --> a */
|
||||
ka = ea->offset_r_spec;
|
||||
if (eb->is_rev) {
|
||||
vc = eb->e->v1;
|
||||
vb = eb->e->v2;
|
||||
}
|
||||
else {
|
||||
vb = eb->e->v1;
|
||||
vc = eb->e->v2;
|
||||
}
|
||||
va = ea->is_rev ? ea->e->v1 : ea->e->v2;
|
||||
bvc = NULL;
|
||||
ebother = find_other_end_edge_half(bp, eb, &bvc);
|
||||
if (ebother != NULL) {
|
||||
ec = ebother->prev; /* note: this is in direction c --> d*/
|
||||
vc = bvc->v;
|
||||
kc = ec->offset_l_spec;
|
||||
vd = ec->is_rev ? ec->e->v1 : ec->e->v2;
|
||||
}
|
||||
else {
|
||||
/* No bevvert for w, so C can't be beveled */
|
||||
kc = 0.0f;
|
||||
ec = NULL;
|
||||
/* Find an edge from c that has same face */
|
||||
lb = BM_face_edge_share_loop(eb->fnext, eb->e);
|
||||
if (!lb) {
|
||||
return no_collide_offset;
|
||||
}
|
||||
if (lb->next->v == vc)
|
||||
vd = lb->next->next->v;
|
||||
else if (lb->v == vc)
|
||||
vd = lb->prev->v;
|
||||
else {
|
||||
return no_collide_offset;
|
||||
}
|
||||
}
|
||||
if (ea->e == eb->e || (ec && ec->e == eb->e))
|
||||
return no_collide_offset;
|
||||
ka = ka / bp->offset;
|
||||
kb = kb / bp->offset;
|
||||
kc = kc / bp->offset;
|
||||
th1 = angle_v3v3v3(va->co, vb->co, vc->co);
|
||||
th2 = angle_v3v3v3(vb->co, vc->co, vd->co);
|
||||
|
||||
/* First calculate offset at which edge B collapses, which happens
|
||||
* when advancing clones of A, B, C all meet at a point.
|
||||
* This only happens if at least two of those three edges have non-zero k's */
|
||||
sin1 = sinf(th1);
|
||||
sin2 = sinf(th2);
|
||||
if ((ka > 0.0f) + (kb > 0.0f) + (kc > 0.0f) >= 2) {
|
||||
tan1 = tanf(th1);
|
||||
tan2 = tanf(th2);
|
||||
g = tan1 * tan2;
|
||||
h = sin1 * sin2;
|
||||
den = g * (ka * sin2 + kc * sin1) + kb * h * (tan1 + tan2);
|
||||
if (den != 0.0f) {
|
||||
t = BM_edge_calc_length(eb->e);
|
||||
t *= g * h / den;
|
||||
if (t >= 0.0f)
|
||||
limit = t;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now check edge slide cases */
|
||||
if (kb > 0.0f && ka == 0.0f /*&& bvb->selcount == 1 && bvb->edgecount > 2*/) {
|
||||
t = BM_edge_calc_length(ea->e);
|
||||
t *= sin1 / kb;
|
||||
if (t >= 0.0f && t < limit)
|
||||
limit = t;
|
||||
}
|
||||
if (kb > 0.0f && kc == 0.0f /* && bvc && ec && bvc->selcount == 1 && bvc->edgecount > 2 */) {
|
||||
t = BM_edge_calc_length(ec->e);
|
||||
t *= sin2 / kb;
|
||||
if (t >= 0.0f && t < limit)
|
||||
limit = t;
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have an edge A between vertices a and b,
|
||||
* where EdgeHalf ea is the half of A that starts at a.
|
||||
* For vertex-only bevels, the new vertices slide from a at a rate ka*t
|
||||
* and from b at a rate kb*t.
|
||||
* We want to calculate the t at which the two meet.
|
||||
*/
|
||||
static float vertex_collide_offset(BevelParams *bp, EdgeHalf *ea)
|
||||
{
|
||||
float limit, ka, kb, no_collide_offset, la, kab;
|
||||
EdgeHalf *eb;
|
||||
|
||||
limit = no_collide_offset = bp->offset + 1e6;
|
||||
if (bp->offset == 0.0f)
|
||||
return no_collide_offset;
|
||||
ka = ea->offset_l_spec / bp->offset;
|
||||
eb = find_other_end_edge_half(bp, ea, NULL);
|
||||
kb = eb ? eb->offset_l_spec / bp->offset : 0.0f;
|
||||
kab = ka + kb;
|
||||
la = BM_edge_calc_length(ea->e);
|
||||
if (kab <= 0.0f)
|
||||
return no_collide_offset;
|
||||
limit = la / kab;
|
||||
return limit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate an offset that is the lesser of the current
|
||||
* bp.offset and the maximum possible offset before geometry
|
||||
* collisions happen.
|
||||
* Currently this is a quick and dirty estimate of the max
|
||||
* possible: half the minimum edge length of any vertex involved
|
||||
* in a bevel. This is usually conservative.
|
||||
* The correct calculation is quite complicated.
|
||||
* TODO: implement this correctly.
|
||||
* If the offset changes as a result of this, adjust the
|
||||
* current edge offset specs to reflect this clamping,
|
||||
* and store the new offset in bp.offset.
|
||||
*/
|
||||
static float bevel_limit_offset(BMesh *bm, BevelParams *bp)
|
||||
static void bevel_limit_offset(BevelParams *bp)
|
||||
{
|
||||
BMVert *v;
|
||||
BMEdge *e;
|
||||
BMIter v_iter, e_iter;
|
||||
float limited_offset, half_elen;
|
||||
bool vbeveled;
|
||||
BevVert *bv;
|
||||
EdgeHalf *eh;
|
||||
GHashIterator giter;
|
||||
float limited_offset, offset_factor, collision_offset;
|
||||
int i;
|
||||
|
||||
limited_offset = bp->offset;
|
||||
if (bp->offset_type == BEVEL_AMT_PERCENT) {
|
||||
if (limited_offset > 50.0f)
|
||||
limited_offset = 50.0f;
|
||||
return limited_offset;
|
||||
}
|
||||
BM_ITER_MESH (v, &v_iter, bm, BM_VERTS_OF_MESH) {
|
||||
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
|
||||
GHASH_ITER(giter, bp->vert_hash) {
|
||||
bv = BLI_ghashIterator_getValue(&giter);
|
||||
for (i = 0; i < bv->edgecount; i++) {
|
||||
eh = &bv->edges[i];
|
||||
if (bp->vertex_only) {
|
||||
vbeveled = true;
|
||||
collision_offset = vertex_collide_offset(bp, eh);
|
||||
if (collision_offset < limited_offset)
|
||||
limited_offset = collision_offset;
|
||||
}
|
||||
else {
|
||||
vbeveled = false;
|
||||
BM_ITER_ELEM (e, &e_iter, v, BM_EDGES_OF_VERT) {
|
||||
if (BM_elem_flag_test(BM_edge_other_vert(e, v), BM_ELEM_TAG)) {
|
||||
vbeveled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vbeveled) {
|
||||
BM_ITER_ELEM (e, &e_iter, v, BM_EDGES_OF_VERT) {
|
||||
half_elen = 0.5f * BM_edge_calc_length(e);
|
||||
if (half_elen < limited_offset)
|
||||
limited_offset = half_elen;
|
||||
}
|
||||
collision_offset = geometry_collide_offset(bp, eh);
|
||||
if (collision_offset < limited_offset)
|
||||
limited_offset = collision_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
return limited_offset;
|
||||
|
||||
if (limited_offset < bp->offset) {
|
||||
/* All current offset specs have some number times bp->offset,
|
||||
* so we can just multiply them all by the reduction factor
|
||||
* of the offset to have the effect of recalculating the specs
|
||||
* with the new limited_offset.
|
||||
*/
|
||||
offset_factor = limited_offset / bp->offset;
|
||||
GHASH_ITER(giter, bp->vert_hash) {
|
||||
bv = BLI_ghashIterator_getValue(&giter);
|
||||
for (i = 0; i < bv->edgecount; i++) {
|
||||
eh = &bv->edges[i];
|
||||
eh->offset_l_spec *= offset_factor;
|
||||
eh->offset_r_spec *= offset_factor;
|
||||
eh->offset_l *= offset_factor;
|
||||
eh->offset_r *= offset_factor;
|
||||
}
|
||||
}
|
||||
bp->offset = limited_offset;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4604,6 +4749,7 @@ void BM_mesh_bevel(
|
||||
BMEdge *e;
|
||||
BevVert *bv;
|
||||
BevelParams bp = {NULL};
|
||||
GHashIterator giter;
|
||||
|
||||
bp.offset = offset;
|
||||
bp.offset_type = offset_type;
|
||||
@ -4627,24 +4773,33 @@ void BM_mesh_bevel(
|
||||
BLI_memarena_use_calloc(bp.mem_arena);
|
||||
set_profile_spacing(&bp);
|
||||
|
||||
if (limit_offset)
|
||||
bp.offset = bevel_limit_offset(bm, &bp);
|
||||
|
||||
/* Analyze input vertices, sorting edges and assigning initial new vertex positions */
|
||||
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
|
||||
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
|
||||
bv = bevel_vert_construct(bm, &bp, v);
|
||||
if (bv)
|
||||
if (!limit_offset && bv)
|
||||
build_boundary(&bp, bv, true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Perhaps clamp offset to avoid geometry colliisions */
|
||||
if (limit_offset) {
|
||||
bevel_limit_offset(&bp);
|
||||
|
||||
/* Assign initial new vertex positions */
|
||||
GHASH_ITER(giter, bp.vert_hash) {
|
||||
bv = BLI_ghashIterator_getValue(&giter);
|
||||
build_boundary(&bp, bv, true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Perhaps do a pass to try to even out widths */
|
||||
if (!bp.vertex_only) {
|
||||
adjust_offsets(&bp);
|
||||
}
|
||||
|
||||
/* Build the meshes around vertices, now that positions are final */
|
||||
/* Note: could use GHASH_ITER over bp.vert_hash when backward compatibility no longer matters */
|
||||
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
|
||||
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
|
||||
bv = find_bevvert(&bp, v);
|
||||
|
@ -1788,7 +1788,9 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
|
||||
NlaStrip *strip = (NlaStrip *)ptr.data;
|
||||
FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
|
||||
|
||||
success = insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, 0);
|
||||
if (fcu) {
|
||||
success = insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, 0);
|
||||
}
|
||||
}
|
||||
else if (UI_but_flag_is_set(but, UI_BUT_DRIVEN)) {
|
||||
/* Driven property - Find driver */
|
||||
@ -1893,27 +1895,27 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
|
||||
NlaStrip *strip = (NlaStrip *)ptr.data;
|
||||
FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), 0);
|
||||
|
||||
BLI_assert(fcu != NULL); /* NOTE: This should be true, or else we wouldn't be able to get here */
|
||||
|
||||
if (BKE_fcurve_is_protected(fcu)) {
|
||||
BKE_reportf(op->reports, RPT_WARNING,
|
||||
"Not deleting keyframe for locked F-Curve for NLA Strip influence on %s - %s '%s'",
|
||||
strip->name, BKE_idcode_to_name(GS(id->name)), id->name + 2);
|
||||
}
|
||||
else {
|
||||
/* remove the keyframe directly
|
||||
* NOTE: cannot use delete_keyframe_fcurve(), as that will free the curve,
|
||||
* and delete_keyframe() expects the FCurve to be part of an action
|
||||
*/
|
||||
bool found = false;
|
||||
int i;
|
||||
|
||||
/* try to find index of beztriple to get rid of */
|
||||
i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
|
||||
if (found) {
|
||||
/* delete the key at the index (will sanity check + do recalc afterwards) */
|
||||
delete_fcurve_key(fcu, i, 1);
|
||||
success = true;
|
||||
if (fcu) {
|
||||
if (BKE_fcurve_is_protected(fcu)) {
|
||||
BKE_reportf(op->reports, RPT_WARNING,
|
||||
"Not deleting keyframe for locked F-Curve for NLA Strip influence on %s - %s '%s'",
|
||||
strip->name, BKE_idcode_to_name(GS(id->name)), id->name + 2);
|
||||
}
|
||||
else {
|
||||
/* remove the keyframe directly
|
||||
* NOTE: cannot use delete_keyframe_fcurve(), as that will free the curve,
|
||||
* and delete_keyframe() expects the FCurve to be part of an action
|
||||
*/
|
||||
bool found = false;
|
||||
int i;
|
||||
|
||||
/* try to find index of beztriple to get rid of */
|
||||
i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
|
||||
if (found) {
|
||||
/* delete the key at the index (will sanity check + do recalc afterwards) */
|
||||
delete_fcurve_key(fcu, i, 1);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@
|
||||
/* ************************** Object Tools Exports ******************************* */
|
||||
/* NOTE: these functions are exported to the Object module to be called from the tools there */
|
||||
|
||||
void ED_armature_apply_transform(Object *ob, float mat[4][4])
|
||||
void ED_armature_apply_transform(Object *ob, float mat[4][4], const bool do_props)
|
||||
{
|
||||
bArmature *arm = ob->data;
|
||||
|
||||
@ -74,14 +74,14 @@ void ED_armature_apply_transform(Object *ob, float mat[4][4])
|
||||
ED_armature_to_edit(arm);
|
||||
|
||||
/* Transform the bones */
|
||||
ED_armature_transform_bones(arm, mat);
|
||||
ED_armature_transform_bones(arm, mat, do_props);
|
||||
|
||||
/* Turn the list into an armature */
|
||||
ED_armature_from_edit(arm);
|
||||
ED_armature_edit_free(arm);
|
||||
}
|
||||
|
||||
void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4])
|
||||
void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4], const bool do_props)
|
||||
{
|
||||
EditBone *ebone;
|
||||
float scale = mat4_to_scale(mat); /* store the scale of the matrix here to use on envelopes */
|
||||
@ -106,27 +106,29 @@ void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4])
|
||||
/* apply the transformed roll back */
|
||||
mat3_to_vec_roll(tmat, NULL, &ebone->roll);
|
||||
|
||||
ebone->rad_head *= scale;
|
||||
ebone->rad_tail *= scale;
|
||||
ebone->dist *= scale;
|
||||
|
||||
/* we could be smarter and scale by the matrix along the x & z axis */
|
||||
ebone->xwidth *= scale;
|
||||
ebone->zwidth *= scale;
|
||||
if (do_props) {
|
||||
ebone->rad_head *= scale;
|
||||
ebone->rad_tail *= scale;
|
||||
ebone->dist *= scale;
|
||||
|
||||
/* we could be smarter and scale by the matrix along the x & z axis */
|
||||
ebone->xwidth *= scale;
|
||||
ebone->zwidth *= scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ED_armature_transform(struct bArmature *arm, float mat[4][4])
|
||||
void ED_armature_transform(struct bArmature *arm, float mat[4][4], const bool do_props)
|
||||
{
|
||||
if (arm->edbo) {
|
||||
ED_armature_transform_bones(arm, mat);
|
||||
ED_armature_transform_bones(arm, mat, do_props);
|
||||
}
|
||||
else {
|
||||
/* Put the armature into editmode */
|
||||
ED_armature_to_edit(arm);
|
||||
|
||||
/* Transform the bones */
|
||||
ED_armature_transform_bones(arm, mat);
|
||||
ED_armature_transform_bones(arm, mat, do_props);
|
||||
|
||||
/* Go back to object mode*/
|
||||
ED_armature_from_edit(arm);
|
||||
|
@ -166,9 +166,9 @@ void ED_armature_ebone_from_mat4(EditBone *ebone, float mat[4][4]);
|
||||
void transform_armature_mirror_update(struct Object *obedit);
|
||||
void ED_armature_origin_set(struct Scene *scene, struct Object *ob, float cursor[3], int centermode, int around);
|
||||
|
||||
void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4]);
|
||||
void ED_armature_apply_transform(struct Object *ob, float mat[4][4]);
|
||||
void ED_armature_transform(struct bArmature *arm, float mat[4][4]);
|
||||
void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4], const bool do_props);
|
||||
void ED_armature_apply_transform(struct Object *ob, float mat[4][4], const bool do_props);
|
||||
void ED_armature_transform(struct bArmature *arm, float mat[4][4], const bool do_props);
|
||||
|
||||
#define ARM_GROUPS_NAME 1
|
||||
#define ARM_GROUPS_ENVELOPE 2
|
||||
|
@ -247,7 +247,9 @@ static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, bool
|
||||
variable = (ui_layout_vary_direction(layout) == UI_ITEM_VARY_X);
|
||||
|
||||
if (variable) {
|
||||
layout->item.flag |= UI_ITEM_MIN;
|
||||
if (layout->alignment != UI_LAYOUT_ALIGN_EXPAND) {
|
||||
layout->item.flag |= UI_ITEM_MIN;
|
||||
}
|
||||
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
|
||||
/* it may seem odd that the icon only adds (UI_UNIT_X / 4)
|
||||
* but taking margins into account its fine */
|
||||
|
@ -422,7 +422,10 @@ static void ignore_parent_tx(const bContext *C, Main *bmain, Scene *scene, Objec
|
||||
}
|
||||
}
|
||||
|
||||
static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_loc, bool apply_rot, bool apply_scale)
|
||||
static int apply_objects_internal(
|
||||
bContext *C, ReportList *reports,
|
||||
bool apply_loc, bool apply_rot, bool apply_scale,
|
||||
bool do_props)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
@ -542,7 +545,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_l
|
||||
BKE_mesh_calc_normals(me);
|
||||
}
|
||||
else if (ob->type == OB_ARMATURE) {
|
||||
ED_armature_apply_transform(ob, mat);
|
||||
ED_armature_apply_transform(ob, mat, do_props);
|
||||
}
|
||||
else if (ob->type == OB_LATTICE) {
|
||||
Lattice *lt = ob->data;
|
||||
@ -551,12 +554,12 @@ static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_l
|
||||
}
|
||||
else if (ob->type == OB_MBALL) {
|
||||
MetaBall *mb = ob->data;
|
||||
BKE_mball_transform(mb, mat);
|
||||
BKE_mball_transform(mb, mat, do_props);
|
||||
}
|
||||
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
|
||||
Curve *cu = ob->data;
|
||||
scale = mat3_to_scale(rsmat);
|
||||
BKE_curve_transform_ex(cu, mat, true, scale);
|
||||
BKE_curve_transform_ex(cu, mat, true, do_props, scale);
|
||||
}
|
||||
else if (ob->type == OB_FONT) {
|
||||
Curve *cu = ob->data;
|
||||
@ -572,7 +575,9 @@ static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_l
|
||||
tb->h *= scale;
|
||||
}
|
||||
|
||||
cu->fsize *= scale;
|
||||
if (do_props) {
|
||||
cu->fsize *= scale;
|
||||
}
|
||||
}
|
||||
else if (ob->type == OB_CAMERA) {
|
||||
MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
|
||||
@ -691,9 +696,10 @@ static int object_transform_apply_exec(bContext *C, wmOperator *op)
|
||||
const bool loc = RNA_boolean_get(op->ptr, "location");
|
||||
const bool rot = RNA_boolean_get(op->ptr, "rotation");
|
||||
const bool sca = RNA_boolean_get(op->ptr, "scale");
|
||||
const bool do_props = RNA_boolean_get(op->ptr, "properties");
|
||||
|
||||
if (loc || rot || sca) {
|
||||
return apply_objects_internal(C, op->reports, loc, rot, sca);
|
||||
return apply_objects_internal(C, op->reports, loc, rot, sca, do_props);
|
||||
}
|
||||
else {
|
||||
/* allow for redo */
|
||||
@ -718,6 +724,8 @@ void OBJECT_OT_transform_apply(wmOperatorType *ot)
|
||||
RNA_def_boolean(ot->srna, "location", 0, "Location", "");
|
||||
RNA_def_boolean(ot->srna, "rotation", 0, "Rotation", "");
|
||||
RNA_def_boolean(ot->srna, "scale", 0, "Scale", "");
|
||||
RNA_def_boolean(ot->srna, "properties", true, "Apply Properties",
|
||||
"Modify properties such as curve vertex radius, font size and bone envelope");
|
||||
}
|
||||
|
||||
/********************* Set Object Center ************************/
|
||||
|
@ -1753,8 +1753,7 @@ typedef struct Scene {
|
||||
/* use preview range */
|
||||
#define SCER_PRV_RANGE (1<<0)
|
||||
#define SCER_LOCK_FRAME_SELECTION (1<<1)
|
||||
/* timeline/keyframe jumping - only selected items (on by default) */
|
||||
#define SCE_KEYS_NO_SELONLY (1<<2)
|
||||
/* show/use subframes (for checking motion blur) */
|
||||
#define SCER_SHOW_SUBFRAME (1<<3)
|
||||
|
||||
/* mode (int now) */
|
||||
@ -2091,6 +2090,7 @@ typedef enum eVGroupSelect {
|
||||
#define SCE_DS_COLLAPSED (1<<1)
|
||||
#define SCE_NLA_EDIT_ON (1<<2)
|
||||
#define SCE_FRAME_DROP (1<<3)
|
||||
#define SCE_KEYS_NO_SELONLY (1<<4)
|
||||
|
||||
|
||||
/* return flag BKE_scene_base_iter_next functions */
|
||||
|
@ -70,7 +70,8 @@ void RNA_def_struct_refine_func(StructRNA *srna, const char *refine);
|
||||
void RNA_def_struct_idprops_func(StructRNA *srna, const char *refine);
|
||||
void RNA_def_struct_register_funcs(StructRNA *srna, const char *reg, const char *unreg, const char *instance);
|
||||
void RNA_def_struct_path_func(StructRNA *srna, const char *path);
|
||||
void RNA_def_struct_identifier(StructRNA *srna, const char *identifier);
|
||||
void RNA_def_struct_identifier_no_struct_map(StructRNA *srna, const char *identifier);
|
||||
void RNA_def_struct_identifier(BlenderRNA *brna, StructRNA *srna, const char *identifier);
|
||||
void RNA_def_struct_ui_text(StructRNA *srna, const char *name, const char *description);
|
||||
void RNA_def_struct_ui_icon(StructRNA *srna, int icon);
|
||||
void RNA_struct_free_extension(StructRNA *srna, ExtensionRNA *ext);
|
||||
|
@ -2583,17 +2583,23 @@ static void rna_generate_blender(BlenderRNA *brna, FILE *f)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
fprintf(f, "BlenderRNA BLENDER_RNA = {");
|
||||
|
||||
fprintf(f,
|
||||
"BlenderRNA BLENDER_RNA = {\n"
|
||||
"\t.structs = {"
|
||||
);
|
||||
srna = brna->structs.first;
|
||||
if (srna) fprintf(f, "{&RNA_%s, ", srna->identifier);
|
||||
else fprintf(f, "{NULL, ");
|
||||
if (srna) fprintf(f, "&RNA_%s, ", srna->identifier);
|
||||
else fprintf(f, "NULL, ");
|
||||
|
||||
srna = brna->structs.last;
|
||||
if (srna) fprintf(f, "&RNA_%s}", srna->identifier);
|
||||
else fprintf(f, "NULL}");
|
||||
if (srna) fprintf(f, "&RNA_%s},\n", srna->identifier);
|
||||
else fprintf(f, "NULL},\n");
|
||||
|
||||
fprintf(f, "};\n\n");
|
||||
fprintf(f,
|
||||
"\t.structs_map = NULL,\n"
|
||||
"\t.structs_len = 0,\n"
|
||||
"};\n\n"
|
||||
);
|
||||
}
|
||||
|
||||
static void rna_generate_property_prototypes(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE *f)
|
||||
|
@ -77,6 +77,9 @@ void RNA_init(void)
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
BLENDER_RNA.structs_map = BLI_ghash_str_new_ex(__func__, 2048);
|
||||
BLENDER_RNA.structs_len = 0;
|
||||
|
||||
for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) {
|
||||
if (!srna->cont.prophash) {
|
||||
srna->cont.prophash = BLI_ghash_str_new("RNA_init gh");
|
||||
@ -87,6 +90,8 @@ void RNA_init(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
BLI_ghash_insert(BLENDER_RNA.structs_map, (void *)srna->identifier, srna);
|
||||
BLENDER_RNA.structs_len += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -514,13 +519,7 @@ static const char *rna_ensure_property_name(const PropertyRNA *prop)
|
||||
|
||||
StructRNA *RNA_struct_find(const char *identifier)
|
||||
{
|
||||
StructRNA *type;
|
||||
if (identifier) {
|
||||
for (type = BLENDER_RNA.structs.first; type; type = type->cont.next)
|
||||
if (STREQ(type->identifier, identifier))
|
||||
return type;
|
||||
}
|
||||
return NULL;
|
||||
return BLI_ghash_lookup(BLENDER_RNA.structs_map, identifier);
|
||||
}
|
||||
|
||||
const char *RNA_struct_identifier(const StructRNA *type)
|
||||
|
@ -481,7 +481,7 @@ static int rna_Armature_is_editmode_get(PointerRNA *ptr)
|
||||
|
||||
static void rna_Armature_transform(struct bArmature *arm, float *mat)
|
||||
{
|
||||
ED_armature_transform(arm, (float (*)[4])mat);
|
||||
ED_armature_transform(arm, (float (*)[4])mat, true);
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -45,7 +45,7 @@
|
||||
#ifdef RNA_RUNTIME
|
||||
static void rna_Curve_transform(Curve *cu, float *mat, int shape_keys)
|
||||
{
|
||||
BKE_curve_transform(cu, (float (*)[4])mat, shape_keys);
|
||||
BKE_curve_transform(cu, (float (*)[4])mat, shape_keys, true);
|
||||
|
||||
DEG_id_tag_update(&cu->id, 0);
|
||||
}
|
||||
|
@ -135,6 +135,36 @@ void rna_freelistN(ListBase *listbase)
|
||||
listbase->first = listbase->last = NULL;
|
||||
}
|
||||
|
||||
static void rna_brna_structs_add(BlenderRNA *brna, StructRNA *srna)
|
||||
{
|
||||
rna_addtail(&brna->structs, srna);
|
||||
brna->structs_len += 1;
|
||||
|
||||
/* This exception is only needed for pre-processing.
|
||||
* otherwise we don't allow empty names. */
|
||||
if (srna->identifier[0] != '\0') {
|
||||
BLI_ghash_insert(brna->structs_map, (void *)srna->identifier, srna);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
static void rna_brna_structs_remove_and_free(BlenderRNA *brna, StructRNA *srna)
|
||||
{
|
||||
if (brna->structs_map) {
|
||||
if (srna->identifier[0] != '\0') {
|
||||
BLI_ghash_remove(brna->structs_map, (void *)srna->identifier, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
RNA_def_struct_free_pointers(srna);
|
||||
|
||||
if (srna->flag & STRUCT_RUNTIME) {
|
||||
rna_freelinkN(&brna->structs, srna);
|
||||
}
|
||||
brna->structs_len -= 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
StructDefRNA *rna_find_struct_def(StructRNA *srna)
|
||||
{
|
||||
StructDefRNA *dsrna;
|
||||
@ -534,6 +564,8 @@ BlenderRNA *RNA_create(void)
|
||||
const char *error_message = NULL;
|
||||
|
||||
BLI_listbase_clear(&DefRNA.structs);
|
||||
brna->structs_map = BLI_ghash_str_new_ex(__func__, 2048);
|
||||
|
||||
DefRNA.error = 0;
|
||||
DefRNA.preprocess = 1;
|
||||
|
||||
@ -640,10 +672,8 @@ void RNA_struct_free(BlenderRNA *brna, StructRNA *srna)
|
||||
rna_freelinkN(&srna->functions, func);
|
||||
}
|
||||
|
||||
RNA_def_struct_free_pointers(srna);
|
||||
|
||||
if (srna->flag & STRUCT_RUNTIME)
|
||||
rna_freelinkN(&brna->structs, srna);
|
||||
rna_brna_structs_remove_and_free(brna, srna);
|
||||
#else
|
||||
UNUSED_VARS(brna, srna);
|
||||
#endif
|
||||
@ -654,6 +684,9 @@ void RNA_free(BlenderRNA *brna)
|
||||
StructRNA *srna, *nextsrna;
|
||||
FunctionRNA *func;
|
||||
|
||||
BLI_ghash_free(brna->structs_map, NULL, NULL);
|
||||
brna->structs_map = NULL;
|
||||
|
||||
if (DefRNA.preprocess) {
|
||||
RNA_define_free(brna);
|
||||
|
||||
@ -747,7 +780,7 @@ StructRNA *RNA_def_struct_ptr(BlenderRNA *brna, const char *identifier, StructRN
|
||||
if (!srnafrom)
|
||||
srna->icon = ICON_DOT;
|
||||
|
||||
rna_addtail(&brna->structs, srna);
|
||||
rna_brna_structs_add(brna, srna);
|
||||
|
||||
if (DefRNA.preprocess) {
|
||||
ds = MEM_callocN(sizeof(StructDefRNA), "StructDefRNA");
|
||||
@ -819,10 +852,8 @@ StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char *
|
||||
|
||||
if (from) {
|
||||
/* find struct to derive from */
|
||||
for (srnafrom = brna->structs.first; srnafrom; srnafrom = srnafrom->cont.next)
|
||||
if (STREQ(srnafrom->identifier, from))
|
||||
break;
|
||||
|
||||
/* Inline RNA_struct_find(...) because it wont link from here. */
|
||||
srnafrom = BLI_ghash_lookup(brna->structs_map, from);
|
||||
if (!srnafrom) {
|
||||
fprintf(stderr, "%s: struct %s not found to define %s.\n", __func__, from, identifier);
|
||||
DefRNA.error = 1;
|
||||
@ -901,10 +932,7 @@ void RNA_def_struct_nested(BlenderRNA *brna, StructRNA *srna, const char *struct
|
||||
StructRNA *srnafrom;
|
||||
|
||||
/* find struct to derive from */
|
||||
for (srnafrom = brna->structs.first; srnafrom; srnafrom = srnafrom->cont.next)
|
||||
if (STREQ(srnafrom->identifier, structname))
|
||||
break;
|
||||
|
||||
srnafrom = BLI_ghash_lookup(brna->structs_map, structname);
|
||||
if (!srnafrom) {
|
||||
fprintf(stderr, "%s: struct %s not found for %s.\n", __func__, structname, srna->identifier);
|
||||
DefRNA.error = 1;
|
||||
@ -965,7 +993,30 @@ void RNA_def_struct_path_func(StructRNA *srna, const char *path)
|
||||
if (path) srna->path = (StructPathFunc)path;
|
||||
}
|
||||
|
||||
void RNA_def_struct_identifier(StructRNA *srna, const char *identifier)
|
||||
void RNA_def_struct_identifier(BlenderRNA *brna, StructRNA *srna, const char *identifier)
|
||||
{
|
||||
if (DefRNA.preprocess) {
|
||||
fprintf(stderr, "%s: only at runtime.\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Operator registration may set twice, see: operator_properties_init */
|
||||
if (identifier != srna->identifier) {
|
||||
if (srna->identifier[0] != '\0') {
|
||||
BLI_ghash_remove(brna->structs_map, (void *)srna->identifier, NULL, NULL);
|
||||
}
|
||||
if (identifier[0] != '\0') {
|
||||
BLI_ghash_insert(brna->structs_map, (void *)identifier, srna);
|
||||
}
|
||||
}
|
||||
|
||||
srna->identifier = identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only used in one case when we name the struct for the purpose of useful error messages.
|
||||
*/
|
||||
void RNA_def_struct_identifier_no_struct_map(StructRNA *srna, const char *identifier)
|
||||
{
|
||||
if (DefRNA.preprocess) {
|
||||
fprintf(stderr, "%s: only at runtime.\n", __func__);
|
||||
|
@ -404,6 +404,9 @@ struct StructRNA {
|
||||
|
||||
struct BlenderRNA {
|
||||
ListBase structs;
|
||||
struct GHash *structs_map;
|
||||
/* Needed because types with an empty identifier aren't included in 'structs_map'. */
|
||||
unsigned int structs_len;
|
||||
};
|
||||
|
||||
#define CONTAINER_RNA_ID(cont) (*(const char **)(((ContainerRNA *)(cont))+1))
|
||||
|
@ -45,7 +45,7 @@
|
||||
#ifdef RNA_RUNTIME
|
||||
static void rna_Meta_transform(struct MetaBall *mb, float *mat)
|
||||
{
|
||||
BKE_mball_transform(mb, (float (*)[4])mat);
|
||||
BKE_mball_transform(mb, (float (*)[4])mat, true);
|
||||
|
||||
DEG_id_tag_update(&mb->id, 0);
|
||||
}
|
||||
|
@ -599,11 +599,10 @@ static void rna_NodeTree_unregister(Main *UNUSED(bmain), StructRNA *type)
|
||||
return;
|
||||
|
||||
RNA_struct_free_extension(type, &nt->ext);
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
ntreeTypeFreeLink(nt);
|
||||
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
/* update while blender is running */
|
||||
WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
|
||||
}
|
||||
@ -1352,11 +1351,11 @@ static void rna_Node_unregister(Main *UNUSED(bmain), StructRNA *type)
|
||||
return;
|
||||
|
||||
RNA_struct_free_extension(type, &nt->ext);
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
/* this also frees the allocated nt pointer, no MEM_free call needed! */
|
||||
nodeUnregisterType(nt);
|
||||
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
/* update while blender is running */
|
||||
WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
|
||||
@ -1814,10 +1813,10 @@ static void rna_NodeSocket_unregister(Main *UNUSED(bmain), StructRNA *type)
|
||||
return;
|
||||
|
||||
RNA_struct_free_extension(type, &st->ext_socket);
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
nodeUnregisterSocketType(st);
|
||||
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
/* update while blender is running */
|
||||
WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
|
||||
|
@ -299,8 +299,8 @@ static void rna_RenderEngine_unregister(Main *UNUSED(bmain), StructRNA *type)
|
||||
return;
|
||||
|
||||
RNA_struct_free_extension(type, &et->ext);
|
||||
BLI_freelinkN(&R_engines, et);
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
BLI_freelinkN(&R_engines, et);
|
||||
}
|
||||
|
||||
static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
|
||||
|
@ -985,19 +985,22 @@ static int rna_Function_use_self_type_get(PointerRNA *ptr)
|
||||
|
||||
static void rna_BlenderRNA_structs_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
rna_iterator_listbase_begin(iter, &((BlenderRNA *)ptr->data)->structs, NULL);
|
||||
BlenderRNA *brna = ptr->data;
|
||||
rna_iterator_listbase_begin(iter, &brna->structs, NULL);
|
||||
}
|
||||
|
||||
/* optional, for faster lookups */
|
||||
static int rna_BlenderRNA_structs_length(PointerRNA *ptr)
|
||||
{
|
||||
return BLI_listbase_count(&((BlenderRNA *)ptr->data)->structs);
|
||||
BlenderRNA *brna = ptr->data;
|
||||
BLI_assert(brna->structs_len == BLI_listbase_count(&brna->structs));
|
||||
return brna->structs_len;
|
||||
}
|
||||
static int rna_BlenderRNA_structs_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr)
|
||||
{
|
||||
StructRNA *srna = BLI_findlink(&((BlenderRNA *)ptr->data)->structs, index);
|
||||
|
||||
if (srna) {
|
||||
BlenderRNA *brna = ptr->data;
|
||||
StructRNA *srna = index < brna->structs_len ? BLI_findlink(&brna->structs, index) : NULL;
|
||||
if (srna != NULL) {
|
||||
RNA_pointer_create(NULL, &RNA_Struct, srna, r_ptr);
|
||||
return true;
|
||||
}
|
||||
@ -1007,12 +1010,11 @@ static int rna_BlenderRNA_structs_lookup_int(PointerRNA *ptr, int index, Pointer
|
||||
}
|
||||
static int rna_BlenderRNA_structs_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
|
||||
{
|
||||
StructRNA *srna = ((BlenderRNA *)ptr->data)->structs.first;
|
||||
for (; srna; srna = srna->cont.next) {
|
||||
if (key[0] == srna->identifier[0] && STREQ(key, srna->identifier)) {
|
||||
RNA_pointer_create(NULL, &RNA_Struct, srna, r_ptr);
|
||||
return true;
|
||||
}
|
||||
BlenderRNA *brna = ptr->data;
|
||||
StructRNA *srna = BLI_ghash_lookup(brna->structs_map, (void *)key);
|
||||
if (srna != NULL) {
|
||||
RNA_pointer_create(NULL, &RNA_Struct, srna, r_ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -177,9 +177,9 @@ static void rna_Panel_unregister(Main *UNUSED(bmain), StructRNA *type)
|
||||
return;
|
||||
|
||||
RNA_struct_free_extension(type, &pt->ext);
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
BLI_freelinkN(&art->paneltypes, pt);
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
/* update while blender is running */
|
||||
WM_main_add_notifier(NC_WINDOW, NULL);
|
||||
@ -455,11 +455,10 @@ static void rna_UIList_unregister(Main *UNUSED(bmain), StructRNA *type)
|
||||
return;
|
||||
|
||||
RNA_struct_free_extension(type, &ult->ext);
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
WM_uilisttype_freelink(ult);
|
||||
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
/* update while blender is running */
|
||||
WM_main_add_notifier(NC_WINDOW, NULL);
|
||||
}
|
||||
@ -551,9 +550,9 @@ static void rna_Header_unregister(Main *UNUSED(bmain), StructRNA *type)
|
||||
return;
|
||||
|
||||
RNA_struct_free_extension(type, &ht->ext);
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
BLI_freelinkN(&art->headertypes, ht);
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
/* update while blender is running */
|
||||
WM_main_add_notifier(NC_WINDOW, NULL);
|
||||
@ -673,11 +672,10 @@ static void rna_Menu_unregister(Main *UNUSED(bmain), StructRNA *type)
|
||||
return;
|
||||
|
||||
RNA_struct_free_extension(type, &mt->ext);
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
WM_menutype_freelink(mt);
|
||||
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
/* update while blender is running */
|
||||
WM_main_add_notifier(NC_WINDOW, NULL);
|
||||
}
|
||||
|
@ -609,9 +609,9 @@ static void rna_AddonPref_unregister(Main *UNUSED(bmain), StructRNA *type)
|
||||
return;
|
||||
|
||||
RNA_struct_free_extension(type, &apt->ext);
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
BKE_addon_pref_type_remove(apt);
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
/* update while blender is running */
|
||||
WM_main_add_notifier(NC_WINDOW, NULL);
|
||||
|
@ -1361,10 +1361,11 @@ static void rna_Operator_unregister(struct Main *bmain, StructRNA *type)
|
||||
|
||||
idname = ot->idname;
|
||||
WM_operatortype_remove_ptr(ot);
|
||||
MEM_freeN((void *)idname);
|
||||
|
||||
/* not to be confused with the RNA_struct_free that WM_operatortype_remove calls, they are 2 different srna's */
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
MEM_freeN((void *)idname);
|
||||
}
|
||||
|
||||
static void **rna_Operator_instance(PointerRNA *ptr)
|
||||
|
@ -130,7 +130,7 @@ static void manipulator_properties_init(wmManipulatorType *wt)
|
||||
/* only call this so pyrna_deferred_register_class gives a useful error
|
||||
* WM_operatortype_append_ptr will call RNA_def_struct_identifier
|
||||
* later */
|
||||
RNA_def_struct_identifier(wt->srna, wt->idname);
|
||||
RNA_def_struct_identifier(&BLENDER_RNA, wt->srna, wt->idname);
|
||||
|
||||
if (pyrna_deferred_register_class(wt->srna, py_class) != 0) {
|
||||
PyErr_Print(); /* failed to register operator props */
|
||||
|
@ -48,10 +48,12 @@ static void operator_properties_init(wmOperatorType *ot)
|
||||
PyTypeObject *py_class = ot->ext.data;
|
||||
RNA_struct_blender_type_set(ot->ext.srna, ot);
|
||||
|
||||
/* only call this so pyrna_deferred_register_class gives a useful error
|
||||
* WM_operatortype_append_ptr will call RNA_def_struct_identifier
|
||||
* later */
|
||||
RNA_def_struct_identifier(ot->srna, ot->idname);
|
||||
/* Only call this so pyrna_deferred_register_class gives a useful error
|
||||
* WM_operatortype_append_ptr will call RNA_def_struct_identifier later.
|
||||
*
|
||||
* Note the 'no_struct_map' function is used since the actual struct name is already used by the operator.
|
||||
*/
|
||||
RNA_def_struct_identifier_no_struct_map(ot->srna, ot->idname);
|
||||
|
||||
if (pyrna_deferred_register_class(ot->srna, py_class) != 0) {
|
||||
PyErr_Print(); /* failed to register operator props */
|
||||
|
@ -179,7 +179,7 @@ static void wm_operatortype_append__end(wmOperatorType *ot)
|
||||
|
||||
/* XXX All ops should have a description but for now allow them not to. */
|
||||
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP);
|
||||
RNA_def_struct_identifier(ot->srna, ot->idname);
|
||||
RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
|
||||
|
||||
BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
|
||||
}
|
||||
@ -401,7 +401,7 @@ wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *nam
|
||||
ot->description = UNDOCUMENTED_OPERATOR_TIP;
|
||||
|
||||
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description);
|
||||
RNA_def_struct_identifier(ot->srna, ot->idname);
|
||||
RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
|
||||
/* Use i18n context from ext.srna if possible (py operators). */
|
||||
i18n_context = ot->ext.srna ? RNA_struct_translation_context(ot->ext.srna) : BLT_I18NCONTEXT_OPERATOR_DEFAULT;
|
||||
RNA_def_struct_translation_context(ot->srna, i18n_context);
|
||||
@ -435,7 +435,7 @@ void WM_operatortype_append_macro_ptr(void (*opfunc)(wmOperatorType *, void *),
|
||||
opfunc(ot, userdata);
|
||||
|
||||
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description);
|
||||
RNA_def_struct_identifier(ot->srna, ot->idname);
|
||||
RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
|
||||
|
||||
BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ static void wm_manipulatortype_append__end(wmManipulatorType *wt)
|
||||
{
|
||||
BLI_assert(wt->struct_size >= sizeof(wmManipulator));
|
||||
|
||||
RNA_def_struct_identifier(wt->srna, wt->idname);
|
||||
RNA_def_struct_identifier(&BLENDER_RNA, wt->srna, wt->idname);
|
||||
|
||||
BLI_ghash_insert(global_manipulatortype_hash, (void *)wt->idname, wt);
|
||||
}
|
||||
|
@ -410,7 +410,7 @@ int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, const struc
|
||||
void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference) RET_NONE
|
||||
void WM_main_add_notifier(unsigned int type, void *reference) RET_NONE
|
||||
void ED_armature_bone_rename(struct bArmature *arm, const char *oldnamep, const char *newnamep) RET_NONE
|
||||
void ED_armature_transform(struct bArmature *arm, float mat[4][4]) RET_NONE
|
||||
void ED_armature_transform(struct bArmature *arm, float mat[4][4], const bool do_props) RET_NONE
|
||||
struct wmEventHandler *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op) RET_NULL
|
||||
struct wmTimer *WM_event_add_timer(struct wmWindowManager *wm, struct wmWindow *win, int event_type, double timestep) RET_NULL
|
||||
void WM_event_remove_timer(struct wmWindowManager *wm, struct wmWindow *win, struct wmTimer *timer) RET_NONE
|
||||
|
@ -163,6 +163,25 @@ class Report:
|
||||
<title>Cycles Test Report</title>
|
||||
<style>
|
||||
img {{ image-rendering: pixelated; width: 256; background-color: #000; }}
|
||||
img.render {{
|
||||
background-color: #fff;
|
||||
background-image:
|
||||
-moz-linear-gradient(45deg, #eee 25%, transparent 25%),
|
||||
-moz-linear-gradient(-45deg, #eee 25%, transparent 25%),
|
||||
-moz-linear-gradient(45deg, transparent 75%, #eee 75%),
|
||||
-moz-linear-gradient(-45deg, transparent 75%, #eee 75%);
|
||||
background-image:
|
||||
-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, #eee), color-stop(.25, transparent)),
|
||||
-webkit-gradient(linear, 0 0, 100% 100%, color-stop(.25, #eee), color-stop(.25, transparent)),
|
||||
-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.75, transparent), color-stop(.75, #eee)),
|
||||
-webkit-gradient(linear, 0 0, 100% 100%, color-stop(.75, transparent), color-stop(.75, #eee));
|
||||
|
||||
-moz-background-size:50px 50px;
|
||||
background-size:50px 50px;
|
||||
-webkit-background-size:50px 51px; /* override value for shitty webkit */
|
||||
|
||||
background-position:0 0, 25px 0, 25px -25px, 0px 25px;
|
||||
}}
|
||||
table td:first-child {{ width: 100%; }}
|
||||
</style>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css">
|
||||
@ -206,8 +225,8 @@ class Report:
|
||||
test_html = """
|
||||
<tr{}>
|
||||
<td><b>{}</b><br/>{}<br/>{}</td>
|
||||
<td><img src="{}" onmouseover="this.src='{}';" onmouseout="this.src='{}';"></td>
|
||||
<td><img src="{}" onmouseover="this.src='{}';" onmouseout="this.src='{}';"></td>
|
||||
<td><img src="{}" onmouseover="this.src='{}';" onmouseout="this.src='{}';" class="render"></td>
|
||||
<td><img src="{}" onmouseover="this.src='{}';" onmouseout="this.src='{}';" class="render"></td>
|
||||
<td><img src="{}"></td>
|
||||
</tr>""" . format(style, name, self.testname, status,
|
||||
new_url, ref_url, new_url,
|
||||
|
Loading…
Reference in New Issue
Block a user