diff options
Diffstat (limited to 'source/blender')
99 files changed, 1570 insertions, 1515 deletions
diff --git a/source/blender/alembic/intern/abc_writer_curves.cc b/source/blender/alembic/intern/abc_writer_curves.cc index bb9109dc025..3ab9b365a72 100644 --- a/source/blender/alembic/intern/abc_writer_curves.cc +++ b/source/blender/alembic/intern/abc_writer_curves.cc @@ -31,6 +31,7 @@ extern "C" { #include "BKE_curve.h" #include "BKE_mesh.h" +#include "BKE_object.h" } using Alembic::AbcGeom::OCompoundProperty; @@ -176,10 +177,11 @@ Mesh *AbcCurveMeshWriter::getEvaluatedMesh(Scene * /*scene_eval*/, Object *ob_eval, bool &r_needsfree) { - if (ob_eval->runtime.mesh_eval != NULL) { + Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval); + if (mesh_eval != NULL) { /* Mesh_eval only exists when generative modifiers are in use. */ r_needsfree = false; - return ob_eval->runtime.mesh_eval; + return mesh_eval; } r_needsfree = true; diff --git a/source/blender/alembic/intern/abc_writer_mball.cc b/source/blender/alembic/intern/abc_writer_mball.cc index aa08146c6e2..cc0775bd537 100644 --- a/source/blender/alembic/intern/abc_writer_mball.cc +++ b/source/blender/alembic/intern/abc_writer_mball.cc @@ -30,6 +30,7 @@ extern "C" { #include "BKE_lib_id.h" #include "BKE_mball.h" #include "BKE_mesh.h" +#include "BKE_object.h" #include "BLI_utildefines.h" } @@ -55,10 +56,11 @@ bool AbcMBallWriter::isAnimated() const Mesh *AbcMBallWriter::getEvaluatedMesh(Scene * /*scene_eval*/, Object *ob_eval, bool &r_needsfree) { - if (ob_eval->runtime.mesh_eval != NULL) { + Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval); + if (mesh_eval != NULL) { /* Mesh_eval only exists when generative modifiers are in use. */ r_needsfree = false; - return ob_eval->runtime.mesh_eval; + return mesh_eval; } r_needsfree = true; diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index 8e88bda37a5..3ab6814c531 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -461,7 +461,7 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl return; } - if (!g->cached) { + if (g->glyph_cache == NULL) { if (font->tex_size_max == -1) { font->tex_size_max = GPU_max_texture_size(); } @@ -492,7 +492,7 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl gc->bitmap_len = bitmap_len; gc->glyphs_len_free--; - g->cached = true; + g->glyph_cache = gc; } if (font->flags & BLF_CLIPPING) { @@ -505,8 +505,10 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl } } - g_batch.glyph_cache = gc; - BLI_assert(g->offset < gc->bitmap_len); + if (g_batch.glyph_cache != g->glyph_cache) { + blf_batch_draw(); + g_batch.glyph_cache = g->glyph_cache; + } if (font->flags & BLF_SHADOW) { rctf rect_ofs; diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index bb1697d7860..6ea1702200f 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -131,7 +131,7 @@ typedef struct GlyphBLF { float pos_x; float pos_y; - bool cached; + struct GlyphCacheBLF *glyph_cache; } GlyphBLF; typedef struct FontBufInfoBLF { diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 9f436db97ee..8963f241ca8 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -287,6 +287,7 @@ void BKE_object_eval_uber_transform(struct Depsgraph *depsgraph, struct Object * void BKE_object_eval_uber_data(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); +void BKE_object_eval_assign_data(struct Object *object, struct ID *data, bool is_owned); void BKE_object_eval_boundbox(struct Depsgraph *depsgraph, struct Object *object); void BKE_object_synchronize_to_original(struct Depsgraph *depsgraph, struct Object *object); @@ -326,8 +327,7 @@ int BKE_object_obdata_texspace_get(struct Object *ob, float **r_loc, float **r_size); -struct Mesh *BKE_object_get_evaluated_mesh(const struct Depsgraph *depsgraph, struct Object *ob); -struct Mesh *BKE_object_get_final_mesh(struct Object *object); +struct Mesh *BKE_object_get_evaluated_mesh(struct Object *object); struct Mesh *BKE_object_get_pre_modified_mesh(struct Object *object); struct Mesh *BKE_object_get_original_mesh(struct Object *object); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 3006ab76032..148c7a6b6c0 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1719,43 +1719,12 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, } } -static void assign_object_mesh_eval(Object *object) -{ - BLI_assert(object->id.tag & LIB_TAG_COPIED_ON_WRITE); - - Mesh *mesh = (Mesh *)object->data; - Mesh *mesh_eval = object->runtime.mesh_eval; - - /* The modifier stack evaluation is storing result in mesh->runtime.mesh_eval, but this result - * is not guaranteed to be owned by object. - * - * Check ownership now, since later on we can not go to a mesh owned by someone else via object's - * runtime: this could cause access freed data on depsgraph destruction (mesh who owns the final - * result might be freed prior to object). */ - if (mesh_eval == mesh->runtime.mesh_eval) { - object->runtime.is_mesh_eval_owned = false; - } - else { - mesh_eval->id.tag |= LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT; - object->runtime.is_mesh_eval_owned = true; - } - - /* NOTE: We are not supposed to invoke evaluation for original object, but some areas are still - * under process of being ported, so we play safe here. */ - if (object->id.tag & LIB_TAG_COPIED_ON_WRITE) { - object->data = mesh_eval; - } - else { - /* evaluated will be available via: 'object->runtime.mesh_eval' */ - } -} - -static void mesh_build_extra_data(struct Depsgraph *depsgraph, Object *ob) +static void mesh_build_extra_data(struct Depsgraph *depsgraph, Object *ob, Mesh *mesh_eval) { uint32_t eval_flags = DEG_get_eval_flags_for_id(depsgraph, &ob->id); if (eval_flags & DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY) { - BKE_shrinkwrap_compute_boundary_data(ob->runtime.mesh_eval); + BKE_shrinkwrap_compute_boundary_data(mesh_eval); } } @@ -1793,6 +1762,7 @@ static void mesh_build_data(struct Depsgraph *depsgraph, } #endif + Mesh *mesh_eval = NULL, *mesh_deform_eval = NULL; mesh_calc_modifiers(depsgraph, scene, ob, @@ -1802,26 +1772,35 @@ static void mesh_build_data(struct Depsgraph *depsgraph, -1, true, true, - &ob->runtime.mesh_deform_eval, - &ob->runtime.mesh_eval); - - BKE_object_boundbox_calc_from_mesh(ob, ob->runtime.mesh_eval); - - assign_object_mesh_eval(ob); + &mesh_deform_eval, + &mesh_eval); + /* The modifier stack evaluation is storing result in mesh->runtime.mesh_eval, but this result + * is not guaranteed to be owned by object. + * + * Check ownership now, since later on we can not go to a mesh owned by someone else via + * object's runtime: this could cause access freed data on depsgraph destruction (mesh who owns + * the final result might be freed prior to object). */ + Mesh *mesh = ob->data; + const bool is_mesh_eval_owned = (mesh_eval != mesh->runtime.mesh_eval); + BKE_object_eval_assign_data(ob, &mesh_eval->id, is_mesh_eval_owned); + + ob->runtime.mesh_deform_eval = mesh_deform_eval; ob->runtime.last_data_mask = *dataMask; ob->runtime.last_need_mapping = need_mapping; + BKE_object_boundbox_calc_from_mesh(ob, mesh_eval); + if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) { if (DEG_is_active(depsgraph)) { BKE_sculpt_update_object_after_eval(depsgraph, ob); } } - if (ob->runtime.mesh_eval != NULL) { - mesh_runtime_check_normals_valid(ob->runtime.mesh_eval); + if (mesh_eval != NULL) { + mesh_runtime_check_normals_valid(mesh_eval); } - mesh_build_extra_data(depsgraph, ob); + mesh_build_extra_data(depsgraph, ob, mesh_eval); } static void editbmesh_build_data(struct Depsgraph *depsgraph, @@ -1942,18 +1921,20 @@ Mesh *mesh_get_eval_final(struct Depsgraph *depsgraph, CustomData_MeshMasks cddata_masks = *dataMask; object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping); - if (!ob->runtime.mesh_eval || + Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); + if ((mesh_eval == NULL) || !CustomData_MeshMasks_are_matching(&(ob->runtime.last_data_mask), &cddata_masks) || (need_mapping && !ob->runtime.last_need_mapping)) { CustomData_MeshMasks_update(&cddata_masks, &ob->runtime.last_data_mask); mesh_build_data( depsgraph, scene, ob, &cddata_masks, need_mapping || ob->runtime.last_need_mapping); + mesh_eval = BKE_object_get_evaluated_mesh(ob); } - if (ob->runtime.mesh_eval) { - BLI_assert(!(ob->runtime.mesh_eval->runtime.cd_dirty_vert & CD_MASK_NORMAL)); + if (mesh_eval != NULL) { + BLI_assert(!(mesh_eval->runtime.cd_dirty_vert & CD_MASK_NORMAL)); } - return ob->runtime.mesh_eval; + return mesh_eval; } Mesh *mesh_get_eval_deform(struct Depsgraph *depsgraph, diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 8ba746e3493..3df1a84a0c9 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -368,7 +368,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[ /* when not in EditMode, use the 'final' evaluated mesh, depsgraph * ensures we build with CD_MDEFORMVERT layer */ - Mesh *me_eval = ob->runtime.mesh_eval; + Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); BMEditMesh *em = BKE_editmesh_from_object(ob); float plane[3]; float imat[3][3], tmat[3][3]; @@ -860,94 +860,88 @@ static void childof_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar } float parmat[4][4]; - - /* simple matrix parenting */ - if (data->flag == CHILDOF_ALL) { - - /* multiply target (parent matrix) by offset (parent inverse) to get - * the effect of the parent that will be exerted on the owner - */ - mul_m4_m4m4(parmat, ct->matrix, data->invmat); - - /* now multiply the parent matrix by the owner matrix to get the - * the effect of this constraint (i.e. owner is 'parented' to parent) - */ - mul_m4_m4m4(cob->matrix, parmat, cob->matrix); + /* Simple matrix parenting. */ + if ((data->flag & CHILDOF_ALL) == CHILDOF_ALL) { + copy_m4_m4(parmat, ct->matrix); } + /* Filter the parent matrix by channel. */ else { - float invmat[4][4], tempmat[4][4]; float loc[3], eul[3], size[3]; - float loco[3], eulo[3], sizo[3]; - - /* get offset (parent-inverse) matrix */ - copy_m4_m4(invmat, data->invmat); /* extract components of both matrices */ copy_v3_v3(loc, ct->matrix[3]); mat4_to_eulO(eul, ct->rotOrder, ct->matrix); mat4_to_size(size, ct->matrix); - copy_v3_v3(loco, invmat[3]); - mat4_to_eulO(eulo, cob->rotOrder, invmat); - mat4_to_size(sizo, invmat); - /* disable channels not enabled */ if (!(data->flag & CHILDOF_LOCX)) { - loc[0] = loco[0] = 0.0f; + loc[0] = 0.0f; } if (!(data->flag & CHILDOF_LOCY)) { - loc[1] = loco[1] = 0.0f; + loc[1] = 0.0f; } if (!(data->flag & CHILDOF_LOCZ)) { - loc[2] = loco[2] = 0.0f; + loc[2] = 0.0f; } if (!(data->flag & CHILDOF_ROTX)) { - eul[0] = eulo[0] = 0.0f; + eul[0] = 0.0f; } if (!(data->flag & CHILDOF_ROTY)) { - eul[1] = eulo[1] = 0.0f; + eul[1] = 0.0f; } if (!(data->flag & CHILDOF_ROTZ)) { - eul[2] = eulo[2] = 0.0f; + eul[2] = 0.0f; } if (!(data->flag & CHILDOF_SIZEX)) { - size[0] = sizo[0] = 1.0f; + size[0] = 1.0f; } if (!(data->flag & CHILDOF_SIZEY)) { - size[1] = sizo[1] = 1.0f; + size[1] = 1.0f; } if (!(data->flag & CHILDOF_SIZEZ)) { - size[2] = sizo[2] = 1.0f; + size[2] = 1.0f; } /* make new target mat and offset mat */ - loc_eulO_size_to_mat4(ct->matrix, loc, eul, size, ct->rotOrder); - loc_eulO_size_to_mat4(invmat, loco, eulo, sizo, cob->rotOrder); + loc_eulO_size_to_mat4(parmat, loc, eul, size, ct->rotOrder); + } - /* multiply target (parent matrix) by offset (parent inverse) to get - * the effect of the parent that will be exerted on the owner - */ - mul_m4_m4m4(parmat, ct->matrix, invmat); + /* Compute the inverse matrix if requested. */ + if (data->flag & CHILDOF_SET_INVERSE) { + invert_m4_m4(data->invmat, parmat); - /* now multiply the parent matrix by the owner matrix to get the - * the effect of this constraint (i.e. owner is 'parented' to parent) - */ - copy_m4_m4(tempmat, cob->matrix); - mul_m4_m4m4(cob->matrix, parmat, tempmat); + data->flag &= ~CHILDOF_SET_INVERSE; - /* without this, changes to scale and rotation can change location - * of a parentless bone or a disconnected bone. Even though its set - * to zero above. */ - if (!(data->flag & CHILDOF_LOCX)) { - cob->matrix[3][0] = tempmat[3][0]; - } - if (!(data->flag & CHILDOF_LOCY)) { - cob->matrix[3][1] = tempmat[3][1]; - } - if (!(data->flag & CHILDOF_LOCZ)) { - cob->matrix[3][2] = tempmat[3][2]; + /* Write the computed matrix back to the master copy if in COW evaluation. */ + bConstraint *orig_con = constraint_find_original_for_update(cob, con); + + if (orig_con != NULL) { + bChildOfConstraint *orig_data = orig_con->data; + + copy_m4_m4(orig_data->invmat, data->invmat); + orig_data->flag &= ~CHILDOF_SET_INVERSE; } } + + /* Multiply together the target (parent) matrix, parent inverse, + * and the owner transform matrixto get the effect of this constraint + * (i.e. owner is 'parented' to parent). */ + float orig_cob_matrix[4][4]; + copy_m4_m4(orig_cob_matrix, cob->matrix); + mul_m4_series(cob->matrix, parmat, data->invmat, orig_cob_matrix); + + /* Without this, changes to scale and rotation can change location + * of a parentless bone or a disconnected bone. Even though its set + * to zero above. */ + if (!(data->flag & CHILDOF_LOCX)) { + cob->matrix[3][0] = orig_cob_matrix[3][0]; + } + if (!(data->flag & CHILDOF_LOCY)) { + cob->matrix[3][1] = orig_cob_matrix[3][1]; + } + if (!(data->flag & CHILDOF_LOCZ)) { + cob->matrix[3][2] = orig_cob_matrix[3][2]; + } } /* XXX note, con->flag should be CONSTRAINT_SPACEONCE for bone-childof, patched in readfile.c */ @@ -3974,7 +3968,7 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *UNUSED(depsgraph), float track_no[3] = {0.0f, 0.0f, 0.0f}; SpaceTransform transform; - Mesh *target_eval = ct->tar->runtime.mesh_eval; + Mesh *target_eval = BKE_object_get_evaluated_mesh(ct->tar); copy_m4_m4(ct->matrix, cob->matrix); @@ -4742,7 +4736,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase if (data->depth_ob) { Object *depth_ob = data->depth_ob; - Mesh *target_eval = depth_ob->runtime.mesh_eval; + Mesh *target_eval = BKE_object_get_evaluated_mesh(depth_ob); if (target_eval) { BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; BVHTreeRayHit hit; @@ -4891,23 +4885,35 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase return; } - float mat[4][4], obmat[4][4], imat[4][4], cammat[4][4], camimat[4][4], parmat[4][4]; + float mat[4][4], obmat[4][4], imat[4][4], parmat[4][4]; float ctime = DEG_get_ctime(depsgraph); float framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime); - BKE_object_where_is_calc_mat4(camob, cammat); - BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, framenr, mat); - invert_m4_m4(camimat, cammat); - mul_m4_m4m4(parmat, cammat, data->invmat); + invert_m4_m4(imat, mat); + mul_m4_m4m4(parmat, camob->obmat, imat); - copy_m4_m4(cammat, camob->obmat); copy_m4_m4(obmat, cob->matrix); - invert_m4_m4(imat, mat); + /* Recalculate the inverse matrix if requested. */ + if (data->flag & OBJECTSOLVER_SET_INVERSE) { + invert_m4_m4(data->invmat, parmat); + + data->flag &= ~OBJECTSOLVER_SET_INVERSE; + + /* Write the computed matrix back to the master copy if in COW evaluation. */ + bConstraint *orig_con = constraint_find_original_for_update(cob, con); + + if (orig_con != NULL) { + bObjectSolverConstraint *orig_data = orig_con->data; + + copy_m4_m4(orig_data->invmat, data->invmat); + orig_data->flag &= ~OBJECTSOLVER_SET_INVERSE; + } + } - mul_m4_series(cob->matrix, cammat, imat, camimat, parmat, obmat); + mul_m4_series(cob->matrix, parmat, data->invmat, obmat); } static bConstraintTypeInfo CTI_OBJECTSOLVER = { diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index e0abe836bf8..bdca888efcc 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -338,8 +338,8 @@ static void crazyspace_init_object_for_eval(struct Depsgraph *depsgraph, { Object *object_eval = DEG_get_evaluated_object(depsgraph, object); *object_crazy = *object_eval; - if (object_crazy->runtime.mesh_orig != NULL) { - object_crazy->data = object_crazy->runtime.mesh_orig; + if (object_crazy->runtime.data_orig != NULL) { + object_crazy->data = object_crazy->runtime.data_orig; } } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 6d7d42b2293..6963f629798 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -1772,7 +1772,7 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph, curve_calc_modifiers_post(depsgraph, scene, ob, &nubase, dispbase, r_final, for_render); } - if (cu->flag & CU_DEFORM_FILL && !ob->runtime.mesh_eval) { + if (cu->flag & CU_DEFORM_FILL && !ob->runtime.data_eval) { curve_to_filledpoly(cu, &nubase, dispbase); } @@ -1800,12 +1800,11 @@ void BKE_displist_make_curveTypes( dispbase = &(ob->runtime.curve_cache->disp); - do_makeDispListCurveTypes( - depsgraph, scene, ob, dispbase, for_render, for_orco, &ob->runtime.mesh_eval); + Mesh *mesh_eval = NULL; + do_makeDispListCurveTypes(depsgraph, scene, ob, dispbase, for_render, for_orco, &mesh_eval); - if (ob->runtime.mesh_eval != NULL) { - ob->runtime.mesh_eval->id.tag |= LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT; - ob->runtime.is_mesh_eval_owned = true; + if (mesh_eval != NULL) { + BKE_object_eval_assign_data(ob, &mesh_eval->id, true); } boundbox_displist_object(ob); @@ -1861,8 +1860,9 @@ static void boundbox_displist_object(Object *ob) ob->runtime.bb = MEM_callocN(sizeof(BoundBox), "boundbox"); } - if (ob->runtime.mesh_eval) { - BKE_object_boundbox_calc_from_mesh(ob, ob->runtime.mesh_eval); + Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); + if (mesh_eval) { + BKE_object_boundbox_calc_from_mesh(ob, mesh_eval); } else { float min[3], max[3]; diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 8971021329a..4a9efc7cac4 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -315,7 +315,7 @@ ListBase *BKE_effectors_create(Depsgraph *depsgraph, else if (weights->weight[ob->pd->forcefield] == 0.0f) { continue; } - else if (ob->pd->shape == PFIELD_SHAPE_POINTS && ob->runtime.mesh_eval == NULL) { + else if (ob->pd->shape == PFIELD_SHAPE_POINTS && BKE_object_get_evaluated_mesh(ob) == NULL) { continue; } @@ -656,7 +656,7 @@ int get_effector_data(EffectorCache *eff, efd->size = 0.0f; } else if (eff->pd && eff->pd->shape == PFIELD_SHAPE_POINTS) { - Mesh *me_eval = eff->ob->runtime.mesh_eval; + Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob); if (me_eval != NULL) { copy_v3_v3(efd->loc, me_eval->mvert[*efd->index].co); normal_short_to_float_v3(efd->nor, me_eval->mvert[*efd->index].no); @@ -769,7 +769,7 @@ static void get_effector_tot( efd->index = p; if (eff->pd->shape == PFIELD_SHAPE_POINTS) { - Mesh *me_eval = eff->ob->runtime.mesh_eval; + Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob); *tot = me_eval != NULL ? me_eval->totvert : 1; if (*tot && eff->pd->forcefield == PFIELD_HARMONIC && point->index >= 0) { diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 7868b72e9cf..5761bec98b2 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -5180,6 +5180,14 @@ void BKE_image_user_frame_calc(Image *ima, ImageUser *iuser, int cfra) iuser->ok = 1; } + if (ima) { + LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { + if (tile->ok == 0) { + tile->ok = IMA_OK; + } + } + } + iuser->flag &= ~IMA_NEED_FRAME_RECALC; } } diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index af5e867ac38..d8d5653730b 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -1608,6 +1608,7 @@ static void material_default_surface_init(Material *ma) { bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname); ma->nodetree = ntree; + ma->use_nodes = true; bNode *principled = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_PRINCIPLED); bNodeSocket *base_color = nodeFindSocket(principled, SOCK_IN, "Base Color"); @@ -1633,6 +1634,7 @@ static void material_default_volume_init(Material *ma) { bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname); ma->nodetree = ntree; + ma->use_nodes = true; bNode *principled = nodeAddStaticNode(NULL, ntree, SH_NODE_VOLUME_PRINCIPLED); bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL); diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index 014ccdb913e..f0bab4c0aa2 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -582,7 +582,7 @@ void BKE_mesh_from_nurbs_displist( Main *bmain, Object *ob, ListBase *dispbase, const char *obdata_name, bool temporary) { Object *ob1; - Mesh *me_eval = ob->runtime.mesh_eval; + Mesh *me_eval = (Mesh *)ob->runtime.data_eval; Mesh *me; Curve *cu; MVert *allvert = NULL; @@ -644,7 +644,7 @@ void BKE_mesh_from_nurbs_displist( me = BKE_id_new_nomain(ID_ME, obdata_name); } - ob->runtime.mesh_eval = NULL; + ob->runtime.data_eval = NULL; BKE_mesh_nomain_to_mesh(me_eval, me, ob, &CD_MASK_MESH, true); } @@ -929,11 +929,9 @@ static Object *object_for_curve_to_mesh_create(Object *object) BKE_displist_copy(&temp_object->runtime.curve_cache->disp, &object->runtime.curve_cache->disp); } /* Constructive modifiers will use mesh to store result. */ - if (object->runtime.mesh_eval != NULL) { - BKE_id_copy_ex(NULL, - &object->runtime.mesh_eval->id, - (ID **)&temp_object->runtime.mesh_eval, - LIB_ID_COPY_LOCALIZE); + if (object->runtime.data_eval != NULL) { + BKE_id_copy_ex( + NULL, object->runtime.data_eval, &temp_object->runtime.data_eval, LIB_ID_COPY_LOCALIZE); } /* Need to create copy of curve itself as well, it will be freed by underlying conversion @@ -994,19 +992,15 @@ static void curve_to_mesh_eval_ensure(Object *object) * bit of internal functions (BKE_mesh_from_nurbs_displist, BKE_mesh_nomain_to_mesh) and also * Mesh From Curve operator. * Brecht says hold off with that. */ - BKE_displist_make_curveTypes_forRender(NULL, - NULL, - &remapped_object, - &remapped_object.runtime.curve_cache->disp, - &remapped_object.runtime.mesh_eval, - false); + Mesh *mesh_eval = NULL; + BKE_displist_make_curveTypes_forRender( + NULL, NULL, &remapped_object, &remapped_object.runtime.curve_cache->disp, &mesh_eval, false); /* Note: this is to be consistent with `BKE_displist_make_curveTypes()`, however that is not a * real issue currently, code here is broken in more than one way, fix(es) will be done * separately. */ - if (remapped_object.runtime.mesh_eval != NULL) { - remapped_object.runtime.mesh_eval->id.tag |= LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT; - remapped_object.runtime.is_mesh_eval_owned = true; + if (mesh_eval != NULL) { + BKE_object_eval_assign_data(&remapped_object, &mesh_eval->id, true); } BKE_object_free_curve_cache(&bevel_object); @@ -1104,8 +1098,8 @@ static Mesh *mesh_new_from_mesh_object_with_layers(Depsgraph *depsgraph, Object } Object object_for_eval = *object; - if (object_for_eval.runtime.mesh_orig != NULL) { - object_for_eval.data = object_for_eval.runtime.mesh_orig; + if (object_for_eval.runtime.data_orig != NULL) { + object_for_eval.data = object_for_eval.runtime.data_orig; } Scene *scene = DEG_get_evaluated_scene(depsgraph); @@ -1306,7 +1300,7 @@ Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph, ModifierData *md_eval, int build_shapekey_layers) { - Mesh *me = ob_eval->runtime.mesh_orig ? ob_eval->runtime.mesh_orig : ob_eval->data; + Mesh *me = ob_eval->runtime.data_orig ? ob_eval->runtime.data_orig : ob_eval->data; const ModifierTypeInfo *mti = modifierType_getInfo(md_eval->type); Mesh *result; KeyBlock *kb; diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 51c70406692..381e43241ea 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -1019,7 +1019,7 @@ Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval, if (me == NULL) { me = (get_cage_mesh && ob_eval->runtime.mesh_deform_eval != NULL) ? ob_eval->runtime.mesh_deform_eval : - ob_eval->runtime.mesh_eval; + BKE_object_get_evaluated_mesh(ob_eval); } return me; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 51d397a44bc..4d7d5861a09 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -363,11 +363,11 @@ static void object_update_from_subsurf_ccg(Object *object) * (happens on dependency graph free where order of CoW-ed IDs free is undefined). * * Good news is: such mesh does not have modifiers applied, so no need to worry about CCG. */ - if (!object->runtime.is_mesh_eval_owned) { + if (!object->runtime.is_data_eval_owned) { return; } /* Object was never evaluated, so can not have CCG subdivision surface. */ - Mesh *mesh_eval = object->runtime.mesh_eval; + Mesh *mesh_eval = BKE_object_get_evaluated_mesh(object); if (mesh_eval == NULL) { return; } @@ -410,13 +410,13 @@ static void object_update_from_subsurf_ccg(Object *object) /* TODO(sergey): Solve this somehow, to be fully stable for threaded * evaluation environment. */ - /* NOTE: runtime.mesh_orig is what was before assigning mesh_eval, + /* NOTE: runtime.data_orig is what was before assigning mesh_eval, * it is orig as in what was in object_eval->data before evaluating * modifier stack. * * mesh_cow is a copy-on-written version od object_orig->data. */ - Mesh *mesh_cow = object->runtime.mesh_orig; + Mesh *mesh_cow = (Mesh *)object->runtime.data_orig; copy_ccg_data(mesh_cow, mesh_orig, CD_MDISPS); copy_ccg_data(mesh_cow, mesh_orig, CD_GRID_PAINT_MASK); /* Everything is now up-to-date. */ @@ -424,6 +424,33 @@ static void object_update_from_subsurf_ccg(Object *object) subdiv_ccg->dirty.hidden = false; } +/* Assign data after modifier stack evaluation. */ +void BKE_object_eval_assign_data(Object *object_eval, ID *data_eval, bool is_owned) +{ + BLI_assert(object_eval->id.tag & LIB_TAG_COPIED_ON_WRITE); + BLI_assert(object_eval->runtime.data_eval == NULL); + BLI_assert(data_eval->tag & LIB_TAG_NO_MAIN); + + if (is_owned) { + /* Set flag for debugging. */ + data_eval->tag |= LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT; + } + + /* Assigned evaluated data. */ + object_eval->runtime.data_eval = data_eval; + object_eval->runtime.is_data_eval_owned = is_owned; + + /* Overwrite data of evaluated object, if the datablock types match. */ + ID *data = object_eval->data; + if (GS(data->name) == GS(data_eval->name)) { + /* NOTE: we are not supposed to invoke evaluation for original objects, + * but some areas are still being ported, so we play safe here. */ + if (object_eval->id.tag & LIB_TAG_COPIED_ON_WRITE) { + object_eval->data = data_eval; + } + } +} + /* free data derived from mesh, called when mesh changes or is freed */ void BKE_object_free_derived_caches(Object *ob) { @@ -431,17 +458,18 @@ void BKE_object_free_derived_caches(Object *ob) object_update_from_subsurf_ccg(ob); - /* Restore initial pointer. */ - if (ob->runtime.mesh_orig != NULL) { - ob->data = ob->runtime.mesh_orig; - } - - if (ob->runtime.mesh_eval != NULL) { - if (ob->runtime.is_mesh_eval_owned) { - Mesh *mesh_eval = ob->runtime.mesh_eval; - BKE_mesh_eval_delete(mesh_eval); + if (ob->runtime.data_eval != NULL) { + if (ob->runtime.is_data_eval_owned) { + ID *data_eval = ob->runtime.data_eval; + if (GS(data_eval->name) == ID_ME) { + BKE_mesh_eval_delete((Mesh *)data_eval); + } + else { + BKE_libblock_free_datablock(data_eval, 0); + MEM_freeN(data_eval); + } } - ob->runtime.mesh_eval = NULL; + ob->runtime.data_eval = NULL; } if (ob->runtime.mesh_deform_eval != NULL) { Mesh *mesh_deform_eval = ob->runtime.mesh_deform_eval; @@ -449,6 +477,12 @@ void BKE_object_free_derived_caches(Object *ob) ob->runtime.mesh_deform_eval = NULL; } + /* Restore initial pointer for copy-on-write datablocks, object->data + * might be pointing to an evaluated datablock data was just freed above. */ + if (ob->runtime.data_orig != NULL) { + ob->data = ob->runtime.data_orig; + } + BKE_object_to_mesh_clear(ob); BKE_object_free_curve_cache(ob); @@ -2308,7 +2342,7 @@ static void give_parvert(Object *par, int nr, float vec[3]) if (par->type == OB_MESH) { Mesh *me = par->data; BMEditMesh *em = me->edit_mesh; - Mesh *me_eval = (em) ? em->mesh_eval_final : par->runtime.mesh_eval; + Mesh *me_eval = (em) ? em->mesh_eval_final : BKE_object_get_evaluated_mesh(par); if (me_eval) { int count = 0; @@ -3067,12 +3101,12 @@ void BKE_object_foreach_display_point(Object *ob, void (*func_cb)(const float[3], void *), void *user_data) { + Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); float co[3]; - if (ob->runtime.mesh_eval) { - const Mesh *me = ob->runtime.mesh_eval; - const MVert *mv = me->mvert; - const int totvert = me->totvert; + if (mesh_eval != NULL) { + const MVert *mv = mesh_eval->mvert; + const int totvert = mesh_eval->totvert; for (int i = 0; i < totvert; i++, mv++) { mul_v3_m4v3(co, obmat, mv->co); func_cb(co, user_data); @@ -3342,24 +3376,11 @@ int BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc, return 1; } -/** Get evaluated mesh for given (main, original) object and depsgraph. */ -Mesh *BKE_object_get_evaluated_mesh(const Depsgraph *depsgraph, Object *ob) +/** Get evaluated mesh for given object. */ +Mesh *BKE_object_get_evaluated_mesh(Object *object) { - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - return ob_eval->runtime.mesh_eval; -} - -/* Get object's mesh with all modifiers applied. */ -Mesh *BKE_object_get_final_mesh(Object *object) -{ - if (object->runtime.mesh_eval != NULL) { - BLI_assert((object->id.tag & LIB_TAG_COPIED_ON_WRITE) != 0); - BLI_assert(object->runtime.mesh_eval == object->data); - BLI_assert((object->runtime.mesh_eval->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) != 0); - return object->runtime.mesh_eval; - } - /* Wasn't evaluated yet. */ - return object->data; + ID *data_eval = object->runtime.data_eval; + return (data_eval && GS(data_eval->name) == ID_ME) ? (Mesh *)data_eval : NULL; } /* Get mesh which is not affected by modifiers: @@ -3370,11 +3391,11 @@ Mesh *BKE_object_get_final_mesh(Object *object) */ Mesh *BKE_object_get_pre_modified_mesh(Object *object) { - if (object->runtime.mesh_orig != NULL) { + if (object->type == OB_MESH && object->runtime.data_orig != NULL) { BLI_assert(object->id.tag & LIB_TAG_COPIED_ON_WRITE); BLI_assert(object->id.orig_id != NULL); - BLI_assert(object->runtime.mesh_orig->id.orig_id == ((Object *)object->id.orig_id)->data); - Mesh *result = object->runtime.mesh_orig; + BLI_assert(object->runtime.data_orig->orig_id == ((Object *)object->id.orig_id)->data); + Mesh *result = (Mesh *)object->runtime.data_orig; BLI_assert((result->id.tag & LIB_TAG_COPIED_ON_WRITE) != 0); BLI_assert((result->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0); return result; @@ -3925,7 +3946,7 @@ void BKE_object_runtime_reset(Object *object) void BKE_object_runtime_reset_on_copy(Object *object, const int UNUSED(flag)) { Object_Runtime *runtime = &object->runtime; - runtime->mesh_eval = NULL; + runtime->data_eval = NULL; runtime->mesh_deform_eval = NULL; runtime->curve_cache = NULL; runtime->gpencil_cache = NULL; diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index c10ab3cddab..28b6e0d4e02 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -426,7 +426,7 @@ static void make_duplis_verts(const DupliContext *ctx) vdd.me_eval = vdd.edit_mesh->mesh_eval_cage; } else { - vdd.me_eval = parent->runtime.mesh_eval; + vdd.me_eval = BKE_object_get_evaluated_mesh(parent); } if (vdd.me_eval == NULL) { @@ -702,7 +702,7 @@ static void make_duplis_faces(const DupliContext *ctx) fdd.me_eval = em->mesh_eval_cage; } else { - fdd.me_eval = parent->runtime.mesh_eval; + fdd.me_eval = BKE_object_get_evaluated_mesh(parent); } if (fdd.me_eval == NULL) { diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 366fd0950fa..c647afdd00a 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -398,8 +398,8 @@ void BKE_object_data_select_update(Depsgraph *depsgraph, ID *object_data) void BKE_object_select_update(Depsgraph *depsgraph, Object *object) { DEG_debug_print_eval(depsgraph, __func__, object->id.name, object); - if (object->type == OB_MESH && !object->runtime.is_mesh_eval_owned) { - Mesh *mesh_input = object->runtime.mesh_orig; + if (object->type == OB_MESH && !object->runtime.is_data_eval_owned) { + Mesh *mesh_input = (Mesh *)object->runtime.data_orig; Mesh_Runtime *mesh_runtime = &mesh_input->runtime; BLI_mutex_lock(mesh_runtime->eval_mutex); BKE_object_data_select_update(depsgraph, object->data); diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 2cc1681d436..4da7d8d007a 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -1351,7 +1351,7 @@ void BKE_sculpt_update_object_after_eval(Depsgraph *depsgraph, Object *ob_eval) /* Update after mesh evaluation in the dependency graph, to rebuild PBVH or * other data when modifiers change the mesh. */ Object *ob_orig = DEG_get_original_object(ob_eval); - Mesh *me_eval = ob_eval->runtime.mesh_eval; + Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); BLI_assert(me_eval != NULL); diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index c2180e50b74..494c5e21613 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -332,22 +332,24 @@ void BKE_rigidbody_object_copy(Main *bmain, Object *ob_dst, const Object *ob_src /* get the appropriate evaluated mesh based on rigid body mesh source */ static Mesh *rigidbody_get_mesh(Object *ob) { + BLI_assert(ob->type == OB_MESH); + switch (ob->rigidbody_object->mesh_source) { case RBO_MESH_DEFORM: return ob->runtime.mesh_deform_eval; case RBO_MESH_FINAL: - return ob->runtime.mesh_eval; + return BKE_object_get_evaluated_mesh(ob); case RBO_MESH_BASE: /* This mesh may be used for computing looptris, which should be done * on the original; otherwise every time the CoW is recreated it will * have to be recomputed. */ BLI_assert(ob->rigidbody_object->mesh_source == RBO_MESH_BASE); - return ob->runtime.mesh_orig; + return (Mesh *)ob->runtime.data_orig; } /* Just return something sensible so that at least Blender won't crash. */ BLI_assert(!"Unknown mesh source"); - return ob->runtime.mesh_eval; + return BKE_object_get_evaluated_mesh(ob); } /* create collision shape of mesh - convex hull */ diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 1e4e07d63b3..1de0c192a20 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -277,6 +277,12 @@ if(WIN32) ) endif() +if(UNIX AND NOT APPLE) + list(APPEND LIB + bf_intern_libc_compat + ) +endif() + # no need to compile object files for inline headers. set_source_files_properties( intern/math_base_inline.c diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 7f5b1e7ea65..99db2f0a290 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -818,7 +818,7 @@ void BLI_str_toupper_ascii(char *str, const size_t len) */ void BLI_str_rstrip(char *str) { - for (int i = (int)strlen(str) - 1; i > 0; i--) { + for (int i = (int)strlen(str) - 1; i >= 0; i--) { if (isspace(str[i])) { str[i] = '\0'; } diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index d8c2057bb56..0ff89aa3127 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -7145,7 +7145,7 @@ static void bevel_limit_offset(BevelParams *bp, BMesh *bm) void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, - const float segments, + const int segments, const float profile, const bool vertex_only, const bool use_weights, @@ -7176,7 +7176,7 @@ void BM_mesh_bevel(BMesh *bm, bp.offset = offset; bp.offset_type = offset_type; - bp.seg = (int)segments; + bp.seg = segments; bp.profile = profile; bp.pro_super_r = -logf(2.0) / logf(sqrtf(profile)); /* Convert to superellipse exponent. */ bp.vertex_only = vertex_only; @@ -7207,6 +7207,10 @@ void BM_mesh_bevel(BMesh *bm, bp.miter_inner = BEVEL_MITER_SHARP; } + if (bp.seg <= 1) { + bp.seg = 1; + } + if (profile >= 0.950f) { /* r ~ 692, so PRO_SQUARE_R is 1e4 */ bp.pro_super_r = PRO_SQUARE_R; } diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h index 45bebbb33ce..479a8a3f6d6 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.h +++ b/source/blender/bmesh/tools/bmesh_bevel.h @@ -27,7 +27,7 @@ struct MDeformVert; void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, - const float segments, + const int segments, const float profile, const bool vertex_only, const bool use_weights, diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index edb02ee331f..95521ee9e47 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -781,9 +781,7 @@ void update_id_after_copy(const Depsgraph *depsgraph, const Object *object_orig = (const Object *)id_orig; object_cow->mode = object_orig->mode; object_cow->sculpt = object_orig->sculpt; - if (object_cow->type == OB_MESH) { - object_cow->runtime.mesh_orig = (Mesh *)object_cow->data; - } + object_cow->runtime.data_orig = (ID *)object_cow->data; if (object_cow->type == OB_ARMATURE) { const bArmature *armature_orig = (bArmature *)object_orig->data; bArmature *armature_cow = (bArmature *)object_cow->data; diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc index df7338e1076..acbcd4d551d 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc @@ -44,7 +44,6 @@ ObjectRuntimeBackup::ObjectRuntimeBackup(const Depsgraph * /*depsgraph*/) void ObjectRuntimeBackup::init_from_object(Object *object) { /* Store evaluated mesh and curve_cache, and make sure we don't free it. */ - Mesh *mesh_eval = object->runtime.mesh_eval; runtime = object->runtime; BKE_object_runtime_reset(object); /* Keep bbox (for now at least). */ @@ -52,9 +51,7 @@ void ObjectRuntimeBackup::init_from_object(Object *object) /* Object update will override actual object->data to an evaluated version. * Need to make sure we don't have data set to evaluated one before free * anything. */ - if (mesh_eval != nullptr && object->data == mesh_eval) { - object->data = runtime.mesh_orig; - } + object->data = runtime.data_orig; /* Make a backup of base flags. */ base_flag = object->base_flag; base_local_view_bits = object->base_local_view_bits; @@ -98,12 +95,13 @@ void ObjectRuntimeBackup::backup_pose_channel_runtime_data(Object *object) void ObjectRuntimeBackup::restore_to_object(Object *object) { - Mesh *mesh_orig = object->runtime.mesh_orig; + ID *data_orig = object->runtime.data_orig; + ID *data_eval = object->runtime.data_eval; BoundBox *bb = object->runtime.bb; object->runtime = runtime; - object->runtime.mesh_orig = mesh_orig; + object->runtime.data_orig = data_orig; object->runtime.bb = bb; - if (object->type == OB_MESH && object->runtime.mesh_eval != nullptr) { + if (object->type == OB_MESH && data_eval != nullptr) { if (object->id.recalc & ID_RECALC_GEOMETRY) { /* If geometry is tagged for update it means, that part of * evaluated mesh are not valid anymore. In this case we can not @@ -111,20 +109,24 @@ void ObjectRuntimeBackup::restore_to_object(Object *object) * * We restore object's data datablock to an original copy of * that datablock. */ - object->data = mesh_orig; + object->data = data_orig; /* After that, immediately free the invalidated caches. */ BKE_object_free_derived_caches(object); } else { - Mesh *mesh_eval = object->runtime.mesh_eval; /* Do same thing as object update: override actual object data * pointer with evaluated datablock. */ - object->data = mesh_eval; + object->data = data_eval; + /* Evaluated mesh simply copied edit_mesh pointer from * original mesh during update, need to make sure no dead * pointers are left behind. */ - mesh_eval->edit_mesh = mesh_orig->edit_mesh; + if (object->type == OB_MESH) { + Mesh *mesh_eval = (Mesh *)data_eval; + Mesh *mesh_orig = (Mesh *)data_orig; + mesh_eval->edit_mesh = mesh_orig->edit_mesh; + } } } object->base_flag = base_flag; diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 6480847092b..a886fa26589 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -120,7 +120,7 @@ void EEVEE_cache_populate(void *vedata, Object *ob) bool cast_shadow = false; if (ob_visibility & OB_VISIBLE_PARTICLES) { - EEVEE_hair_cache_populate(vedata, sldata, ob, &cast_shadow); + EEVEE_particle_hair_cache_populate(vedata, sldata, ob, &cast_shadow); } if (DRW_object_is_renderable(ob) && (ob_visibility & OB_VISIBLE_SELF)) { diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 7661dfb41a5..89e45148ee8 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -1728,6 +1728,144 @@ BLI_INLINE Material *eevee_object_material_get(Object *ob, int slot) return ma; } +static void eevee_hair_cache_populate(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, + Object *ob, + ParticleSystem *psys, + ModifierData *md, + int matnr, + bool *cast_shadow) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + + DRWShadingGroup *shgrp = NULL; + Material *ma = eevee_object_material_get(ob, matnr - 1); + + float *color_p = &ma->r; + float *metal_p = &ma->metallic; + float *spec_p = &ma->spec; + float *rough_p = &ma->roughness; + + bool use_ssr = ((stl->effects->enabled_effects & EFFECT_SSR) != 0); + const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0; + + shgrp = DRW_shgroup_hair_create(ob, psys, md, psl->depth_pass, e_data.default_hair_prepass_sh); + + shgrp = DRW_shgroup_hair_create( + ob, psys, md, psl->depth_pass_clip, e_data.default_hair_prepass_clip_sh); + + shgrp = NULL; + + if (ma->use_nodes && ma->nodetree && !holdout) { + static int ssr_id; + ssr_id = (use_ssr) ? 1 : -1; + static float half = 0.5f; + static float error_col[3] = {1.0f, 0.0f, 1.0f}; + static float compile_col[3] = {0.5f, 0.5f, 0.5f}; + struct GPUMaterial *gpumat = EEVEE_material_hair_get(scene, ma); + + switch (GPU_material_status(gpumat)) { + case GPU_MAT_SUCCESS: { + bool use_diffuse = GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE); + bool use_glossy = GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY); + bool use_refract = GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT); + + shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->material_pass, gpumat); + + if (!use_diffuse && !use_glossy && !use_refract) { + /* HACK: Small hack to avoid issue when utilTex is needed for + * world_normals_get and none of the bsdfs are present. + * This binds utilTex even if not needed. */ + DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); + } + + add_standard_uniforms(shgrp, + sldata, + vedata, + &ssr_id, + NULL, + use_diffuse, + use_glossy, + use_refract, + false, + false, + DEFAULT_RENDER_PASS_FLAG); + + /* Add the hair to all the render_passes that are enabled */ + RENDER_PASS_ITER_BEGIN(stl->g_data->render_passes, render_pass_index, render_pass_flag) + shgrp = DRW_shgroup_material_hair_create( + ob, psys, md, psl->material_accum_pass[render_pass_index], gpumat); + if (!use_diffuse && !use_glossy && !use_refract) { + /* Small hack to avoid issue when utilTex is needed for + * world_normals_get and none of the bsdfs that need it are present. + * This binds `utilTex` even if not needed. */ + DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); + } + + add_standard_uniforms(shgrp, + sldata, + vedata, + &ssr_id, + NULL, + use_diffuse, + use_glossy, + use_refract, + false, + false, + render_pass_flag); + RENDER_PASS_ITER_END(render_pass_index) + + break; + } + case GPU_MAT_QUEUED: { + stl->g_data->queued_shaders_count++; + color_p = compile_col; + metal_p = spec_p = rough_p = ½ + break; + } + case GPU_MAT_FAILED: + default: + color_p = error_col; + metal_p = spec_p = rough_p = ½ + break; + } + } + + /* Fallback to default shader */ + if (shgrp == NULL) { + shgrp = EEVEE_default_shading_group_get(sldata, vedata, ob, psys, md, true, holdout, use_ssr); + DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); + DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); + DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); + DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); + + RENDER_PASS_ITER_BEGIN(stl->g_data->render_passes, render_pass_index, render_pass_flag) + shgrp = EEVEE_default_hair_render_pass_shading_group_get( + sldata, + vedata, + ob, + psys, + md, + holdout, + use_ssr, + psl->material_accum_pass[render_pass_index], + render_pass_flag); + + DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); + DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); + DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); + DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); + RENDER_PASS_ITER_END(render_pass_index) + } + + /* Shadows */ + DRW_shgroup_hair_create(ob, psys, md, psl->shadow_pass, e_data.default_hair_prepass_sh); + *cast_shadow = true; +} + void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob, @@ -1906,18 +2044,12 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, } } -void EEVEE_hair_cache_populate(EEVEE_Data *vedata, - EEVEE_ViewLayerData *sldata, - Object *ob, - bool *cast_shadow) +void EEVEE_particle_hair_cache_populate(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, + Object *ob, + bool *cast_shadow) { - EEVEE_PassList *psl = vedata->psl; - EEVEE_StorageList *stl = vedata->stl; const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - - bool use_ssr = ((stl->effects->enabled_effects & EFFECT_SSR) != 0); - const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0; if (ob->type == OB_MESH) { if (ob != draw_ctx->object_edit) { @@ -1934,130 +2066,7 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata, if (draw_as != PART_DRAW_PATH) { continue; } - - DRWShadingGroup *shgrp = NULL; - Material *ma = eevee_object_material_get(ob, part->omat - 1); - - float *color_p = &ma->r; - float *metal_p = &ma->metallic; - float *spec_p = &ma->spec; - float *rough_p = &ma->roughness; - - shgrp = DRW_shgroup_hair_create( - ob, psys, md, psl->depth_pass, e_data.default_hair_prepass_sh); - - shgrp = DRW_shgroup_hair_create( - ob, psys, md, psl->depth_pass_clip, e_data.default_hair_prepass_clip_sh); - - shgrp = NULL; - - if (ma->use_nodes && ma->nodetree && !holdout) { - static int ssr_id; - ssr_id = (use_ssr) ? 1 : -1; - static float half = 0.5f; - static float error_col[3] = {1.0f, 0.0f, 1.0f}; - static float compile_col[3] = {0.5f, 0.5f, 0.5f}; - struct GPUMaterial *gpumat = EEVEE_material_hair_get(scene, ma); - - switch (GPU_material_status(gpumat)) { - case GPU_MAT_SUCCESS: { - bool use_diffuse = GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE); - bool use_glossy = GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY); - bool use_refract = GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT); - - shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->material_pass, gpumat); - - if (!use_diffuse && !use_glossy && !use_refract) { - /* HACK: Small hack to avoid issue when utilTex is needed for - * world_normals_get and none of the bsdfs are present. - * This binds utilTex even if not needed. */ - DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); - } - - add_standard_uniforms(shgrp, - sldata, - vedata, - &ssr_id, - NULL, - use_diffuse, - use_glossy, - use_refract, - false, - false, - DEFAULT_RENDER_PASS_FLAG); - - /* Add the hair to all the render_passes that are enabled */ - RENDER_PASS_ITER_BEGIN( - stl->g_data->render_passes, render_pass_index, render_pass_flag) - shgrp = DRW_shgroup_material_hair_create( - ob, psys, md, psl->material_accum_pass[render_pass_index], gpumat); - if (!use_diffuse && !use_glossy && !use_refract) { - /* Small hack to avoid issue when utilTex is needed for - * world_normals_get and none of the bsdfs that need it are present. - * This binds `utilTex` even if not needed. */ - DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); - } - - add_standard_uniforms(shgrp, - sldata, - vedata, - &ssr_id, - NULL, - use_diffuse, - use_glossy, - use_refract, - false, - false, - render_pass_flag); - RENDER_PASS_ITER_END(render_pass_index) - - break; - } - case GPU_MAT_QUEUED: { - stl->g_data->queued_shaders_count++; - color_p = compile_col; - metal_p = spec_p = rough_p = ½ - break; - } - case GPU_MAT_FAILED: - default: - color_p = error_col; - metal_p = spec_p = rough_p = ½ - break; - } - } - - /* Fallback to default shader */ - if (shgrp == NULL) { - shgrp = EEVEE_default_shading_group_get( - sldata, vedata, ob, psys, md, true, holdout, use_ssr); - DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); - DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); - DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); - DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); - - RENDER_PASS_ITER_BEGIN(stl->g_data->render_passes, render_pass_index, render_pass_flag) - shgrp = EEVEE_default_hair_render_pass_shading_group_get( - sldata, - vedata, - ob, - psys, - md, - holdout, - use_ssr, - psl->material_accum_pass[render_pass_index], - render_pass_flag); - - DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); - DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); - DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); - DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); - RENDER_PASS_ITER_END(render_pass_index) - } - - /* Shadows */ - DRW_shgroup_hair_create(ob, psys, md, psl->shadow_pass, e_data.default_hair_prepass_sh); - *cast_shadow = true; + eevee_hair_cache_populate(vedata, sldata, ob, psys, md, part->omat, cast_shadow); } } } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index a2ed0a16d89..9a8b2cb793a 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -897,10 +897,10 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob, bool *cast_shadow); -void EEVEE_hair_cache_populate(EEVEE_Data *vedata, - EEVEE_ViewLayerData *sldata, - Object *ob, - bool *cast_shadow); +void EEVEE_particle_hair_cache_populate(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, + Object *ob, + bool *cast_shadow); void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo); struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, struct World *wo); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 3a5d9e96b80..ed81665bcfb 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -204,7 +204,7 @@ void EEVEE_render_cache(void *vedata, const int ob_visibility = DRW_object_visibility_in_active_context(ob); if (ob_visibility & OB_VISIBLE_PARTICLES) { - EEVEE_hair_cache_populate(vedata, sldata, ob, &cast_shadow); + EEVEE_particle_hair_cache_populate(vedata, sldata, ob, &cast_shadow); } if (ob_visibility & OB_VISIBLE_SELF) { diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c index 2f9e8f3d555..e9dcb6376bb 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.c +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -88,7 +88,17 @@ void EEVEE_renderpasses_init(EEVEE_Data *vedata) View3D *v3d = draw_ctx->v3d; if (v3d) { - g_data->render_passes = v3d->shading.render_pass; + const Scene *scene = draw_ctx->scene; + eViewLayerEEVEEPassType render_pass = v3d->shading.render_pass; + if (render_pass == EEVEE_RENDER_PASS_AO && + ((scene->eevee.flag & SCE_EEVEE_GTAO_ENABLED) == 0)) { + render_pass = EEVEE_RENDER_PASS_COMBINED; + } + else if (render_pass == EEVEE_RENDER_PASS_BLOOM && + ((scene->eevee.flag & SCE_EEVEE_BLOOM_ENABLED) == 0)) { + render_pass = EEVEE_RENDER_PASS_COMBINED; + } + g_data->render_passes = render_pass; } else { eViewLayerEEVEEPassType enabled_render_passes = view_layer->eevee.render_passes; diff --git a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl index 1faa02fd354..8c876cf582c 100644 --- a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl @@ -12,7 +12,9 @@ uniform float studioLightIntensity = 1.0; uniform float studioLightBlur = 0.0; in vec3 viewPosition; -# define M_PI 3.14159265358979323846 +# ifndef M_PI +# define M_PI 3.14159265358979323846 +# endif vec3 background_transform_to_world(vec3 viewvec) { diff --git a/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl index 18f92c0dd33..489e87e9a7d 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl @@ -202,9 +202,9 @@ vec4 step_resolve(void) #else vec3 blur = upsample_filter(sourceBuffer, uvcoordsvar.xy, sourceBufferTexelSize); #endif - vec3 base = bloomAddBase ? textureLod(baseBuffer, uvcoordsvar.xy, 0.0).rgb : vec3(0.0); - vec3 cout = base + blur * bloomColor; - return vec4(cout, 1.0); + vec4 base = bloomAddBase ? textureLod(baseBuffer, uvcoordsvar.xy, 0.0) : vec4(0.0); + vec3 cout = base.rgb + blur * bloomColor; + return vec4(cout, base.a); } void main(void) diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl index 5214301bc03..03520c55a85 100644 --- a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl @@ -15,6 +15,38 @@ uniform sampler2D inputColorBuffer; out vec4 fragColor; +vec3 safe_divide_even_color(vec3 a, vec3 b) +{ + vec3 result = vec3((b.r != 0.0) ? a.r / b.r : 0.0, + (b.g != 0.0) ? a.g / b.g : 0.0, + (b.b != 0.0) ? a.b / b.b : 0.0); + /* try to get gray even if b is zero */ + if (b.r == 0.0) { + if (b.g == 0.0) { + result = result.bbb; + } + else if (b.b == 0.0) { + result = result.ggg; + } + else { + result.r = 0.5 * (result.g + result.b); + } + } + else if (b.g == 0.0) { + if (b.b == 0.0) { + result = result.rrr; + } + else { + result.g = 0.5 * (result.r + result.b); + } + } + else if (b.b == 0.0) { + result.b = 0.5 * (result.r + result.g); + } + + return result; +} + void main() { ivec2 texel = ivec2(gl_FragCoord.xy); @@ -58,41 +90,13 @@ void main() else if (postProcessType == PASS_POST_ACCUMULATED_LIGHT) { vec3 accumulated_light = texelFetch(inputBuffer, texel, 0).rgb; vec3 accumulated_color = texelFetch(inputColorBuffer, texel, 0).rgb; - - /* Fix INF in the case a color component is 0.0 */ - if (accumulated_color.r == 0.0) { - accumulated_color.r = 1.0; - accumulated_light.r = 0.0; - } - if (accumulated_color.g == 0.0) { - accumulated_color.g = 1.0; - accumulated_light.g = 0.0; - } - if (accumulated_color.b == 0.0) { - accumulated_color.b = 1.0; - accumulated_light.b = 0.0; - } - fragColor = vec4(accumulated_light / accumulated_color, 1.0); + fragColor = vec4(safe_divide_even_color(accumulated_light, accumulated_color), 1.0); } else if (postProcessType == PASS_POST_TWO_LIGHT_BUFFERS) { vec3 accumulated_light = texelFetch(inputBuffer, texel, 0).rgb + texelFetch(inputSecondLightBuffer, texel, 0).rgb; vec3 accumulated_color = texelFetch(inputColorBuffer, texel, 0).rgb; - - /* Fix INF in the case a color component is 0.0 */ - if (accumulated_color.r == 0.0) { - accumulated_color.r = 1.0; - accumulated_light.r = 0.0; - } - if (accumulated_color.g == 0.0) { - accumulated_color.g = 1.0; - accumulated_light.g = 0.0; - } - if (accumulated_color.b == 0.0) { - accumulated_color.b = 1.0; - accumulated_light.b = 0.0; - } - fragColor = vec4(accumulated_light / accumulated_color, 1.0); + fragColor = vec4(safe_divide_even_color(accumulated_light, accumulated_color), 1.0); } else { /* Output error color: Unknown how to post process this pass. */ diff --git a/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl index fa02bee45b7..5778f02f692 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl @@ -11,7 +11,7 @@ void main() { if (laNumLight == 0) { /* Early exit: No lights in scene */ - fragColor.r = 0.0; + fragColor.r = 1.0; return; } @@ -19,7 +19,7 @@ void main() float depth = texelFetch(depthBuffer, texel, 0).r; if (depth == 1.0f) { /* Early exit background does not receive shadows */ - fragColor.r = 1.0; + fragColor.r = 0.0; return; } @@ -40,6 +40,7 @@ void main() vec3 worldPosition = transform_point(ViewMatrixInverse, viewPosition); vec3 true_normal = normalize(cross(dFdx(viewPosition), dFdy(viewPosition))); + vec3 N = normal_view_to_world(true_normal); for (int i = 0; i < MAX_LIGHT && i < laNumLight; i++) { LightData ld = lights_data[i]; @@ -48,8 +49,9 @@ void main() l_vector.xyz = ld.l_position - worldPosition; l_vector.w = length(l_vector.xyz); + float light_input = smoothstep(0.2, -0.2, -dot(N, normalize(l_vector.xyz))); float l_vis = light_shadowing( - ld, worldPosition, viewPosition, tracing_depth, true_normal, rand.x, true, 1.0); + ld, worldPosition, viewPosition, tracing_depth, true_normal, rand.x, true, light_input); accum_light += l_vis; } diff --git a/source/blender/draw/engines/overlay/shaders/motion_path_line_vert.glsl b/source/blender/draw/engines/overlay/shaders/motion_path_line_vert.glsl index 6d7f673731e..7486f287a79 100644 --- a/source/blender/draw/engines/overlay/shaders/motion_path_line_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/motion_path_line_vert.glsl @@ -32,7 +32,7 @@ void main() float intensity; /* how faint */ - vec3 blend_base = (abs(frame - frameCurrent) == 1) ? + vec3 blend_base = (abs(frame - frameCurrent) == 0) ? colorCurrentFrame.rgb : colorBackground.rgb; /* "bleed" cframe color to ease color blending */ bool use_custom_color = customColor.x >= 0.0; @@ -78,13 +78,12 @@ void main() else { /* green - on frameCurrent */ if (selected) { - intensity = 0.5f; + intensity = 0.92f; } else { - intensity = 0.99f; + intensity = 0.75f; } - finalColor_geom.rgb = clamp( - mix(colorCurrentFrame.rgb, colorBackground.rgb, intensity) - 0.1, 0.0, 0.1); + finalColor_geom.rgb = mix(colorBackground.rgb, blend_base, intensity); } } diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 8057d167e2f..f37e5b14d83 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -836,12 +836,12 @@ GPUBatch *DRW_cache_object_surface_get(Object *ob) int DRW_cache_object_material_count_get(struct Object *ob) { - Mesh *me = (ob->runtime.mesh_eval != NULL) ? ob->runtime.mesh_eval : (Mesh *)ob->data; - short type = (ob->runtime.mesh_eval != NULL) ? OB_MESH : ob->type; + Mesh *me = BKE_object_get_evaluated_mesh(ob); + short type = (me != NULL) ? OB_MESH : ob->type; switch (type) { case OB_MESH: - return DRW_mesh_material_count_get(me); + return DRW_mesh_material_count_get((me != NULL) ? me : ob->data); case OB_CURVE: case OB_SURF: case OB_FONT: @@ -2807,7 +2807,7 @@ GPUBatch *DRW_cache_curve_edge_wire_get(Object *ob) BLI_assert(ob->type == OB_CURVE); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_loose_edges(mesh_eval); } @@ -2845,7 +2845,7 @@ GPUBatch *DRW_cache_curve_surface_get(Object *ob) BLI_assert(ob->type == OB_CURVE); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_surface(mesh_eval); } @@ -2859,7 +2859,7 @@ GPUBatch *DRW_cache_curve_loose_edges_get(Object *ob) BLI_assert(ob->type == OB_CURVE); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_loose_edges(mesh_eval); } @@ -2875,7 +2875,7 @@ GPUBatch *DRW_cache_curve_face_wireframe_get(Object *ob) BLI_assert(ob->type == OB_CURVE); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_wireframes_face(mesh_eval); } @@ -2888,7 +2888,7 @@ GPUBatch *DRW_cache_curve_edge_detection_get(Object *ob, bool *r_is_manifold) { BLI_assert(ob->type == OB_CURVE); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_edge_detection(mesh_eval, r_is_manifold); } @@ -2905,7 +2905,7 @@ GPUBatch **DRW_cache_curve_surface_shaded_get(Object *ob, BLI_assert(ob->type == OB_CURVE); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len); } @@ -2957,7 +2957,7 @@ GPUBatch *DRW_cache_text_edge_wire_get(Object *ob) { BLI_assert(ob->type == OB_FONT); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); const bool has_surface = (cu->flag & (CU_FRONT | CU_BACK)) || cu->ext1 != 0.0f || cu->ext2 != 0.0f; if (!has_surface) { @@ -2975,7 +2975,7 @@ GPUBatch *DRW_cache_text_surface_get(Object *ob) { BLI_assert(ob->type == OB_FONT); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (cu->editfont && (cu->flag & CU_FAST)) { return NULL; } @@ -2991,7 +2991,7 @@ GPUBatch *DRW_cache_text_edge_detection_get(Object *ob, bool *r_is_manifold) { BLI_assert(ob->type == OB_FONT); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (cu->editfont && (cu->flag & CU_FAST)) { return NULL; } @@ -3007,7 +3007,7 @@ GPUBatch *DRW_cache_text_loose_edges_get(Object *ob) { BLI_assert(ob->type == OB_FONT); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (cu->editfont && (cu->flag & CU_FAST)) { return NULL; } @@ -3024,7 +3024,7 @@ GPUBatch *DRW_cache_text_face_wireframe_get(Object *ob) { BLI_assert(ob->type == OB_FONT); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (cu->editfont && (cu->flag & CU_FAST)) { return NULL; } @@ -3042,7 +3042,7 @@ GPUBatch **DRW_cache_text_surface_shaded_get(Object *ob, { BLI_assert(ob->type == OB_FONT); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (cu->editfont && (cu->flag & CU_FAST)) { return NULL; } @@ -3065,7 +3065,7 @@ GPUBatch *DRW_cache_surf_surface_get(Object *ob) BLI_assert(ob->type == OB_SURF); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_surface(mesh_eval); } @@ -3079,7 +3079,7 @@ GPUBatch *DRW_cache_surf_edge_wire_get(Object *ob) BLI_assert(ob->type == OB_SURF); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_loose_edges(mesh_eval); } @@ -3093,7 +3093,7 @@ GPUBatch *DRW_cache_surf_face_wireframe_get(Object *ob) BLI_assert(ob->type == OB_SURF); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_wireframes_face(mesh_eval); } @@ -3106,7 +3106,7 @@ GPUBatch *DRW_cache_surf_edge_detection_get(Object *ob, bool *r_is_manifold) { BLI_assert(ob->type == OB_SURF); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_edge_detection(mesh_eval, r_is_manifold); } @@ -3120,7 +3120,7 @@ GPUBatch *DRW_cache_surf_loose_edges_get(Object *ob) BLI_assert(ob->type == OB_SURF); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_loose_edges(mesh_eval); } @@ -3139,7 +3139,7 @@ GPUBatch **DRW_cache_surf_surface_shaded_get(Object *ob, BLI_assert(ob->type == OB_SURF); struct Curve *cu = ob->data; - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len); } @@ -3398,7 +3398,7 @@ GPUBatch *DRW_cache_cursor_get(bool crosshair_lines) void drw_batch_cache_validate(Object *ob) { - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); switch (ob->type) { case OB_MESH: DRW_mesh_batch_cache_validate((Mesh *)ob->data); @@ -3436,7 +3436,7 @@ void drw_batch_cache_generate_requested(Object *ob) DRW_object_use_hide_faces(ob)) || ((mode == CTX_MODE_EDIT_MESH) && DRW_object_is_in_edit_mode(ob)))); - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); switch (ob->type) { case OB_MESH: DRW_mesh_batch_cache_create_requested(ob, (Mesh *)ob->data, scene, is_paint_mode, use_hide); @@ -3457,7 +3457,7 @@ void drw_batch_cache_generate_requested(Object *ob) void DRW_batch_cache_free_old(Object *ob, int ctime) { - struct Mesh *mesh_eval = ob->runtime.mesh_eval; + struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); switch (ob->type) { case OB_MESH: diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index fbdabb44b15..43e8e2a4733 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -1203,6 +1203,19 @@ static DRWShadingGroup *drw_shgroup_material_create_ex(GPUPass *gpupass, DRWPass return grp; } +static void drw_shgroup_material_texture(DRWShadingGroup *grp, + GPUMaterialTexture *tex, + const char *name, + int textarget) +{ + GPUTexture *gputex = GPU_texture_from_blender(tex->ima, tex->iuser, NULL, textarget); + DRW_shgroup_uniform_texture(grp, name, gputex); + + GPUTexture **gputex_ref = BLI_memblock_alloc(DST.vmempool->images); + *gputex_ref = gputex; + GPU_texture_ref(gputex); +} + static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp, struct GPUMaterial *material) { @@ -1210,35 +1223,20 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp, /* Bind all textures needed by the material. */ for (GPUMaterialTexture *tex = textures.first; tex; tex = tex->next) { - GPUTexture *gputex; - if (tex->ima) { /* Image */ - GPUTexture **gputex_ref = BLI_memblock_alloc(DST.vmempool->images); - - int textarget; - if (tex->type == GPU_TEX2D_ARRAY) { - textarget = GL_TEXTURE_2D_ARRAY; - } - else if (tex->type == GPU_TEX1D_ARRAY) { - textarget = GL_TEXTURE_1D_ARRAY; + if (tex->tiled_mapping_name[0]) { + drw_shgroup_material_texture(grp, tex, tex->sampler_name, GL_TEXTURE_2D_ARRAY); + drw_shgroup_material_texture(grp, tex, tex->tiled_mapping_name, GL_TEXTURE_1D_ARRAY); } else { - textarget = GL_TEXTURE_2D; + drw_shgroup_material_texture(grp, tex, tex->sampler_name, GL_TEXTURE_2D); } - *gputex_ref = gputex = GPU_texture_from_blender(tex->ima, tex->iuser, NULL, textarget); - - GPU_texture_ref(gputex); } else if (tex->colorband) { /* Color Ramp */ - gputex = *tex->colorband; + DRW_shgroup_uniform_texture(grp, tex->sampler_name, *tex->colorband); } - else { - continue; - } - - DRW_shgroup_uniform_texture(grp, tex->shadername, gputex); } GPUUniformBuffer *ubo = GPU_material_uniform_buffer_get(material); diff --git a/source/blender/draw/intern/shaders/common_view_lib.glsl b/source/blender/draw/intern/shaders/common_view_lib.glsl index 6605e1165d4..cfe79cb3ee0 100644 --- a/source/blender/draw/intern/shaders/common_view_lib.glsl +++ b/source/blender/draw/intern/shaders/common_view_lib.glsl @@ -164,6 +164,7 @@ uniform mat4 ModelMatrixInverse; #define normal_object_to_world(n) (transpose(mat3(ModelMatrixInverse)) * n) #define normal_world_to_object(n) (transpose(mat3(ModelMatrix)) * n) #define normal_world_to_view(n) (mat3(ViewMatrix) * n) +#define normal_view_to_world(n) (mat3(ViewMatrixInverse) * n) #define point_object_to_ndc(p) (ViewProjectionMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)) #define point_object_to_view(p) ((ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)).xyz) diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index a9ddc53e5bb..5a0e60f8d58 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -2996,7 +2996,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m */ if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) { /* layer visibility - we check both object and base, since these may not be in sync yet */ - if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0) { + if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0 || (base->flag & BASE_VISIBLE_VIEWLAYER) == 0) { return false; } diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c index 5ff76d886c2..4490892695f 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c @@ -91,7 +91,7 @@ static bool gizmo_calc_rect_view_scale(const wmGizmo *gz, const float dims[2], f static bool gizmo_calc_rect_view_margin(const wmGizmo *gz, const float dims[2], float margin[2]) { float handle_size; - handle_size = 0.15f; + handle_size = 10.0f; handle_size *= gz->scale_final; float scale_xy[2]; if (!gizmo_calc_rect_view_scale(gz, dims, scale_xy)) { diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index e6d8684a8b2..d78c2620253 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -24,15 +24,21 @@ #ifndef __ED_IMAGE_H__ #define __ED_IMAGE_H__ +#include "DNA_listBase.h" +#include "DNA_space_types.h" + struct ARegion; struct ImBuf; struct Image; struct ImageUser; +struct LinkNodePair; +struct Main; struct ReportList; struct Scene; struct SpaceImage; struct ViewLayer; struct bContext; +struct wmOperator; struct wmWindowManager; /* image_edit.c, exported for transform */ @@ -116,4 +122,24 @@ bool ED_image_should_save_modified(const struct bContext *C); int ED_image_save_all_modified_info(const struct bContext *C, struct ReportList *reports); bool ED_image_save_all_modified(const struct bContext *C, struct ReportList *reports); +/* image_sequence.c */ +typedef struct ImageFrameRange { + struct ImageFrameRange *next, *prev; + + /** Absolute file path of the first file in the range. */ + char filepath[FILE_MAX]; + /* Sequence parameters. */ + int length; + int offset; + /* UDIM tiles. */ + ListBase udim_tiles; + + /* Temporary data. */ + ListBase frames; +} ImageFrameRange; + +ListBase ED_image_filesel_detect_sequences(struct Main *bmain, + struct wmOperator *op, + const bool detect_udim); + #endif /* __ED_IMAGE_H__ */ diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index c66967a9365..d53ad7c4229 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -153,7 +153,6 @@ int BIF_countTransformOrientation(const struct bContext *C); #define P_GPENCIL_EDIT (1 << 13) #define P_CURSOR_EDIT (1 << 14) #define P_CLNOR_INVALIDATE (1 << 15) -#define P_MOUSE (1 << 16) void Transform_Properties(struct wmOperatorType *ot, int flags); diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 5c9fb866df7..5f948595a22 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -35,6 +35,7 @@ #include "BKE_customdata.h" #include "BKE_global.h" #include "BKE_mesh.h" +#include "BKE_object.h" #include "ED_mesh.h" #include "ED_screen.h" @@ -80,8 +81,8 @@ void paintface_flush_flags(struct bContext *C, Object *ob, short flag) return; } - Mesh *me_orig = ob_eval->runtime.mesh_orig; - Mesh *me_eval = ob_eval->runtime.mesh_eval; + Mesh *me_orig = (Mesh *)ob_eval->runtime.data_orig; + Mesh *me_eval = (Mesh *)ob_eval->runtime.data_eval; bool updated = false; if (me_orig != NULL && me_eval != NULL && me_orig->totpoly == me->totpoly) { @@ -443,7 +444,7 @@ bool paintface_mouse_select( void paintvert_flush_flags(Object *ob) { Mesh *me = BKE_mesh_from_object(ob); - Mesh *me_eval = ob->runtime.mesh_eval; + Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); MVert *mvert_eval, *mv; const int *index_array = NULL; int totvert; diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c index 8d5c1469694..21de89d33dd 100644 --- a/source/blender/editors/mesh/editmesh_knife_project.c +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -33,6 +33,7 @@ #include "BKE_curve.h" #include "BKE_editmesh.h" #include "BKE_mesh_runtime.h" +#include "BKE_object.h" #include "BKE_report.h" #include "DEG_depsgraph.h" @@ -61,9 +62,9 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C, struct Mesh *me_eval; bool me_eval_needs_free; - if (ob->type == OB_MESH || ob->runtime.mesh_eval) { + if (ob->type == OB_MESH || ob->runtime.data_eval) { Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - me_eval = ob_eval->runtime.mesh_eval; + me_eval = BKE_object_get_evaluated_mesh(ob_eval); if (me_eval == NULL) { Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id); me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 7891f59a62e..a8eaa663285 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -410,45 +410,54 @@ bool ED_object_add_generic_get_opts(bContext *C, rot = _rot; } - prop = RNA_struct_find_property(op->ptr, "align"); - int alignment = RNA_property_enum_get(op->ptr, prop); - bool alignment_set = RNA_property_is_set(op->ptr, prop); - if (RNA_struct_property_is_set(op->ptr, "rotation")) { + /* If rotation is set, always use it. Alignment (and corresponding user preference) + * can be ignored since this is in world space anyways. + * To not confuse (e.g. on redo), dont set it to ALIGN_WORLD in the op UI though. */ *is_view_aligned = false; - RNA_property_enum_set(op->ptr, prop, ALIGN_WORLD); - alignment = ALIGN_WORLD; - } - else if (alignment_set) { - *is_view_aligned = alignment == ALIGN_VIEW; + RNA_float_get_array(op->ptr, "rotation", rot); } else { - *is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0; - if (*is_view_aligned) { - RNA_property_enum_set(op->ptr, prop, ALIGN_VIEW); - alignment = ALIGN_VIEW; + int alignment = ALIGN_WORLD; + prop = RNA_struct_find_property(op->ptr, "align"); + + if (RNA_property_is_set(op->ptr, prop)) { + /* If alignment is set, always use it. */ + *is_view_aligned = alignment == ALIGN_VIEW; + alignment = RNA_property_enum_get(op->ptr, prop); } - else if (U.flag & USER_ADD_CURSORALIGNED) { - RNA_property_enum_set(op->ptr, prop, ALIGN_CURSOR); - alignment = ALIGN_CURSOR; + else { + /* If alignment is not set, use User Preferences. */ + *is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0; + if (*is_view_aligned) { + RNA_property_enum_set(op->ptr, prop, ALIGN_VIEW); + alignment = ALIGN_VIEW; + } + else if ((U.flag & USER_ADD_CURSORALIGNED) != 0) { + RNA_property_enum_set(op->ptr, prop, ALIGN_CURSOR); + alignment = ALIGN_CURSOR; + } + else { + RNA_property_enum_set(op->ptr, prop, ALIGN_WORLD); + alignment = ALIGN_WORLD; + } } - } - - switch (alignment) { - case ALIGN_WORLD: - RNA_float_get_array(op->ptr, "rotation", rot); - break; - case ALIGN_VIEW: - ED_object_rotation_from_view(C, rot, view_align_axis); - RNA_float_set_array(op->ptr, "rotation", rot); - break; - case ALIGN_CURSOR: { - const Scene *scene = CTX_data_scene(C); - float tmat[3][3]; - BKE_scene_cursor_rot_to_mat3(&scene->cursor, tmat); - mat3_normalized_to_eul(rot, tmat); - RNA_float_set_array(op->ptr, "rotation", rot); - break; + switch (alignment) { + case ALIGN_WORLD: + RNA_float_get_array(op->ptr, "rotation", rot); + break; + case ALIGN_VIEW: + ED_object_rotation_from_view(C, rot, view_align_axis); + RNA_float_set_array(op->ptr, "rotation", rot); + break; + case ALIGN_CURSOR: { + const Scene *scene = CTX_data_scene(C); + float tmat[3][3]; + BKE_scene_cursor_rot_to_mat3(&scene->cursor, tmat); + mat3_normalized_to_eul(rot, tmat); + RNA_float_set_array(op->ptr, "rotation", rot); + break; + } } } } diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 906a9e44870..bfff36bb83a 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -871,118 +871,31 @@ void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot) /* ------------- Child-Of Constraint ------------------ */ -static void child_get_inverse_matrix_owner_bone( - Depsgraph *depsgraph, wmOperator *op, Scene *scene, Object *ob, float invmat[4][4]) +/* Force evaluation so that the 'set inverse' flag is handled. + * No-op when the constraint is enabled, as in such cases the evaluation will happen anyway. + */ +static void force_evaluation_if_constraint_disabled(bContext *C, Object *ob, bConstraint *con) { - /* For bone owner we want to do this in evaluated domain. - * BKE_pose_where_is / BKE_pose_where_is_bone relies on (re)evaluating parts of the scene - * and copying new evaluated stuff back to original. - */ - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - bConstraint *con_eval = edit_constraint_property_get(op, ob_eval, CONSTRAINT_TYPE_CHILDOF); - - /* nullify inverse matrix first */ - unit_m4(invmat); - - bPoseChannel *pchan_eval = BKE_pose_channel_active(ob_eval); - - /* try to find a pose channel - assume that this is the constraint owner */ - /* TODO: get from context instead? */ - if (ob_eval && ob_eval->pose && pchan_eval) { - bConstraint *con_last; - - /* calculate/set inverse matrix: - * We just calculate all transform-stack eval up to but not including this constraint. - * This is because inverse should just inverse correct for just the constraint's influence - * when it gets applied; that is, at the time of application, we don't know anything about - * what follows. - */ - float imat[4][4], tmat[4][4]; - float pmat[4][4]; - - /* make sure we passed the correct constraint */ - BLI_assert(BLI_findindex(&pchan_eval->constraints, con_eval) != -1); - - /* 1. calculate posemat where inverse doesn't exist yet (inverse was cleared above), - * to use as baseline ("pmat") to derive delta from. This extra calc saves users - * from having pressing "Clear Inverse" first - */ - BKE_pose_where_is(depsgraph, scene, ob_eval); - copy_m4_m4(pmat, pchan_eval->pose_mat); - - /* 2. knock out constraints starting from this one */ - con_last = pchan_eval->constraints.last; - pchan_eval->constraints.last = con_eval->prev; - - if (con_eval->prev) { - /* new end must not point to this one, else this chain cutting is useless */ - con_eval->prev->next = NULL; - } - else { - /* constraint was first */ - pchan_eval->constraints.first = NULL; - } - - /* 3. solve pose without disabled constraints */ - BKE_pose_where_is(depsgraph, scene, ob_eval); - - /* 4. determine effect of constraint by removing the newly calculated - * pchan->pose_mat from the original pchan->pose_mat, thus determining - * the effect of the constraint - */ - invert_m4_m4(imat, pchan_eval->pose_mat); - mul_m4_m4m4(tmat, pmat, imat); - invert_m4_m4(invmat, tmat); - - /* 5. restore constraints */ - pchan_eval->constraints.last = con_last; - - if (con_eval->prev) { - /* hook up prev to this one again */ - con_eval->prev->next = con_eval; - } - else { - /* set as first again */ - pchan_eval->constraints.first = con_eval; - } - - /* 6. recalculate pose with new inv-mat applied */ - /* this one is unnecessary? (DEG seems to update correctly without) - + if we leave this in, we have to click "Set Inverse" twice to see updates... - BKE_pose_where_is(depsgraph, scene, ob_eval); */ + if ((con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) == 0) { + return; } -} - -static void child_get_inverse_matrix_owner_object( - Depsgraph *depsgraph, Scene *scene, Object *ob, bConstraint *con, float invmat[4][4]) -{ - /* nullify inverse matrix first */ - unit_m4(invmat); - - if (ob) { - Object workob; - - /* make sure we passed the correct constraint */ - BLI_assert(BLI_findindex(&ob->constraints, con) != -1); - UNUSED_VARS_NDEBUG(con); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = DEG_get_evaluated_scene(depsgraph); - /* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */ - BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob); - invert_m4_m4(invmat, workob.obmat); - } + short flag_backup = con->flag; + con->flag &= ~(CONSTRAINT_DISABLE | CONSTRAINT_OFF); + BKE_object_eval_constraints(depsgraph, scene, ob); + con->flag = flag_backup; } /* ChildOf Constraint - set inverse callback */ static int childof_set_inverse_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF); bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL; - const int owner = RNA_enum_get(op->ptr, "owner"); /* despite 3 layers of checks, we may still not be able to find a constraint */ if (data == NULL) { @@ -991,12 +904,11 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) { - child_get_inverse_matrix_owner_object(depsgraph, scene, ob, con, data->invmat); - } - else if (owner == EDIT_CONSTRAINT_OWNER_BONE) { - child_get_inverse_matrix_owner_bone(depsgraph, op, scene, ob, data->invmat); - } + /* Set a flag to request recalculation on next update. */ + data->flag |= CHILDOF_SET_INVERSE; + + /* Force constraint to run, it will perform the recalculation. */ + force_evaluation_if_constraint_disabled(C, ob, con); ED_object_constraint_update(bmain, ob); WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob); @@ -1231,12 +1143,9 @@ void CONSTRAINT_OT_followpath_path_animate(wmOperatorType *ot) static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER); bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL; - const int owner = RNA_enum_get(op->ptr, "owner"); /* despite 3 layers of checks, we may still not be able to find a constraint */ if (data == NULL) { @@ -1246,12 +1155,11 @@ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) { - child_get_inverse_matrix_owner_object(depsgraph, scene, ob, con, data->invmat); - } - else if (owner == EDIT_CONSTRAINT_OWNER_BONE) { - child_get_inverse_matrix_owner_bone(depsgraph, op, scene, ob, data->invmat); - } + /* Set a flag to request recalculation on next update. */ + data->flag |= OBJECTSOLVER_SET_INVERSE; + + /* Force constraint to run, it will perform the recalculation. */ + force_evaluation_if_constraint_disabled(C, ob, con); ED_object_constraint_update(bmain, ob); WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob); diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 92e76ab31fa..49b6acc9003 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -488,7 +488,8 @@ static void PE_set_view3d_data(bContext *C, PEData *data) static bool PE_create_shape_tree(PEData *data, Object *shapeob) { - Mesh *mesh = BKE_object_get_evaluated_mesh(data->depsgraph, shapeob); + Object *shapeob_eval = DEG_get_evaluated_object(data->depsgraph, shapeob); + Mesh *mesh = BKE_object_get_evaluated_mesh(shapeob_eval); memset(&data->shape_bvh, 0, sizeof(data->shape_bvh)); diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 8c8fc412663..e58183bfc0f 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -1062,7 +1062,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf) keymap->poll = weight_paint_mode_poll; /*Weight paint's Vertex Selection Mode */ - keymap = WM_keymap_ensure(keyconf, "Weight Paint Vertex Selection", 0, 0); + keymap = WM_keymap_ensure(keyconf, "Paint Vertex Selection (Weight, Vertex)", 0, 0); keymap->poll = vert_paint_poll; /* Image/Texture Paint mode */ @@ -1070,7 +1070,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf) keymap->poll = image_texture_paint_poll; /* face-mask mode */ - keymap = WM_keymap_ensure(keyconf, "Face Mask", 0, 0); + keymap = WM_keymap_ensure(keyconf, "Paint Face Mask (Weight, Vertex, Texture)", 0, 0); keymap->poll = facemask_paint_poll; /* paint stroke */ diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 7372ea6d44a..6971182e5b8 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -181,7 +181,7 @@ static MDeformVert *defweight_prev_init(MDeformVert *dvert_prev, * (without evaluating modifiers) */ static bool vertex_paint_use_fast_update_check(Object *ob) { - Mesh *me_eval = ob->runtime.mesh_eval; + Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); if (me_eval != NULL) { Mesh *me = BKE_mesh_from_object(ob); diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 28e6d95beb3..9defff74c6f 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -2181,8 +2181,17 @@ int ED_path_extension_type(const char *path) else if (BLI_path_extension_check(path, ".py")) { return FILE_TYPE_PYSCRIPT; } - else if (BLI_path_extension_check_n( - path, ".txt", ".glsl", ".osl", ".data", ".pov", ".ini", ".mcr", ".inc", NULL)) { + else if (BLI_path_extension_check_n(path, + ".txt", + ".glsl", + ".osl", + ".data", + ".pov", + ".ini", + ".mcr", + ".inc", + ".fountain", + NULL)) { return FILE_TYPE_TEXT; } else if (BLI_path_extension_check_n(path, ".ttf", ".ttc", ".pfb", ".otf", ".otc", NULL)) { diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index 94747e79c84..dcd348706d6 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -115,8 +115,9 @@ struct FSMenuEntry *ED_fsmenu_get_category(struct FSMenu *fsmenu, FSMenuCategory */ static GHash *fsmenu_xdg_user_dirs_parse(const char *home) { - size_t data_len; - char *data; + /* Add to the default for variable, equals & quotes. */ + char l[128 + FILE_MAXDIR]; + FILE *fp; /* Check if the config file exists. */ { @@ -128,17 +129,14 @@ static GHash *fsmenu_xdg_user_dirs_parse(const char *home) else { BLI_path_join(filepath, sizeof(filepath), home, ".config", "user-dirs.dirs", NULL); } - data = BLI_file_read_text_as_mem_with_newline_as_nil(filepath, true, 1, &data_len); - if (data == NULL) { + fp = BLI_fopen(filepath, "r"); + if (!fp) { return NULL; } } /* By default there are 8 paths. */ GHash *xdg_map = BLI_ghash_str_new_ex(__func__, 8); - char *data_end = data + data_len; - uint l_len; - for (char *l = data; l != data_end; l += l_len + 1) { - l_len = strlen(l); + while (fgets(l, sizeof(l), fp) != NULL) { /* read a line */ /* Avoid inserting invalid values. */ if (STRPREFIX(l, "XDG_")) { @@ -146,9 +144,12 @@ static GHash *fsmenu_xdg_user_dirs_parse(const char *home) if (l_value != NULL) { *l_value = '\0'; l_value++; - if (*l_value == '"' && l[l_len - 1] == '"') { + + BLI_str_rstrip(l_value); + const uint l_value_len = strlen(l_value); + if ((l_value[0] == '"') && (l_value_len > 0) && (l_value[l_value_len - 1] == '"')) { l_value++; - l[l_len - 1] = '\0'; + l_value[l_value_len - 1] = '\0'; char l_value_expanded[FILE_MAX]; char *l_value_final = l_value; @@ -166,7 +167,6 @@ static GHash *fsmenu_xdg_user_dirs_parse(const char *home) } } } - MEM_freeN(data); return xdg_map; } diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt index 5abcff436f1..12de74c6ae7 100644 --- a/source/blender/editors/space_image/CMakeLists.txt +++ b/source/blender/editors/space_image/CMakeLists.txt @@ -43,6 +43,7 @@ set(SRC image_draw.c image_edit.c image_ops.c + image_sequence.c image_undo.c space_image.c diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index f4688ce17fd..54bd2f37f3a 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -985,7 +985,7 @@ void uiTemplateImage(uiLayout *layout, void *lock; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); - if (ibuf->rect_float && (ibuf->flags & IB_halffloat) == 0) { + if (ibuf && ibuf->rect_float && (ibuf->flags & IB_halffloat) == 0) { uiItemR(col, &imaptr, "use_half_precision", 0, NULL, ICON_NONE); } BKE_image_release_ibuf(ima, ibuf, lock); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index a3fa03b18b7..fe1cb1ead9e 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1207,18 +1207,6 @@ typedef struct ImageOpenData { ImageFormatData im_format; } ImageOpenData; -typedef struct ImageFrameRange { - struct ImageFrameRange *next, *prev; - ListBase frames; - /** The full path of the first file in the list of image files */ - char filepath[FILE_MAX]; -} ImageFrameRange; - -typedef struct ImageFrame { - struct ImageFrame *next, *prev; - int framenr; -} ImageFrame; - static void image_open_init(bContext *C, wmOperator *op) { ImageOpenData *iod; @@ -1233,179 +1221,18 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op) op->customdata = NULL; } -/** - * Get a list of frames from the list of image files matching the first file name sequence pattern. - * \param ptr[in]: The RNA pointer containing the "directory" entry and "files" collection. - * \param frames_all[out]: the list of frame numbers found in the files matching - * the first one by name. - */ -static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_all) -{ - char dir[FILE_MAXDIR]; - const bool do_frame_range = RNA_boolean_get(ptr, "use_sequence_detection"); - ImageFrameRange *frame_range = NULL; - - RNA_string_get(ptr, "directory", dir); - RNA_BEGIN (ptr, itemptr, "files") { - char base_head[FILE_MAX], base_tail[FILE_MAX]; - char head[FILE_MAX], tail[FILE_MAX]; - unsigned short digits; - char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); - ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame"); - - /* use the first file in the list as base filename */ - frame->framenr = BLI_stringdec(filename, head, tail, &digits); - - /* still in the same sequence */ - if (do_frame_range && (frame_range != NULL) && (STREQLEN(base_head, head, FILE_MAX)) && - (STREQLEN(base_tail, tail, FILE_MAX))) { - /* pass */ - } - else { - /* start a new frame range */ - frame_range = MEM_callocN(sizeof(*frame_range), __func__); - BLI_join_dirfile(frame_range->filepath, sizeof(frame_range->filepath), dir, filename); - BLI_addtail(frames_all, frame_range); - - BLI_strncpy(base_head, head, sizeof(base_head)); - BLI_strncpy(base_tail, tail, sizeof(base_tail)); - } - - BLI_addtail(&frame_range->frames, frame); - MEM_freeN(filename); - } - RNA_END; -} - -static int image_cmp_frame(const void *a, const void *b) -{ - const ImageFrame *frame_a = a; - const ImageFrame *frame_b = b; - - if (frame_a->framenr < frame_b->framenr) { - return -1; - } - if (frame_a->framenr > frame_b->framenr) { - return 1; - } - return 0; -} - -/* Checks whether the given filepath refers to a UDIM texture. - * If yes, the range from 1001 to the highest tile is returned, otherwise 0. - * - * If the result is positive, the filepath will be overwritten with that of - * the 1001 tile. - * udim_tiles may get filled even if the result ultimately is false! */ -static int image_get_udim(char *filepath, LinkNodePair *udim_tiles) -{ - char filename[FILE_MAX], dirname[FILE_MAXDIR]; - BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename)); - - unsigned short digits; - char base_head[FILE_MAX], base_tail[FILE_MAX]; - int id = BLI_stringdec(filename, base_head, base_tail, &digits); - - if (id < 1001 || id >= IMA_UDIM_MAX) { - return 0; - } - - bool is_udim = true; - bool has_primary = false; - int max_udim = 0; - - struct direntry *dir; - uint totfile = BLI_filelist_dir_contents(dirname, &dir); - for (int i = 0; i < totfile; i++) { - if (!(dir[i].type & S_IFREG)) { - continue; - } - char head[FILE_MAX], tail[FILE_MAX]; - id = BLI_stringdec(dir[i].relname, head, tail, &digits); - - if (digits > 4 || !(STREQLEN(base_head, head, FILE_MAX)) || - !(STREQLEN(base_tail, tail, FILE_MAX))) { - continue; - } - - if (id < 1001 || id >= IMA_UDIM_MAX) { - is_udim = false; - break; - } - if (id == 1001) { - has_primary = true; - } - - BLI_linklist_append(udim_tiles, POINTER_FROM_INT(id)); - max_udim = max_ii(max_udim, id); - } - BLI_filelist_free(dir, totfile); - - if (is_udim && has_primary) { - char primary_filename[FILE_MAX]; - BLI_stringenc(primary_filename, base_head, base_tail, digits, 1001); - BLI_join_dirfile(filepath, FILE_MAX, dirname, primary_filename); - return max_udim - 1000; - } - return 0; -} - -/** - * Return the start (offset) and the length of the sequence of - * continuous frames in the list of frames. - * - * \param frames: [in] the list of frame numbers, as a side-effect the list is sorted. - * \param ofs: [out] offset the first frame number in the sequence. - * \return the number of contiguous frames in the sequence - */ -static int image_sequence_get_len(ImageFrameRange *frame_range, - int *ofs, - char *filepath_range, - LinkNodePair *udim_tiles) -{ - ImageFrame *frame; - - BLI_listbase_sort(&frame_range->frames, image_cmp_frame); - BLI_strncpy(filepath_range, frame_range->filepath, FILE_MAX); - - frame = frame_range->frames.first; - if (frame != NULL) { - int frame_curr = frame->framenr; - (*ofs) = frame_curr; - - if (udim_tiles != NULL) { - int len_udim = image_get_udim(filepath_range, udim_tiles); - if (len_udim > 0) { - *ofs = 1001; - return len_udim; - } - } - - while (frame != NULL && (frame->framenr == frame_curr)) { - frame_curr++; - frame = frame->next; - } - return frame_curr - (*ofs); - } - *ofs = 0; - return 0; -} - static Image *image_open_single(Main *bmain, wmOperator *op, - const char *filepath, + ImageFrameRange *range, const char *relbase, bool is_relative_path, - bool use_multiview, - int frame_seq_len, - int frame_seq_ofs, - LinkNodePair *udim_tiles) + bool use_multiview) { bool exists = false; Image *ima = NULL; errno = 0; - ima = BKE_image_load_exists_ex(bmain, filepath, &exists); + ima = BKE_image_load_exists_ex(bmain, range->filepath, &exists); if (!ima) { if (op->customdata) { @@ -1414,7 +1241,7 @@ static Image *image_open_single(Main *bmain, BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s", - filepath, + range->filepath, errno ? strerror(errno) : TIP_("unsupported image format")); return NULL; } @@ -1439,11 +1266,11 @@ static Image *image_open_single(Main *bmain, BKE_image_free_views(ima); } - if ((frame_seq_len > 1) && (ima->source == IMA_SRC_FILE)) { - if (udim_tiles && frame_seq_ofs == 1001) { + if ((range->length > 1) && (ima->source == IMA_SRC_FILE)) { + if (range->udim_tiles.first && range->offset == 1001) { ima->source = IMA_SRC_TILED; - for (LinkNode *node = udim_tiles->list; node; node = node->next) { - BKE_image_add_tile(ima, POINTER_AS_INT(node->link), NULL); + for (LinkData *node = range->udim_tiles.first; node; node = node->next) { + BKE_image_add_tile(ima, POINTER_AS_INT(node->data), NULL); } } else { @@ -1464,7 +1291,6 @@ static int image_open_exec(bContext *C, wmOperator *op) ImageUser *iuser = NULL; ImageOpenData *iod = op->customdata; Image *ima = NULL; - char filepath[FILE_MAX]; int frame_seq_len = 0; int frame_ofs = 1; @@ -1476,83 +1302,21 @@ static int image_open_exec(bContext *C, wmOperator *op) image_open_init(C, op); } - RNA_string_get(op->ptr, "filepath", filepath); - - if (RNA_struct_property_is_set(op->ptr, "directory") && - RNA_struct_property_is_set(op->ptr, "files")) { - bool was_relative = BLI_path_is_rel(filepath); - ListBase frame_ranges_all; - - BLI_listbase_clear(&frame_ranges_all); - image_sequence_get_frame_ranges(op->ptr, &frame_ranges_all); - for (ImageFrameRange *frame_range = frame_ranges_all.first; frame_range; - frame_range = frame_range->next) { - int frame_range_ofs; - - LinkNodePair udim_tiles = {NULL}; - LinkNodePair *udim_tiles_ptr = use_udim ? (&udim_tiles) : NULL; - - char filepath_range[FILE_MAX]; - int frame_range_seq_len = image_sequence_get_len( - frame_range, &frame_range_ofs, filepath_range, udim_tiles_ptr); - BLI_freelistN(&frame_range->frames); - - if (was_relative) { - BLI_path_rel(filepath_range, BKE_main_blendfile_path(bmain)); - } - - Image *ima_range = image_open_single(bmain, - op, - filepath_range, - BKE_main_blendfile_path(bmain), - is_relative_path, - use_multiview, - frame_range_seq_len, - frame_range_ofs, - udim_tiles_ptr); - - /* take the first image */ - if ((ima == NULL) && ima_range) { - ima = ima_range; - frame_seq_len = frame_range_seq_len; - frame_ofs = frame_range_ofs; - } + ListBase ranges = ED_image_filesel_detect_sequences(bmain, op, use_udim); + for (ImageFrameRange *range = ranges.first; range; range = range->next) { + Image *ima_range = image_open_single( + bmain, op, range, BKE_main_blendfile_path(bmain), is_relative_path, use_multiview); - BLI_linklist_free(udim_tiles.list, NULL); + /* take the first image */ + if ((ima == NULL) && ima_range) { + ima = ima_range; + frame_seq_len = range->length; + frame_ofs = range->offset; } - BLI_freelistN(&frame_ranges_all); - } - else { - /* for drag & drop etc. */ - - LinkNodePair udim_tiles = {NULL}; - frame_seq_len = 1; - char filepath_range[FILE_MAX]; - BLI_strncpy(filepath_range, filepath, FILE_MAX); - - if (use_udim > 0) { - /* Try to find UDIM tiles corresponding to the image */ - int udim_len = image_get_udim(filepath_range, &udim_tiles); - - /* If we found something, mark the image as tiled. */ - if (udim_len) { - frame_seq_len = udim_len; - frame_ofs = 1001; - } - } - - ima = image_open_single(bmain, - op, - filepath_range, - BKE_main_blendfile_path(bmain), - is_relative_path, - use_multiview, - frame_seq_len, - frame_ofs, - &udim_tiles); - BLI_linklist_free(udim_tiles.list, NULL); + BLI_freelistN(&range->udim_tiles); } + BLI_freelistN(&ranges); if (ima == NULL) { return OPERATOR_CANCELLED; diff --git a/source/blender/editors/space_image/image_sequence.c b/source/blender/editors/space_image/image_sequence.c new file mode 100644 index 00000000000..09e717621d8 --- /dev/null +++ b/source/blender/editors/space_image/image_sequence.c @@ -0,0 +1,249 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + */ + +/** \file + * \ingroup spimage + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_fileops.h" +#include "BLI_fileops_types.h" +#include "BLI_linklist.h" +#include "BLI_listbase.h" +#include "BLI_math_base.h" +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "DNA_image_types.h" +#include "DNA_space_types.h" +#include "DNA_windowmanager_types.h" + +#include "RNA_access.h" + +#include "BKE_image.h" +#include "BKE_main.h" + +#include "ED_image.h" + +#include "WM_types.h" + +typedef struct ImageFrame { + struct ImageFrame *next, *prev; + int framenr; +} ImageFrame; + +/** + * Get a list of frames from the list of image files matching the first file + * name sequence pattern. The files and directory are read from standard + * fileselect operator properties. + * + * The output is a list of frame ranges, each containg a list of frames with + * matching names. + */ +static void image_sequence_get_frame_ranges(wmOperator *op, ListBase *ranges) +{ + char dir[FILE_MAXDIR]; + const bool do_frame_range = RNA_boolean_get(op->ptr, "use_sequence_detection"); + ImageFrameRange *range = NULL; + + RNA_string_get(op->ptr, "directory", dir); + RNA_BEGIN (op->ptr, itemptr, "files") { + char base_head[FILE_MAX], base_tail[FILE_MAX]; + char head[FILE_MAX], tail[FILE_MAX]; + unsigned short digits; + char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); + ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame"); + + /* use the first file in the list as base filename */ + frame->framenr = BLI_stringdec(filename, head, tail, &digits); + + /* still in the same sequence */ + if (do_frame_range && (range != NULL) && (STREQLEN(base_head, head, FILE_MAX)) && + (STREQLEN(base_tail, tail, FILE_MAX))) { + /* pass */ + } + else { + /* start a new frame range */ + range = MEM_callocN(sizeof(*range), __func__); + BLI_join_dirfile(range->filepath, sizeof(range->filepath), dir, filename); + BLI_addtail(ranges, range); + + BLI_strncpy(base_head, head, sizeof(base_head)); + BLI_strncpy(base_tail, tail, sizeof(base_tail)); + } + + BLI_addtail(&range->frames, frame); + MEM_freeN(filename); + } + RNA_END; +} + +static int image_cmp_frame(const void *a, const void *b) +{ + const ImageFrame *frame_a = a; + const ImageFrame *frame_b = b; + + if (frame_a->framenr < frame_b->framenr) { + return -1; + } + if (frame_a->framenr > frame_b->framenr) { + return 1; + } + return 0; +} + +/* + * Checks whether the given filepath refers to a UDIM texture. + * If yes, the range from 1001 to the highest tile is returned, otherwise 0. + * + * If the result is positive, the filepath will be overwritten with that of + * the 1001 tile. + * + * udim_tiles may get filled even if the result ultimately is false! + */ +static int image_get_udim(char *filepath, ListBase *udim_tiles) +{ + char filename[FILE_MAX], dirname[FILE_MAXDIR]; + BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename)); + + unsigned short digits; + char base_head[FILE_MAX], base_tail[FILE_MAX]; + int id = BLI_stringdec(filename, base_head, base_tail, &digits); + + if (id < 1001 || id >= IMA_UDIM_MAX) { + return 0; + } + + bool is_udim = true; + bool has_primary = false; + int max_udim = 0; + + struct direntry *dir; + uint totfile = BLI_filelist_dir_contents(dirname, &dir); + for (int i = 0; i < totfile; i++) { + if (!(dir[i].type & S_IFREG)) { + continue; + } + char head[FILE_MAX], tail[FILE_MAX]; + id = BLI_stringdec(dir[i].relname, head, tail, &digits); + + if (digits > 4 || !(STREQLEN(base_head, head, FILE_MAX)) || + !(STREQLEN(base_tail, tail, FILE_MAX))) { + continue; + } + + if (id < 1001 || id >= IMA_UDIM_MAX) { + is_udim = false; + break; + } + if (id == 1001) { + has_primary = true; + } + + BLI_addtail(udim_tiles, BLI_genericNodeN(POINTER_FROM_INT(id))); + max_udim = max_ii(max_udim, id); + } + BLI_filelist_free(dir, totfile); + + if (is_udim && has_primary) { + char primary_filename[FILE_MAX]; + BLI_stringenc(primary_filename, base_head, base_tail, digits, 1001); + BLI_join_dirfile(filepath, FILE_MAX, dirname, primary_filename); + return max_udim - 1000; + } + return 0; +} + +/** + * From a list of frames, compute the start (offset) and length of the sequence + * of contiguous frames. If UDIM is detect, it will return UDIM tiles as well. + */ +static void image_detect_frame_range(ImageFrameRange *range, const bool detect_udim) +{ + /* UDIM */ + if (detect_udim) { + int len_udim = image_get_udim(range->filepath, &range->udim_tiles); + + if (len_udim > 0) { + range->offset = 1001; + range->length = len_udim; + return; + } + } + + /* Image Sequence */ + BLI_listbase_sort(&range->frames, image_cmp_frame); + + ImageFrame *frame = range->frames.first; + if (frame != NULL) { + int frame_curr = frame->framenr; + range->offset = frame_curr; + + while (frame != NULL && (frame->framenr == frame_curr)) { + frame_curr++; + frame = frame->next; + } + + range->length = frame_curr - range->offset; + } + else { + range->length = 1; + range->offset = 0; + } +} + +/* Used for both images and volume file loading. */ +ListBase ED_image_filesel_detect_sequences(Main *bmain, wmOperator *op, const bool detect_udim) +{ + ListBase ranges; + BLI_listbase_clear(&ranges); + + char filepath[FILE_MAX]; + RNA_string_get(op->ptr, "filepath", filepath); + + /* File browser. */ + if (RNA_struct_property_is_set(op->ptr, "directory") && + RNA_struct_property_is_set(op->ptr, "files")) { + const bool was_relative = BLI_path_is_rel(filepath); + + image_sequence_get_frame_ranges(op, &ranges); + for (ImageFrameRange *range = ranges.first; range; range = range->next) { + image_detect_frame_range(range, detect_udim); + BLI_freelistN(&range->frames); + + if (was_relative) { + BLI_path_rel(range->filepath, BKE_main_blendfile_path(bmain)); + } + } + } + /* Filepath property for drag & drop etc. */ + else { + ImageFrameRange *range = MEM_callocN(sizeof(*range), __func__); + BLI_addtail(&ranges, range); + + BLI_strncpy(range->filepath, filepath, FILE_MAX); + image_detect_frame_range(range, detect_udim); + } + + return ranges; +} diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 225ca72a7d0..d00083d343b 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -137,7 +137,7 @@ static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset) switch (ob->type) { case OB_MESH: { /* we assume evaluated mesh is already built, this strictly does stats now. */ - Mesh *me_eval = ob->runtime.mesh_eval; + Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); if (!BLI_gset_add(objects_gset, me_eval)) { break; } @@ -153,8 +153,7 @@ static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset) case OB_SURF: case OB_CURVE: case OB_FONT: { - Mesh *me_eval = ob->runtime.mesh_eval; - + Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); if ((me_eval != NULL) && !BLI_gset_add(objects_gset, me_eval)) { break; } diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 5cd2a86adf8..e5f6b25ee25 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -340,6 +340,8 @@ static void nla_region_listener(wmWindow *UNUSED(win), case ND_OB_ACTIVE: case ND_FRAME: case ND_MARKERS: + case ND_LAYER_CONTENT: + case ND_OB_SELECT: ED_region_tag_redraw(ar); break; } @@ -349,6 +351,7 @@ static void nla_region_listener(wmWindow *UNUSED(win), case ND_BONE_ACTIVE: case ND_BONE_SELECT: case ND_KEYS: + case ND_DRAW: ED_region_tag_redraw(ar); break; } @@ -379,6 +382,8 @@ static void nla_main_region_listener(wmWindow *UNUSED(win), case ND_FRAME: case ND_FRAME_RANGE: case ND_MARKERS: + case ND_LAYER_CONTENT: + case ND_OB_SELECT: ED_region_tag_redraw(ar); break; } @@ -474,6 +479,8 @@ static void nla_channel_region_listener(wmWindow *UNUSED(win), case NC_SCENE: switch (wmn->data) { case ND_OB_ACTIVE: + case ND_LAYER_CONTENT: + case ND_OB_SELECT: ED_region_tag_redraw(ar); break; } @@ -483,6 +490,7 @@ static void nla_channel_region_listener(wmWindow *UNUSED(win), case ND_BONE_ACTIVE: case ND_BONE_SELECT: case ND_KEYS: + case ND_DRAW: ED_region_tag_redraw(ar); break; } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 0daa5aa53ae..00f61a4d0aa 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -28,9 +28,9 @@ #include "BLI_math.h" #include "BKE_DerivedMesh.h" -#include "BKE_global.h" - #include "BKE_editmesh.h" +#include "BKE_global.h" +#include "BKE_object.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" @@ -120,8 +120,9 @@ void ED_draw_object_facemap(Depsgraph *depsgraph, Mesh *me = ob->data; { Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - if (ob_eval->runtime.mesh_eval) { - me = ob_eval->runtime.mesh_eval; + Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); + if (me_eval != NULL) { + me = me_eval; } } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 9d84309d222..df743415fec 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -361,10 +361,10 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar) /* object ops. */ /* important to be before Pose keymap since they can both be enabled at once */ - keymap = WM_keymap_ensure(wm->defaultconf, "Face Mask", 0, 0); + keymap = WM_keymap_ensure(wm->defaultconf, "Paint Face Mask (Weight, Vertex, Texture)", 0, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Weight Paint Vertex Selection", 0, 0); + keymap = WM_keymap_ensure(wm->defaultconf, "Paint Vertex Selection (Weight, Vertex)", 0, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); /* Before 'Pose' so weight paint menus aren't overridden by pose menus. */ diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 06a4147e34d..4ff8a9a3884 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -98,7 +98,7 @@ #include "view3d_intern.h" /* own include */ -#define M_GOLDEN_RATION_CONJUGATE 0.618033988749895f +#define M_GOLDEN_RATIO_CONJUGATE 0.618033988749895f /* -------------------------------------------------------------------- */ /** \name General Functions @@ -452,7 +452,7 @@ static void drawviewborder_triangle( if (w > h) { if (golden) { - ofs = w * (1.0f - (1.0f / M_GOLDEN_RATION_CONJUGATE)); + ofs = w * (1.0f - M_GOLDEN_RATIO_CONJUGATE); } else { ofs = h * (h / w); @@ -472,7 +472,7 @@ static void drawviewborder_triangle( } else { if (golden) { - ofs = h * (1.0f - (1.0f / M_GOLDEN_RATION_CONJUGATE)); + ofs = h * (1.0f - M_GOLDEN_RATIO_CONJUGATE); } else { ofs = w * (w / h); @@ -662,7 +662,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View } if (ca->dtx & CAM_DTX_GOLDEN) { - drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f - (1.0f / M_GOLDEN_RATION_CONJUGATE)); + drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f - M_GOLDEN_RATIO_CONJUGATE); } if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) { diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index bc81817647e..ed42a0e35f3 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1635,9 +1635,9 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } } - if ((prop = RNA_struct_find_property(op->ptr, "mouse_coordinate_override"))) { + if ((prop = RNA_struct_find_property(op->ptr, "center_override"))) { /* Important for redo operations. */ - RNA_property_int_set_array(op->ptr, prop, t->mouse.imval); + RNA_property_float_set_array(op->ptr, prop, t->center_global); } if (t->flag & T_PROP_EDIT_ALL) { diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index 027ae04795a..c2e3c8ef508 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -69,6 +69,8 @@ #include "ED_clip.h" #include "ED_mask.h" +#include "UI_view2d.h" + #include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */ #include "WM_types.h" @@ -787,6 +789,28 @@ void clipUVData(TransInfo *t) /* ********************* ANIMATION EDITORS (GENERAL) ************************* */ +/** + * For modal operation: `t->center_global` may not have been set yet. + */ +void transform_convert_center_global_v2(TransInfo *t, float r_center[2]) +{ + if (t->flag & T_MODAL) { + UI_view2d_region_to_view( + (View2D *)t->view, t->mouse.imval[0], t->mouse.imval[1], &r_center[0], &r_center[1]); + } + else { + copy_v2_v2(r_center, t->center_global); + } +} + +void transform_convert_center_global_v2_int(TransInfo *t, int r_center[2]) +{ + float center[2]; + transform_convert_center_global_v2(t, center); + r_center[0] = round_fl_to_int(center[0]); + r_center[1] = round_fl_to_int(center[1]); +} + /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */ bool FrameOnMouseSide(char side, float frame, float cframe) { @@ -2514,7 +2538,7 @@ void createTransData(bContext *C, TransInfo *t) t->obedit_type = -1; t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point trasnform */ - createTransSeqData(C, t); + createTransSeqData(t); countAndCleanTransDataContainer(t); } else if (t->spacetype == SPACE_GRAPH) { diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h index 075bf0a5a4b..d616f24ba86 100644 --- a/source/blender/editors/transform/transform_convert.h +++ b/source/blender/editors/transform/transform_convert.h @@ -104,6 +104,8 @@ void transform_around_single_fallback(TransInfo *t); bool constraints_list_needinv(TransInfo *t, ListBase *list); void calc_distanceCurveVerts(TransData *head, TransData *tail); struct TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTriple *bezt); +void transform_convert_center_global_v2(TransInfo *t, float r_center[2]); +void transform_convert_center_global_v2_int(TransInfo *t, int r_center[2]); bool FrameOnMouseSide(char side, float frame, float cframe); /* transform_convert_action.c */ @@ -162,7 +164,7 @@ void createTransParticleVerts(bContext *C, TransInfo *t); void createTransSculpt(TransInfo *t); /* transform_convert_sequence.c */ -void createTransSeqData(bContext *C, TransInfo *t); +void createTransSeqData(TransInfo *t); /* transform_convert_tracking.c */ void createTransTrackingData(bContext *C, TransInfo *t); diff --git a/source/blender/editors/transform/transform_convert_action.c b/source/blender/editors/transform/transform_convert_action.c index 0b1d2757435..42e8523d4cb 100644 --- a/source/blender/editors/transform/transform_convert_action.c +++ b/source/blender/editors/transform/transform_convert_action.c @@ -36,8 +36,6 @@ #include "ED_anim_api.h" -#include "UI_view2d.h" - #include "transform.h" #include "transform_convert.h" @@ -333,11 +331,10 @@ void createTransActionData(bContext *C, TransInfo *t) /* which side of the current frame should be allowed */ if (t->mode == TFM_TIME_EXTEND) { - /* only side on which mouse is gets transformed */ - float xmouse, ymouse; - - UI_view2d_region_to_view(&ac.ar->v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse); - t->frame_side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side + /* only side on which center is gets transformed */ + float center[2]; + transform_convert_center_global_v2(t, center); + t->frame_side = (center[0] > CFRA) ? 'R' : 'L'; } else { /* normal transform - both sides of current frame are considered */ diff --git a/source/blender/editors/transform/transform_convert_graph.c b/source/blender/editors/transform/transform_convert_graph.c index f6f982e854a..502679efedf 100644 --- a/source/blender/editors/transform/transform_convert_graph.c +++ b/source/blender/editors/transform/transform_convert_graph.c @@ -1,4 +1,4 @@ -/* +/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -261,11 +261,10 @@ void createTransGraphEditData(bContext *C, TransInfo *t) /* which side of the current frame should be allowed */ // XXX we still want this mode, but how to get this using standard transform too? if (t->mode == TFM_TIME_EXTEND) { - /* only side on which mouse is gets transformed */ - float xmouse, ymouse; - - UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse); - t->frame_side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side + /* only side on which center is gets transformed */ + float center[2]; + transform_convert_center_global_v2(t, center); + t->frame_side = (center[0] > CFRA) ? 'R' : 'L'; } else { /* normal transform - both sides of current frame are considered */ diff --git a/source/blender/editors/transform/transform_convert_nla.c b/source/blender/editors/transform/transform_convert_nla.c index 114968ec83f..7c34c583210 100644 --- a/source/blender/editors/transform/transform_convert_nla.c +++ b/source/blender/editors/transform/transform_convert_nla.c @@ -35,8 +35,6 @@ #include "ED_anim_api.h" -#include "UI_view2d.h" - #include "transform.h" #include "transform_convert.h" @@ -73,11 +71,10 @@ void createTransNlaData(bContext *C, TransInfo *t) /* which side of the current frame should be allowed */ if (t->mode == TFM_TIME_EXTEND) { - /* only side on which mouse is gets transformed */ - float xmouse, ymouse; - - UI_view2d_region_to_view(&ac.ar->v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse); - t->frame_side = (xmouse > CFRA) ? 'R' : 'L'; + /* only side on which center is gets transformed */ + float center[2]; + transform_convert_center_global_v2(t, center); + t->frame_side = (center[0] > CFRA) ? 'R' : 'L'; } else { /* normal transform - both sides of current frame are considered */ diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c index 4baf0e8a3cb..a35c814ee23 100644 --- a/source/blender/editors/transform/transform_convert_sequencer.c +++ b/source/blender/editors/transform/transform_convert_sequencer.c @@ -31,8 +31,6 @@ #include "BKE_sequencer.h" #include "BKE_report.h" -#include "UI_view2d.h" - #include "transform.h" #include "transform_convert.h" @@ -522,18 +520,16 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c DEG_id_tag_update(&t->scene->id, ID_RECALC_SEQUENCER_STRIPS); } -void createTransSeqData(bContext *C, TransInfo *t) +void createTransSeqData(TransInfo *t) { #define XXX_DURIAN_ANIM_TX_HACK - View2D *v2d = UI_view2d_fromcontext(C); Scene *scene = t->scene; Editing *ed = BKE_sequencer_editing_get(t->scene, false); TransData *td = NULL; TransData2D *td2d = NULL; TransDataSeq *tdsq = NULL; TransSeq *ts = NULL; - int xmouse; int count = 0; @@ -545,18 +541,10 @@ void createTransSeqData(bContext *C, TransInfo *t) } tc->custom.type.free_cb = freeSeqData; - - xmouse = (int)UI_view2d_region_to_view_x(v2d, t->mouse.imval[0]); - - /* which side of the current frame should be allowed */ - if (t->mode == TFM_TIME_EXTEND) { - /* only side on which mouse is gets transformed */ - t->frame_side = (xmouse > CFRA) ? 'R' : 'L'; - } - else { - /* normal transform - both sides of current frame are considered */ - t->frame_side = 'B'; - } + /* only side on which center is gets transformed */ + int center[2]; + transform_convert_center_global_v2_int(t, center); + t->frame_side = (center[0] > CFRA) ? 'R' : 'L'; #ifdef XXX_DURIAN_ANIM_TX_HACK { @@ -599,7 +587,7 @@ void createTransSeqData(bContext *C, TransInfo *t) SeqTransDataBounds(t, ed->seqbasep, ts); /* set the snap mode based on how close the mouse is at the end/start points */ - if (abs(xmouse - ts->max) > abs(xmouse - ts->min)) { + if (abs(center[0] - ts->max) > abs(center[0] - ts->min)) { ts->snap_left = true; } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index c925f5c9a8e..7d9a122f802 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1374,17 +1374,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve bGPdata *gpd = CTX_data_gpencil_data(C); PropertyRNA *prop; - if (op && (prop = RNA_struct_find_property(op->ptr, "mouse_coordinate_override")) && - RNA_property_is_set(op->ptr, prop)) { - RNA_property_int_get_array(op->ptr, prop, t->mval); - } - else if (event) { - copy_v2_v2_int(t->mval, event->mval); - } - else { - zero_v2_int(t->mval); - } - t->depsgraph = CTX_data_depsgraph_pointer(C); t->scene = sce; t->view_layer = view_layer; @@ -1413,11 +1402,16 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->redraw = TREDRAW_HARD; /* redraw first time */ - t->mouse.imval[0] = t->mval[0]; - t->mouse.imval[1] = t->mval[1]; - - t->con.imval[0] = t->mouse.imval[0]; - t->con.imval[1] = t->mouse.imval[1]; + int mval[2]; + if (event) { + copy_v2_v2_int(mval, event->mval); + } + else { + zero_v2_int(mval); + } + copy_v2_v2_int(t->mval, mval); + copy_v2_v2_int(t->mouse.imval, mval); + copy_v2_v2_int(t->con.imval, mval); t->transform = NULL; t->handleEvent = NULL; diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index d3d5d785eac..39f6f24eb8d 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -694,14 +694,6 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) RNA_def_property_ui_text(prop, "Center Override", "Force using this center value (when set)"); } - if (flags & P_MOUSE) { - prop = RNA_def_property(ot->srna, "mouse_coordinate_override", PROP_INT, PROP_XYZ); - RNA_def_property_array(prop, 2); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - RNA_def_property_ui_text( - prop, "Mouse Coordinate Override", "Force using this mouse value (when set)"); - } - if ((flags & P_NO_DEFAULTS) == 0) { prop = RNA_def_boolean(ot->srna, "release_confirm", @@ -1247,7 +1239,7 @@ static void TRANSFORM_OT_transform(struct wmOperatorType *ot) Transform_Properties(ot, P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | - P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER | P_MOUSE); + P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER); } static int transform_from_gizmo_invoke(bContext *C, diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index c4358168adb..ecd267d6f2a 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -19,9 +19,6 @@ */ #include <stdlib.h> -#include <math.h> -#include <float.h> -#include <stdio.h> #include "MEM_guardedalloc.h" @@ -34,10 +31,10 @@ #include "DNA_armature_types.h" #include "DNA_curve_types.h" -#include "DNA_scene_types.h" -#include "DNA_object_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_view3d_types.h" @@ -50,19 +47,16 @@ #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_tracking.h" -#include "BKE_context.h" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" -#include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" -#include "ED_transform.h" #include "ED_transform_snap_object_context.h" #include "ED_view3d.h" #include "ED_armature.h" -#include "transform.h" +#include "ED_transform.h" /* -------------------------------------------------------------------- */ /** \name Internal Data Types @@ -92,25 +86,27 @@ typedef struct SnapObjectData { SNAP_MESH = 1, SNAP_EDIT_MESH, } type; -} SnapObjectData; - -typedef struct SnapObjectData_Mesh { - SnapObjectData sd; - BVHTreeFromMesh treedata; - const struct MPoly *poly; - BVHTree *bvhtree[2]; /* from loose verts and from loose edges */ - uint has_looptris : 1; - uint has_loose_edge : 1; - uint has_loose_vert : 1; -} SnapObjectData_Mesh; + BVHTree *bvhtree[2]; /* MESH: loose edges, loose verts + * EDIT_MESH: verts, edges. */ + bool cached[2]; -typedef struct SnapObjectData_EditMesh { - SnapObjectData sd; - BVHTreeFromEditMesh *bvh_trees[3]; - float min[3], max[3]; - -} SnapObjectData_EditMesh; + union { + struct { + /* SNAP_MESH */ + BVHTreeFromMesh treedata_mesh; + const struct MPoly *poly; + uint has_looptris : 1; + uint has_loose_edge : 1; + uint has_loose_vert : 1; + }; + struct { + /* SNAP_EDIT_MESH */ + BVHTreeFromEditMesh treedata_editmesh; + float min[3], max[3]; + }; + }; +} SnapObjectData; struct SnapObjectContext { Main *bmain; @@ -149,7 +145,7 @@ struct SnapObjectContext { /** \} */ /* -------------------------------------------------------------------- */ -/** \name Common Utilities +/** \name Snap Object Data * \{ */ /** @@ -166,6 +162,45 @@ static void bm_mesh_minmax(BMesh *bm, float r_min[3], float r_max[3]) } } +static void snap_object_data_mesh_clear(SnapObjectData *sod) +{ + BLI_assert(sod->type == SNAP_MESH); + for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) { + if (!sod->cached[i]) { + BLI_bvhtree_free(sod->bvhtree[i]); + } + sod->bvhtree[i] = NULL; + } + free_bvhtree_from_mesh(&sod->treedata_mesh); +} + +static void snap_object_data_editmesh_clear(SnapObjectData *sod) +{ + BLI_assert(sod->type == SNAP_EDIT_MESH); + for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) { + if (!sod->cached[i]) { + BLI_bvhtree_free(sod->bvhtree[i]); + } + sod->bvhtree[i] = NULL; + } + free_bvhtree_from_editmesh(&sod->treedata_editmesh); +} + +static void snap_object_data_clear(SnapObjectData *sod) +{ + switch (sod->type) { + case SNAP_MESH: { + snap_object_data_mesh_clear(sod); + break; + } + case SNAP_EDIT_MESH: { + snap_object_data_editmesh_clear(sod); + break; + } + } + memset(&sod->type, 0x0, sizeof(*sod) - offsetof(SnapObjectData, type)); +} + static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *ob) { SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob); @@ -181,15 +216,17 @@ static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object * return sod; } -static SnapObjectData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob) +static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob) { void **sod_p; if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_MESH); } else { - SnapObjectData_Mesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); - sod->sd.type = SNAP_MESH; + SnapObjectData *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + + /* Init. */ + sod->type = SNAP_MESH; /* start assuming that it has each of these element types */ sod->has_looptris = true; sod->has_loose_edge = true; @@ -199,9 +236,9 @@ static SnapObjectData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, O return *sod_p; } -static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx, - Object *ob, - BMEditMesh *em) +static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, + Object *ob, + BMEditMesh *em) { void **sod_p; @@ -224,15 +261,23 @@ static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_EDIT_MESH); } else { - SnapObjectData_EditMesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, - sizeof(*sod)); - sod->sd.type = SNAP_EDIT_MESH; + SnapObjectData *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + + /* Init. */ + sod->type = SNAP_EDIT_MESH; + sod->treedata_editmesh.em = em; bm_mesh_minmax(em->bm, sod->min, sod->max); } return *sod_p; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Iterator + * \{ */ + typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, bool use_backface_culling, @@ -516,9 +561,9 @@ static bool raycastMesh(SnapObjectContext *sctx, len_diff = 0.0f; } - SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob); + SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob); - BVHTreeFromMesh *treedata = &sod->treedata; + BVHTreeFromMesh *treedata = &sod->treedata_mesh; /* The tree is owned by the Mesh and may have been freed since we last used. */ if (treedata->tree) { @@ -668,7 +713,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx, local_depth *= local_scale; } - SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob, em); + SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob, em); /* Test BoundBox */ @@ -690,24 +735,21 @@ static bool raycastEditMesh(SnapObjectContext *sctx, len_diff = 0.0f; } - if (sod->bvh_trees[2] == NULL) { - sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(BVHTreeFromEditMesh)); - } - - BVHTreeFromEditMesh *treedata = sod->bvh_trees[2]; + BVHTreeFromEditMesh *treedata = &sod->treedata_editmesh; BVHCache **em_bvh_cache = &((Mesh *)ob->data)->runtime.bvh_cache; - if (sctx->callbacks.edit_mesh.test_face_fn == NULL) { + if (treedata->tree && treedata->cached) { /* The tree is owned by the Mesh and may have been freed since we last used! */ - if (treedata->tree && !bvhcache_has_tree(*em_bvh_cache, treedata->tree)) { - free_bvhtree_from_editmesh(treedata); + if (!bvhcache_has_tree(*em_bvh_cache, treedata->tree)) { + treedata->tree = NULL; } } if (treedata->tree == NULL) { /* Get original version of the edit_mesh. */ - BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob)); + BLI_assert(sod->treedata_editmesh.em == BKE_editmesh_from_object(DEG_get_original_object(ob))); + BMEditMesh *em_orig = sod->treedata_editmesh.em; if (sctx->callbacks.edit_mesh.test_face_fn) { BMesh *bm = em_orig->bm; @@ -796,7 +838,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx, if (r_index) { /* Get original version of the edit_mesh. */ - BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob)); + BMEditMesh *em_orig = sod->treedata_editmesh.em; *r_index = BM_elem_index_get(em_orig->looptris[hit.index][0]->f); } @@ -850,7 +892,10 @@ static bool raycastObj(SnapObjectContext *sctx, Mesh *me = ob->data; bool use_hide = false; if (BKE_object_is_in_editmode(ob)) { - BMEditMesh *em = BKE_editmesh_from_object(ob); + /* Strange, sometimes the `em` of the evaluated object has + * uninitialized memory. Need to be investigated. + * Use the `em` of the original object then. */ + BMEditMesh *em = BKE_editmesh_from_object(DEG_get_original_object(ob)); if (use_obedit) { retval = raycastEditMesh(sctx, ray_start, @@ -891,12 +936,13 @@ static bool raycastObj(SnapObjectContext *sctx, case OB_CURVE: case OB_SURF: case OB_FONT: { - if (ob->runtime.mesh_eval) { + Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); + if (mesh_eval) { retval = raycastMesh(sctx, ray_start, ray_dir, ob, - ob->runtime.mesh_eval, + mesh_eval, obmat, ob_index, false, @@ -1400,14 +1446,14 @@ static short snap_mesh_polygon(SnapObjectContext *sctx, BLI_assert(sod != NULL); if (sod->type == SNAP_MESH) { - BVHTreeFromMesh *treedata = &((SnapObjectData_Mesh *)sod)->treedata; + BVHTreeFromMesh *treedata = &sod->treedata_mesh; nearest2d.userdata = treedata; nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get; nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get; nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy; - const MPoly *mp = &((SnapObjectData_Mesh *)sod)->poly[*r_index]; + const MPoly *mp = &sod->poly[*r_index]; const MLoop *ml = &treedata->loop[mp->loopstart]; if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { elem = SCE_SNAP_MODE_EDGE; @@ -1435,7 +1481,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx, } else { BLI_assert(sod->type == SNAP_EDIT_MESH); - BMEditMesh *em = BKE_editmesh_from_object(ob); + BMEditMesh *em = sod->treedata_editmesh.em; nearest2d.userdata = em; nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get; @@ -1525,14 +1571,14 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, nearest2d.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; nearest2d.use_backface_culling = use_backface_culling; if (sod->type == SNAP_MESH) { - nearest2d.userdata = &((SnapObjectData_Mesh *)sod)->treedata; + nearest2d.userdata = &sod->treedata_mesh; nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get; nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get; nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy; } else { BLI_assert(sod->type == SNAP_EDIT_MESH); - nearest2d.userdata = BKE_editmesh_from_object(ob); + nearest2d.userdata = sod->treedata_editmesh.em; nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get; nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get; nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy; @@ -2160,27 +2206,23 @@ static short snapMesh(SnapObjectContext *sctx, return 0; } - SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob); + SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob); BVHTreeFromMesh *treedata, dummy_treedata; - BVHTree **bvhtree; - treedata = &sod->treedata; - bvhtree = sod->bvhtree; + treedata = &sod->treedata_mesh; /* The tree is owned by the Mesh and may have been freed since we last used! */ - if ((sod->has_looptris && treedata->tree && - !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) || - (sod->has_loose_edge && bvhtree[0] && - !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0])) || - (sod->has_loose_vert && bvhtree[1] && - !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1]))) { - BLI_assert(!treedata->tree || !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)); - BLI_assert(!bvhtree[0] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0])); - BLI_assert(!bvhtree[1] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1])); - + if (treedata->cached && treedata->tree && + !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) { free_bvhtree_from_mesh(treedata); - bvhtree[0] = NULL; - bvhtree[1] = NULL; + } + if (sod->cached[0] && sod->bvhtree[0] && + !bvhcache_has_tree(me->runtime.bvh_cache, sod->bvhtree[0])) { + sod->bvhtree[0] = NULL; + } + if (sod->cached[1] && sod->bvhtree[1] && + !bvhcache_has_tree(me->runtime.bvh_cache, sod->bvhtree[1])) { + sod->bvhtree[1] = NULL; } if (sod->has_looptris && treedata->tree == NULL) { @@ -2191,9 +2233,10 @@ static short snapMesh(SnapObjectContext *sctx, treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */ } } - if (sod->has_loose_edge && bvhtree[0] == NULL) { - bvhtree[0] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEEDGES, 2); - sod->has_loose_edge = bvhtree[0] != NULL; + if (sod->has_loose_edge && sod->bvhtree[0] == NULL) { + sod->bvhtree[0] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEEDGES, 2); + sod->has_loose_edge = sod->bvhtree[0] != NULL; + sod->cached[0] = dummy_treedata.cached; if (sod->has_loose_edge) { BLI_assert(treedata->vert_allocated == false); @@ -2206,9 +2249,10 @@ static short snapMesh(SnapObjectContext *sctx, } } if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) { - if (sod->has_loose_vert && bvhtree[1] == NULL) { - bvhtree[1] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEVERTS, 2); - sod->has_loose_vert = bvhtree[1] != NULL; + if (sod->has_loose_vert && sod->bvhtree[1] == NULL) { + sod->bvhtree[1] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEVERTS, 2); + sod->has_loose_vert = sod->bvhtree[1] != NULL; + sod->cached[1] = dummy_treedata.cached; if (sod->has_loose_vert) { BLI_assert(treedata->vert_allocated == false); @@ -2226,7 +2270,7 @@ static short snapMesh(SnapObjectContext *sctx, if (treedata->vert_allocated == false) { treedata->vert = me->mvert; /* CustomData_get_layer(&me->vdata, CD_MVERT);? */ } - if (treedata->tree || bvhtree[0]) { + if (treedata->tree || sod->bvhtree[0]) { if (treedata->edge_allocated == false) { /* If raycast has been executed before, `treedata->edge` can be NULL. */ treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */ @@ -2263,9 +2307,9 @@ static short snapMesh(SnapObjectContext *sctx, mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]); } - if (bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) { + if (sod->bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) { /* snap to loose verts */ - BLI_bvhtree_find_nearest_projected(bvhtree[1], + BLI_bvhtree_find_nearest_projected(sod->bvhtree[1], lpmat, snapdata->win_size, snapdata->mval, @@ -2279,9 +2323,9 @@ static short snapMesh(SnapObjectContext *sctx, } if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { - if (bvhtree[0]) { + if (sod->bvhtree[0]) { /* snap to loose edges */ - BLI_bvhtree_find_nearest_projected(bvhtree[0], + BLI_bvhtree_find_nearest_projected(sod->bvhtree[0], lpmat, snapdata->win_size, snapdata->mval, @@ -2311,9 +2355,9 @@ static short snapMesh(SnapObjectContext *sctx, } else { BLI_assert(snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX); - if (bvhtree[0]) { - /* snap to loose edges */ - BLI_bvhtree_find_nearest_projected(bvhtree[0], + if (sod->bvhtree[0]) { + /* snap to loose edge verts */ + BLI_bvhtree_find_nearest_projected(sod->bvhtree[0], lpmat, snapdata->win_size, snapdata->mval, @@ -2325,7 +2369,7 @@ static short snapMesh(SnapObjectContext *sctx, } if (treedata->tree) { - /* snap to looptris */ + /* snap to looptri verts */ BLI_bvhtree_find_nearest_projected(treedata->tree, lpmat, snapdata->win_size, @@ -2388,17 +2432,12 @@ static short snapEditMesh(SnapObjectContext *sctx, } } - BVHTreeFromEditMesh *treedata_vert = NULL, *treedata_edge = NULL; - - BLI_assert(BKE_object_get_pre_modified_mesh(ob) == BKE_object_get_pre_modified_mesh(ob)); - UNUSED_VARS_NDEBUG(ob); - float lpmat[4][4]; mul_m4_m4m4(lpmat, snapdata->pmat, obmat); float dist_px_sq = SQUARE(*dist_px); - SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob, em); + SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob, em); /* Test BoundBox */ @@ -2411,19 +2450,16 @@ static short snapEditMesh(SnapObjectContext *sctx, BVHCache **em_bvh_cache = &((Mesh *)ob->data)->runtime.bvh_cache; if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) { - if (sod->bvh_trees[0] == NULL) { - sod->bvh_trees[0] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees)); - } - treedata_vert = sod->bvh_trees[0]; + BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[0]}; - if (sctx->callbacks.edit_mesh.test_vert_fn == NULL) { + if (treedata.tree && sod->cached[0]) { /* The tree is owned by the Mesh and may have been freed since we last used! */ - if (treedata_vert->tree && !bvhcache_has_tree(*em_bvh_cache, treedata_vert->tree)) { - free_bvhtree_from_editmesh(treedata_vert); + if (!bvhcache_has_tree(*em_bvh_cache, treedata.tree)) { + treedata.tree = sod->bvhtree[0] = NULL; } } - if (treedata_vert->tree == NULL) { + if (treedata.tree == NULL) { BLI_bitmap *verts_mask = NULL; int verts_num_active = -1; if (sctx->callbacks.edit_mesh.test_vert_fn) { @@ -2436,29 +2472,28 @@ static short snapEditMesh(SnapObjectContext *sctx, sctx->callbacks.edit_mesh.user_data); bvhtree_from_editmesh_verts_ex( - treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL); + &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL); MEM_freeN(verts_mask); } else { - BKE_bvhtree_from_editmesh_get(treedata_vert, em, 2, BVHTREE_FROM_EM_VERTS, em_bvh_cache); + BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_VERTS, em_bvh_cache); } + sod->bvhtree[0] = treedata.tree; + sod->cached[0] = treedata.cached; } } if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { - if (sod->bvh_trees[1] == NULL) { - sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees)); - } - treedata_edge = sod->bvh_trees[1]; + BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[1]}; - if (sctx->callbacks.edit_mesh.test_edge_fn == NULL) { + if (treedata.tree && sod->cached[1]) { /* The tree is owned by the Mesh and may have been freed since we last used! */ - if (treedata_edge->tree && !bvhcache_has_tree(*em_bvh_cache, treedata_edge->tree)) { - free_bvhtree_from_editmesh(treedata_edge); + if (!bvhcache_has_tree(*em_bvh_cache, treedata.tree)) { + treedata.tree = sod->bvhtree[1] = NULL; } } - if (treedata_edge->tree == NULL) { + if (treedata.tree == NULL) { BLI_bitmap *edges_mask = NULL; int edges_num_active = -1; if (sctx->callbacks.edit_mesh.test_edge_fn) { @@ -2471,12 +2506,14 @@ static short snapEditMesh(SnapObjectContext *sctx, sctx->callbacks.edit_mesh.user_data); bvhtree_from_editmesh_edges_ex( - treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL); + &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL); MEM_freeN(edges_mask); } else { - BKE_bvhtree_from_editmesh_get(treedata_edge, em, 2, BVHTREE_FROM_EM_EDGES, em_bvh_cache); + BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_EDGES, em_bvh_cache); } + sod->bvhtree[1] = treedata.tree; + sod->cached[1] = treedata.cached; } } @@ -2502,10 +2539,10 @@ static short snapEditMesh(SnapObjectContext *sctx, mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]); } - if (treedata_vert && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) { + if (sod->bvhtree[0] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) { BM_mesh_elem_table_ensure(em->bm, BM_VERT); BM_mesh_elem_index_ensure(em->bm, BM_VERT); - BLI_bvhtree_find_nearest_projected(treedata_vert->tree, + BLI_bvhtree_find_nearest_projected(sod->bvhtree[0], lpmat, snapdata->win_size, snapdata->mval, @@ -2516,12 +2553,12 @@ static short snapEditMesh(SnapObjectContext *sctx, &nearest2d); } - if (treedata_edge && (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE)) { + if (sod->bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE)) { int last_index = nearest.index; nearest.index = -1; BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT); BM_mesh_elem_index_ensure(em->bm, BM_EDGE | BM_VERT); - BLI_bvhtree_find_nearest_projected(treedata_edge->tree, + BLI_bvhtree_find_nearest_projected(sod->bvhtree[1], lpmat, snapdata->win_size, snapdata->mval, @@ -2588,7 +2625,10 @@ static short snapObject(SnapObjectContext *sctx, case OB_MESH: { Mesh *me = ob->data; if (BKE_object_is_in_editmode(ob)) { - BMEditMesh *em = BKE_editmesh_from_object(ob); + /* Strange, sometimes the `em` of the evaluated object has + * uninitialized memory. Need to be investigated. + * Use the `em` of the original object then. */ + BMEditMesh *em = BKE_editmesh_from_object(DEG_get_original_object(ob)); if (use_obedit) { retval = snapEditMesh( sctx, snapdata, ob, em, obmat, use_backface_culling, dist_px, r_loc, r_no, r_index); @@ -2615,11 +2655,12 @@ static short snapObject(SnapObjectContext *sctx, break; /* Use ATTR_FALLTHROUGH if we want to snap to the generated mesh. */ case OB_SURF: case OB_FONT: { - if (ob->runtime.mesh_eval) { + Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); + if (mesh_eval) { retval |= snapMesh(sctx, snapdata, ob, - ob->runtime.mesh_eval, + mesh_eval, obmat, use_backface_culling, dist_px, @@ -2794,24 +2835,8 @@ SnapObjectContext *ED_transform_snap_object_context_create_view3d(Main *bmain, static void snap_object_data_free(void *sod_v) { - switch (((SnapObjectData *)sod_v)->type) { - case SNAP_MESH: { - SnapObjectData_Mesh *sod = sod_v; - if (sod->treedata.tree) { - free_bvhtree_from_mesh(&sod->treedata); - } - break; - } - case SNAP_EDIT_MESH: { - SnapObjectData_EditMesh *sod = sod_v; - for (int i = 0; i < ARRAY_SIZE(sod->bvh_trees); i++) { - if (sod->bvh_trees[i]) { - free_bvhtree_from_editmesh(sod->bvh_trees[i]); - } - } - break; - } - } + SnapObjectData *sod = sod_v; + snap_object_data_clear(sod); } void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx) diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 43ccc1a8250..72376b977eb 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -238,15 +238,12 @@ bool ED_editors_flush_edits_for_object_ex(Main *bmain, /* Don't allow flushing while in the middle of a stroke (frees data in use). * Auto-save prevents this from happening but scripts * may cause a flush on saving: T53986. */ - if ((ob->sculpt && ob->sculpt->cache) == 0) { - - { - char *needs_flush_ptr = &ob->sculpt->needs_flush_to_id; - if (check_needs_flush && (*needs_flush_ptr == 0)) { - return false; - } - *needs_flush_ptr = 0; + if (!ELEM(NULL, ob->sculpt, ob->sculpt->cache)) { + char *needs_flush_ptr = &ob->sculpt->needs_flush_to_id; + if (check_needs_flush && (*needs_flush_ptr == 0)) { + return false; } + *needs_flush_ptr = 0; /* flush multires changes (for sculpt) */ multires_flush_sculpt_updates(ob); diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 800843dd851..37fe30bc96b 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -64,6 +64,7 @@ typedef enum eGPUType { GPU_VEC4 = 4, GPU_MAT3 = 9, GPU_MAT4 = 16, + GPU_MAX_CONSTANT_DATA = GPU_MAT4, /* Values not in GPU_DATATYPE_STR */ GPU_TEX1D_ARRAY = 1001, @@ -137,10 +138,12 @@ typedef enum eGPUMaterialStatus { GPU_MAT_SUCCESS, } eGPUMaterialStatus; -GPUNodeLink *GPU_attribute(CustomDataType type, const char *name); -GPUNodeLink *GPU_constant(float *num); -GPUNodeLink *GPU_uniform(float *num); -GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser); +GPUNodeLink *GPU_constant(const float *num); +GPUNodeLink *GPU_uniform(const float *num); +GPUNodeLink *GPU_attribute(GPUMaterial *mat, CustomDataType type, const char *name); +GPUNodeLink *GPU_image(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser); +GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser); +GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser); GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *layer); GPUNodeLink *GPU_builtin(eGPUBuiltin builtin); @@ -212,17 +215,19 @@ typedef struct GPUMaterialAttribute { struct GPUMaterialAttribute *next, *prev; int type; /* CustomDataType */ char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ + eGPUType gputype; int id; + int users; } GPUMaterialAttribute; typedef struct GPUMaterialTexture { struct GPUMaterialTexture *next, *prev; - eGPUType type; struct Image *ima; struct ImageUser *iuser; struct GPUTexture **colorband; - char shadername[32]; /* Name of sampler in GLSL. */ - int id; + char sampler_name[32]; /* Name of sampler in GLSL. */ + char tiled_mapping_name[32]; /* Name of tile mapping sampler in GLSL. */ + int users; } GPUMaterialTexture; ListBase GPU_material_attributes(GPUMaterial *material); diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 6c14d918816..553ecb65529 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -216,16 +216,6 @@ static void codegen_print_datatype(DynStr *ds, const eGPUType type, float *data) } } -static int codegen_input_has_texture(GPUInput *input) -{ - if (input->link) { - return 0; - } - else { - return (input->source == GPU_SOURCE_TEX); - } -} - static const char *gpu_builtin_name(eGPUBuiltin builtin) { if (builtin == GPU_VIEW_MATRIX) { @@ -299,14 +289,14 @@ static const char *gpu_builtin_name(eGPUBuiltin builtin) } } -static void codegen_set_unique_ids(ListBase *nodes) +static void codegen_set_unique_ids(GPUNodeGraph *graph) { GPUNode *node; GPUInput *input; GPUOutput *output; int id = 1; - for (node = nodes->first; node; node = node->next) { + for (node = graph->nodes.first; node; node = node->next) { for (input = node->inputs.first; input; input = input->next) { /* set id for unique names of uniform variables */ input->id = id++; @@ -322,7 +312,9 @@ static void codegen_set_unique_ids(ListBase *nodes) /** * It will create an UBO for GPUMaterial if there is any GPU_DYNAMIC_UBO. */ -static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds, ListBase *nodes) +static int codegen_process_uniforms_functions(GPUMaterial *material, + DynStr *ds, + GPUNodeGraph *graph) { GPUNode *node; GPUInput *input; @@ -330,27 +322,29 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds, int builtins = 0; ListBase ubo_inputs = {NULL, NULL}; - /* print uniforms */ - for (node = nodes->first; node; node = node->next) { + /* Attributes */ + for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) { + BLI_dynstr_appendf(ds, "in %s var%d;\n", gpu_data_type_to_string(attr->gputype), attr->id); + } + + /* Textures */ + for (GPUMaterialTexture *tex = graph->textures.first; tex; tex = tex->next) { + if (tex->colorband) { + BLI_dynstr_appendf(ds, "uniform sampler1DArray %s;\n", tex->sampler_name); + } + else if (tex->tiled_mapping_name[0]) { + BLI_dynstr_appendf(ds, "uniform sampler2DArray %s;\n", tex->sampler_name); + BLI_dynstr_appendf(ds, "uniform sampler1DArray %s;\n", tex->tiled_mapping_name); + } + else { + BLI_dynstr_appendf(ds, "uniform sampler2D %s;\n", tex->sampler_name); + } + } + + /* Print other uniforms */ + for (node = graph->nodes.first; node; node = node->next) { for (input = node->inputs.first; input; input = input->next) { - if (input->source == GPU_SOURCE_TEX) { - /* create exactly one sampler for each texture */ - if (codegen_input_has_texture(input) && input->bindtex) { - const char *type; - if (input->colorband || input->type == GPU_TEX1D_ARRAY) { - type = "sampler1DArray"; - } - else if (input->type == GPU_TEX2D_ARRAY) { - type = "sampler2DArray"; - } - else { - BLI_assert(input->type == GPU_TEX2D); - type = "sampler2D"; - } - BLI_dynstr_appendf(ds, "uniform %s samp%d;\n", type, input->texid); - } - } - else if (input->source == GPU_SOURCE_BUILTIN) { + if (input->source == GPU_SOURCE_BUILTIN) { /* only define each builtin uniform/varying once */ if (!(builtins & input->builtin)) { builtins |= input->builtin; @@ -385,10 +379,6 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds, codegen_print_datatype(ds, input->type, input->vec); BLI_dynstr_append(ds, ";\n"); } - else if (input->source == GPU_SOURCE_ATTR && input->attr_first) { - BLI_dynstr_appendf( - ds, "in %s var%d;\n", gpu_data_type_to_string(input->type), input->attr_id); - } } } @@ -412,12 +402,12 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds, return builtins; } -static void codegen_declare_tmps(DynStr *ds, ListBase *nodes) +static void codegen_declare_tmps(DynStr *ds, GPUNodeGraph *graph) { GPUNode *node; GPUOutput *output; - for (node = nodes->first; node; node = node->next) { + for (node = graph->nodes.first; node; node = node->next) { /* declare temporary variables for node output storage */ for (output = node->outputs.first; output; output = output->next) { if (output->type == GPU_CLOSURE) { @@ -432,18 +422,21 @@ static void codegen_declare_tmps(DynStr *ds, ListBase *nodes) BLI_dynstr_append(ds, "\n"); } -static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput) +static void codegen_call_functions(DynStr *ds, GPUNodeGraph *graph, GPUOutput *finaloutput) { GPUNode *node; GPUInput *input; GPUOutput *output; - for (node = nodes->first; node; node = node->next) { + for (node = graph->nodes.first; node; node = node->next) { BLI_dynstr_appendf(ds, "\t%s(", node->name); for (input = node->inputs.first; input; input = input->next) { if (input->source == GPU_SOURCE_TEX) { - BLI_dynstr_appendf(ds, "samp%d", input->texid); + BLI_dynstr_append(ds, input->texture->sampler_name); + } + else if (input->source == GPU_SOURCE_TEX_TILED_MAPPING) { + BLI_dynstr_append(ds, input->texture->tiled_mapping_name); } else if (input->source == GPU_SOURCE_OUTPUT) { codegen_convert_datatype( @@ -507,7 +500,7 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final BLI_dynstr_appendf(ds, "cons%d", input->id); } else if (input->source == GPU_SOURCE_ATTR) { - BLI_dynstr_appendf(ds, "var%d", input->attr_id); + BLI_dynstr_appendf(ds, "var%d", input->attr->id); } BLI_dynstr_append(ds, ", "); @@ -527,7 +520,7 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final BLI_dynstr_append(ds, ";\n"); } -static char *code_generate_fragment(GPUMaterial *material, ListBase *nodes, GPUOutput *output) +static char *code_generate_fragment(GPUMaterial *material, GPUNodeGraph *graph) { DynStr *ds = BLI_dynstr_new(); char *code; @@ -537,8 +530,8 @@ static char *code_generate_fragment(GPUMaterial *material, ListBase *nodes, GPUO BLI_dynstr_append(ds, FUNCTION_PROTOTYPES); #endif - codegen_set_unique_ids(nodes); - builtins = codegen_process_uniforms_functions(material, ds, nodes); + codegen_set_unique_ids(graph); + builtins = codegen_process_uniforms_functions(material, ds, graph); if (builtins & (GPU_OBJECT_INFO | GPU_OBJECT_COLOR)) { BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl); @@ -614,8 +607,8 @@ static char *code_generate_fragment(GPUMaterial *material, ListBase *nodes, GPUO BLI_dynstr_append(ds, "\t#define viewposition viewPosition\n"); } - codegen_declare_tmps(ds, nodes); - codegen_call_functions(ds, nodes, output); + codegen_declare_tmps(ds, graph); + codegen_call_functions(ds, graph, graph->outlink->output); BLI_dynstr_append(ds, "}\n"); @@ -666,7 +659,7 @@ static const char *attr_prefix_get(CustomDataType type) } } -static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool use_geom) +static char *code_generate_vertex(GPUNodeGraph *graph, const char *vert_code, bool use_geom) { DynStr *ds = BLI_dynstr_new(); GPUNode *node; @@ -682,48 +675,44 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u "#define DEFINE_ATTR(type, attr) in type attr\n" "#endif\n"); - for (node = nodes->first; node; node = node->next) { + for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) { + /* XXX FIXME : see notes in mesh_render_data_create() */ + /* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */ + if (attr->type == CD_ORCO) { + /* OPTI : orco is computed from local positions, but only if no modifier is present. */ + BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl); + BLI_dynstr_append(ds, "DEFINE_ATTR(vec4, orco);\n"); + } + else if (attr->name[0] == '\0') { + BLI_dynstr_appendf(ds, + "DEFINE_ATTR(%s, %s);\n", + gpu_data_type_to_string(attr->gputype), + attr_prefix_get(attr->type)); + BLI_dynstr_appendf(ds, "#define att%d %s\n", attr->id, attr_prefix_get(attr->type)); + } + else { + char attr_safe_name[GPU_MAX_SAFE_ATTRIB_NAME]; + GPU_vertformat_safe_attrib_name(attr->name, attr_safe_name, GPU_MAX_SAFE_ATTRIB_NAME); + BLI_dynstr_appendf(ds, + "DEFINE_ATTR(%s, %s%s);\n", + gpu_data_type_to_string(attr->gputype), + attr_prefix_get(attr->type), + attr_safe_name); + BLI_dynstr_appendf( + ds, "#define att%d %s%s\n", attr->id, attr_prefix_get(attr->type), attr_safe_name); + } + BLI_dynstr_appendf(ds, + "out %s var%d%s;\n", + gpu_data_type_to_string(attr->gputype), + attr->id, + use_geom ? "g" : ""); + } + + for (node = graph->nodes.first; node; node = node->next) { for (input = node->inputs.first; input; input = input->next) { if (input->source == GPU_SOURCE_BUILTIN) { builtins |= input->builtin; } - if (input->source == GPU_SOURCE_ATTR && input->attr_first) { - /* XXX FIXME : see notes in mesh_render_data_create() */ - /* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */ - if (input->attr_type == CD_ORCO) { - /* OPTI : orco is computed from local positions, but only if no modifier is present. */ - BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl); - BLI_dynstr_append(ds, "DEFINE_ATTR(vec4, orco);\n"); - } - else if (input->attr_name[0] == '\0') { - BLI_dynstr_appendf(ds, - "DEFINE_ATTR(%s, %s);\n", - gpu_data_type_to_string(input->type), - attr_prefix_get(input->attr_type)); - BLI_dynstr_appendf( - ds, "#define att%d %s\n", input->attr_id, attr_prefix_get(input->attr_type)); - } - else { - char attr_safe_name[GPU_MAX_SAFE_ATTRIB_NAME]; - GPU_vertformat_safe_attrib_name( - input->attr_name, attr_safe_name, GPU_MAX_SAFE_ATTRIB_NAME); - BLI_dynstr_appendf(ds, - "DEFINE_ATTR(%s, %s%s);\n", - gpu_data_type_to_string(input->type), - attr_prefix_get(input->attr_type), - attr_safe_name); - BLI_dynstr_appendf(ds, - "#define att%d %s%s\n", - input->attr_id, - attr_prefix_get(input->attr_type), - attr_safe_name); - } - BLI_dynstr_appendf(ds, - "out %s var%d%s;\n", - gpu_data_type_to_string(input->type), - input->attr_id, - use_geom ? "g" : ""); - } } } @@ -800,30 +789,26 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u BLI_dynstr_append(ds, "\tbarycentricPosg = position;\n"); } - for (node = nodes->first; node; node = node->next) { - for (input = node->inputs.first; input; input = input->next) { - if (input->source == GPU_SOURCE_ATTR && input->attr_first) { - if (input->attr_type == CD_TANGENT) { - /* Not supported by hairs */ - BLI_dynstr_appendf(ds, "\tvar%d%s = vec4(0.0);\n", input->attr_id, use_geom ? "g" : ""); - } - else if (input->attr_type == CD_ORCO) { - BLI_dynstr_appendf(ds, - "\tvar%d%s = OrcoTexCoFactors[0].xyz + (ModelMatrixInverse * " - "vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1].xyz;\n", - input->attr_id, - use_geom ? "g" : ""); - /* TODO: fix ORCO with modifiers. */ - } - else { - BLI_dynstr_appendf(ds, - "\tvar%d%s = hair_get_customdata_%s(att%d);\n", - input->attr_id, - use_geom ? "g" : "", - gpu_data_type_to_string(input->type), - input->attr_id); - } - } + for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) { + if (attr->type == CD_TANGENT) { + /* Not supported by hairs */ + BLI_dynstr_appendf(ds, "\tvar%d%s = vec4(0.0);\n", attr->id, use_geom ? "g" : ""); + } + else if (attr->type == CD_ORCO) { + BLI_dynstr_appendf(ds, + "\tvar%d%s = OrcoTexCoFactors[0].xyz + (ModelMatrixInverse * " + "vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1].xyz;\n", + attr->id, + use_geom ? "g" : ""); + /* TODO: fix ORCO with modifiers. */ + } + else { + BLI_dynstr_appendf(ds, + "\tvar%d%s = hair_get_customdata_%s(att%d);\n", + attr->id, + use_geom ? "g" : "", + gpu_data_type_to_string(attr->gputype), + attr->id); } } @@ -837,49 +822,43 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u BLI_dynstr_append(ds, "\tbarycentricPosg = (ModelMatrix * vec4(position, 1.0)).xyz;\n"); } - for (node = nodes->first; node; node = node->next) { - for (input = node->inputs.first; input; input = input->next) { - if (input->source == GPU_SOURCE_ATTR && input->attr_first) { - if (input->attr_type == CD_TANGENT) { /* silly exception */ - BLI_dynstr_appendf(ds, - "\tvar%d%s.xyz = transpose(mat3(ModelMatrixInverse)) * att%d.xyz;\n", - input->attr_id, - use_geom ? "g" : "", - input->attr_id); - BLI_dynstr_appendf( - ds, "\tvar%d%s.w = att%d.w;\n", input->attr_id, use_geom ? "g" : "", input->attr_id); - /* Normalize only if vector is not null. */ - BLI_dynstr_appendf(ds, - "\tfloat lvar%d = dot(var%d%s.xyz, var%d%s.xyz);\n", - input->attr_id, - input->attr_id, - use_geom ? "g" : "", - input->attr_id, - use_geom ? "g" : ""); - BLI_dynstr_appendf(ds, - "\tvar%d%s.xyz *= (lvar%d > 0.0) ? inversesqrt(lvar%d) : 1.0;\n", - input->attr_id, - use_geom ? "g" : "", - input->attr_id, - input->attr_id); - } - else if (input->attr_type == CD_ORCO) { - BLI_dynstr_appendf(ds, - "\tvar%d%s = OrcoTexCoFactors[0].xyz + position *" - " OrcoTexCoFactors[1].xyz;\n", - input->attr_id, - use_geom ? "g" : ""); - /* See mesh_create_loop_orco() for explanation. */ - BLI_dynstr_appendf(ds, - "\tif (orco.w == 0.0) { var%d%s = orco.xyz * 0.5 + 0.5; }\n", - input->attr_id, - use_geom ? "g" : ""); - } - else { - BLI_dynstr_appendf( - ds, "\tvar%d%s = att%d;\n", input->attr_id, use_geom ? "g" : "", input->attr_id); - } - } + for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) { + if (attr->type == CD_TANGENT) { /* silly exception */ + BLI_dynstr_appendf(ds, + "\tvar%d%s.xyz = transpose(mat3(ModelMatrixInverse)) * att%d.xyz;\n", + attr->id, + use_geom ? "g" : "", + attr->id); + BLI_dynstr_appendf(ds, "\tvar%d%s.w = att%d.w;\n", attr->id, use_geom ? "g" : "", attr->id); + /* Normalize only if vector is not null. */ + BLI_dynstr_appendf(ds, + "\tfloat lvar%d = dot(var%d%s.xyz, var%d%s.xyz);\n", + attr->id, + attr->id, + use_geom ? "g" : "", + attr->id, + use_geom ? "g" : ""); + BLI_dynstr_appendf(ds, + "\tvar%d%s.xyz *= (lvar%d > 0.0) ? inversesqrt(lvar%d) : 1.0;\n", + attr->id, + use_geom ? "g" : "", + attr->id, + attr->id); + } + else if (attr->type == CD_ORCO) { + BLI_dynstr_appendf(ds, + "\tvar%d%s = OrcoTexCoFactors[0].xyz + position *" + " OrcoTexCoFactors[1].xyz;\n", + attr->id, + use_geom ? "g" : ""); + /* See mesh_create_loop_orco() for explanation. */ + BLI_dynstr_appendf(ds, + "\tif (orco.w == 0.0) { var%d%s = orco.xyz * 0.5 + 0.5; }\n", + attr->id, + use_geom ? "g" : ""); + } + else { + BLI_dynstr_appendf(ds, "\tvar%d%s = att%d;\n", attr->id, use_geom ? "g" : "", attr->id); } } BLI_dynstr_append(ds, "#endif /* HAIR_SHADER */\n"); @@ -899,7 +878,9 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u return code; } -static char *code_generate_geometry(ListBase *nodes, const char *geom_code, const char *defines) +static char *code_generate_geometry(GPUNodeGraph *graph, + const char *geom_code, + const char *defines) { DynStr *ds = BLI_dynstr_new(); GPUNode *node; @@ -916,20 +897,19 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons BLI_dynstr_append(ds, "#define USE_ATTR\n"); /* Generate varying declarations. */ - for (node = nodes->first; node; node = node->next) { + for (node = graph->nodes.first; node; node = node->next) { for (input = node->inputs.first; input; input = input->next) { if (input->source == GPU_SOURCE_BUILTIN) { builtins |= input->builtin; } - if (input->source == GPU_SOURCE_ATTR && input->attr_first) { - BLI_dynstr_appendf( - ds, "in %s var%dg[];\n", gpu_data_type_to_string(input->type), input->attr_id); - BLI_dynstr_appendf( - ds, "out %s var%d;\n", gpu_data_type_to_string(input->type), input->attr_id); - } } } + for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) { + BLI_dynstr_appendf(ds, "in %s var%dg[];\n", gpu_data_type_to_string(attr->gputype), attr->id); + BLI_dynstr_appendf(ds, "out %s var%d;\n", gpu_data_type_to_string(attr->gputype), attr->id); + } + if (builtins & GPU_BARYCENTRIC_TEXCO) { BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n"); BLI_dynstr_append(ds, "in vec2 barycentricTexCog[];\n"); @@ -1032,13 +1012,9 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons BLI_dynstr_append(ds, "#endif\n"); } - for (node = nodes->first; node; node = node->next) { - for (input = node->inputs.first; input; input = input->next) { - if (input->source == GPU_SOURCE_ATTR && input->attr_first) { - /* TODO let shader choose what to do depending on what the attribute is. */ - BLI_dynstr_appendf(ds, "\tvar%d = var%dg[vert];\n", input->attr_id, input->attr_id); - } - } + for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) { + /* TODO let shader choose what to do depending on what the attribute is. */ + BLI_dynstr_appendf(ds, "\tvar%d = var%dg[vert];\n", attr->id, attr->id); } BLI_dynstr_append(ds, "}\n"); @@ -1053,94 +1029,6 @@ GPUShader *GPU_pass_shader_get(GPUPass *pass) return pass->shader; } -/* Requested Attributes */ - -static ListBase gpu_nodes_requested_attributes(ListBase *nodes) -{ - ListBase attributes = {NULL}; - int num_attributes = 0; - - /* Convert attributes requested by node inputs to list, checking for - * checking for duplicates and assigning id's starting from zero. */ - for (GPUNode *node = nodes->first; node; node = node->next) { - for (GPUInput *input = node->inputs.first; input; input = input->next) { - if (input->source != GPU_SOURCE_ATTR) { - continue; - } - - GPUMaterialAttribute *attr = attributes.first; - for (; attr; attr = attr->next) { - if (attr->type == input->attr_type && STREQ(attr->name, input->attr_name)) { - break; - } - } - - /* Add new requested attribute if it's within GPU limits. */ - if (attr == NULL && num_attributes < GPU_MAX_ATTR) { - attr = MEM_callocN(sizeof(*attr), __func__); - attr->type = input->attr_type; - STRNCPY(attr->name, input->attr_name); - attr->id = num_attributes++; - BLI_addtail(&attributes, attr); - - input->attr_id = attr->id; - input->attr_first = true; - } - else if (attr != NULL) { - input->attr_id = attr->id; - } - } - } - - return attributes; -} - -/* Requested Textures */ - -static ListBase gpu_nodes_requested_textures(ListBase *nodes) -{ - ListBase textures = {NULL}; - int num_textures = 0; - - /* Convert textures requested by node inputs to list, checking for - * checking for duplicates and assigning id's starting from zero. */ - for (GPUNode *node = nodes->first; node; node = node->next) { - for (GPUInput *input = node->inputs.first; input; input = input->next) { - if (!codegen_input_has_texture(input)) { - continue; - } - - GPUMaterialTexture *tex = textures.first; - for (; tex; tex = tex->next) { - if (tex->ima == input->ima && tex->colorband == input->colorband && - tex->type == input->type) { - break; - } - } - - if (tex == NULL) { - tex = MEM_callocN(sizeof(*tex), __func__); - tex->ima = input->ima; - tex->iuser = input->iuser; - tex->colorband = input->colorband; - tex->id = num_textures++; - tex->type = input->type; - BLI_snprintf(tex->shadername, sizeof(tex->shadername), "samp%d", tex->id); - BLI_addtail(&textures, tex); - - input->texid = tex->id; - input->bindtex = true; - } - else { - input->texid = tex->id; - input->bindtex = false; - } - } - } - - return textures; -} - /* Pass create/free */ static bool gpu_pass_is_valid(GPUPass *pass) @@ -1160,11 +1048,8 @@ GPUPass *GPU_generate_pass(GPUMaterial *material, * generated VBOs are ready to accept the future shader. */ gpu_node_graph_prune_unused(graph); - graph->attributes = gpu_nodes_requested_attributes(&graph->nodes); - graph->textures = gpu_nodes_requested_textures(&graph->nodes); - /* generate code */ - char *fragmentgen = code_generate_fragment(material, &graph->nodes, graph->outlink->output); + char *fragmentgen = code_generate_fragment(material, graph); /* Cache lookup: Reuse shaders already compiled */ uint32_t hash = gpu_pass_hash(fragmentgen, defines, &graph->attributes); @@ -1186,8 +1071,8 @@ GPUPass *GPU_generate_pass(GPUMaterial *material, GSet *used_libraries = gpu_material_used_libraries(material); char *tmp = gpu_material_library_generate_code(used_libraries, frag_lib); - char *geometrycode = code_generate_geometry(&graph->nodes, geom_code, defines); - char *vertexcode = code_generate_vertex(&graph->nodes, vert_code, (geometrycode != NULL)); + char *geometrycode = code_generate_geometry(graph, geom_code, defines); + char *vertexcode = code_generate_vertex(graph, vert_code, (geometrycode != NULL)); char *fragmentcode = BLI_strdupcat(tmp, fragmentgen); MEM_freeN(fragmentgen); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 62a5de7ebe6..d674f8600c2 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -1077,7 +1077,8 @@ void GPU_create_gl_tex(uint *bind, glGenTextures(1, (GLuint *)bind); glBindTexture(textarget, *bind); - GLenum float_format = (!half_float && ima->flag & IMA_HIGH_BITDEPTH) ? GL_RGBA32F : GL_RGBA16F; + GLenum float_format = (!half_float && (ima && (ima->flag & IMA_HIGH_BITDEPTH))) ? GL_RGBA32F : + GL_RGBA16F; GLenum internal_format = (frect) ? float_format : (use_srgb) ? GL_SRGB8_ALPHA8 : GL_RGBA8; if (textarget == GL_TEXTURE_2D) { diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index d8d3e5a2ff2..b2658839d67 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -207,11 +207,6 @@ GPUPass *GPU_material_get_pass(GPUMaterial *material) return material->pass; } -ListBase *GPU_material_get_inputs(GPUMaterial *material) -{ - return &material->graph.inputs; -} - /* Return can be NULL if it's a world material. */ Material *GPU_material_get_material(GPUMaterial *material) { @@ -579,9 +574,9 @@ void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link) } } -void gpu_material_add_node(GPUMaterial *material, GPUNode *node) +GPUNodeGraph *gpu_material_node_graph(GPUMaterial *material) { - BLI_addtail(&material->graph.nodes, node); + return &material->graph; } GSet *gpu_material_used_libraries(GPUMaterial *material) diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c index b271ac48f75..de35b43109f 100644 --- a/source/blender/gpu/intern/gpu_node_graph.c +++ b/source/blender/gpu/intern/gpu_node_graph.c @@ -109,20 +109,20 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType input->link = link; link->users++; break; + case GPU_NODE_LINK_IMAGE: + case GPU_NODE_LINK_IMAGE_TILED: case GPU_NODE_LINK_COLORBAND: input->source = GPU_SOURCE_TEX; - input->colorband = link->colorband; + input->texture = link->texture; break; - case GPU_NODE_LINK_IMAGE_BLENDER: - case GPU_NODE_LINK_IMAGE_TILEMAP: - input->source = GPU_SOURCE_TEX; - input->ima = link->ima; - input->iuser = link->iuser; + case GPU_NODE_LINK_IMAGE_TILED_MAPPING: + input->source = GPU_SOURCE_TEX_TILED_MAPPING; + input->texture = link->texture; break; case GPU_NODE_LINK_ATTR: input->source = GPU_SOURCE_ATTR; - input->attr_type = link->attr_type; - BLI_strncpy(input->attr_name, link->attr_name, sizeof(input->attr_name)); + input->attr = link->attr; + input->attr->gputype = type; break; case GPU_NODE_LINK_CONSTANT: input->source = (type == GPU_CLOSURE) ? GPU_SOURCE_STRUCT : GPU_SOURCE_CONSTANT; @@ -249,24 +249,97 @@ static void gpu_node_output(GPUNode *node, const eGPUType type, GPUNodeLink **li BLI_addtail(&node->outputs, output); } -/* Creating Inputs */ +/* Attributes and Textures */ -GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name) +static GPUMaterialAttribute *gpu_node_graph_add_attribute(GPUNodeGraph *graph, + CustomDataType type, + const char *name) { - GPUNodeLink *link = gpu_node_link_create(); - link->link_type = GPU_NODE_LINK_ATTR; - link->attr_name = name; /* Fall back to the UV layer, which matches old behavior. */ if (type == CD_AUTO_FROM_NAME && name[0] == '\0') { - link->attr_type = CD_MTFACE; + type = CD_MTFACE; } - else { - link->attr_type = type; + + /* Find existing attribute. */ + int num_attributes = 0; + GPUMaterialAttribute *attr = graph->attributes.first; + for (; attr; attr = attr->next) { + if (attr->type == type && STREQ(attr->name, name)) { + break; + } + num_attributes++; + } + + /* Add new requested attribute if it's within GPU limits. */ + if (attr == NULL && num_attributes < GPU_MAX_ATTR) { + attr = MEM_callocN(sizeof(*attr), __func__); + attr->type = type; + STRNCPY(attr->name, name); + attr->id = num_attributes; + BLI_addtail(&graph->attributes, attr); + } + + if (attr != NULL) { + attr->users++; + } + + return attr; +} + +static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph, + Image *ima, + ImageUser *iuser, + struct GPUTexture **colorband, + GPUNodeLinkType link_type) +{ + /* Find existing texture. */ + int num_textures = 0; + GPUMaterialTexture *tex = graph->textures.first; + for (; tex; tex = tex->next) { + if (tex->ima == ima && tex->colorband == colorband) { + break; + } + num_textures++; } + + /* Add new requested texture. */ + if (tex == NULL) { + tex = MEM_callocN(sizeof(*tex), __func__); + tex->ima = ima; + tex->iuser = iuser; + tex->colorband = colorband; + BLI_snprintf(tex->sampler_name, sizeof(tex->sampler_name), "samp%d", num_textures); + if (ELEM(link_type, GPU_NODE_LINK_IMAGE_TILED, GPU_NODE_LINK_IMAGE_TILED_MAPPING)) { + BLI_snprintf( + tex->tiled_mapping_name, sizeof(tex->tiled_mapping_name), "tsamp%d", num_textures); + } + BLI_addtail(&graph->textures, tex); + } + + tex->users++; + + return tex; +} + +/* Creating Inputs */ + +GPUNodeLink *GPU_attribute(GPUMaterial *mat, const CustomDataType type, const char *name) +{ + GPUNodeGraph *graph = gpu_material_node_graph(mat); + GPUMaterialAttribute *attr = gpu_node_graph_add_attribute(graph, type, name); + + if (attr == NULL) { + static const float zero_data[GPU_MAX_CONSTANT_DATA] = {0.0f}; + return GPU_constant(zero_data); + } + + GPUNodeLink *link = gpu_node_link_create(); + link->link_type = GPU_NODE_LINK_ATTR; + link->attr = attr; return link; } -GPUNodeLink *GPU_constant(float *num) +GPUNodeLink *GPU_constant(const float *num) { GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_CONSTANT; @@ -274,7 +347,7 @@ GPUNodeLink *GPU_constant(float *num) return link; } -GPUNodeLink *GPU_uniform(float *num) +GPUNodeLink *GPU_uniform(const float *num) { GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_UNIFORM; @@ -282,21 +355,42 @@ GPUNodeLink *GPU_uniform(float *num) return link; } -GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser) +GPUNodeLink *GPU_image(GPUMaterial *mat, Image *ima, ImageUser *iuser) { + GPUNodeGraph *graph = gpu_material_node_graph(mat); GPUNodeLink *link = gpu_node_link_create(); - link->link_type = GPU_NODE_LINK_IMAGE_BLENDER; - link->ima = ima; - link->iuser = iuser; + link->link_type = GPU_NODE_LINK_IMAGE; + link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type); + return link; +} + +GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, Image *ima, ImageUser *iuser) +{ + GPUNodeGraph *graph = gpu_material_node_graph(mat); + GPUNodeLink *link = gpu_node_link_create(); + link->link_type = GPU_NODE_LINK_IMAGE_TILED; + link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type); + return link; +} + +GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, Image *ima, ImageUser *iuser) +{ + GPUNodeGraph *graph = gpu_material_node_graph(mat); + GPUNodeLink *link = gpu_node_link_create(); + link->link_type = GPU_NODE_LINK_IMAGE_TILED_MAPPING; + link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type); return link; } GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *row) { + struct GPUTexture **colorband = gpu_material_ramp_texture_row_set(mat, size, pixels, row); + MEM_freeN(pixels); + + GPUNodeGraph *graph = gpu_material_node_graph(mat); GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_COLORBAND; - link->colorband = gpu_material_ramp_texture_row_set(mat, size, pixels, row); - MEM_freeN(pixels); + link->texture = gpu_node_graph_add_texture(graph, NULL, NULL, colorband, link->link_type); return link; } @@ -340,7 +434,8 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...) } va_end(params); - gpu_material_add_node(mat, node); + GPUNodeGraph *graph = gpu_material_node_graph(mat); + BLI_addtail(&graph->nodes, node); return true; } @@ -415,7 +510,8 @@ bool GPU_stack_link(GPUMaterial *material, } va_end(params); - gpu_material_add_node(material, node); + GPUNodeGraph *graph = gpu_material_node_graph(material); + BLI_addtail(&graph->nodes, node); return true; } @@ -435,6 +531,13 @@ static void gpu_inputs_free(ListBase *inputs) GPUInput *input; for (input = inputs->first; input; input = input->next) { + if (input->source == GPU_SOURCE_ATTR) { + input->attr->users--; + } + else if (ELEM(input->source, GPU_SOURCE_TEX, GPU_SOURCE_TEX_TILED_MAPPING)) { + input->texture->users--; + } + if (input->link) { gpu_node_link_free(input->link); } @@ -469,7 +572,6 @@ void gpu_node_graph_free_nodes(GPUNodeGraph *graph) gpu_node_free(node); } - gpu_inputs_free(&graph->inputs); graph->outlink = NULL; } @@ -477,8 +579,8 @@ void gpu_node_graph_free_nodes(GPUNodeGraph *graph) void gpu_node_graph_free(GPUNodeGraph *graph) { gpu_node_graph_free_nodes(graph); - BLI_freelistN(&graph->attributes); BLI_freelistN(&graph->textures); + BLI_freelistN(&graph->attributes); } /* Prune Unused Nodes */ @@ -507,15 +609,13 @@ static void gpu_nodes_tag(GPUNodeLink *link) void gpu_node_graph_prune_unused(GPUNodeGraph *graph) { - GPUNode *node, *next; - - for (node = graph->nodes.first; node; node = node->next) { + for (GPUNode *node = graph->nodes.first; node; node = node->next) { node->tag = false; } gpu_nodes_tag(graph->outlink); - for (node = graph->nodes.first; node; node = next) { + for (GPUNode *node = graph->nodes.first, *next = NULL; node; node = next) { next = node->next; if (!node->tag) { @@ -523,4 +623,18 @@ void gpu_node_graph_prune_unused(GPUNodeGraph *graph) gpu_node_free(node); } } + + for (GPUMaterialAttribute *attr = graph->attributes.first, *next = NULL; attr; attr = next) { + next = attr->next; + if (attr->users == 0) { + BLI_freelinkN(&graph->attributes, attr); + } + } + + for (GPUMaterialTexture *tex = graph->textures.first, *next = NULL; tex; tex = next) { + next = tex->next; + if (tex->users == 0) { + BLI_freelinkN(&graph->textures, tex); + } + } } diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h index 2ffde8dba39..9214bd7f1ba 100644 --- a/source/blender/gpu/intern/gpu_node_graph.h +++ b/source/blender/gpu/intern/gpu_node_graph.h @@ -19,6 +19,8 @@ /** \file * \ingroup gpu + * + * Intermediate node graph for generating GLSL shaders. */ #ifndef __GPU_NODE_GRAPH_H__ @@ -45,6 +47,7 @@ typedef enum eGPUDataSource { GPU_SOURCE_BUILTIN, GPU_SOURCE_STRUCT, GPU_SOURCE_TEX, + GPU_SOURCE_TEX_TILED_MAPPING, } eGPUDataSource; typedef enum { @@ -53,8 +56,9 @@ typedef enum { GPU_NODE_LINK_BUILTIN, GPU_NODE_LINK_COLORBAND, GPU_NODE_LINK_CONSTANT, - GPU_NODE_LINK_IMAGE_BLENDER, - GPU_NODE_LINK_IMAGE_TILEMAP, + GPU_NODE_LINK_IMAGE, + GPU_NODE_LINK_IMAGE_TILED, + GPU_NODE_LINK_IMAGE_TILED_MAPPING, GPU_NODE_LINK_OUTPUT, GPU_NODE_LINK_UNIFORM, } GPUNodeLinkType; @@ -79,7 +83,7 @@ struct GPUNodeLink { union { /* GPU_NODE_LINK_CONSTANT | GPU_NODE_LINK_UNIFORM */ - float *data; + const float *data; /* GPU_NODE_LINK_BUILTIN */ eGPUBuiltin builtin; /* GPU_NODE_LINK_COLORBAND */ @@ -87,15 +91,9 @@ struct GPUNodeLink { /* GPU_NODE_LINK_OUTPUT */ struct GPUOutput *output; /* GPU_NODE_LINK_ATTR */ - struct { - const char *attr_name; - CustomDataType attr_type; - }; - /* GPU_NODE_LINK_IMAGE_BLENDER | GPU_NODE_LINK_IMAGE_TILEMAP */ - struct { - struct Image *ima; - struct ImageUser *iuser; - }; + struct GPUMaterialAttribute *attr; + /* GPU_NODE_LINK_IMAGE_BLENDER */ + struct GPUMaterialTexture *texture; }; }; @@ -118,35 +116,16 @@ typedef struct GPUInput { eGPUDataSource source; /* data source */ - int shaderloc; /* id from opengl */ - char shadername[32]; /* name in shader */ - /* Content based on eGPUDataSource */ union { /* GPU_SOURCE_CONSTANT | GPU_SOURCE_UNIFORM */ float vec[16]; /* vector data */ /* GPU_SOURCE_BUILTIN */ eGPUBuiltin builtin; /* builtin uniform */ - /* GPU_SOURCE_TEX */ - struct { - struct GPUTexture **colorband; /* input texture, only set at runtime */ - struct Image *ima; /* image */ - struct ImageUser *iuser; /* image user */ - bool bindtex; /* input is responsible for binding the texture? */ - int texid; /* number for multitexture, starting from zero */ - eGPUType textype; /* texture type (2D, 1D Array ...) */ - }; + /* GPU_SOURCE_TEX | GPU_SOURCE_TEX_TILED_MAPPING */ + struct GPUMaterialTexture *texture; /* GPU_SOURCE_ATTR */ - struct { - /** Attribute name. */ - char attr_name[MAX_CUSTOMDATA_LAYER_NAME]; - /** ID for vertex attributes. */ - int attr_id; - /** This is the first one that is bound. */ - bool attr_first; - /** Attribute type. */ - CustomDataType attr_type; - }; + struct GPUMaterialAttribute *attr; }; } GPUInput; @@ -154,8 +133,7 @@ typedef struct GPUNodeGraph { /* Nodes */ ListBase nodes; - /* Inputs and output. */ - ListBase inputs; + /* Output. */ GPUNodeLink *outlink; /* Requested attributes and textures. */ @@ -171,7 +149,7 @@ void gpu_node_graph_free(GPUNodeGraph *graph); /* Material calls */ -void gpu_material_add_node(struct GPUMaterial *material, struct GPUNode *node); +struct GPUNodeGraph *gpu_material_node_graph(struct GPUMaterial *material); struct GPUTexture **gpu_material_ramp_texture_row_set(struct GPUMaterial *mat, int size, float *pixels, diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 6caa0ac5a74..670a6c46187 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -1096,6 +1096,8 @@ typedef enum eChildOf_Flags { CHILDOF_SIZEY = (1 << 7), CHILDOF_SIZEZ = (1 << 8), CHILDOF_ALL = 511, + /* Temporary flag used by the Set Inverse operator. */ + CHILDOF_SET_INVERSE = (1 << 9), } eChildOf_Flags; /* Pivot Constraint */ @@ -1147,6 +1149,8 @@ typedef enum eCameraSolver_Flags { /* ObjectSolver Constraint -> flag */ typedef enum eObjectSolver_Flags { OBJECTSOLVER_ACTIVECLIP = (1 << 0), + /* Temporary flag used by the Set Inverse operator. */ + OBJECTSOLVER_SET_INVERSE = (1 << 1), } eObjectSolver_Flags; /* ObjectSolver Constraint -> flag */ diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index b142939eaeb..bfa7400f926 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -124,7 +124,7 @@ struct CustomData_MeshMasks; typedef struct Object_Runtime { /** * The custom data layer mask that was last used - * to calculate mesh_eval and mesh_deform_eval. + * to calculate data_eval and mesh_deform_eval. */ CustomData_MeshMasks last_data_mask; @@ -141,25 +141,25 @@ typedef struct Object_Runtime { char _pad1[3]; /** - * Denotes whether the evaluated mesh is owned by this object or is referenced and owned by + * Denotes whether the evaluated data is owned by this object or is referenced and owned by * somebody else. */ - char is_mesh_eval_owned; + char is_data_eval_owned; /** Axis aligned boundbox (in localspace). */ struct BoundBox *bb; /** - * Original mesh pointer, before object->data was changed to point - * to mesh_eval. + * Original data pointer, before object->data was changed to point + * to data_eval. * Is assigned by dependency graph's copy-on-write evaluation. */ - struct Mesh *mesh_orig; + struct ID *data_orig; /** - * Mesh structure created during object evaluation. + * Object data structure created during object evaluation. * It has all modifiers applied. */ - struct Mesh *mesh_eval; + struct ID *data_eval; /** * Mesh structure created during object evaluation. * It has deformation only modifiers applied on it. diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 02aec9527f0..a219bbcfc8e 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -155,7 +155,7 @@ static EnumPropertyItem rna_enum_gpencil_brush_eraser_modes_items[] = { {GP_BRUSH_ERASER_SOFT, "SOFT", 0, - "Dissolve,", + "Dissolve", "Erase strokes, fading their points strength and thickness"}, {GP_BRUSH_ERASER_HARD, "HARD", 0, "Point", "Erase stroke points"}, {GP_BRUSH_ERASER_STROKE, "STROKE", 0, "Stroke", "Erase entire strokes"}, diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 8e57de9baeb..64e6fc9059c 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -973,11 +973,18 @@ static void rna_def_constraint_childof(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Scale Z", "Use Z Scale of Parent"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "set_inverse_pending", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", CHILDOF_SET_INVERSE); + RNA_def_property_ui_text( + prop, "Set Inverse Pending", "Set to true to request recalculation of the inverse matrix"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "inverse_matrix", PROP_FLOAT, PROP_MATRIX); RNA_def_property_float_sdna(prop, NULL, "invmat"); RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Inverse Matrix", "Transformation matrix to apply before"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); } static void rna_def_constraint_python(BlenderRNA *brna) @@ -3152,6 +3159,12 @@ static void rna_def_constraint_object_solver(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Active Clip", "Use active clip defined in scene"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "set_inverse_pending", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", OBJECTSOLVER_SET_INVERSE); + RNA_def_property_ui_text( + prop, "Set Inverse Pending", "Set to true to request recalculation of the inverse matrix"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + /* object */ prop = RNA_def_property(srna, "object", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "object"); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 9a4048e6aaa..cc0ebd8e6b2 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -5635,7 +5635,7 @@ static void rna_def_modifier_laplaciandeform(BlenderRNA *brna) prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "anchor_grp_name"); RNA_def_property_ui_text( - prop, "Vertex Group for Anchors", "Name of Vertex Group which determines Anchors"); + prop, "Anchor Weights", "Name of Vertex Group which determines Anchors"); RNA_def_property_string_funcs( prop, NULL, NULL, "rna_LaplacianDeformModifier_anchor_grp_name_set"); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 5552de00be8..cbeb8f17991 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -487,7 +487,7 @@ static Object *eval_object_ensure(Object *ob, ReportList *reports, PointerRNA *rnaptr_depsgraph) { - if (ob->runtime.mesh_eval == NULL) { + if (ob->runtime.data_eval == NULL) { Object *ob_orig = ob; Depsgraph *depsgraph = rnaptr_depsgraph != NULL ? rnaptr_depsgraph->data : NULL; if (depsgraph == NULL) { @@ -496,7 +496,7 @@ static Object *eval_object_ensure(Object *ob, if (depsgraph != NULL) { ob = DEG_get_evaluated_object(depsgraph, ob); } - if (ob == NULL || ob->runtime.mesh_eval == NULL) { + if (ob == NULL || BKE_object_get_evaluated_mesh(ob) == NULL) { BKE_reportf( reports, RPT_ERROR, "Object '%s' has no evaluated mesh data", ob_orig->id.name + 2); return NULL; @@ -521,8 +521,7 @@ static void rna_Object_ray_cast(Object *ob, /* TODO(sergey): This isn't very reliable check. It is possible to have non-NULL pointer * but which is out of date, and possibly dangling one. */ - if (ob->runtime.mesh_eval == NULL && - (ob = eval_object_ensure(ob, C, reports, rnaptr_depsgraph)) == NULL) { + if ((ob = eval_object_ensure(ob, C, reports, rnaptr_depsgraph)) == NULL) { return; } @@ -538,7 +537,8 @@ static void rna_Object_ray_cast(Object *ob, /* No need to managing allocation or freeing of the BVH data. * This is generated and freed as needed. */ - BKE_bvhtree_from_mesh_get(&treeData, ob->runtime.mesh_eval, BVHTREE_FROM_LOOPTRI, 4); + Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); + BKE_bvhtree_from_mesh_get(&treeData, mesh_eval, BVHTREE_FROM_LOOPTRI, 4); /* may fail if the mesh has no faces, in that case the ray-cast misses */ if (treeData.tree != NULL) { @@ -559,8 +559,7 @@ static void rna_Object_ray_cast(Object *ob, copy_v3_v3(r_location, hit.co); copy_v3_v3(r_normal, hit.no); - *r_index = mesh_looptri_to_poly_index(ob->runtime.mesh_eval, - &treeData.looptri[hit.index]); + *r_index = mesh_looptri_to_poly_index(mesh_eval, &treeData.looptri[hit.index]); } } @@ -589,14 +588,14 @@ static void rna_Object_closest_point_on_mesh(Object *ob, { BVHTreeFromMesh treeData = {NULL}; - if (ob->runtime.mesh_eval == NULL && - (ob = eval_object_ensure(ob, C, reports, rnaptr_depsgraph)) == NULL) { + if ((ob = eval_object_ensure(ob, C, reports, rnaptr_depsgraph)) == NULL) { return; } /* No need to managing allocation or freeing of the BVH data. * this is generated and freed as needed. */ - BKE_bvhtree_from_mesh_get(&treeData, ob->runtime.mesh_eval, BVHTREE_FROM_LOOPTRI, 4); + Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); + BKE_bvhtree_from_mesh_get(&treeData, mesh_eval, BVHTREE_FROM_LOOPTRI, 4); if (treeData.tree == NULL) { BKE_reportf(reports, @@ -617,8 +616,7 @@ static void rna_Object_closest_point_on_mesh(Object *ob, copy_v3_v3(r_location, nearest.co); copy_v3_v3(r_normal, nearest.no); - *r_index = mesh_looptri_to_poly_index(ob->runtime.mesh_eval, - &treeData.looptri[nearest.index]); + *r_index = mesh_looptri_to_poly_index(mesh_eval, &treeData.looptri[nearest.index]); goto finally; } @@ -659,8 +657,7 @@ void rna_Object_me_eval_info( switch (type) { case 1: case 2: - if (ob->runtime.mesh_eval == NULL && - (ob = eval_object_ensure(ob, C, NULL, rnaptr_depsgraph)) == NULL) { + if ((ob = eval_object_ensure(ob, C, NULL, rnaptr_depsgraph)) == NULL) { return; } } @@ -675,7 +672,7 @@ void rna_Object_me_eval_info( me_eval = ob->runtime.mesh_deform_eval; break; case 2: - me_eval = ob->runtime.mesh_eval; + me_eval = BKE_object_get_evaluated_mesh(ob); break; } diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index a3cf6fcd0b7..2031c444c9a 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -128,14 +128,12 @@ static int engine_get_preview_pixel_size(RenderEngine *UNUSED(engine), Scene *sc static void engine_bind_display_space_shader(RenderEngine *UNUSED(engine), Scene *UNUSED(scene)) { - GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_COLOR); + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE); GPU_shader_bind(shader); int img_loc = GPU_shader_get_uniform_ensure(shader, "image"); - int color_loc = GPU_shader_get_uniform_ensure(shader, "color"); GPU_shader_uniform_int(shader, img_loc, 0); - GPU_shader_uniform_vector(shader, color_loc, 3, 1, (float[3]){1.0f, 1.0f, 1.0f}); } static void engine_unbind_display_space_shader(RenderEngine *UNUSED(engine)) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 3d5d5091bf1..762c1985fa9 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -1280,9 +1280,26 @@ static const EnumPropertyItem *rna_3DViewShading_render_pass_itemf(bContext *C, RNA_enum_item_add(&result, &totitem, item); } } + + RNA_enum_item_end(&result, &totitem); *r_free = true; return result; } +static int rna_3DViewShading_render_pass_get(PointerRNA *ptr) +{ + View3DShading *shading = (View3DShading *)ptr->data; + eViewLayerEEVEEPassType result = shading->render_pass; + Scene *scene = rna_3DViewShading_scene(ptr); + + if (result == EEVEE_RENDER_PASS_AO && ((scene->eevee.flag & SCE_EEVEE_GTAO_ENABLED) == 0)) { + result = EEVEE_RENDER_PASS_COMBINED; + } + if (result == EEVEE_RENDER_PASS_BLOOM && ((scene->eevee.flag & SCE_EEVEE_BLOOM_ENABLED) == 0)) { + result = EEVEE_RENDER_PASS_COMBINED; + } + + return result; +} static void rna_SpaceView3D_use_local_collections_update(bContext *C, PointerRNA *ptr) { @@ -3379,7 +3396,8 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "render_pass"); RNA_def_property_enum_items(prop, rna_enum_view3dshading_render_pass_type_items); RNA_def_property_ui_text(prop, "Render Pass", "Render Pass to show in the viewport"); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_3DViewShading_render_pass_itemf"); + RNA_def_property_enum_funcs( + prop, "rna_3DViewShading_render_pass_get", NULL, "rna_3DViewShading_render_pass_itemf"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); } diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c index 9615c6f01e0..93d03720058 100644 --- a/source/blender/nodes/shader/node_shader_util.c +++ b/source/blender/nodes/shader/node_shader_util.c @@ -276,7 +276,7 @@ void node_shader_gpu_bump_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink * void node_shader_gpu_default_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink **link) { if (!*link) { - *link = GPU_attribute(CD_ORCO, ""); + *link = GPU_attribute(mat, CD_ORCO, ""); GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), *link, link); node_shader_gpu_bump_tex_coord(mat, node, link); } diff --git a/source/blender/nodes/shader/nodes/node_shader_attribute.c b/source/blender/nodes/shader/nodes/node_shader_attribute.c index ecb8c53c312..757db5fe8b3 100644 --- a/source/blender/nodes/shader/nodes/node_shader_attribute.c +++ b/source/blender/nodes/shader/nodes/node_shader_attribute.c @@ -66,7 +66,7 @@ static int node_shader_gpu_attribute(GPUMaterial *mat, GPU_builtin(GPU_VOLUME_TEMPERATURE)); } else { - GPUNodeLink *cd_attr = GPU_attribute(CD_AUTO_FROM_NAME, attr->name); + GPUNodeLink *cd_attr = GPU_attribute(mat, CD_AUTO_FROM_NAME, attr->name); GPU_stack_link(mat, node, "node_attribute", in, out, cd_attr); /* for each output. */ diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.c b/source/blender/nodes/shader/nodes/node_shader_geometry.c index 6b23fec5f18..b1ee3c4806a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_geometry.c +++ b/source/blender/nodes/shader/nodes/node_shader_geometry.c @@ -46,7 +46,8 @@ static int node_shader_gpu_geometry(GPUMaterial *mat, GPUNodeLink *bary_link = (!out[5].hasoutput) ? GPU_constant(val) : GPU_builtin(GPU_BARYCENTRIC_TEXCO); /* Opti: don't request orco if not needed. */ - GPUNodeLink *orco_link = (!out[2].hasoutput) ? GPU_constant(val) : GPU_attribute(CD_ORCO, ""); + GPUNodeLink *orco_link = (!out[2].hasoutput) ? GPU_constant(val) : + GPU_attribute(mat, CD_ORCO, ""); const bool success = GPU_stack_link(mat, node, diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c index 006f15f40a1..0f3ffe51706 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c +++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c @@ -92,7 +92,7 @@ static int gpu_shader_normal_map(GPUMaterial *mat, GPU_link(mat, "node_normal_map", GPU_builtin(GPU_OBJECT_INFO), - GPU_attribute(CD_TANGENT, nm->uv_map), + GPU_attribute(mat, CD_TANGENT, nm->uv_map), GPU_builtin(GPU_WORLD_NORMAL), newnormal, &newnormal); diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.c b/source/blender/nodes/shader/nodes/node_shader_tangent.c index 478b9524737..474db465d87 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tangent.c +++ b/source/blender/nodes/shader/nodes/node_shader_tangent.c @@ -43,10 +43,10 @@ static int node_shader_gpu_tangent(GPUMaterial *mat, if (attr->direction_type == SHD_TANGENT_UVMAP) { return GPU_stack_link( - mat, node, "node_tangentmap", in, out, GPU_attribute(CD_TANGENT, attr->uv_map)); + mat, node, "node_tangentmap", in, out, GPU_attribute(mat, CD_TANGENT, attr->uv_map)); } else { - GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); + GPUNodeLink *orco = GPU_attribute(mat, CD_ORCO, ""); if (attr->axis == SHD_TANGENT_AXIS_X) { GPU_link(mat, "tangent_orco_x", orco, &orco); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c index 3c1a2280aae..81a5ee31f7d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c @@ -47,8 +47,8 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, /* Opti: don't request orco if not needed. */ GPUNodeLink *orco = (!out[0].hasoutput) ? GPU_constant((float[4]){0.0f, 0.0f, 0.0f, 0.0f}) : - GPU_attribute(CD_ORCO, ""); - GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, ""); + GPU_attribute(mat, CD_ORCO, ""); + GPUNodeLink *mtface = GPU_attribute(mat, CD_MTFACE, ""); GPUNodeLink *viewpos = GPU_builtin(GPU_VIEW_POSITION); GPUNodeLink *worldnor = GPU_builtin(GPU_WORLD_NORMAL); GPUNodeLink *texcofacs = GPU_builtin(GPU_CAMERA_TEXCO_FACTORS); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index 6c380efe0b2..d2615d76345 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -88,7 +88,7 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, "node_tex_environment_equirectangular", in[0].link, GPU_constant(&clamp_size), - GPU_image(ima, iuser), + GPU_image(mat, ima, iuser), &in[0].link); } else { @@ -103,7 +103,7 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, GPU_link(mat, "node_tex_image_linear_no_mip", in[0].link, - GPU_image(ima, iuser), + GPU_image(mat, ima, iuser), &out[0].link, &outalpha); break; @@ -111,13 +111,17 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, GPU_link(mat, "node_tex_image_nearest", in[0].link, - GPU_image(ima, iuser), + GPU_image(mat, ima, iuser), &out[0].link, &outalpha); break; default: - GPU_link( - mat, "node_tex_image_cubic", in[0].link, GPU_image(ima, iuser), &out[0].link, &outalpha); + GPU_link(mat, + "node_tex_image_cubic", + in[0].link, + GPU_image(mat, ima, iuser), + &out[0].link, + &outalpha); break; } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index 781fd1eb579..ebc852486dc 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -123,26 +123,21 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, } if (!*texco) { - *texco = GPU_attribute(CD_MTFACE, ""); + *texco = GPU_attribute(mat, CD_MTFACE, ""); node_shader_gpu_bump_tex_coord(mat, node, texco); } node_shader_gpu_tex_mapping(mat, node, in, out); if (ima->source == IMA_SRC_TILED) { - /* The tiled shader needs both the tile array itself as well as the mapping from tile to array - * position. Which of these to allocate is automatically decided based on the shader argument - * type, so here the first GPU_image(ima, iuser) will resolve to the array and the second to - * the mapping since the third argument in the shader has type sampler2DArray while - * the fourth is sampler1DArray. - */ + /* UDIM tiles needs a samper2DArray and sampler1DArray for tile mapping. */ GPU_stack_link(mat, node, names_tiled[tex->interpolation], in, out, - GPU_image(ima, iuser), - GPU_image(ima, iuser)); + GPU_image_tiled(mat, ima, iuser), + GPU_image_tiled_mapping(mat, ima, iuser)); } else { switch (tex->projection) { @@ -157,20 +152,21 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, GPU_link(mat, "set_rgb", *texco, &input_coords); } if (do_texco_extend) { - GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser), texco); + GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco); } - GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser)); + GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser)); break; case SHD_PROJ_BOX: vnor = GPU_builtin(GPU_WORLD_NORMAL); ob_mat = GPU_builtin(GPU_OBJECT_MATRIX); blend = GPU_uniform(&tex->projection_blend); - gpu_image = GPU_image(ima, iuser); + gpu_image = GPU_image(mat, ima, iuser); /* equivalent to normal_world_to_object */ GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &norm); - GPU_link(mat, gpu_node_name, *texco, norm, GPU_image(ima, iuser), &col1, &col2, &col3); + GPU_link( + mat, gpu_node_name, *texco, norm, GPU_image(mat, ima, iuser), &col1, &col2, &col3); GPU_stack_link( mat, node, "node_tex_image_box", in, out, norm, col1, col2, col3, gpu_image, blend); break; @@ -184,9 +180,9 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, GPU_link(mat, "set_rgb", *texco, &input_coords); } if (do_texco_extend) { - GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser), texco); + GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco); } - GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser)); + GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser)); break; case SHD_PROJ_TUBE: @@ -198,9 +194,9 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, GPU_link(mat, "set_rgb", *texco, &input_coords); } if (do_texco_extend) { - GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser), texco); + GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco); } - GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser)); + GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser)); break; } @@ -208,7 +204,7 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, if (do_texco_clip) { gpu_node_name = names_clip[tex->interpolation]; in[0].link = input_coords; - GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser), out[0].link); + GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser), out[0].link); } } } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c index b1fb0cad4b2..0a576e465fa 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c @@ -63,7 +63,7 @@ static int node_shader_gpu_tex_sky(GPUMaterial *mat, GPUNodeStack *out) { if (!in[0].link) { - in[0].link = GPU_attribute(CD_ORCO, ""); + in[0].link = GPU_attribute(mat, CD_ORCO, ""); } node_shader_gpu_tex_mapping(mat, node, in, out); diff --git a/source/blender/nodes/shader/nodes/node_shader_uvmap.c b/source/blender/nodes/shader/nodes/node_shader_uvmap.c index a2e47735490..f01542be44a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_uvmap.c +++ b/source/blender/nodes/shader/nodes/node_shader_uvmap.c @@ -41,7 +41,7 @@ static int node_shader_gpu_uvmap(GPUMaterial *mat, GPUNodeStack *out) { NodeShaderUVMap *attr = node->storage; - GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, attr->uv_map); + GPUNodeLink *mtface = GPU_attribute(mat, CD_MTFACE, attr->uv_map); GPU_stack_link(mat, node, "node_uvmap", in, out, mtface); diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c index ac8b49c4572..df303b2d3f1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c +++ b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c @@ -60,7 +60,7 @@ static int gpu_shader_vector_displacement(GPUMaterial *mat, "node_vector_displacement_tangent", in, out, - GPU_attribute(CD_TANGENT, ""), + GPU_attribute(mat, CD_TANGENT, ""), GPU_builtin(GPU_WORLD_NORMAL), GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_VIEW_MATRIX)); diff --git a/source/blender/nodes/shader/nodes/node_shader_vertex_color.c b/source/blender/nodes/shader/nodes/node_shader_vertex_color.c index 8848fc37c66..98d575cece2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vertex_color.c +++ b/source/blender/nodes/shader/nodes/node_shader_vertex_color.c @@ -39,7 +39,7 @@ static int node_shader_gpu_vertex_color(GPUMaterial *mat, GPUNodeStack *out) { NodeShaderVertexColor *vertexColor = (NodeShaderVertexColor *)node->storage; - GPUNodeLink *vertexColorLink = GPU_attribute(CD_MCOL, vertexColor->layer_name); + GPUNodeLink *vertexColorLink = GPU_attribute(mat, CD_MCOL, vertexColor->layer_name); return GPU_stack_link(mat, node, "node_vertex_color", in, out, vertexColorLink); } diff --git a/source/blender/usd/intern/usd_writer_mesh.cc b/source/blender/usd/intern/usd_writer_mesh.cc index bc3bc06f8a6..74005afaf31 100644 --- a/source/blender/usd/intern/usd_writer_mesh.cc +++ b/source/blender/usd/intern/usd_writer_mesh.cc @@ -483,7 +483,7 @@ USDMeshWriter::USDMeshWriter(const USDExporterContext &ctx) : USDGenericMeshWrit Mesh *USDMeshWriter::get_export_mesh(Object *object_eval, bool & /*r_needsfree*/) { - return object_eval->runtime.mesh_eval; + return BKE_object_get_evaluated_mesh(object_eval); } } // namespace USD diff --git a/source/blender/windowmanager/intern/wm_keymap_utils.c b/source/blender/windowmanager/intern/wm_keymap_utils.c index 4603f14729d..5e6b55a508e 100644 --- a/source/blender/windowmanager/intern/wm_keymap_utils.c +++ b/source/blender/windowmanager/intern/wm_keymap_utils.c @@ -318,7 +318,7 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname) } /* Paint Face Mask */ else if (STRPREFIX(opname, "PAINT_OT_face_select")) { - km = WM_keymap_find_all(C, "Face Mask", 0, 0); + km = WM_keymap_find_all(C, "Paint Face Mask (Weight, Vertex, Texture)", 0, 0); } else if (STRPREFIX(opname, "PAINT_OT")) { /* check for relevant mode */ |