diff options
Diffstat (limited to 'source/blender/blenkernel/intern')
49 files changed, 1312 insertions, 3434 deletions
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index d76a4d8f859..98deddb4316 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -32,13 +32,6 @@ #include "CCGSubSurf.h" #include "CCGSubSurf_intern.h" -#ifdef WITH_OPENSUBDIV -# include "opensubdiv_capi.h" -# include "opensubdiv_converter_capi.h" -# include "opensubdiv_evaluator_capi.h" -# include "opensubdiv_topology_refiner_capi.h" -#endif - #include "GPU_glew.h" /***/ @@ -305,21 +298,6 @@ CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, ss->tempVerts = NULL; ss->tempEdges = NULL; -#ifdef WITH_OPENSUBDIV - ss->osd_evaluator = NULL; - ss->osd_mesh = NULL; - ss->osd_topology_refiner = NULL; - ss->osd_mesh_invalid = false; - ss->osd_coarse_coords_invalid = false; - ss->osd_vao = 0; - ss->skip_grids = false; - ss->osd_compute = 0; - ss->osd_next_face_ptex_index = 0; - ss->osd_coarse_coords = NULL; - ss->osd_num_coarse_coords = 0; - ss->osd_subdiv_uvs = false; -#endif - return ss; } } @@ -328,23 +306,6 @@ void ccgSubSurf_free(CCGSubSurf *ss) { CCGAllocatorIFC allocatorIFC = ss->allocatorIFC; CCGAllocatorHDL allocator = ss->allocator; -#ifdef WITH_OPENSUBDIV - if (ss->osd_evaluator != NULL) { - openSubdiv_deleteEvaluator(ss->osd_evaluator); - } - if (ss->osd_mesh != NULL) { - ccgSubSurf__delete_osdGLMesh(ss->osd_mesh); - } - if (ss->osd_vao != 0) { - ccgSubSurf__delete_vertex_array(ss->osd_vao); - } - if (ss->osd_coarse_coords != NULL) { - MEM_freeN(ss->osd_coarse_coords); - } - if (ss->osd_topology_refiner != NULL) { - openSubdiv_deleteTopologyRefiner(ss->osd_topology_refiner); - } -#endif if (ss->syncState) { ccg_ehash_free(ss->oldFMap, (EHEntryFreeFP)_face_free, ss); @@ -529,9 +490,6 @@ CCGError ccgSubSurf_initFullSync(CCGSubSurf *ss) ss->tempEdges = MEM_mallocN(sizeof(*ss->tempEdges) * ss->lenTempArrays, "CCGSubsurf tempEdges"); ss->syncState = eSyncState_Vert; -#ifdef WITH_OPENSUBDIV - ss->osd_next_face_ptex_index = 0; -#endif return eCCGError_None; } @@ -671,9 +629,6 @@ CCGError ccgSubSurf_syncVert( ccg_ehash_insert(ss->vMap, (EHEntry *)v); v->flags = 0; } -#ifdef WITH_OPENSUBDIV - v->osd_index = ss->vMap->numEntries - 1; -#endif } if (v_r) { @@ -874,15 +829,6 @@ CCGError ccgSubSurf_syncFace( } } } -#ifdef WITH_OPENSUBDIV - f->osd_index = ss->osd_next_face_ptex_index; - if (numVerts == 4) { - ss->osd_next_face_ptex_index++; - } - else { - ss->osd_next_face_ptex_index += numVerts; - } -#endif } if (f_r) { @@ -893,15 +839,7 @@ CCGError ccgSubSurf_syncFace( static void ccgSubSurf__sync(CCGSubSurf *ss) { -#ifdef WITH_OPENSUBDIV - if (ss->skip_grids) { - ccgSubSurf__sync_opensubdiv(ss); - } - else -#endif - { - ccgSubSurf__sync_legacy(ss); - } + ccgSubSurf__sync_legacy(ss); } CCGError ccgSubSurf_processSync(CCGSubSurf *ss) @@ -1615,12 +1553,6 @@ int ccgSubSurf_getNumFinalVerts(const CCGSubSurf *ss) ss->fMap->numEntries + ss->numGrids * ((gridSize - 2) + ((gridSize - 2) * (gridSize - 2)))); -#ifdef WITH_OPENSUBDIV - if (ss->skip_grids) { - return 0; - } -#endif - return numFinalVerts; } int ccgSubSurf_getNumFinalEdges(const CCGSubSurf *ss) @@ -1629,22 +1561,12 @@ int ccgSubSurf_getNumFinalEdges(const CCGSubSurf *ss) int gridSize = ccg_gridsize(ss->subdivLevels); int numFinalEdges = (ss->eMap->numEntries * (edgeSize - 1) + ss->numGrids * ((gridSize - 1) + 2 * ((gridSize - 2) * (gridSize - 1)))); -#ifdef WITH_OPENSUBDIV - if (ss->skip_grids) { - return 0; - } -#endif return numFinalEdges; } int ccgSubSurf_getNumFinalFaces(const CCGSubSurf *ss) { int gridSize = ccg_gridsize(ss->subdivLevels); int numFinalFaces = ss->numGrids * ((gridSize - 1) * (gridSize - 1)); -#ifdef WITH_OPENSUBDIV - if (ss->skip_grids) { - return 0; - } -#endif return numFinalFaces; } diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h index 83b59941ac7..2e5100db6de 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.h +++ b/source/blender/blenkernel/intern/CCGSubSurf.h @@ -211,57 +211,4 @@ CCGFace *ccgFaceIterator_getCurrent(CCGFaceIterator *fi); int ccgFaceIterator_isStopped(CCGFaceIterator *fi); void ccgFaceIterator_next(CCGFaceIterator *fi); -#ifdef WITH_OPENSUBDIV -struct DerivedMesh; - -/* Check if topology changed and evaluators are to be re-created. */ -void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, struct DerivedMesh *dm); - -/* Create topology refiner from give derived mesh which then later will be - * used for GL mesh creation. - */ -void ccgSubSurf_prepareTopologyRefiner(CCGSubSurf *ss, struct DerivedMesh *dm); - -/* Make sure GL mesh exists, up to date and ready to draw. */ -bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl, int active_uv_index); - -/* Draw given partitions of the GL mesh. - * - * TODO(sergey): fill_quads is actually an invariant and should be part - * of the prepare routine. - */ -void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, - bool fill_quads, - int start_partition, - int num_partitions); - -/* Get number of base faces in a particular GL mesh. */ -int ccgSubSurf_getNumGLMeshBaseFaces(CCGSubSurf *ss); - -/* Get number of vertices in base faces in a particular GL mesh. */ -int ccgSubSurf_getNumGLMeshBaseFaceVerts(CCGSubSurf *ss, int face); - -/* Controls whether CCG are needed (Cmeaning CPU evaluation) or fully GPU compute - * and draw is allowed. - */ -void ccgSubSurf_setSkipGrids(CCGSubSurf *ss, bool skip_grids); -bool ccgSubSurf_needGrids(CCGSubSurf *ss); - -/* Set evaluator's face varying data from UV coordinates. - * Used for CPU evaluation. - */ -void ccgSubSurf_evaluatorSetFVarUV(CCGSubSurf *ss, struct DerivedMesh *dm, int layer_index); - -/* TODO(sergey): Temporary call to test things. */ -void ccgSubSurf_evaluatorFVarUV( - CCGSubSurf *ss, int face_index, int S, float grid_u, float grid_v, float uv[2]); - -void ccgSubSurf_free_osd_mesh(CCGSubSurf *ss); - -void ccgSubSurf_getMinMax(CCGSubSurf *ss, float r_min[3], float r_max[3]); - -void ccgSubSurf__sync_subdivUvs(CCGSubSurf *ss, bool subsurf_uvs); - -#endif - #endif /* __CCGSUBSURF_H__ */ diff --git a/source/blender/blenkernel/intern/CCGSubSurf_intern.h b/source/blender/blenkernel/intern/CCGSubSurf_intern.h index 51486db1bdc..7c35d2ccfce 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf_intern.h +++ b/source/blender/blenkernel/intern/CCGSubSurf_intern.h @@ -157,9 +157,6 @@ typedef enum { eSyncState_Edge, eSyncState_Face, eSyncState_Partial, -#ifdef WITH_OPENSUBDIV - eSyncState_OpenSubdiv, -#endif } SyncState; struct CCGSubSurf { @@ -202,58 +199,6 @@ struct CCGSubSurf { int lenTempArrays; CCGVert **tempVerts; CCGEdge **tempEdges; - -#ifdef WITH_OPENSUBDIV - /* Skip grids means no CCG geometry is created and subsurf is possible - * to be completely done on GPU. - */ - bool skip_grids; - - /* ** GPU backend. ** */ - - /* Compute device used by GL mesh. */ - short osd_compute; - /* Coarse (base mesh) vertex coordinates. - * - * Filled in from the modifier stack and passed to OpenSubdiv compute - * on mesh display. - */ - float (*osd_coarse_coords)[3]; - int osd_num_coarse_coords; - /* Denotes whether coarse positions in the GL mesh are invalid. - * Used to avoid updating GL mesh coords on every redraw. - */ - bool osd_coarse_coords_invalid; - - /* GL mesh descriptor, used for refinement and draw. */ - struct OpenSubdiv_GLMesh *osd_mesh; - /* Refiner which is used to create GL mesh. - * - * Refiner is created from the modifier stack and used later from the main - * thread to construct GL mesh to avoid threaded access to GL. - */ - struct OpenSubdiv_TopologyRefiner - *osd_topology_refiner; /* Only used at synchronization stage. */ - /* Denotes whether osd_mesh is invalid now due to topology changes and needs - * to be reconstructed. - * - * Reconstruction happens from main thread due to OpenGL communication. - */ - bool osd_mesh_invalid; - /* Vertex array used for osd_mesh draw. */ - unsigned int osd_vao; - - /* ** CPU backend. ** */ - - /* Limit evaluator, used to evaluate CCG. */ - struct OpenSubdiv_Evaluator *osd_evaluator; - /* Next PTex face index, used while CCG synchronization - * to fill in PTex index of CCGFace. - */ - int osd_next_face_ptex_index; - - bool osd_subdiv_uvs; -#endif }; /* ** Utility macros ** */ @@ -322,16 +267,6 @@ void ccgSubSurf__sync_legacy(CCGSubSurf *ss); void ccgSubSurf__sync_opensubdiv(CCGSubSurf *ss); -/* Delayed free routines. Will do actual free if called from - * main thread and schedule free for later free otherwise. - */ - -#ifdef WITH_OPENSUBDIV -void ccgSubSurf__delete_osdGLMesh(struct OpenSubdiv_GLMesh *osd_mesh); -void ccgSubSurf__delete_vertex_array(unsigned int vao); -void ccgSubSurf__delete_pending(void); -#endif - /* * CCGSubSurf_opensubdiv_converter.c * */ struct OpenSubdiv_Converter; diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c deleted file mode 100644 index 3257dd2334c..00000000000 --- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c +++ /dev/null @@ -1,970 +0,0 @@ -/* - * 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. - */ - -/** \file - * \ingroup bke - */ - -#ifdef WITH_OPENSUBDIV - -# include "BLI_sys_types.h" // for intptr_t support -# include "MEM_guardedalloc.h" - -# include "BLI_listbase.h" -# include "BLI_math.h" -# include "BLI_threads.h" -# include "BLI_utildefines.h" /* for BLI_assert */ - -# include "CCGSubSurf.h" -# include "CCGSubSurf_intern.h" - -# include "BKE_DerivedMesh.h" -# include "BKE_subsurf.h" - -# include "DNA_userdef_types.h" - -# include "opensubdiv_capi.h" -# include "opensubdiv_converter_capi.h" -# include "opensubdiv_evaluator_capi.h" -# include "opensubdiv_gl_mesh_capi.h" -# include "opensubdiv_topology_refiner_capi.h" - -# include "GPU_extensions.h" -# include "GPU_glew.h" - -# define OSD_LOG \ - if (false) \ - printf - -static bool compare_ccg_derivedmesh_topology(CCGSubSurf *ss, DerivedMesh *dm) -{ - const int num_verts = dm->getNumVerts(dm); - const int num_edges = dm->getNumEdges(dm); - const int num_polys = dm->getNumPolys(dm); - const MEdge *medge = dm->getEdgeArray(dm); - const MLoop *mloop = dm->getLoopArray(dm); - const MPoly *mpoly = dm->getPolyArray(dm); - - /* Quick preliminary tests based on the number of verts and facces. */ - { - if (num_verts != ss->vMap->numEntries || num_edges != ss->eMap->numEntries || - num_polys != ss->fMap->numEntries) { - return false; - } - } - - /* Rather slow check for faces topology change. */ - { - CCGFaceIterator ccg_face_iter; - for (ccgSubSurf_initFaceIterator(ss, &ccg_face_iter); - !ccgFaceIterator_isStopped(&ccg_face_iter); - ccgFaceIterator_next(&ccg_face_iter)) { - /*const*/ CCGFace *ccg_face = ccgFaceIterator_getCurrent(&ccg_face_iter); - const int poly_index = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(ccg_face)); - const MPoly *mp = &mpoly[poly_index]; - int corner; - if (ccg_face->numVerts != mp->totloop) { - return false; - } - for (corner = 0; corner < ccg_face->numVerts; corner++) { - /*const*/ CCGVert *ccg_vert = FACE_getVerts(ccg_face)[corner]; - const int vert_index = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(ccg_vert)); - if (vert_index != mloop[mp->loopstart + corner].v) { - return false; - } - } - } - } - - /* Check for edge topology change. */ - { - CCGEdgeIterator ccg_edge_iter; - for (ccgSubSurf_initEdgeIterator(ss, &ccg_edge_iter); - !ccgEdgeIterator_isStopped(&ccg_edge_iter); - ccgEdgeIterator_next(&ccg_edge_iter)) { - /* const */ CCGEdge *ccg_edge = ccgEdgeIterator_getCurrent(&ccg_edge_iter); - /* const */ CCGVert *ccg_vert1 = ccg_edge->v0; - /* const */ CCGVert *ccg_vert2 = ccg_edge->v1; - const int ccg_vert1_index = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(ccg_vert1)); - const int ccg_vert2_index = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(ccg_vert2)); - const int edge_index = POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(ccg_edge)); - const MEdge *me = &medge[edge_index]; - if (me->v1 != ccg_vert1_index || me->v2 != ccg_vert2_index) { - return false; - } - } - } - - /* TODO(sergey): Crease topology changes detection. */ - { - CCGEdgeIterator ccg_edge_iter; - for (ccgSubSurf_initEdgeIterator(ss, &ccg_edge_iter); - !ccgEdgeIterator_isStopped(&ccg_edge_iter); - ccgEdgeIterator_next(&ccg_edge_iter)) { - /* const */ CCGEdge *ccg_edge = ccgEdgeIterator_getCurrent(&ccg_edge_iter); - const int edge_index = POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(ccg_edge)); - if (ccg_edge->crease != medge[edge_index].crease) { - return false; - } - } - } - - return true; -} - -static bool compare_osd_derivedmesh_topology(CCGSubSurf *ss, DerivedMesh *dm) -{ - OpenSubdiv_Converter converter; - bool result; - if (ss->osd_mesh == NULL && ss->osd_topology_refiner == NULL) { - return true; - } - /* TODO(sergey): De-duplicate with topology counter at the bottom of - * the file. - */ - ccgSubSurf_converter_setup_from_derivedmesh(ss, dm, &converter); - result = openSubdiv_topologyRefinerCompareWithConverter(ss->osd_topology_refiner, &converter); - ccgSubSurf_converter_free(&converter); - return result; -} - -static bool opensubdiv_is_topology_changed(CCGSubSurf *ss, DerivedMesh *dm) -{ - if (ss->osd_compute != U.opensubdiv_compute_type) { - return true; - } - if (ss->osd_topology_refiner != NULL) { - const int levels = ss->osd_topology_refiner->getSubdivisionLevel(ss->osd_topology_refiner); - BLI_assert(ss->osd_mesh_invalid == true); - if (levels != ss->subdivLevels) { - return true; - } - } - if (ss->skip_grids == false) { - return compare_ccg_derivedmesh_topology(ss, dm) == false; - } - else { - return compare_osd_derivedmesh_topology(ss, dm) == false; - } - return false; -} - -void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, DerivedMesh *dm) -{ - if (opensubdiv_is_topology_changed(ss, dm)) { - /* ** Make sure both GPU and CPU backends are properly reset. ** */ - - ss->osd_coarse_coords_invalid = true; - - /* Reset GPU part. */ - ss->osd_mesh_invalid = true; - if (ss->osd_topology_refiner != NULL) { - openSubdiv_deleteTopologyRefiner(ss->osd_topology_refiner); - ss->osd_topology_refiner = NULL; - } - - /* Reset CPU side. */ - if (ss->osd_evaluator != NULL) { - openSubdiv_deleteEvaluator(ss->osd_evaluator); - ss->osd_evaluator = NULL; - } - } -} - -static void ccgSubSurf__updateGLMeshCoords(CCGSubSurf *ss) -{ - BLI_assert(ss->meshIFC.numLayers == 3); - ss->osd_mesh->setCoarsePositions( - ss->osd_mesh, (float *)ss->osd_coarse_coords, 0, ss->osd_num_coarse_coords); -} - -bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl, int active_uv_index) -{ - int compute_type; - - switch (U.opensubdiv_compute_type) { -# define CHECK_COMPUTE_TYPE(type) \ - case USER_OPENSUBDIV_COMPUTE_##type: \ - compute_type = OPENSUBDIV_EVALUATOR_##type; \ - break; - CHECK_COMPUTE_TYPE(CPU) - CHECK_COMPUTE_TYPE(OPENMP) - CHECK_COMPUTE_TYPE(OPENCL) - CHECK_COMPUTE_TYPE(CUDA) - CHECK_COMPUTE_TYPE(GLSL_TRANSFORM_FEEDBACK) - CHECK_COMPUTE_TYPE(GLSL_COMPUTE) - default: - compute_type = OPENSUBDIV_EVALUATOR_CPU; - break; -# undef CHECK_COMPUTE_TYPE - } - - if (ss->osd_vao == 0) { - glGenVertexArrays(1, &ss->osd_vao); - } - - if (ss->osd_mesh_invalid) { - if (ss->osd_mesh != NULL) { - ccgSubSurf__delete_osdGLMesh(ss->osd_mesh); - ss->osd_mesh = NULL; - } - ss->osd_mesh_invalid = false; - } - - if (ss->osd_mesh == NULL) { - if (ss->osd_topology_refiner == NULL) { - /* Happens with empty meshes. */ - /* TODO(sergey): Add assert that mesh is indeed empty. */ - return false; - } - - ss->osd_mesh = openSubdiv_createOsdGLMeshFromTopologyRefiner(ss->osd_topology_refiner, - compute_type); - - if (UNLIKELY(ss->osd_mesh == NULL)) { - /* Most likely compute device is not available. */ - return false; - } - - ccgSubSurf__updateGLMeshCoords(ss); - ss->osd_mesh->refine(ss->osd_mesh); - ss->osd_mesh->synchronize(ss->osd_mesh); - ss->osd_coarse_coords_invalid = false; - - glBindVertexArray(ss->osd_vao); - ss->osd_mesh->bindVertexBuffer(ss->osd_mesh); - - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, 0); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (float *)12); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - } - else if (ss->osd_coarse_coords_invalid) { - ccgSubSurf__updateGLMeshCoords(ss); - ss->osd_mesh->refine(ss->osd_mesh); - ss->osd_mesh->synchronize(ss->osd_mesh); - ss->osd_coarse_coords_invalid = false; - } - - ss->osd_mesh->prepareDraw(ss->osd_mesh, use_osd_glsl, active_uv_index); - - return true; -} - -void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, - bool fill_quads, - int start_partition, - int num_partitions) -{ - if (LIKELY(ss->osd_mesh != NULL)) { - glBindVertexArray(ss->osd_vao); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ss->osd_mesh->getPatchIndexBuffer(ss->osd_mesh)); - - ss->osd_mesh->bindVertexBuffer(ss->osd_mesh); - glBindVertexArray(ss->osd_vao); - ss->osd_mesh->drawPatches(ss->osd_mesh, fill_quads, start_partition, num_partitions); - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } -} - -int ccgSubSurf_getNumGLMeshBaseFaces(CCGSubSurf *ss) -{ - if (ss->osd_topology_refiner != NULL) { - return ss->osd_topology_refiner->getNumFaces(ss->osd_topology_refiner); - } - return 0; -} - -/* Get number of vertices in base faces in a particular GL mesh. */ -int ccgSubSurf_getNumGLMeshBaseFaceVerts(CCGSubSurf *ss, int face) -{ - if (ss->osd_topology_refiner != NULL) { - return ss->osd_topology_refiner->getNumFaceVertices(ss->osd_topology_refiner, face); - } - return 0; -} - -void ccgSubSurf_setSkipGrids(CCGSubSurf *ss, bool skip_grids) -{ - ss->skip_grids = skip_grids; -} - -bool ccgSubSurf_needGrids(CCGSubSurf *ss) -{ - return ss->skip_grids == false; -} - -BLI_INLINE void ccgSubSurf__mapGridToFace( - int S, float grid_u, float grid_v, float *face_u, float *face_v) -{ - float u, v; - - /* - Each grid covers half of the face along the edges. - * - Grid's (0, 0) starts from the middle of the face. - */ - u = 0.5f - 0.5f * grid_u; - v = 0.5f - 0.5f * grid_v; - - if (S == 0) { - *face_u = v; - *face_v = u; - } - else if (S == 1) { - *face_u = 1.0f - u; - *face_v = v; - } - else if (S == 2) { - *face_u = 1.0f - v; - *face_v = 1.0f - u; - } - else { - *face_u = u; - *face_v = 1.0f - v; - } -} - -BLI_INLINE void ccgSubSurf__mapEdgeToFace( - int S, int edge_segment, bool inverse_edge, int edgeSize, float *face_u, float *face_v) -{ - int t = inverse_edge ? edgeSize - edge_segment - 1 : edge_segment; - if (S == 0) { - *face_u = (float)t / (edgeSize - 1); - *face_v = 0.0f; - } - else if (S == 1) { - *face_u = 1.0f; - *face_v = (float)t / (edgeSize - 1); - } - else if (S == 2) { - *face_u = 1.0f - (float)t / (edgeSize - 1); - *face_v = 1.0f; - } - else { - *face_u = 0.0f; - *face_v = 1.0f - (float)t / (edgeSize - 1); - } -} - -void ccgSubSurf_evaluatorSetFVarUV(CCGSubSurf *ss, DerivedMesh *dm, int layer_index) -{ - MPoly *mpoly = dm->getPolyArray(dm); - MLoopUV *mloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, layer_index); - int num_polys = dm->getNumPolys(dm); - int index, poly; - BLI_assert(ss->osd_evaluator != NULL); - for (poly = 0, index = 0; poly < num_polys; poly++) { - int loop; - MPoly *mp = &mpoly[poly]; - for (loop = 0; loop < mp->totloop; loop++, index++) { - MLoopUV *mluv = &mloopuv[loop + mp->loopstart]; - (void)mluv; - /* TODO(sergey): Send mluv->uv to the evaluator's face varying - * buffer. - */ - } - } - (void)ss; -} - -void ccgSubSurf_evaluatorFVarUV( - CCGSubSurf *ss, int face_index, int S, float grid_u, float grid_v, float uv[2]) -{ - float face_u, face_v; - ccgSubSurf__mapGridToFace(S, grid_u, grid_v, &face_u, &face_v); - (void)ss; - (void)face_index; - /* TODO(sergey): Evaluate face varying coordinate. */ - zero_v2(uv); -} - -static bool opensubdiv_createEvaluator(CCGSubSurf *ss) -{ - OpenSubdiv_Converter converter; - OpenSubdiv_TopologyRefiner *topology_refiner; - if (ss->fMap->numEntries == 0) { - /* OpenSubdiv doesn't support meshes without faces. */ - return false; - } - ccgSubSurf_converter_setup_from_ccg(ss, &converter); - OpenSubdiv_TopologyRefinerSettings settings; - settings.level = ss->subdivLevels; - settings.is_adaptive = false; - topology_refiner = openSubdiv_createTopologyRefinerFromConverter(&converter, &settings); - ccgSubSurf_converter_free(&converter); - ss->osd_evaluator = openSubdiv_createEvaluatorFromTopologyRefiner(topology_refiner); - if (ss->osd_evaluator == NULL) { - BLI_assert(!"OpenSubdiv initialization failed, should not happen."); - return false; - } - return true; -} - -static bool opensubdiv_ensureEvaluator(CCGSubSurf *ss) -{ - if (ss->osd_evaluator == NULL) { - OSD_LOG("Allocating new evaluator, %d verts\n", ss->vMap->numEntries); - opensubdiv_createEvaluator(ss); - } - return ss->osd_evaluator != NULL; -} - -static void opensubdiv_updateEvaluatorCoarsePositions(CCGSubSurf *ss) -{ - float(*positions)[3]; - int vertDataSize = ss->meshIFC.vertDataSize; - int num_basis_verts = ss->vMap->numEntries; - int i; - - /* TODO(sergey): Avoid allocation on every update. We could either update - * coordinates in chunks of 1K vertices (which will only use stack memory) - * or do some callback magic for OSD evaluator can invoke it and fill in - * buffer directly. - */ - if (ss->meshIFC.numLayers == 3) { - /* If all the components are to be initialized, no need to memset the - * new memory block. - */ - positions = MEM_mallocN(3 * sizeof(float) * num_basis_verts, "OpenSubdiv coarse points"); - } - else { - /* Calloc in order to have z component initialized to 0 for Uvs */ - positions = MEM_callocN(3 * sizeof(float) * num_basis_verts, "OpenSubdiv coarse points"); - } -# pragma omp parallel for - for (i = 0; i < ss->vMap->curSize; i++) { - CCGVert *v = (CCGVert *)ss->vMap->buckets[i]; - for (; v; v = v->next) { - float *co = VERT_getCo(v, 0); - BLI_assert(v->osd_index < ss->vMap->numEntries); - VertDataCopy(positions[v->osd_index], co, ss); - OSD_LOG("Point %d has value %f %f %f\n", - v->osd_index, - positions[v->osd_index][0], - positions[v->osd_index][1], - positions[v->osd_index][2]); - } - } - - ss->osd_evaluator->setCoarsePositions(ss->osd_evaluator, (float *)positions, 0, num_basis_verts); - ss->osd_evaluator->refine(ss->osd_evaluator); - - MEM_freeN(positions); -} - -static void opensubdiv_evaluateQuadFaceGrids(CCGSubSurf *ss, - CCGFace *face, - const int osd_face_index) -{ - int normalDataOffset = ss->normalDataOffset; - int subdivLevels = ss->subdivLevels; - int gridSize = ccg_gridsize(subdivLevels); - int edgeSize = ccg_edgesize(subdivLevels); - int vertDataSize = ss->meshIFC.vertDataSize; - int S; - bool do_normals = ss->meshIFC.numLayers == 3; - -# pragma omp parallel for - for (S = 0; S < face->numVerts; S++) { - int x, y, k; - CCGEdge *edge = NULL; - bool inverse_edge = false; - - for (x = 0; x < gridSize; x++) { - for (y = 0; y < gridSize; y++) { - float *co = FACE_getIFCo(face, subdivLevels, S, x, y); - float *no = FACE_getIFNo(face, subdivLevels, S, x, y); - float grid_u = (float)x / (gridSize - 1), grid_v = (float)y / (gridSize - 1); - float face_u, face_v; - float P[3], dPdu[3], dPdv[3]; - - ccgSubSurf__mapGridToFace(S, grid_u, grid_v, &face_u, &face_v); - - /* TODO(sergey): Need proper port. */ - ss->osd_evaluator->evaluateLimit(ss->osd_evaluator, - osd_face_index, - face_u, - face_v, - P, - do_normals ? dPdu : NULL, - do_normals ? dPdv : NULL); - - OSD_LOG("face=%d, corner=%d, grid_u=%f, grid_v=%f, face_u=%f, face_v=%f, P=(%f, %f, %f)\n", - osd_face_index, - S, - grid_u, - grid_v, - face_u, - face_v, - P[0], - P[1], - P[2]); - - VertDataCopy(co, P, ss); - if (do_normals) { - cross_v3_v3v3(no, dPdu, dPdv); - normalize_v3(no); - } - - if (x == gridSize - 1 && y == gridSize - 1) { - float *vert_co = VERT_getCo(FACE_getVerts(face)[S], subdivLevels); - VertDataCopy(vert_co, co, ss); - if (do_normals) { - float *vert_no = VERT_getNo(FACE_getVerts(face)[S], subdivLevels); - VertDataCopy(vert_no, no, ss); - } - } - if (S == 0 && x == 0 && y == 0) { - float *center_co = (float *)FACE_getCenterData(face); - VertDataCopy(center_co, co, ss); - if (do_normals) { - float *center_no = (float *)((byte *)FACE_getCenterData(face) + normalDataOffset); - VertDataCopy(center_no, no, ss); - } - } - } - } - - for (x = 0; x < gridSize; x++) { - VertDataCopy( - FACE_getIECo(face, subdivLevels, S, x), FACE_getIFCo(face, subdivLevels, S, x, 0), ss); - if (do_normals) { - VertDataCopy( - FACE_getIENo(face, subdivLevels, S, x), FACE_getIFNo(face, subdivLevels, S, x, 0), ss); - } - } - - for (k = 0; k < face->numVerts; k++) { - CCGEdge *current_edge = FACE_getEdges(face)[k]; - CCGVert **face_verts = FACE_getVerts(face); - if (current_edge->v0 == face_verts[S] && - current_edge->v1 == face_verts[(S + 1) % face->numVerts]) { - edge = current_edge; - inverse_edge = false; - break; - } - if (current_edge->v1 == face_verts[S] && - current_edge->v0 == face_verts[(S + 1) % face->numVerts]) { - edge = current_edge; - inverse_edge = true; - break; - } - } - - BLI_assert(edge != NULL); - - for (x = 0; x < edgeSize; x++) { - float u = 0, v = 0; - float *co = EDGE_getCo(edge, subdivLevels, x); - float *no = EDGE_getNo(edge, subdivLevels, x); - float P[3], dPdu[3], dPdv[3]; - ccgSubSurf__mapEdgeToFace(S, x, inverse_edge, edgeSize, &u, &v); - - /* TODO(sergey): Ideally we will re-use grid here, but for now - * let's just re-evaluate for simplicity. - */ - /* TODO(sergey): Need proper port. */ - ss->osd_evaluator->evaluateLimit(ss->osd_evaluator, osd_face_index, u, v, P, dPdu, dPdv); - VertDataCopy(co, P, ss); - if (do_normals) { - cross_v3_v3v3(no, dPdu, dPdv); - normalize_v3(no); - } - } - } -} - -static void opensubdiv_evaluateNGonFaceGrids(CCGSubSurf *ss, - CCGFace *face, - const int osd_face_index) -{ - CCGVert **all_verts = FACE_getVerts(face); - int normalDataOffset = ss->normalDataOffset; - int subdivLevels = ss->subdivLevels; - int gridSize = ccg_gridsize(subdivLevels); - int edgeSize = ccg_edgesize(subdivLevels); - int vertDataSize = ss->meshIFC.vertDataSize; - int S; - bool do_normals = ss->meshIFC.numLayers == 3; - - /* Note about handling non-quad faces. - * - * In order to deal with non-quad faces we need to split them - * into a quads in the following way: - * - * | - * (vert_next) - * | - * | - * | - * (face_center) ------------------- (v2) - * | (o)--------------------> | - * | | v | - * | | | - * | | | - * | | | - * | | y ^ | - * | | | | - * | v u x | | - * | <---(o) | - * ---- (vert_prev) ---- (v1) -------------------- (vert) - * - * This is how grids are expected to be stored and it's how - * OpenSubdiv deals with non-quad faces using ptex face indices. - * We only need to convert ptex (x, y) to grid (u, v) by some - * simple flips and evaluate the ptex face. - */ - - /* Evaluate face grids. */ -# pragma omp parallel for - for (S = 0; S < face->numVerts; S++) { - int x, y; - for (x = 0; x < gridSize; x++) { - for (y = 0; y < gridSize; y++) { - float *co = FACE_getIFCo(face, subdivLevels, S, x, y); - float *no = FACE_getIFNo(face, subdivLevels, S, x, y); - float u = 1.0f - (float)y / (gridSize - 1), v = 1.0f - (float)x / (gridSize - 1); - float P[3], dPdu[3], dPdv[3]; - - /* TODO(sergey): Need proper port. */ - ss->osd_evaluator->evaluateLimit( - ss->osd_evaluator, osd_face_index + S, u, v, P, dPdu, dPdv); - - OSD_LOG("face=%d, corner=%d, u=%f, v=%f, P=(%f, %f, %f)\n", - osd_face_index + S, - S, - u, - v, - P[0], - P[1], - P[2]); - - VertDataCopy(co, P, ss); - if (do_normals) { - cross_v3_v3v3(no, dPdu, dPdv); - normalize_v3(no); - } - - /* TODO(sergey): De-dpuplicate with the quad case. */ - if (x == gridSize - 1 && y == gridSize - 1) { - float *vert_co = VERT_getCo(FACE_getVerts(face)[S], subdivLevels); - VertDataCopy(vert_co, co, ss); - if (do_normals) { - float *vert_no = VERT_getNo(FACE_getVerts(face)[S], subdivLevels); - VertDataCopy(vert_no, no, ss); - } - } - if (S == 0 && x == 0 && y == 0) { - float *center_co = (float *)FACE_getCenterData(face); - VertDataCopy(center_co, co, ss); - if (do_normals) { - float *center_no = (float *)((byte *)FACE_getCenterData(face) + normalDataOffset); - VertDataCopy(center_no, no, ss); - } - } - } - } - for (x = 0; x < gridSize; x++) { - VertDataCopy( - FACE_getIECo(face, subdivLevels, S, x), FACE_getIFCo(face, subdivLevels, S, x, 0), ss); - if (do_normals) { - VertDataCopy( - FACE_getIENo(face, subdivLevels, S, x), FACE_getIFNo(face, subdivLevels, S, x, 0), ss); - } - } - } - - /* Evaluate edges. */ - for (S = 0; S < face->numVerts; S++) { - CCGEdge *edge = FACE_getEdges(face)[S]; - int x, S0 = 0, S1 = 0; - bool flip; - - for (x = 0; x < face->numVerts; x++) { - if (all_verts[x] == edge->v0) { - S0 = x; - } - else if (all_verts[x] == edge->v1) { - S1 = x; - } - } - if (S == face->numVerts - 1) { - flip = S0 > S1; - } - else { - flip = S0 < S1; - } - - for (x = 0; x <= edgeSize / 2; x++) { - float *edge_co = EDGE_getCo(edge, subdivLevels, x); - float *edge_no = EDGE_getNo(edge, subdivLevels, x); - float *face_edge_co; - float *face_edge_no; - if (flip) { - face_edge_co = FACE_getIFCo(face, subdivLevels, S0, gridSize - 1, gridSize - 1 - x); - face_edge_no = FACE_getIFNo(face, subdivLevels, S0, gridSize - 1, gridSize - 1 - x); - } - else { - face_edge_co = FACE_getIFCo(face, subdivLevels, S0, gridSize - 1 - x, gridSize - 1); - face_edge_no = FACE_getIFNo(face, subdivLevels, S0, gridSize - 1 - x, gridSize - 1); - } - VertDataCopy(edge_co, face_edge_co, ss); - if (do_normals) { - VertDataCopy(edge_no, face_edge_no, ss); - } - } - for (x = edgeSize / 2 + 1; x < edgeSize; x++) { - float *edge_co = EDGE_getCo(edge, subdivLevels, x); - float *edge_no = EDGE_getNo(edge, subdivLevels, x); - float *face_edge_co; - float *face_edge_no; - if (flip) { - face_edge_co = FACE_getIFCo(face, subdivLevels, S1, x - edgeSize / 2, gridSize - 1); - face_edge_no = FACE_getIFNo(face, subdivLevels, S1, x - edgeSize / 2, gridSize - 1); - } - else { - face_edge_co = FACE_getIFCo(face, subdivLevels, S1, gridSize - 1, x - edgeSize / 2); - face_edge_no = FACE_getIFNo(face, subdivLevels, S1, gridSize - 1, x - edgeSize / 2); - } - VertDataCopy(edge_co, face_edge_co, ss); - if (do_normals) { - VertDataCopy(edge_no, face_edge_no, ss); - } - } - } -} - -static void opensubdiv_evaluateGrids(CCGSubSurf *ss) -{ - int i; - for (i = 0; i < ss->fMap->curSize; i++) { - CCGFace *face = (CCGFace *)ss->fMap->buckets[i]; - for (; face; face = face->next) { - if (face->numVerts == 4) { - /* For quads we do special magic with converting face coords - * into corner coords and interpolating grids from it. - */ - opensubdiv_evaluateQuadFaceGrids(ss, face, face->osd_index); - } - else { - /* NGons and tris are split into separate osd faces which - * evaluates onto grids directly. - */ - opensubdiv_evaluateNGonFaceGrids(ss, face, face->osd_index); - } - } - } -} - -CCGError ccgSubSurf_initOpenSubdivSync(CCGSubSurf *ss) -{ - if (ss->syncState != eSyncState_None) { - return eCCGError_InvalidSyncState; - } - ss->syncState = eSyncState_OpenSubdiv; - return eCCGError_None; -} - -void ccgSubSurf_prepareTopologyRefiner(CCGSubSurf *ss, DerivedMesh *dm) -{ - if (ss->osd_mesh == NULL || ss->osd_mesh_invalid) { - if (dm->getNumPolys(dm) != 0) { - OpenSubdiv_Converter converter; - ccgSubSurf_converter_setup_from_derivedmesh(ss, dm, &converter); - /* TODO(sergey): Remove possibly previously allocated refiner. */ - OpenSubdiv_TopologyRefinerSettings settings; - settings.level = ss->subdivLevels; - settings.is_adaptive = false; - ss->osd_topology_refiner = openSubdiv_createTopologyRefinerFromConverter(&converter, - &settings); - ccgSubSurf_converter_free(&converter); - } - } - - /* Update number of grids, needed for things like final faces - * counter, used by display drawing. - */ - { - const int num_polys = dm->getNumPolys(dm); - const MPoly *mpoly = dm->getPolyArray(dm); - int poly; - ss->numGrids = 0; - for (poly = 0; poly < num_polys; poly++) { - ss->numGrids += mpoly[poly].totloop; - } - } - - { - const int num_verts = dm->getNumVerts(dm); - const MVert *mvert = dm->getVertArray(dm); - int vert; - if (ss->osd_coarse_coords != NULL && num_verts != ss->osd_num_coarse_coords) { - MEM_freeN(ss->osd_coarse_coords); - ss->osd_coarse_coords = NULL; - } - if (ss->osd_coarse_coords == NULL) { - ss->osd_coarse_coords = MEM_mallocN(sizeof(float) * 6 * num_verts, "osd coarse positions"); - } - for (vert = 0; vert < num_verts; vert++) { - copy_v3_v3(ss->osd_coarse_coords[vert * 2 + 0], mvert[vert].co); - normal_short_to_float_v3(ss->osd_coarse_coords[vert * 2 + 1], mvert[vert].no); - } - ss->osd_num_coarse_coords = num_verts; - ss->osd_coarse_coords_invalid = true; - } -} - -void ccgSubSurf__sync_opensubdiv(CCGSubSurf *ss) -{ - BLI_assert(ss->meshIFC.numLayers == 2 || ss->meshIFC.numLayers == 3); - - /* Common synchronization steps */ - ss->osd_compute = U.opensubdiv_compute_type; - - if (ss->skip_grids == false) { - /* Make sure OSD evaluator is up-to-date. */ - if (opensubdiv_ensureEvaluator(ss)) { - /* Update coarse points in the OpenSubdiv evaluator. */ - opensubdiv_updateEvaluatorCoarsePositions(ss); - - /* Evaluate opensubdiv mesh into the CCG grids. */ - opensubdiv_evaluateGrids(ss); - } - } - else { - BLI_assert(ss->meshIFC.numLayers == 3); - } - -# ifdef DUMP_RESULT_GRIDS - ccgSubSurf__dumpCoords(ss); -# endif -} - -void ccgSubSurf_free_osd_mesh(CCGSubSurf *ss) -{ - if (ss->osd_mesh != NULL) { - ccgSubSurf__delete_osdGLMesh(ss->osd_mesh); - ss->osd_mesh = NULL; - } - if (ss->osd_vao != 0) { - glDeleteVertexArrays(1, &ss->osd_vao); - ss->osd_vao = 0; - } -} - -void ccgSubSurf_getMinMax(CCGSubSurf *ss, float r_min[3], float r_max[3]) -{ - int i; - BLI_assert(ss->skip_grids == true); - if (ss->osd_num_coarse_coords == 0) { - zero_v3(r_min); - zero_v3(r_max); - } - for (i = 0; i < ss->osd_num_coarse_coords; i++) { - /* Coarse coordinates has normals interleaved into the array. */ - DO_MINMAX(ss->osd_coarse_coords[2 * i], r_min, r_max); - } -} - -/* ** Delayed delete routines ** */ - -typedef struct OsdDeletePendingItem { - struct OsdDeletePendingItem *next, *prev; - OpenSubdiv_GLMesh *osd_mesh; - unsigned int vao; -} OsdDeletePendingItem; - -static SpinLock delete_spin; -static ListBase delete_pool = {NULL, NULL}; - -static void delete_pending_push(OpenSubdiv_GLMesh *osd_mesh, unsigned int vao) -{ - OsdDeletePendingItem *new_entry = MEM_mallocN(sizeof(OsdDeletePendingItem), - "opensubdiv delete entry"); - new_entry->osd_mesh = osd_mesh; - new_entry->vao = vao; - BLI_spin_lock(&delete_spin); - BLI_addtail(&delete_pool, new_entry); - BLI_spin_unlock(&delete_spin); -} - -void ccgSubSurf__delete_osdGLMesh(OpenSubdiv_GLMesh *osd_mesh) -{ - if (BLI_thread_is_main()) { - openSubdiv_deleteOsdGLMesh(osd_mesh); - } - else { - delete_pending_push(osd_mesh, 0); - } -} - -void ccgSubSurf__delete_vertex_array(unsigned int vao) -{ - if (BLI_thread_is_main()) { - glDeleteVertexArrays(1, &vao); - } - else { - delete_pending_push(NULL, vao); - } -} - -void ccgSubSurf__delete_pending(void) -{ - OsdDeletePendingItem *entry; - BLI_assert(BLI_thread_is_main()); - BLI_spin_lock(&delete_spin); - for (entry = delete_pool.first; entry != NULL; entry = entry->next) { - if (entry->osd_mesh != NULL) { - openSubdiv_deleteOsdGLMesh(entry->osd_mesh); - } - if (entry->vao != 0) { - glDeleteVertexArrays(1, &entry->vao); - } - } - BLI_freelistN(&delete_pool); - BLI_spin_unlock(&delete_spin); -} - -void ccgSubSurf__sync_subdivUvs(CCGSubSurf *ss, bool subdiv_uvs) -{ - ss->osd_subdiv_uvs = subdiv_uvs; -} - -/* ** Public API ** */ - -void BKE_subsurf_osd_init(void) -{ - openSubdiv_init(); - BLI_spin_init(&delete_spin); -} - -void BKE_subsurf_free_unused_buffers(void) -{ - ccgSubSurf__delete_pending(); -} - -void BKE_subsurf_osd_cleanup(void) -{ - openSubdiv_cleanup(); - ccgSubSurf__delete_pending(); - BLI_spin_end(&delete_spin); -} - -#endif /* WITH_OPENSUBDIV */ diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c deleted file mode 100644 index 16766d52e57..00000000000 --- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c +++ /dev/null @@ -1,777 +0,0 @@ -/* - * 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. - */ - -/** \file - * \ingroup bke - */ - -#ifdef WITH_OPENSUBDIV - -# include <stdlib.h> - -# include "BLI_sys_types.h" // for intptr_t support -# include "MEM_guardedalloc.h" - -# include "BLI_math.h" -# include "BLI_utildefines.h" /* for BLI_assert */ - -# include "CCGSubSurf.h" -# include "CCGSubSurf_intern.h" - -# include "BKE_DerivedMesh.h" -# include "BKE_mesh_mapping.h" - -# include "opensubdiv_capi.h" -# include "opensubdiv_converter_capi.h" - -/* Use mesh element mapping structures during conversion. - * Uses more memory but is much faster than naive algorithm. - */ -# define USE_MESH_ELEMENT_MAPPING - -/** - * Converter from DerivedMesh. - */ - -typedef struct ConvDMStorage { - CCGSubSurf *ss; - DerivedMesh *dm; - -# ifdef USE_MESH_ELEMENT_MAPPING - MeshElemMap *vert_edge_map, *vert_poly_map, *edge_poly_map; - int *vert_edge_mem, *vert_poly_mem, *edge_poly_mem; -# endif - - MVert *mvert; - MEdge *medge; - MLoop *mloop; - MPoly *mpoly; - - MeshIslandStore island_store; - int num_uvs; - float *uvs; - int *face_uvs; -} ConvDMStorage; - -static OpenSubdiv_SchemeType conv_dm_get_type(const OpenSubdiv_Converter *converter) -{ - ConvDMStorage *storage = converter->user_data; - if (storage->ss->meshIFC.simpleSubdiv) { - return OSD_SCHEME_BILINEAR; - } - else { - return OSD_SCHEME_CATMARK; - } -} - -static OpenSubdiv_VtxBoundaryInterpolation conv_dm_get_vtx_boundary_interpolation( - const OpenSubdiv_Converter *UNUSED(converter)) -{ - return OSD_VTX_BOUNDARY_EDGE_ONLY; -} - -static OpenSubdiv_FVarLinearInterpolation conv_dm_get_fvar_linear_interpolation( - const OpenSubdiv_Converter *converter) -{ - ConvDMStorage *storage = converter->user_data; - if (storage->ss->osd_subdiv_uvs) { - return OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY; - } - return OSD_FVAR_LINEAR_INTERPOLATION_ALL; -} - -static bool conv_dm_specifies_full_topology(const OpenSubdiv_Converter *UNUSED(converter)) -{ - return true; -} - -static int conv_dm_get_num_faces(const OpenSubdiv_Converter *converter) -{ - ConvDMStorage *storage = converter->user_data; - DerivedMesh *dm = storage->dm; - return dm->getNumPolys(dm); -} - -static int conv_dm_get_num_edges(const OpenSubdiv_Converter *converter) -{ - ConvDMStorage *storage = converter->user_data; - DerivedMesh *dm = storage->dm; - return dm->getNumEdges(dm); -} - -static int conv_dm_get_num_verts(const OpenSubdiv_Converter *converter) -{ - ConvDMStorage *storage = converter->user_data; - DerivedMesh *dm = storage->dm; - return dm->getNumVerts(dm); -} - -static int conv_dm_get_num_face_verts(const OpenSubdiv_Converter *converter, int face) -{ - ConvDMStorage *storage = converter->user_data; - const MPoly *mpoly = &storage->mpoly[face]; - return mpoly->totloop; -} - -static void conv_dm_get_face_verts(const OpenSubdiv_Converter *converter, - int face, - int *face_verts) -{ - ConvDMStorage *storage = converter->user_data; - const MPoly *mpoly = &storage->mpoly[face]; - int loop; - for (loop = 0; loop < mpoly->totloop; loop++) { - face_verts[loop] = storage->mloop[mpoly->loopstart + loop].v; - } -} - -static void conv_dm_get_face_edges(const OpenSubdiv_Converter *converter, - int face, - int *face_edges) -{ - ConvDMStorage *storage = converter->user_data; - const MPoly *mpoly = &storage->mpoly[face]; - int loop; - for (loop = 0; loop < mpoly->totloop; loop++) { - face_edges[loop] = storage->mloop[mpoly->loopstart + loop].e; - } -} - -static void conv_dm_get_edge_verts(const OpenSubdiv_Converter *converter, - int edge, - int *edge_verts) -{ - ConvDMStorage *storage = converter->user_data; - const MEdge *medge = &storage->medge[edge]; - edge_verts[0] = medge->v1; - edge_verts[1] = medge->v2; -} - -static int conv_dm_get_num_edge_faces(const OpenSubdiv_Converter *converter, int edge) -{ - ConvDMStorage *storage = converter->user_data; -# ifndef USE_MESH_ELEMENT_MAPPING - DerivedMesh *dm = storage->dm; - int num = 0, poly; - for (poly = 0; poly < dm->getNumPolys(dm); poly++) { - const MPoly *mpoly = &user_data->mpoly[poly]; - int loop; - for (loop = 0; loop < mpoly->totloop; loop++) { - const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop]; - if (mloop->e == edge) { - num++; - break; - } - } - } - return num; -# else - return storage->edge_poly_map[edge].count; -# endif -} - -static void conv_dm_get_edge_faces(const OpenSubdiv_Converter *converter, - int edge, - int *edge_faces) -{ - ConvDMStorage *storage = converter->user_data; -# ifndef USE_MESH_ELEMENT_MAPPING - DerivedMesh *dm = storage->dm; - int num = 0, poly; - for (poly = 0; poly < dm->getNumPolys(dm); poly++) { - const MPoly *mpoly = &user_data->mpoly[poly]; - int loop; - for (loop = 0; loop < mpoly->totloop; loop++) { - const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop]; - if (mloop->e == edge) { - edge_faces[num++] = poly; - break; - } - } - } -# else - memcpy(edge_faces, - storage->edge_poly_map[edge].indices, - sizeof(int) * storage->edge_poly_map[edge].count); -# endif -} - -static float conv_dm_get_edge_sharpness(const OpenSubdiv_Converter *converter, int edge) -{ - ConvDMStorage *storage = converter->user_data; - CCGSubSurf *ss = storage->ss; - const MEdge *medge = storage->medge; - return (float)medge[edge].crease / 255.0f * ss->subdivLevels; -} - -static int conv_dm_get_num_vert_edges(const OpenSubdiv_Converter *converter, int vert) -{ - ConvDMStorage *storage = converter->user_data; -# ifndef USE_MESH_ELEMENT_MAPPING - DerivedMesh *dm = storage->dm; - int num = 0, edge; - for (edge = 0; edge < dm->getNumEdges(dm); edge++) { - const MEdge *medge = &user_data->medge[edge]; - if (medge->v1 == vert || medge->v2 == vert) { - num++; - } - } - return num; -# else - return storage->vert_edge_map[vert].count; -# endif -} - -static void conv_dm_get_vert_edges(const OpenSubdiv_Converter *converter, - int vert, - int *vert_edges) -{ - ConvDMStorage *storage = converter->user_data; -# ifndef USE_MESH_ELEMENT_MAPPING - DerivedMesh *dm = storage->dm; - int num = 0, edge; - for (edge = 0; edge < dm->getNumEdges(dm); edge++) { - const MEdge *medge = &user_data->medge[edge]; - if (medge->v1 == vert || medge->v2 == vert) { - vert_edges[num++] = edge; - } - } -# else - memcpy(vert_edges, - storage->vert_edge_map[vert].indices, - sizeof(int) * storage->vert_edge_map[vert].count); -# endif -} - -static int conv_dm_get_num_vert_faces(const OpenSubdiv_Converter *converter, int vert) -{ - ConvDMStorage *storage = converter->user_data; -# ifndef USE_MESH_ELEMENT_MAPPING - DerivedMesh *dm = storage->dm; - int num = 0, poly; - for (poly = 0; poly < dm->getNumPolys(dm); poly++) { - const MPoly *mpoly = &user_data->mpoly[poly]; - int loop; - for (loop = 0; loop < mpoly->totloop; loop++) { - const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop]; - if (mloop->v == vert) { - num++; - break; - } - } - } - return num; -# else - return storage->vert_poly_map[vert].count; -# endif -} - -static void conv_dm_get_vert_faces(const OpenSubdiv_Converter *converter, - int vert, - int *vert_faces) -{ - ConvDMStorage *storage = converter->user_data; -# ifndef USE_MESH_ELEMENT_MAPPING - DerivedMesh *dm = storage->dm; - int num = 0, poly; - for (poly = 0; poly < dm->getNumPolys(dm); poly++) { - const MPoly *mpoly = &storage->mpoly[poly]; - int loop; - for (loop = 0; loop < mpoly->totloop; loop++) { - const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop]; - if (mloop->v == vert) { - vert_faces[num++] = poly; - break; - } - } - } -# else - memcpy(vert_faces, - storage->vert_poly_map[vert].indices, - sizeof(int) * storage->vert_poly_map[vert].count); -# endif -} - -static bool conv_dm_is_infinite_sharp_vertex(const OpenSubdiv_Converter *UNUSED(converter), - int UNUSED(manifold_vertex_index)) -{ - return false; -} - -static float conv_dm_get_vertex_sharpness(const OpenSubdiv_Converter *UNUSED(converter), - int UNUSED(manifold_vertex_index)) -{ - return 0.0f; -} - -static int conv_dm_get_num_uv_layers(const OpenSubdiv_Converter *converter) -{ - ConvDMStorage *storage = converter->user_data; - DerivedMesh *dm = storage->dm; - int num_uv_layers = CustomData_number_of_layers(&dm->loopData, CD_MLOOPUV); - return num_uv_layers; -} - -static void conv_dm_precalc_uv_layer(const OpenSubdiv_Converter *converter, int layer) -{ - ConvDMStorage *storage = converter->user_data; - DerivedMesh *dm = storage->dm; - - const MLoopUV *mloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, layer); - const int num_loops = dm->getNumLoops(dm); - - /* Initialize memory required for the operations. */ - if (storage->uvs == NULL) { - storage->uvs = MEM_mallocN(sizeof(float) * 2 * num_loops, "osd uvs"); - } - if (storage->face_uvs == NULL) { - storage->face_uvs = MEM_mallocN(sizeof(int) * num_loops, "osd face uvs"); - } - - /* Calculate islands connectivity of the UVs. */ - BKE_mesh_calc_islands_loop_poly_uvmap(storage->mvert, - dm->getNumVerts(dm), - storage->medge, - dm->getNumEdges(dm), - storage->mpoly, - dm->getNumPolys(dm), - storage->mloop, - dm->getNumLoops(dm), - mloopuv, - &storage->island_store); - - /* Here we "weld" duplicated vertices from island to the same UV value. - * The idea here is that we need to pass individual islands to OpenSubdiv. - */ - storage->num_uvs = 0; - for (int island = 0; island < storage->island_store.islands_num; island++) { - MeshElemMap *island_poly_map = storage->island_store.islands[island]; - for (int poly = 0; poly < island_poly_map->count; poly++) { - int poly_index = island_poly_map->indices[poly]; - /* Within the same UV island we should share UV points across - * loops. Otherwise each poly will be subdivided individually - * which we don't really want. - */ - const MPoly *mpoly = &storage->mpoly[poly_index]; - for (int loop = 0; loop < mpoly->totloop; loop++) { - const MLoopUV *luv = &mloopuv[mpoly->loopstart + loop]; - bool found = false; - /* TODO(sergey): Quite bad loop, which gives us O(N^2) - * complexity here. But how can we do it smarter, hopefully - * without requiring lots of additional memory. - */ - for (int i = 0; i < storage->num_uvs; i++) { - if (equals_v2v2(luv->uv, &storage->uvs[2 * i])) { - storage->face_uvs[mpoly->loopstart + loop] = i; - found = true; - break; - } - } - if (!found) { - copy_v2_v2(&storage->uvs[2 * storage->num_uvs], luv->uv); - storage->face_uvs[mpoly->loopstart + loop] = storage->num_uvs; - ++storage->num_uvs; - } - } - } - } -} - -static void conv_dm_finish_uv_layer(const OpenSubdiv_Converter *converter) -{ - ConvDMStorage *storage = converter->user_data; - BKE_mesh_loop_islands_free(&storage->island_store); -} - -static int conv_dm_get_num_uvs(const OpenSubdiv_Converter *converter) -{ - ConvDMStorage *storage = converter->user_data; - return storage->num_uvs; -} - -static int conv_dm_get_face_corner_uv_index(const OpenSubdiv_Converter *converter, - int face, - int corner) -{ - ConvDMStorage *storage = converter->user_data; - const MPoly *mpoly = &storage->mpoly[face]; - return storage->face_uvs[mpoly->loopstart + corner]; -} - -static void conv_dm_free_user_data(const OpenSubdiv_Converter *converter) -{ - ConvDMStorage *user_data = converter->user_data; - if (user_data->uvs != NULL) { - MEM_freeN(user_data->uvs); - } - if (user_data->face_uvs != NULL) { - MEM_freeN(user_data->face_uvs); - } - -# ifdef USE_MESH_ELEMENT_MAPPING - MEM_freeN(user_data->vert_edge_map); - MEM_freeN(user_data->vert_edge_mem); - MEM_freeN(user_data->vert_poly_map); - MEM_freeN(user_data->vert_poly_mem); - MEM_freeN(user_data->edge_poly_map); - MEM_freeN(user_data->edge_poly_mem); -# endif - MEM_freeN(user_data); -} - -void ccgSubSurf_converter_setup_from_derivedmesh(CCGSubSurf *ss, - DerivedMesh *dm, - OpenSubdiv_Converter *converter) -{ - ConvDMStorage *user_data; - - converter->getSchemeType = conv_dm_get_type; - - converter->getVtxBoundaryInterpolation = conv_dm_get_vtx_boundary_interpolation; - converter->getFVarLinearInterpolation = conv_dm_get_fvar_linear_interpolation; - converter->specifiesFullTopology = conv_dm_specifies_full_topology; - - converter->getNumFaces = conv_dm_get_num_faces; - converter->getNumEdges = conv_dm_get_num_edges; - converter->getNumVertices = conv_dm_get_num_verts; - - converter->getNumFaceVertices = conv_dm_get_num_face_verts; - converter->getFaceVertices = conv_dm_get_face_verts; - converter->getFaceEdges = conv_dm_get_face_edges; - - converter->getEdgeVertices = conv_dm_get_edge_verts; - converter->getNumEdgeFaces = conv_dm_get_num_edge_faces; - converter->getEdgeFaces = conv_dm_get_edge_faces; - converter->getEdgeSharpness = conv_dm_get_edge_sharpness; - - converter->getNumVertexEdges = conv_dm_get_num_vert_edges; - converter->getVertexEdges = conv_dm_get_vert_edges; - converter->getNumVertexFaces = conv_dm_get_num_vert_faces; - converter->getVertexFaces = conv_dm_get_vert_faces; - converter->isInfiniteSharpVertex = conv_dm_is_infinite_sharp_vertex; - converter->getVertexSharpness = conv_dm_get_vertex_sharpness; - - converter->getNumUVLayers = conv_dm_get_num_uv_layers; - converter->precalcUVLayer = conv_dm_precalc_uv_layer; - converter->finishUVLayer = conv_dm_finish_uv_layer; - converter->getNumUVCoordinates = conv_dm_get_num_uvs; - converter->getFaceCornerUVIndex = conv_dm_get_face_corner_uv_index; - - user_data = MEM_mallocN(sizeof(ConvDMStorage), __func__); - user_data->ss = ss; - user_data->dm = dm; - - user_data->mvert = dm->getVertArray(dm); - user_data->medge = dm->getEdgeArray(dm); - user_data->mloop = dm->getLoopArray(dm); - user_data->mpoly = dm->getPolyArray(dm); - - memset(&user_data->island_store, 0, sizeof(user_data->island_store)); - - user_data->uvs = NULL; - user_data->face_uvs = NULL; - - converter->freeUserData = conv_dm_free_user_data; - converter->user_data = user_data; - -# ifdef USE_MESH_ELEMENT_MAPPING - { - const MEdge *medge = dm->getEdgeArray(dm); - const MLoop *mloop = dm->getLoopArray(dm); - const MPoly *mpoly = dm->getPolyArray(dm); - const int num_vert = dm->getNumVerts(dm), num_edge = dm->getNumEdges(dm), - num_loop = dm->getNumLoops(dm), num_poly = dm->getNumPolys(dm); - BKE_mesh_vert_edge_map_create( - &user_data->vert_edge_map, &user_data->vert_edge_mem, medge, num_vert, num_edge); - - BKE_mesh_vert_poly_map_create(&user_data->vert_poly_map, - &user_data->vert_poly_mem, - mpoly, - mloop, - num_vert, - num_poly, - num_loop); - - BKE_mesh_edge_poly_map_create(&user_data->edge_poly_map, - &user_data->edge_poly_mem, - medge, - num_edge, - mpoly, - num_poly, - mloop, - num_loop); - } -# endif /* USE_MESH_ELEMENT_MAPPING */ -} - -/** - * Converter from CCGSubSurf - */ - -static OpenSubdiv_SchemeType conv_ccg_get_bilinear_type(const OpenSubdiv_Converter *converter) -{ - CCGSubSurf *ss = converter->user_data; - if (ss->meshIFC.simpleSubdiv) { - return OSD_SCHEME_BILINEAR; - } - else { - return OSD_SCHEME_CATMARK; - } -} - -static OpenSubdiv_VtxBoundaryInterpolation conv_ccg_get_vtx_boundary_interpolation( - const OpenSubdiv_Converter *UNUSED(converter)) -{ - return OSD_VTX_BOUNDARY_EDGE_ONLY; -} - -static OpenSubdiv_FVarLinearInterpolation conv_ccg_get_fvar_linear_interpolation( - const OpenSubdiv_Converter *converter) -{ - CCGSubSurf *ss = converter->user_data; - if (ss->osd_subdiv_uvs) { - return OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY; - } - return OSD_FVAR_LINEAR_INTERPOLATION_ALL; -} - -static bool conv_ccg_specifies_full_topology(const OpenSubdiv_Converter *UNUSED(converter)) -{ - return true; -} - -static int conv_ccg_get_num_faces(const OpenSubdiv_Converter *converter) -{ - CCGSubSurf *ss = converter->user_data; - return ss->fMap->numEntries; -} - -static int conv_ccg_get_num_edges(const OpenSubdiv_Converter *converter) -{ - CCGSubSurf *ss = converter->user_data; - return ss->eMap->numEntries; -} - -static int conv_ccg_get_num_verts(const OpenSubdiv_Converter *converter) -{ - CCGSubSurf *ss = converter->user_data; - return ss->vMap->numEntries; -} - -static int conv_ccg_get_num_face_verts(const OpenSubdiv_Converter *converter, int face) -{ - CCGSubSurf *ss = converter->user_data; - CCGFace *ccg_face = ccgSubSurf_getFace(ss, POINTER_FROM_INT(face)); - return ccgSubSurf_getFaceNumVerts(ccg_face); -} - -static void conv_ccg_get_face_verts(const OpenSubdiv_Converter *converter, - int face, - int *face_verts) -{ - CCGSubSurf *ss = converter->user_data; - CCGFace *ccg_face = ccgSubSurf_getFace(ss, POINTER_FROM_INT(face)); - int num_face_verts = ccgSubSurf_getFaceNumVerts(ccg_face); - int loop; - for (loop = 0; loop < num_face_verts; loop++) { - CCGVert *ccg_vert = ccgSubSurf_getFaceVert(ccg_face, loop); - face_verts[loop] = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(ccg_vert)); - } -} - -static void conv_ccg_get_face_edges(const OpenSubdiv_Converter *converter, - int face, - int *face_edges) -{ - CCGSubSurf *ss = converter->user_data; - CCGFace *ccg_face = ccgSubSurf_getFace(ss, POINTER_FROM_INT(face)); - int num_face_verts = ccgSubSurf_getFaceNumVerts(ccg_face); - int loop; - for (loop = 0; loop < num_face_verts; loop++) { - CCGEdge *ccg_edge = ccgSubSurf_getFaceEdge(ccg_face, loop); - face_edges[loop] = POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(ccg_edge)); - } -} - -static void conv_ccg_get_edge_verts(const OpenSubdiv_Converter *converter, - int edge, - int *edge_verts) -{ - CCGSubSurf *ss = converter->user_data; - CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, POINTER_FROM_INT(edge)); - CCGVert *ccg_vert0 = ccgSubSurf_getEdgeVert0(ccg_edge); - CCGVert *ccg_vert1 = ccgSubSurf_getEdgeVert1(ccg_edge); - edge_verts[0] = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(ccg_vert0)); - edge_verts[1] = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(ccg_vert1)); -} - -static int conv_ccg_get_num_edge_faces(const OpenSubdiv_Converter *converter, int edge) -{ - CCGSubSurf *ss = converter->user_data; - CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, POINTER_FROM_INT(edge)); - return ccgSubSurf_getEdgeNumFaces(ccg_edge); -} - -static void conv_ccg_get_edge_faces(const OpenSubdiv_Converter *converter, - int edge, - int *edge_faces) -{ - CCGSubSurf *ss = converter->user_data; - CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, POINTER_FROM_INT(edge)); - int num_edge_faces = ccgSubSurf_getEdgeNumFaces(ccg_edge); - int face; - for (face = 0; face < num_edge_faces; face++) { - CCGFace *ccg_face = ccgSubSurf_getEdgeFace(ccg_edge, face); - edge_faces[face] = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(ccg_face)); - } -} - -static float conv_ccg_get_edge_sharpness(const OpenSubdiv_Converter *converter, int edge) -{ - CCGSubSurf *ss = converter->user_data; - CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, POINTER_FROM_INT(edge)); - /* TODO(sergey): Multiply by subdivision level once CPU evaluator - * is switched to uniform subdivision type. - */ - return ccg_edge->crease; -} - -static int conv_ccg_get_num_vert_edges(const OpenSubdiv_Converter *converter, int vert) -{ - CCGSubSurf *ss = converter->user_data; - CCGVert *ccg_vert = ccgSubSurf_getVert(ss, POINTER_FROM_INT(vert)); - return ccgSubSurf_getVertNumEdges(ccg_vert); -} - -static void conv_ccg_get_vert_edges(const OpenSubdiv_Converter *converter, - int vert, - int *vert_edges) -{ - CCGSubSurf *ss = converter->user_data; - CCGVert *ccg_vert = ccgSubSurf_getVert(ss, POINTER_FROM_INT(vert)); - int num_vert_edges = ccgSubSurf_getVertNumEdges(ccg_vert); - int edge; - for (edge = 0; edge < num_vert_edges; edge++) { - CCGEdge *ccg_edge = ccgSubSurf_getVertEdge(ccg_vert, edge); - vert_edges[edge] = POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(ccg_edge)); - } -} - -static int conv_ccg_get_num_vert_faces(const OpenSubdiv_Converter *converter, int vert) -{ - CCGSubSurf *ss = converter->user_data; - CCGVert *ccg_vert = ccgSubSurf_getVert(ss, POINTER_FROM_INT(vert)); - return ccgSubSurf_getVertNumFaces(ccg_vert); -} - -static void conv_ccg_get_vert_faces(const OpenSubdiv_Converter *converter, - int vert, - int *vert_faces) -{ - CCGSubSurf *ss = converter->user_data; - CCGVert *ccg_vert = ccgSubSurf_getVert(ss, POINTER_FROM_INT(vert)); - int num_vert_faces = ccgSubSurf_getVertNumFaces(ccg_vert); - int face; - for (face = 0; face < num_vert_faces; face++) { - CCGFace *ccg_face = ccgSubSurf_getVertFace(ccg_vert, face); - vert_faces[face] = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(ccg_face)); - } -} - -static bool conv_ccg_is_infinite_sharp_vertex(const OpenSubdiv_Converter *UNUSED(converter), - int UNUSED(manifold_vertex_index)) -{ - return false; -} - -static float conv_ccg_get_vertex_sharpness(const OpenSubdiv_Converter *UNUSED(converter), - int UNUSED(manifold_vertex_index)) -{ - return 0.0f; -} - -static int conv_ccg_get_num_uv_layers(const OpenSubdiv_Converter *UNUSED(converter)) -{ - return 0; -} - -static void conv_ccg_precalc_uv_layer(const OpenSubdiv_Converter *UNUSED(converter), - int UNUSED(layer)) -{ -} - -static void conv_ccg_finish_uv_layer(const OpenSubdiv_Converter *UNUSED(converter)) -{ -} - -static int conv_ccg_get_num_uvs(const OpenSubdiv_Converter *UNUSED(converter)) -{ - return 0; -} - -static int conv_ccg_get_face_corner_uv_index(const OpenSubdiv_Converter *UNUSED(converter), - int UNUSED(face), - int UNUSED(corner_)) -{ - return 0; -} - -void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss, OpenSubdiv_Converter *converter) -{ - converter->getSchemeType = conv_ccg_get_bilinear_type; - - converter->getVtxBoundaryInterpolation = conv_ccg_get_vtx_boundary_interpolation; - converter->getFVarLinearInterpolation = conv_ccg_get_fvar_linear_interpolation; - converter->specifiesFullTopology = conv_ccg_specifies_full_topology; - - converter->getNumFaces = conv_ccg_get_num_faces; - converter->getNumEdges = conv_ccg_get_num_edges; - converter->getNumVertices = conv_ccg_get_num_verts; - - converter->getNumFaceVertices = conv_ccg_get_num_face_verts; - converter->getFaceVertices = conv_ccg_get_face_verts; - converter->getFaceEdges = conv_ccg_get_face_edges; - - converter->getEdgeVertices = conv_ccg_get_edge_verts; - converter->getNumEdgeFaces = conv_ccg_get_num_edge_faces; - converter->getEdgeFaces = conv_ccg_get_edge_faces; - converter->getEdgeSharpness = conv_ccg_get_edge_sharpness; - - converter->getNumVertexEdges = conv_ccg_get_num_vert_edges; - converter->getVertexEdges = conv_ccg_get_vert_edges; - converter->getNumVertexFaces = conv_ccg_get_num_vert_faces; - converter->getVertexFaces = conv_ccg_get_vert_faces; - converter->isInfiniteSharpVertex = conv_ccg_is_infinite_sharp_vertex; - converter->getVertexSharpness = conv_ccg_get_vertex_sharpness; - - converter->getNumUVLayers = conv_ccg_get_num_uv_layers; - converter->precalcUVLayer = conv_ccg_precalc_uv_layer; - converter->finishUVLayer = conv_ccg_finish_uv_layer; - converter->getNumUVCoordinates = conv_ccg_get_num_uvs; - converter->getFaceCornerUVIndex = conv_ccg_get_face_corner_uv_index; - - converter->freeUserData = NULL; - converter->user_data = ss; -} - -void ccgSubSurf_converter_free(struct OpenSubdiv_Converter *converter) -{ - if (converter->freeUserData) { - converter->freeUserData(converter); - } -} - -#endif /* WITH_OPENSUBDIV */ diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index b3893d8600f..52fe51afcb2 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1798,9 +1798,7 @@ static void mesh_build_data(struct Depsgraph *depsgraph, } } - if (mesh_eval != NULL) { - mesh_runtime_check_normals_valid(mesh_eval); - } + mesh_runtime_check_normals_valid(mesh_eval); mesh_build_extra_data(depsgraph, ob, mesh_eval); } diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 4f51e23496c..bd39ffc65e7 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -52,6 +52,7 @@ #include "BKE_idprop.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_object.h" @@ -154,6 +155,15 @@ static void action_free_data(struct ID *id) BLI_freelistN(&action->markers); } +static void action_foreach_id(ID *id, LibraryForeachIDData *data) +{ + bAction *act = (bAction *)id; + + LISTBASE_FOREACH (TimeMarker *, marker, &act->markers) { + BKE_LIB_FOREACHID_PROCESS(data, marker->camera, IDWALK_CB_NOP); + } +} + IDTypeInfo IDType_ID_AC = { .id_code = ID_AC, .id_filter = FILTER_ID_AC, @@ -168,6 +178,7 @@ IDTypeInfo IDType_ID_AC = { .copy_data = action_copy_data, .free_data = action_free_data, .make_local = NULL, + .foreach_id = action_foreach_id, }; /* ***************** Library data level operations on action ************** */ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 06a97fc3826..36921bd2662 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -67,6 +67,7 @@ #include "BKE_scene.h" #include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" #include "BIK_api.h" @@ -500,14 +501,21 @@ static void armature_refresh_layer_used_recursive(bArmature *arm, ListBase *bone } } -/* Update the layers_used variable after bones are moved between layer - * NOTE: Used to be done in drawing code in 2.7, but that won't work with - * Copy-on-Write, as drawing uses evaluated copies. - */ -void BKE_armature_refresh_layer_used(bArmature *arm) +void BKE_armature_refresh_layer_used(struct Depsgraph *depsgraph, struct bArmature *arm) { + if (arm->edbo != NULL) { + /* Don't perform this update when the armature is in edit mode. In that case it should be + * handled by ED_armature_edit_refresh_layer_used(). */ + return; + } + arm->layer_used = 0; armature_refresh_layer_used_recursive(arm, &arm->bonebase); + + if (depsgraph == NULL || DEG_is_active(depsgraph)) { + bArmature *arm_orig = (bArmature *)DEG_get_original_id(&arm->id); + arm_orig->layer_used = arm->layer_used; + } } /* Finds the best possible extension to the name on a particular axis. (For renaming, check for diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index c21dec16555..133917e441c 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -1063,14 +1063,20 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) } } -static Brush *gpencil_brush_ensure(Main *bmain, - ToolSettings *ts, - const char *brush_name, - eObjectMode mode) +static Brush *gpencil_brush_ensure( + Main *bmain, ToolSettings *ts, const char *brush_name, eObjectMode mode, bool *r_new) { + *r_new = false; Brush *brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); + + /* If the brush exist, but the type is not GPencil or the mode is wrong, create a new one. */ + if ((brush != NULL) && ((brush->gpencil_settings == NULL) || (brush->ob_mode != mode))) { + brush = NULL; + } + if (brush == NULL) { brush = BKE_brush_add_gpencil(bmain, ts, brush_name, mode); + *r_new = true; } if (brush->gpencil_settings == NULL) { @@ -1081,164 +1087,235 @@ static Brush *gpencil_brush_ensure(Main *bmain, } /* Create a set of grease pencil Drawing presets. */ -void BKE_brush_gpencil_paint_presets(Main *bmain, ToolSettings *ts) +void BKE_brush_gpencil_paint_presets(Main *bmain, ToolSettings *ts, const bool reset) { + bool r_new = false; Paint *paint = &ts->gp_paint->paint; - + Brush *brush_prev = paint->brush; Brush *brush, *deft_draw; /* Airbrush brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Airbrush", OB_MODE_PAINT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_AIRBRUSH); + brush = gpencil_brush_ensure(bmain, ts, "Airbrush", OB_MODE_PAINT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_AIRBRUSH); + } /* Ink Pen brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Ink Pen", OB_MODE_PAINT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_INK_PEN); + brush = gpencil_brush_ensure(bmain, ts, "Ink Pen", OB_MODE_PAINT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_INK_PEN); + } /* Ink Pen Rough brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Ink Pen Rough", OB_MODE_PAINT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_INK_PEN_ROUGH); + brush = gpencil_brush_ensure(bmain, ts, "Ink Pen Rough", OB_MODE_PAINT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_INK_PEN_ROUGH); + } /* Marker Bold brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Marker Bold", OB_MODE_PAINT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_MARKER_BOLD); + brush = gpencil_brush_ensure(bmain, ts, "Marker Bold", OB_MODE_PAINT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_MARKER_BOLD); + } /* Marker Chisel brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Marker Chisel", OB_MODE_PAINT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_MARKER_CHISEL); + brush = gpencil_brush_ensure(bmain, ts, "Marker Chisel", OB_MODE_PAINT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_MARKER_CHISEL); + } /* Pen brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Pen", OB_MODE_PAINT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_PEN); + brush = gpencil_brush_ensure(bmain, ts, "Pen", OB_MODE_PAINT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_PEN); + } /* Pencil Soft brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Pencil Soft", OB_MODE_PAINT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_PENCIL_SOFT); + brush = gpencil_brush_ensure(bmain, ts, "Pencil Soft", OB_MODE_PAINT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_PENCIL_SOFT); + } /* Pencil brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Pencil", OB_MODE_PAINT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_PENCIL); + brush = gpencil_brush_ensure(bmain, ts, "Pencil", OB_MODE_PAINT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_PENCIL); + } deft_draw = brush; /* save default brush. */ /* Fill brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Fill Area", OB_MODE_PAINT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_FILL_AREA); + brush = gpencil_brush_ensure(bmain, ts, "Fill Area", OB_MODE_PAINT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_FILL_AREA); + } /* Soft Eraser brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Eraser Soft", OB_MODE_PAINT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_ERASER_SOFT); + brush = gpencil_brush_ensure(bmain, ts, "Eraser Soft", OB_MODE_PAINT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_ERASER_SOFT); + } /* Hard Eraser brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Eraser Hard", OB_MODE_PAINT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_ERASER_HARD); + brush = gpencil_brush_ensure(bmain, ts, "Eraser Hard", OB_MODE_PAINT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_ERASER_HARD); + } /* Point Eraser brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Eraser Point", OB_MODE_PAINT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_ERASER_POINT); + brush = gpencil_brush_ensure(bmain, ts, "Eraser Point", OB_MODE_PAINT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_ERASER_POINT); + } /* Stroke Eraser brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Eraser Stroke", OB_MODE_PAINT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_ERASER_STROKE); + brush = gpencil_brush_ensure(bmain, ts, "Eraser Stroke", OB_MODE_PAINT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_ERASER_STROKE); + } /* Tint brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Tint", OB_MODE_PAINT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_TINT); + brush = gpencil_brush_ensure(bmain, ts, "Tint", OB_MODE_PAINT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_TINT); + } /* Set default Draw brush. */ - BKE_paint_brush_set(paint, deft_draw); + if (reset || brush_prev == NULL) { + BKE_paint_brush_set(paint, deft_draw); + } } /* Create a set of grease pencil Vertex Paint presets. */ -void BKE_brush_gpencil_vertex_presets(Main *bmain, ToolSettings *ts) +void BKE_brush_gpencil_vertex_presets(Main *bmain, ToolSettings *ts, const bool reset) { - Paint *vertexpaint = &ts->gp_vertexpaint->paint; + bool r_new = false; + Paint *vertexpaint = &ts->gp_vertexpaint->paint; + Brush *brush_prev = vertexpaint->brush; Brush *brush, *deft_vertex; /* Vertex Draw brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Vertex Draw", OB_MODE_VERTEX_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_VERTEX_DRAW); + brush = gpencil_brush_ensure(bmain, ts, "Vertex Draw", OB_MODE_VERTEX_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_VERTEX_DRAW); + } deft_vertex = brush; /* save default brush. */ /* Vertex Blur brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Vertex Blur", OB_MODE_VERTEX_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_VERTEX_BLUR); - + brush = gpencil_brush_ensure(bmain, ts, "Vertex Blur", OB_MODE_VERTEX_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_VERTEX_BLUR); + } /* Vertex Average brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Vertex Average", OB_MODE_VERTEX_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_VERTEX_AVERAGE); - + brush = gpencil_brush_ensure(bmain, ts, "Vertex Average", OB_MODE_VERTEX_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_VERTEX_AVERAGE); + } /* Vertex Smear brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Vertex Smear", OB_MODE_VERTEX_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_VERTEX_SMEAR); - + brush = gpencil_brush_ensure(bmain, ts, "Vertex Smear", OB_MODE_VERTEX_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_VERTEX_SMEAR); + } /* Vertex Replace brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Vertex Replace", OB_MODE_VERTEX_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_VERTEX_REPLACE); + brush = gpencil_brush_ensure(bmain, ts, "Vertex Replace", OB_MODE_VERTEX_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_VERTEX_REPLACE); + } /* Set default Vertex brush. */ - BKE_paint_brush_set(vertexpaint, deft_vertex); + if (reset || brush_prev == NULL) { + BKE_paint_brush_set(vertexpaint, deft_vertex); + } } /* Create a set of grease pencil Sculpt Paint presets. */ -void BKE_brush_gpencil_sculpt_presets(Main *bmain, ToolSettings *ts) +void BKE_brush_gpencil_sculpt_presets(Main *bmain, ToolSettings *ts, const bool reset) { + bool r_new = false; + Paint *sculptpaint = &ts->gp_sculptpaint->paint; + Brush *brush_prev = sculptpaint->brush; Brush *brush, *deft_sculpt; /* Smooth brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Smooth Stroke", OB_MODE_SCULPT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_SMOOTH_STROKE); + brush = gpencil_brush_ensure(bmain, ts, "Smooth Stroke", OB_MODE_SCULPT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_SMOOTH_STROKE); + } deft_sculpt = brush; /* Strength brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Strength Stroke", OB_MODE_SCULPT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_STRENGTH_STROKE); + brush = gpencil_brush_ensure(bmain, ts, "Strength Stroke", OB_MODE_SCULPT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_STRENGTH_STROKE); + } /* Thickness brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Thickness Stroke", OB_MODE_SCULPT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_THICKNESS_STROKE); + brush = gpencil_brush_ensure(bmain, ts, "Thickness Stroke", OB_MODE_SCULPT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_THICKNESS_STROKE); + } /* Grab brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Grab Stroke", OB_MODE_SCULPT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_GRAB_STROKE); + brush = gpencil_brush_ensure(bmain, ts, "Grab Stroke", OB_MODE_SCULPT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_GRAB_STROKE); + } /* Push brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Push Stroke", OB_MODE_SCULPT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_PUSH_STROKE); + brush = gpencil_brush_ensure(bmain, ts, "Push Stroke", OB_MODE_SCULPT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_PUSH_STROKE); + } /* Twist brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Twist Stroke", OB_MODE_SCULPT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_TWIST_STROKE); + brush = gpencil_brush_ensure(bmain, ts, "Twist Stroke", OB_MODE_SCULPT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_TWIST_STROKE); + } /* Pinch brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Pinch Stroke", OB_MODE_SCULPT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_PINCH_STROKE); + brush = gpencil_brush_ensure(bmain, ts, "Pinch Stroke", OB_MODE_SCULPT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_PINCH_STROKE); + } /* Randomize brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Randomize Stroke", OB_MODE_SCULPT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_RANDOMIZE_STROKE); + brush = gpencil_brush_ensure(bmain, ts, "Randomize Stroke", OB_MODE_SCULPT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_RANDOMIZE_STROKE); + } /* Clone brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Clone Stroke", OB_MODE_SCULPT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_CLONE_STROKE); + brush = gpencil_brush_ensure(bmain, ts, "Clone Stroke", OB_MODE_SCULPT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_CLONE_STROKE); + } /* Set default brush. */ - BKE_paint_brush_set(sculptpaint, deft_sculpt); + if (reset || brush_prev == NULL) { + BKE_paint_brush_set(sculptpaint, deft_sculpt); + } } /* Create a set of grease pencil Weight Paint presets. */ -void BKE_brush_gpencil_weight_presets(Main *bmain, ToolSettings *ts) +void BKE_brush_gpencil_weight_presets(Main *bmain, ToolSettings *ts, const bool reset) { - Paint *weightpaint = &ts->gp_weightpaint->paint; + bool r_new = false; + Paint *weightpaint = &ts->gp_weightpaint->paint; + Brush *brush_prev = weightpaint->brush; Brush *brush, *deft_weight; /* Vertex Draw brush. */ - brush = gpencil_brush_ensure(bmain, ts, "Draw Weight", OB_MODE_WEIGHT_GPENCIL); - BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_DRAW_WEIGHT); + brush = gpencil_brush_ensure(bmain, ts, "Draw Weight", OB_MODE_WEIGHT_GPENCIL, &r_new); + if ((reset) || (r_new)) { + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_DRAW_WEIGHT); + } deft_weight = brush; /* save default brush. */ /* Set default brush. */ - BKE_paint_brush_set(weightpaint, deft_weight); + if (reset || brush_prev == NULL) { + BKE_paint_brush_set(weightpaint, deft_weight); + } } struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode) diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index d23b643ce70..da9dab36044 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -97,6 +97,7 @@ IDTypeInfo IDType_ID_CF = { .copy_data = cache_file_copy_data, .free_data = cache_file_free_data, .make_local = NULL, + .foreach_id = NULL, }; /* TODO: make this per cache file to avoid global locks. */ diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 583bb39a851..c1d77fd5f9e 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -34,6 +34,7 @@ #include "BKE_idtype.h" #include "BKE_layer.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_main.h" #include "BKE_object.h" @@ -128,6 +129,28 @@ static void collection_free_data(ID *id) BKE_collection_object_cache_free(collection); } +static void collection_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Collection *collection = (Collection *)id; + + LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { + BKE_LIB_FOREACHID_PROCESS(data, cob->ob, IDWALK_CB_USER); + } + LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { + BKE_LIB_FOREACHID_PROCESS(data, child->collection, IDWALK_CB_NEVER_SELF | IDWALK_CB_USER); + } + LISTBASE_FOREACH (CollectionParent *, parent, &collection->parents) { + /* XXX This is very weak. The whole idea of keeping pointers to private IDs is very bad + * anyway... */ + const int cb_flag = ((parent->collection != NULL && + (parent->collection->id.flag & LIB_EMBEDDED_DATA) != 0) ? + IDWALK_CB_EMBEDDED : + IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS( + data, parent->collection, IDWALK_CB_NEVER_SELF | IDWALK_CB_LOOPBACK | cb_flag); + } +} + IDTypeInfo IDType_ID_GR = { .id_code = ID_GR, .id_filter = FILTER_ID_GR, @@ -142,6 +165,7 @@ IDTypeInfo IDType_ID_GR = { .copy_data = collection_copy_data, .free_data = collection_free_data, .make_local = NULL, + .foreach_id = collection_foreach_id, }; /***************************** Add Collection *******************************/ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 72197869f58..0798bc95797 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -4169,7 +4169,8 @@ void BKE_nurb_handle_calc_simple_auto(Nurb *nu, BezTriple *bezt) */ void BKE_nurb_bezt_handle_test(BezTriple *bezt, const eBezTriple_Flag__Alias sel_flag, - const bool use_handle) + const bool use_handle, + const bool use_around_local) { short flag = 0; @@ -4192,6 +4193,10 @@ void BKE_nurb_bezt_handle_test(BezTriple *bezt, flag = (bezt->f2 & sel_flag) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0; } + if (use_around_local) { + flag &= ~SEL_F2; + } + /* check for partial selection */ if (!ELEM(flag, 0, SEL_F1 | SEL_F2 | SEL_F3)) { if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) { @@ -4218,7 +4223,7 @@ void BKE_nurb_bezt_handle_test(BezTriple *bezt, #undef SEL_F3 } -void BKE_nurb_handles_test(Nurb *nu, const bool use_handle) +void BKE_nurb_handles_test(Nurb *nu, const bool use_handle, const bool use_around_local) { BezTriple *bezt; int a; @@ -4230,7 +4235,7 @@ void BKE_nurb_handles_test(Nurb *nu, const bool use_handle) bezt = nu->bezt; a = nu->pntsu; while (a--) { - BKE_nurb_bezt_handle_test(bezt, SELECT, use_handle); + BKE_nurb_bezt_handle_test(bezt, SELECT, use_handle, use_around_local); bezt++; } diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 8c47401cbc3..a022f3f5d14 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -699,6 +699,24 @@ static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), const void *data, int return size; } +static void layerInterp_paint_mask( + const void **sources, const float *weights, const float *sub_weights, int count, void *dest) +{ + float mask = 0.0f; + const float *sub_weight = sub_weights; + for (int i = 0; i < count; i++) { + float weight = weights ? weights[i] : 1.0f; + const float *src = sources[i]; + if (sub_weights) { + mask += (*src) * (*sub_weight) * weight; + sub_weight++; + } + else { + mask += (*src) * weight; + } + } + *(float *)dest = mask; +} static void layerCopy_grid_paint_mask(const void *source, void *dest, int count) { @@ -1595,7 +1613,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* END BMESH ONLY */ /* 34: CD_PAINT_MASK */ - {sizeof(float), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(float), "", 0, NULL, NULL, NULL, layerInterp_paint_mask, NULL, NULL}, /* 35: CD_GRID_PAINT_MASK */ {sizeof(GridPaintMask), "GridPaintMask", diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index d73f92b6073..a3e1eeb89c7 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -1134,17 +1134,18 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, if (r_final) { if (force_mesh_conversion && !modified) { - /* XXX 2.8 : This is a workaround for by some deeper technical depts: + /* XXX 2.8 : This is a workaround for by some deeper technical debts: * - DRW Batch cache is stored inside the ob->data. * - Curve data is not COWed for instances that use different modifiers. - * This can causes the modifiers to be applied on all user of the same datablock (see T71055) + * This can causes the modifiers to be applied on all user of the same data-block + * (see T71055) * * The easy workaround is to force to generate a Mesh that will be used for display data * since a Mesh output is already used for generative modifiers. * However it does not fix problems with actual edit data still being shared. * - * The right solution would be to COW the Curve data block at the input of the modifer stack - * just like what the mesh modifier does. + * The right solution would be to COW the Curve data block at the input of the modifier + * stack just like what the mesh modifier does. * */ modified = BKE_mesh_new_nomain_from_curve_displist(ob, dispbase); } diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 79d9a40f06b..f3cc17f46f6 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -4646,9 +4646,6 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, return 1; } - /* begin thread safe malloc */ - BLI_threaded_malloc_begin(); - /* only continue if particle bb is close enough to canvas bb */ if (boundsIntersectDist(&grid->grid_bounds, &part_bb, range)) { int c_index; @@ -4684,7 +4681,6 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, &settings); } } - BLI_threaded_malloc_end(); BLI_kdtree_3d_free(tree); return 1; diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 543d5c8b7c7..5d2207b5b80 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1147,7 +1147,7 @@ void testhandles_fcurve(FCurve *fcu, eBezTriple_Flag sel_flag, const bool use_ha /* loop over beztriples */ for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) { - BKE_nurb_bezt_handle_test(bezt, sel_flag, use_handle); + BKE_nurb_bezt_handle_test(bezt, sel_flag, use_handle, false); } /* recalculate handles */ diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index fddc6b5e0ee..b75592836e0 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -3306,6 +3306,16 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *mds, Mesh *orgmesh, Obj /* Biggest dimension will be used for upscaling. */ float max_size = MAX3(size[0], size[1], size[2]); + float co_scale[3]; + co_scale[0] = max_size / ob->scale[0]; + co_scale[1] = max_size / ob->scale[1]; + co_scale[2] = max_size / ob->scale[2]; + + float co_offset[3]; + co_offset[0] = (mds->p0[0] + mds->p1[0]) / 2.0f; + co_offset[1] = (mds->p0[1] + mds->p1[1]) / 2.0f; + co_offset[2] = (mds->p0[2] + mds->p1[2]) / 2.0f; + /* Normals. */ normals = MEM_callocN(sizeof(short) * num_normals * 3, "Fluidmesh_tmp_normals"); @@ -3329,9 +3339,9 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *mds, Mesh *orgmesh, Obj mverts->co[2] *= mds->dx / mds->mesh_scale; } - mverts->co[0] *= max_size / fabsf(ob->scale[0]); - mverts->co[1] *= max_size / fabsf(ob->scale[1]); - mverts->co[2] *= max_size / fabsf(ob->scale[2]); + mul_v3_v3(mverts->co, co_scale); + add_v3_v3(mverts->co, co_offset); + # ifdef DEBUG_PRINT /* Debugging: Print coordinates of vertices. */ printf("mverts->co[0]: %f, mverts->co[1]: %f, mverts->co[2]: %f\n", @@ -3977,9 +3987,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, } } if (!baking_data && !baking_noise && next_data && next_noise) { - /* TODO (sebbas): Confirm if this read call is really needed or not. - * Currently only important to load the shadow grid. */ - has_data = manta_update_smoke_structures(mds->fluid, mmd, data_frame); + /* Nothing to do here since we already loaded noise grids. */ } else { has_data = manta_read_data(mds->fluid, mmd, data_frame); @@ -4380,8 +4388,8 @@ static void manta_smoke_calc_transparency(FluidDomainSettings *mds, ViewLayer *v } } -/* get smoke velocity and density at given coordinates - * returns fluid density or -1.0f if outside domain. */ +/* Get fluid velocity and density at given coordinates + * Returns fluid density or -1.0f if outside domain. */ float BKE_fluid_get_velocity_at(struct Object *ob, float position[3], float velocity[3]) { FluidModifierData *mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); @@ -4390,16 +4398,15 @@ float BKE_fluid_get_velocity_at(struct Object *ob, float position[3], float velo if (mmd && (mmd->type & MOD_FLUID_TYPE_DOMAIN) && mmd->domain && mmd->domain->fluid) { FluidDomainSettings *mds = mmd->domain; float time_mult = 25.f * DT_DEFAULT; + float size_mult = MAX3(mds->global_size[0], mds->global_size[1], mds->global_size[2]) / + mds->maxres; float vel_mag; - float *velX = manta_get_velocity_x(mds->fluid); - float *velY = manta_get_velocity_y(mds->fluid); - float *velZ = manta_get_velocity_z(mds->fluid); float density = 0.0f, fuel = 0.0f; float pos[3]; copy_v3_v3(pos, position); manta_pos_to_cell(mds, pos); - /* check if point is outside domain max bounds */ + /* Check if position is outside domain max bounds. */ if (pos[0] < mds->res_min[0] || pos[1] < mds->res_min[1] || pos[2] < mds->res_min[2]) { return -1.0f; } @@ -4412,9 +4419,8 @@ float BKE_fluid_get_velocity_at(struct Object *ob, float position[3], float velo pos[1] = (pos[1] - mds->res_min[1]) / ((float)mds->res[1]); pos[2] = (pos[2] - mds->res_min[2]) / ((float)mds->res[2]); - /* check if point is outside active area */ - if (mmd->domain->type == FLUID_DOMAIN_TYPE_GAS && - mmd->domain->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) { + /* Check if position is outside active area. */ + if (mds->type == FLUID_DOMAIN_TYPE_GAS && mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) { if (pos[0] < 0.0f || pos[1] < 0.0f || pos[2] < 0.0f) { return 0.0f; } @@ -4423,21 +4429,22 @@ float BKE_fluid_get_velocity_at(struct Object *ob, float position[3], float velo } } - /* get interpolated velocity */ - velocity[0] = BLI_voxel_sample_trilinear(velX, mds->res, pos) * mds->global_size[0] * - time_mult; - velocity[1] = BLI_voxel_sample_trilinear(velY, mds->res, pos) * mds->global_size[1] * - time_mult; - velocity[2] = BLI_voxel_sample_trilinear(velZ, mds->res, pos) * mds->global_size[2] * - time_mult; + /* Get interpolated velocity at given position. */ + velocity[0] = BLI_voxel_sample_trilinear(manta_get_velocity_x(mds->fluid), mds->res, pos); + velocity[1] = BLI_voxel_sample_trilinear(manta_get_velocity_y(mds->fluid), mds->res, pos); + velocity[2] = BLI_voxel_sample_trilinear(manta_get_velocity_z(mds->fluid), mds->res, pos); + + /* Convert simulation units to Blender units. */ + mul_v3_fl(velocity, size_mult); + mul_v3_fl(velocity, time_mult); - /* convert velocity direction to global space */ + /* Convert velocity direction to global space. */ vel_mag = len_v3(velocity); mul_mat3_m4_v3(mds->obmat, velocity); normalize_v3(velocity); mul_v3_fl(velocity, vel_mag); - /* use max value of fuel or smoke density */ + /* Use max value of fuel or smoke density. */ density = BLI_voxel_sample_trilinear(manta_smoke_get_density(mds->fluid), mds->res, pos); if (manta_smoke_has_fuel(mds->fluid)) { fuel = BLI_voxel_sample_trilinear(manta_smoke_get_fuel(mds->fluid), mds->res, pos); @@ -4922,7 +4929,7 @@ void BKE_fluid_modifier_create_type_data(struct FluidModifierData *mmd) /* cache options */ mmd->domain->cache_frame_start = 1; - mmd->domain->cache_frame_end = 50; + mmd->domain->cache_frame_end = 250; mmd->domain->cache_frame_pause_data = 0; mmd->domain->cache_frame_pause_noise = 0; mmd->domain->cache_frame_pause_mesh = 0; diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 92eb6ea03e2..54f2492af93 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -134,6 +134,7 @@ IDTypeInfo IDType_ID_VF = { .copy_data = vfont_copy_data, .free_data = vfont_free_data, .make_local = NULL, + .foreach_id = NULL, }; /***************************** VFont *******************************/ diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 041ef0503b9..4311e425abf 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -55,6 +55,7 @@ #include "BKE_idtype.h" #include "BKE_image.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_paint.h" @@ -97,6 +98,19 @@ static void greasepencil_free_data(ID *id) BKE_gpencil_free((bGPdata *)id, true); } +static void greasepencil_foreach_id(ID *id, LibraryForeachIDData *data) +{ + bGPdata *gpencil = (bGPdata *)id; + /* materials */ + for (int i = 0; i < gpencil->totcol; i++) { + BKE_LIB_FOREACHID_PROCESS(data, gpencil->mat[i], IDWALK_CB_USER); + } + + LISTBASE_FOREACH (bGPDlayer *, gplayer, &gpencil->layers) { + BKE_LIB_FOREACHID_PROCESS(data, gplayer->parent, IDWALK_CB_NOP); + } +} + IDTypeInfo IDType_ID_GD = { .id_code = ID_GD, .id_filter = FILTER_ID_GD, @@ -111,6 +125,7 @@ IDTypeInfo IDType_ID_GD = { .copy_data = greasepencil_copy_data, .free_data = greasepencil_free_data, .make_local = NULL, + .foreach_id = greasepencil_foreach_id, }; /* ************************************************** */ @@ -1748,7 +1763,18 @@ void BKE_gpencil_palette_ensure(Main *bmain, Scene *scene) GpPaint *gp_paint = ts->gp_paint; Paint *paint = &gp_paint->paint; + if (paint->palette != NULL) { + return; + } + paint->palette = BLI_findstring(&bmain->palettes, "Palette", offsetof(ID, name) + 2); + /* Try with first palette. */ + if (bmain->palettes.first != NULL) { + paint->palette = bmain->palettes.first; + ts->gp_vertexpaint->paint.palette = paint->palette; + return; + } + if (paint->palette == NULL) { paint->palette = BKE_palette_add(bmain, "Palette"); ts->gp_vertexpaint->paint.palette = paint->palette; diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c index 808c0347a37..90761d24b73 100644 --- a/source/blender/blenkernel/intern/hair.c +++ b/source/blender/blenkernel/intern/hair.c @@ -22,6 +22,7 @@ #include "DNA_defaults.h" #include "DNA_hair_types.h" +#include "DNA_material_types.h" #include "DNA_object_types.h" #include "BLI_listbase.h" @@ -48,50 +49,7 @@ /* Hair datablock */ -static void hair_random(Hair *hair) -{ - const int numpoints = 8; - - hair->totcurve = 500; - hair->totpoint = hair->totcurve * numpoints; - - CustomData_realloc(&hair->pdata, hair->totpoint); - CustomData_realloc(&hair->cdata, hair->totcurve); - BKE_hair_update_customdata_pointers(hair); - - RNG *rng = BLI_rng_new(0); - - for (int i = 0; i < hair->totcurve; i++) { - HairCurve *curve = &hair->curves[i]; - curve->firstpoint = i * numpoints; - curve->numpoints = numpoints; - - float theta = 2.0f * M_PI * BLI_rng_get_float(rng); - float phi = saacosf(2.0f * BLI_rng_get_float(rng) - 1.0f); - - float no[3] = {sinf(theta) * sinf(phi), cosf(theta) * sinf(phi), cosf(phi)}; - normalize_v3(no); - - float co[3]; - copy_v3_v3(co, no); - - float(*curve_co)[3] = hair->co + curve->firstpoint; - float *curve_radius = hair->radius + curve->firstpoint; - for (int key = 0; key < numpoints; key++) { - float t = key / (float)(numpoints - 1); - copy_v3_v3(curve_co[key], co); - curve_radius[key] = 0.02f * (1.0f - t); - - float offset[3] = {2.0f * BLI_rng_get_float(rng) - 1.0f, - 2.0f * BLI_rng_get_float(rng) - 1.0f, - 2.0f * BLI_rng_get_float(rng) - 1.0f}; - add_v3_v3(offset, no); - madd_v3_v3fl(co, offset, 1.0f / numpoints); - } - } - - BLI_rng_free(rng); -} +static void hair_random(Hair *hair); static void hair_init_data(ID *id) { @@ -111,15 +69,6 @@ static void hair_init_data(ID *id) hair_random(hair); } -void *BKE_hair_add(Main *bmain, const char *name) -{ - Hair *hair = BKE_libblock_alloc(bmain, ID_HA, name, 0); - - hair_init_data(&hair->id); - - return hair; -} - static void hair_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag) { Hair *hair_dst = (Hair *)id_dst; @@ -134,18 +83,6 @@ static void hair_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, co hair_dst->batch_cache = NULL; } -Hair *BKE_hair_copy(Main *bmain, const Hair *hair) -{ - Hair *hair_copy; - BKE_id_copy(bmain, &hair->id, (ID **)&hair_copy); - return hair_copy; -} - -static void hair_make_local(Main *bmain, ID *id, const int flags) -{ - BKE_lib_id_make_local_generic(bmain, id, flags); -} - static void hair_free_data(ID *id) { Hair *hair = (Hair *)id; @@ -159,6 +96,14 @@ static void hair_free_data(ID *id) MEM_SAFE_FREE(hair->mat); } +static void hair_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Hair *hair = (Hair *)id; + for (int i = 0; i < hair->totcol; i++) { + BKE_LIB_FOREACHID_PROCESS(data, hair->mat[i], IDWALK_CB_USER); + } +} + IDTypeInfo IDType_ID_HA = { .id_code = ID_HA, .id_filter = FILTER_ID_HA, @@ -172,9 +117,71 @@ IDTypeInfo IDType_ID_HA = { .init_data = hair_init_data, .copy_data = hair_copy_data, .free_data = hair_free_data, - .make_local = hair_make_local, + .make_local = NULL, + .foreach_id = hair_foreach_id, }; +static void hair_random(Hair *hair) +{ + const int numpoints = 8; + + hair->totcurve = 500; + hair->totpoint = hair->totcurve * numpoints; + + CustomData_realloc(&hair->pdata, hair->totpoint); + CustomData_realloc(&hair->cdata, hair->totcurve); + BKE_hair_update_customdata_pointers(hair); + + RNG *rng = BLI_rng_new(0); + + for (int i = 0; i < hair->totcurve; i++) { + HairCurve *curve = &hair->curves[i]; + curve->firstpoint = i * numpoints; + curve->numpoints = numpoints; + + float theta = 2.0f * M_PI * BLI_rng_get_float(rng); + float phi = saacosf(2.0f * BLI_rng_get_float(rng) - 1.0f); + + float no[3] = {sinf(theta) * sinf(phi), cosf(theta) * sinf(phi), cosf(phi)}; + normalize_v3(no); + + float co[3]; + copy_v3_v3(co, no); + + float(*curve_co)[3] = hair->co + curve->firstpoint; + float *curve_radius = hair->radius + curve->firstpoint; + for (int key = 0; key < numpoints; key++) { + float t = key / (float)(numpoints - 1); + copy_v3_v3(curve_co[key], co); + curve_radius[key] = 0.02f * (1.0f - t); + + float offset[3] = {2.0f * BLI_rng_get_float(rng) - 1.0f, + 2.0f * BLI_rng_get_float(rng) - 1.0f, + 2.0f * BLI_rng_get_float(rng) - 1.0f}; + add_v3_v3(offset, no); + madd_v3_v3fl(co, offset, 1.0f / numpoints); + } + } + + BLI_rng_free(rng); +} + +void *BKE_hair_add(Main *bmain, const char *name) +{ + Hair *hair = BKE_libblock_alloc(bmain, ID_HA, name, 0); + + hair_init_data(&hair->id); + + return hair; +} + +Hair *BKE_hair_copy(Main *bmain, const Hair *hair) +{ + Hair *hair_copy; + BKE_id_copy(bmain, &hair->id, (ID **)&hair_copy); + return hair_copy; +} + BoundBox *BKE_hair_boundbox_get(Object *ob) { BLI_assert(ob->type == OB_HAIR); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 56cdce05d57..b4a3f249c63 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -199,6 +199,7 @@ IDTypeInfo IDType_ID_IM = { .copy_data = image_copy_data, .free_data = image_free_data, .make_local = NULL, + .foreach_id = NULL, }; /* prototypes */ diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 12c1cf6bafa..780c3c2f14a 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -123,6 +123,7 @@ IDTypeInfo IDType_ID_IP = { .copy_data = NULL, .free_data = ipo_free_data, .make_local = NULL, + .foreach_id = NULL, }; /* *************************************************** */ diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c index d922c5dd24c..015fa235a06 100644 --- a/source/blender/blenkernel/intern/lib_query.c +++ b/source/blender/blenkernel/intern/lib_query.c @@ -79,64 +79,12 @@ #include "BKE_node.h" #include "BKE_particle.h" #include "BKE_rigidbody.h" +#include "BKE_screen.h" #include "BKE_sequencer.h" #include "BKE_shader_fx.h" #include "BKE_texture.h" #include "BKE_workspace.h" -#define FOREACH_FINALIZE _finalize -#define FOREACH_FINALIZE_VOID \ - if (0) { \ - goto FOREACH_FINALIZE; \ - } \ - FOREACH_FINALIZE: \ - ((void)0) - -#define FOREACH_CALLBACK_INVOKE_ID_PP(_data, id_pp, _cb_flag) \ - CHECK_TYPE(id_pp, ID **); \ - if (!((_data)->status & IDWALK_STOP)) { \ - const int _flag = (_data)->flag; \ - ID *old_id = *(id_pp); \ - const int callback_return = (_data)->callback(&(struct LibraryIDLinkCallbackData){ \ - .user_data = (_data)->user_data, \ - .id_owner = (_data)->owner_id, \ - .id_self = (_data)->self_id, \ - .id_pointer = id_pp, \ - .cb_flag = ((_cb_flag | (_data)->cb_flag) & ~(_data)->cb_flag_clear)}); \ - if (_flag & IDWALK_READONLY) { \ - BLI_assert(*(id_pp) == old_id); \ - } \ - if (old_id && (_flag & IDWALK_RECURSE)) { \ - if (BLI_gset_add((_data)->ids_handled, old_id)) { \ - if (!(callback_return & IDWALK_RET_STOP_RECURSION)) { \ - BLI_LINKSTACK_PUSH((_data)->ids_todo, old_id); \ - } \ - } \ - } \ - if (callback_return & IDWALK_RET_STOP_ITER) { \ - (_data)->status |= IDWALK_STOP; \ - goto FOREACH_FINALIZE; \ - } \ - } \ - else { \ - goto FOREACH_FINALIZE; \ - } \ - ((void)0) - -#define FOREACH_CALLBACK_INVOKE_ID(_data, id, cb_flag) \ - { \ - CHECK_TYPE_ANY(id, ID *, void *); \ - FOREACH_CALLBACK_INVOKE_ID_PP(_data, (ID **)&(id), cb_flag); \ - } \ - ((void)0) - -#define FOREACH_CALLBACK_INVOKE(_data, id_super, cb_flag) \ - { \ - CHECK_TYPE(&((id_super)->id), ID *); \ - FOREACH_CALLBACK_INVOKE_ID_PP(_data, (ID **)&(id_super), cb_flag); \ - } \ - ((void)0) - /* status */ enum { IDWALK_STOP = 1 << 0, @@ -199,6 +147,25 @@ bool BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, int } } +int BKE_lib_query_foreachid_process_flags_get(LibraryForeachIDData *data) +{ + return data->flag; +} + +int BKE_lib_query_foreachid_process_callback_flag_override(LibraryForeachIDData *data, + const int cb_flag, + const bool do_replace) +{ + const int cb_flag_backup = data->cb_flag; + if (do_replace) { + data->cb_flag = cb_flag; + } + else { + data->cb_flag |= cb_flag; + } + return cb_flag_backup; +} + static void library_foreach_ID_link(Main *bmain, ID *id_owner, ID *id, @@ -215,82 +182,13 @@ void BKE_lib_query_idpropertiesForeachIDLink_callback(IDProperty *id_prop, void BKE_LIB_FOREACHID_PROCESS_ID(data, id_prop->data.pointer, IDWALK_CB_USER); } -static void library_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSED(rbw), - ID **id_pointer, - void *user_data, - int cb_flag) -{ - LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); - - FOREACH_FINALIZE_VOID; -} - -static void library_foreach_modifiersForeachIDLink(void *user_data, - Object *UNUSED(object), - ID **id_pointer, - int cb_flag) -{ - LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); - - FOREACH_FINALIZE_VOID; -} - -static void library_foreach_gpencil_modifiersForeachIDLink(void *user_data, - Object *UNUSED(object), - ID **id_pointer, - int cb_flag) -{ - LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); - - FOREACH_FINALIZE_VOID; -} - -static void library_foreach_shaderfxForeachIDLink(void *user_data, - Object *UNUSED(object), - ID **id_pointer, - int cb_flag) -{ - LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); - - FOREACH_FINALIZE_VOID; -} - -static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con), - ID **id_pointer, - bool is_reference, - void *user_data) -{ - LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; - const int cb_flag = is_reference ? IDWALK_CB_USER : IDWALK_CB_NOP; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); - - FOREACH_FINALIZE_VOID; -} - -static void library_foreach_particlesystemsObjectLooper(ParticleSystem *UNUSED(psys), - ID **id_pointer, - void *user_data, - int cb_flag) -{ - LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); - - FOREACH_FINALIZE_VOID; -} - static void library_foreach_nla_strip(LibraryForeachIDData *data, NlaStrip *strip) { - FOREACH_CALLBACK_INVOKE(data, strip->act, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, strip->act, IDWALK_CB_USER); LISTBASE_FOREACH (NlaStrip *, substrip, &strip->strips) { library_foreach_nla_strip(data, substrip); } - - FOREACH_FINALIZE_VOID; } static void library_foreach_animationData(LibraryForeachIDData *data, AnimData *adt) @@ -301,215 +199,20 @@ static void library_foreach_animationData(LibraryForeachIDData *data, AnimData * LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) { /* only used targets */ DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { - FOREACH_CALLBACK_INVOKE_ID(data, dtar->id, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS_ID(data, dtar->id, IDWALK_CB_NOP); } DRIVER_TARGETS_LOOPER_END; } } - FOREACH_CALLBACK_INVOKE(data, adt->action, IDWALK_CB_USER); - FOREACH_CALLBACK_INVOKE(data, adt->tmpact, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, adt->action, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, adt->tmpact, IDWALK_CB_USER); LISTBASE_FOREACH (NlaTrack *, nla_track, &adt->nla_tracks) { LISTBASE_FOREACH (NlaStrip *, nla_strip, &nla_track->strips) { library_foreach_nla_strip(data, nla_strip); } } - - FOREACH_FINALIZE_VOID; -} - -static void library_foreach_paint(LibraryForeachIDData *data, Paint *paint) -{ - FOREACH_CALLBACK_INVOKE(data, paint->brush, IDWALK_CB_USER); - for (int i = 0; i < paint->tool_slots_len; i++) { - FOREACH_CALLBACK_INVOKE(data, paint->tool_slots[i].brush, IDWALK_CB_USER); - } - FOREACH_CALLBACK_INVOKE(data, paint->palette, IDWALK_CB_USER); - - FOREACH_FINALIZE_VOID; -} - -static void library_foreach_layer_collection(LibraryForeachIDData *data, ListBase *lb) -{ - LISTBASE_FOREACH (LayerCollection *, lc, lb) { - /* XXX This is very weak. The whole idea of keeping pointers to private IDs is very bad - * anyway... */ - const int cb_flag = (lc->collection != NULL && - (lc->collection->id.flag & LIB_EMBEDDED_DATA) != 0) ? - IDWALK_CB_EMBEDDED : - IDWALK_CB_NOP; - FOREACH_CALLBACK_INVOKE(data, lc->collection, cb_flag); - library_foreach_layer_collection(data, &lc->layer_collections); - } - - FOREACH_FINALIZE_VOID; -} - -/* Used by both real Collection data-blocks, and the fake horror of master collection from Scene. - */ -static void library_foreach_collection(LibraryForeachIDData *data, Collection *collection) -{ - LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { - FOREACH_CALLBACK_INVOKE(data, cob->ob, IDWALK_CB_USER); - } - LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { - FOREACH_CALLBACK_INVOKE(data, child->collection, IDWALK_CB_NEVER_SELF | IDWALK_CB_USER); - } - LISTBASE_FOREACH (CollectionParent *, parent, &collection->parents) { - /* XXX This is very weak. The whole idea of keeping pointers to private IDs is very bad - * anyway... */ - const int cb_flag = ((parent->collection != NULL && - (parent->collection->id.flag & LIB_EMBEDDED_DATA) != 0) ? - IDWALK_CB_EMBEDDED : - IDWALK_CB_NOP); - FOREACH_CALLBACK_INVOKE( - data, parent->collection, IDWALK_CB_NEVER_SELF | IDWALK_CB_LOOPBACK | cb_flag); - } - - FOREACH_FINALIZE_VOID; -} - -static void library_foreach_dopesheet(LibraryForeachIDData *data, bDopeSheet *ads) -{ - if (ads != NULL) { - FOREACH_CALLBACK_INVOKE_ID(data, ads->source, IDWALK_CB_NOP); - FOREACH_CALLBACK_INVOKE(data, ads->filter_grp, IDWALK_CB_NOP); - } - - FOREACH_FINALIZE_VOID; -} - -static void library_foreach_screen_area(LibraryForeachIDData *data, ScrArea *area) -{ - FOREACH_CALLBACK_INVOKE(data, area->full, IDWALK_CB_NOP); - - LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { - switch (sl->spacetype) { - case SPACE_VIEW3D: { - View3D *v3d = (View3D *)sl; - - FOREACH_CALLBACK_INVOKE(data, v3d->camera, IDWALK_CB_NOP); - FOREACH_CALLBACK_INVOKE(data, v3d->ob_center, IDWALK_CB_NOP); - - if (v3d->localvd) { - FOREACH_CALLBACK_INVOKE(data, v3d->localvd->camera, IDWALK_CB_NOP); - } - break; - } - case SPACE_GRAPH: { - SpaceGraph *sipo = (SpaceGraph *)sl; - - library_foreach_dopesheet(data, sipo->ads); - break; - } - case SPACE_PROPERTIES: { - SpaceProperties *sbuts = (SpaceProperties *)sl; - - FOREACH_CALLBACK_INVOKE_ID(data, sbuts->pinid, IDWALK_CB_NOP); - break; - } - case SPACE_FILE: - break; - case SPACE_ACTION: { - SpaceAction *saction = (SpaceAction *)sl; - - library_foreach_dopesheet(data, &saction->ads); - FOREACH_CALLBACK_INVOKE(data, saction->action, IDWALK_CB_NOP); - break; - } - case SPACE_IMAGE: { - SpaceImage *sima = (SpaceImage *)sl; - - FOREACH_CALLBACK_INVOKE(data, sima->image, IDWALK_CB_USER_ONE); - FOREACH_CALLBACK_INVOKE(data, sima->mask_info.mask, IDWALK_CB_USER_ONE); - FOREACH_CALLBACK_INVOKE(data, sima->gpd, IDWALK_CB_USER); - break; - } - case SPACE_SEQ: { - SpaceSeq *sseq = (SpaceSeq *)sl; - - FOREACH_CALLBACK_INVOKE(data, sseq->gpd, IDWALK_CB_USER); - break; - } - case SPACE_NLA: { - SpaceNla *snla = (SpaceNla *)sl; - - library_foreach_dopesheet(data, snla->ads); - break; - } - case SPACE_TEXT: { - SpaceText *st = (SpaceText *)sl; - - FOREACH_CALLBACK_INVOKE(data, st->text, IDWALK_CB_NOP); - break; - } - case SPACE_SCRIPT: { - SpaceScript *scpt = (SpaceScript *)sl; - - FOREACH_CALLBACK_INVOKE(data, scpt->script, IDWALK_CB_NOP); - break; - } - case SPACE_OUTLINER: { - SpaceOutliner *so = (SpaceOutliner *)sl; - - FOREACH_CALLBACK_INVOKE_ID(data, so->search_tse.id, IDWALK_CB_NOP); - - if (so->treestore != NULL) { - TreeStoreElem *tselem; - BLI_mempool_iter iter; - - BLI_mempool_iternew(so->treestore, &iter); - while ((tselem = BLI_mempool_iterstep(&iter))) { - FOREACH_CALLBACK_INVOKE_ID(data, tselem->id, IDWALK_CB_NOP); - } - } - break; - } - case SPACE_NODE: { - SpaceNode *snode = (SpaceNode *)sl; - - const bool is_private_nodetree = snode->id != NULL && - ntreeFromID(snode->id) == snode->nodetree; - - FOREACH_CALLBACK_INVOKE_ID(data, snode->id, IDWALK_CB_NOP); - FOREACH_CALLBACK_INVOKE_ID(data, snode->from, IDWALK_CB_NOP); - - FOREACH_CALLBACK_INVOKE( - data, snode->nodetree, is_private_nodetree ? IDWALK_CB_EMBEDDED : IDWALK_CB_USER_ONE); - - LISTBASE_FOREACH (bNodeTreePath *, path, &snode->treepath) { - if (path == snode->treepath.first) { - /* first nodetree in path is same as snode->nodetree */ - FOREACH_CALLBACK_INVOKE(data, - path->nodetree, - is_private_nodetree ? IDWALK_CB_EMBEDDED : IDWALK_CB_USER_ONE); - } - else { - FOREACH_CALLBACK_INVOKE(data, path->nodetree, IDWALK_CB_USER_ONE); - } - - if (path->nodetree == NULL) { - break; - } - } - - FOREACH_CALLBACK_INVOKE(data, snode->edittree, IDWALK_CB_NOP); - break; - } - case SPACE_CLIP: { - SpaceClip *sclip = (SpaceClip *)sl; - - FOREACH_CALLBACK_INVOKE(data, sclip->clip, IDWALK_CB_USER_ONE); - FOREACH_CALLBACK_INVOKE(data, sclip->mask_info.mask, IDWALK_CB_USER_ONE); - break; - } - default: - break; - } - } - - FOREACH_FINALIZE_VOID; } bool BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp) @@ -556,7 +259,6 @@ static void library_foreach_ID_link(Main *bmain, LibraryForeachIDData *inherit_data) { LibraryForeachIDData data = {.bmain = bmain}; - int i; BLI_assert(inherit_data == NULL || data.bmain == inherit_data->bmain); @@ -577,10 +279,11 @@ static void library_foreach_ID_link(Main *bmain, data.callback = callback; data.user_data = user_data; -#define CALLBACK_INVOKE_ID(check_id, cb_flag) FOREACH_CALLBACK_INVOKE_ID(&data, check_id, cb_flag) +#define CALLBACK_INVOKE_ID(check_id, cb_flag) \ + BKE_LIB_FOREACHID_PROCESS_ID(&data, check_id, cb_flag) #define CALLBACK_INVOKE(check_id_super, cb_flag) \ - FOREACH_CALLBACK_INVOKE(&data, check_id_super, cb_flag) + BKE_LIB_FOREACHID_PROCESS(&data, check_id_super, cb_flag) for (; id != NULL; id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL) { data.self_id = id; @@ -616,7 +319,7 @@ static void library_foreach_ID_link(Main *bmain, * especially if/when it starts modifying Main database). */ MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->id_user_to_used, id); for (; entry != NULL; entry = entry->next) { - FOREACH_CALLBACK_INVOKE_ID_PP(&data, entry->id_pointer, entry->usage_flag); + BKE_lib_query_foreachid_process(&data, entry->id_pointer, entry->usage_flag); } continue; } @@ -642,569 +345,15 @@ static void library_foreach_ID_link(Main *bmain, } const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id); - - /* Note: this is temp logic until all code has been ported to IDTypeInfo... */ if (id_type->foreach_id != NULL) { id_type->foreach_id(id, &data); if (data.status & IDWALK_STOP) { break; } - else { - continue; - } - } - - switch ((ID_Type)GS(id->name)) { - case ID_LI: { - BLI_assert(0); - break; - } - case ID_SCE: { - Scene *scene = (Scene *)id; - ToolSettings *toolsett = scene->toolsettings; - - CALLBACK_INVOKE(scene->camera, IDWALK_CB_NOP); - CALLBACK_INVOKE(scene->world, IDWALK_CB_USER); - CALLBACK_INVOKE(scene->set, IDWALK_CB_NEVER_SELF); - CALLBACK_INVOKE(scene->clip, IDWALK_CB_USER); - CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER); - CALLBACK_INVOKE(scene->r.bake.cage_object, IDWALK_CB_NOP); - if (scene->nodetree) { - /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - BKE_library_foreach_ID_embedded(&data, (ID **)&scene->nodetree); - } - if (scene->ed) { - Sequence *seq; - SEQP_BEGIN (scene->ed, seq) { - CALLBACK_INVOKE(seq->scene, IDWALK_CB_NEVER_SELF); - CALLBACK_INVOKE(seq->scene_camera, IDWALK_CB_NOP); - CALLBACK_INVOKE(seq->clip, IDWALK_CB_USER); - CALLBACK_INVOKE(seq->mask, IDWALK_CB_USER); - CALLBACK_INVOKE(seq->sound, IDWALK_CB_USER); - IDP_foreach_property(seq->prop, - IDP_TYPE_FILTER_ID, - BKE_lib_query_idpropertiesForeachIDLink_callback, - &data); - LISTBASE_FOREACH (SequenceModifierData *, smd, &seq->modifiers) { - CALLBACK_INVOKE(smd->mask_id, IDWALK_CB_USER); - } - - if (seq->type == SEQ_TYPE_TEXT && seq->effectdata) { - TextVars *text_data = seq->effectdata; - CALLBACK_INVOKE(text_data->text_font, IDWALK_CB_USER); - } - } - SEQ_END; - } - - /* This pointer can be NULL during old files reading, better be safe than sorry. */ - if (scene->master_collection != NULL) { - library_foreach_collection(&data, scene->master_collection); - } - - LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { - CALLBACK_INVOKE(view_layer->mat_override, IDWALK_CB_USER); - - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { - CALLBACK_INVOKE(base->object, IDWALK_CB_NOP); - } - - library_foreach_layer_collection(&data, &view_layer->layer_collections); - - LISTBASE_FOREACH (FreestyleModuleConfig *, fmc, &view_layer->freestyle_config.modules) { - if (fmc->script) { - CALLBACK_INVOKE(fmc->script, IDWALK_CB_NOP); - } - } - - LISTBASE_FOREACH (FreestyleLineSet *, fls, &view_layer->freestyle_config.linesets) { - if (fls->group) { - CALLBACK_INVOKE(fls->group, IDWALK_CB_USER); - } - - if (fls->linestyle) { - CALLBACK_INVOKE(fls->linestyle, IDWALK_CB_USER); - } - } - } - - LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) { - CALLBACK_INVOKE(marker->camera, IDWALK_CB_NOP); - } - - if (toolsett) { - CALLBACK_INVOKE(toolsett->particle.scene, IDWALK_CB_NOP); - CALLBACK_INVOKE(toolsett->particle.object, IDWALK_CB_NOP); - CALLBACK_INVOKE(toolsett->particle.shape_object, IDWALK_CB_NOP); - - library_foreach_paint(&data, &toolsett->imapaint.paint); - CALLBACK_INVOKE(toolsett->imapaint.stencil, IDWALK_CB_USER); - CALLBACK_INVOKE(toolsett->imapaint.clone, IDWALK_CB_USER); - CALLBACK_INVOKE(toolsett->imapaint.canvas, IDWALK_CB_USER); - - if (toolsett->vpaint) { - library_foreach_paint(&data, &toolsett->vpaint->paint); - } - if (toolsett->wpaint) { - library_foreach_paint(&data, &toolsett->wpaint->paint); - } - if (toolsett->sculpt) { - library_foreach_paint(&data, &toolsett->sculpt->paint); - CALLBACK_INVOKE(toolsett->sculpt->gravity_object, IDWALK_CB_NOP); - } - if (toolsett->uvsculpt) { - library_foreach_paint(&data, &toolsett->uvsculpt->paint); - } - if (toolsett->gp_paint) { - library_foreach_paint(&data, &toolsett->gp_paint->paint); - } - if (toolsett->gp_vertexpaint) { - library_foreach_paint(&data, &toolsett->gp_vertexpaint->paint); - } - if (toolsett->gp_sculptpaint) { - library_foreach_paint(&data, &toolsett->gp_sculptpaint->paint); - } - if (toolsett->gp_weightpaint) { - library_foreach_paint(&data, &toolsett->gp_weightpaint->paint); - } - - CALLBACK_INVOKE(toolsett->gp_sculpt.guide.reference_object, IDWALK_CB_NOP); - } - - if (scene->rigidbody_world) { - BKE_rigidbody_world_id_loop( - scene->rigidbody_world, library_foreach_rigidbodyworldSceneLooper, &data); - } - - break; - } - - case ID_OB: { - Object *object = (Object *)id; - - /* Object is special, proxies make things hard... */ - const int data_cb_flag = data.cb_flag; - const int proxy_cb_flag = ((data.flag & IDWALK_NO_INDIRECT_PROXY_DATA_USAGE) == 0 && - (object->proxy || object->proxy_group)) ? - IDWALK_CB_INDIRECT_USAGE : - 0; - - /* object data special case */ - data.cb_flag |= proxy_cb_flag; - if (object->type == OB_EMPTY) { - /* empty can have NULL or Image */ - CALLBACK_INVOKE_ID(object->data, IDWALK_CB_USER); - } - else { - /* when set, this can't be NULL */ - if (object->data) { - CALLBACK_INVOKE_ID(object->data, IDWALK_CB_USER | IDWALK_CB_NEVER_NULL); - } - } - data.cb_flag = data_cb_flag; - - CALLBACK_INVOKE(object->parent, IDWALK_CB_NEVER_SELF); - CALLBACK_INVOKE(object->track, IDWALK_CB_NEVER_SELF); - /* object->proxy is refcounted, but not object->proxy_group... *sigh* */ - CALLBACK_INVOKE(object->proxy, IDWALK_CB_USER | IDWALK_CB_NEVER_SELF); - CALLBACK_INVOKE(object->proxy_group, IDWALK_CB_NOP); - - /* Special case! - * Since this field is set/owned by 'user' of this ID (and not ID itself), - * it is only indirect usage if proxy object is linked... Twisted. */ - if (object->proxy_from) { - data.cb_flag = ID_IS_LINKED(object->proxy_from) ? IDWALK_CB_INDIRECT_USAGE : 0; - } - CALLBACK_INVOKE(object->proxy_from, IDWALK_CB_LOOPBACK | IDWALK_CB_NEVER_SELF); - data.cb_flag = data_cb_flag; - - CALLBACK_INVOKE(object->poselib, IDWALK_CB_USER); - - data.cb_flag |= proxy_cb_flag; - for (i = 0; i < object->totcol; i++) { - CALLBACK_INVOKE(object->mat[i], IDWALK_CB_USER); - } - data.cb_flag = data_cb_flag; - - /* Note that ob->gpd is deprecated, so no need to handle it here. */ - CALLBACK_INVOKE(object->instance_collection, IDWALK_CB_USER); - - if (object->pd) { - CALLBACK_INVOKE(object->pd->tex, IDWALK_CB_USER); - CALLBACK_INVOKE(object->pd->f_source, IDWALK_CB_NOP); - } - /* Note that ob->effect is deprecated, so no need to handle it here. */ - - if (object->pose) { - data.cb_flag |= proxy_cb_flag; - LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - IDP_foreach_property(pchan->prop, - IDP_TYPE_FILTER_ID, - BKE_lib_query_idpropertiesForeachIDLink_callback, - &data); - CALLBACK_INVOKE(pchan->custom, IDWALK_CB_USER); - BKE_constraints_id_loop( - &pchan->constraints, library_foreach_constraintObjectLooper, &data); - } - data.cb_flag = data_cb_flag; - } - - if (object->rigidbody_constraint) { - CALLBACK_INVOKE(object->rigidbody_constraint->ob1, IDWALK_CB_NEVER_SELF); - CALLBACK_INVOKE(object->rigidbody_constraint->ob2, IDWALK_CB_NEVER_SELF); - } - - if (object->lodlevels.first) { - LISTBASE_FOREACH (LodLevel *, level, &object->lodlevels) { - CALLBACK_INVOKE(level->source, IDWALK_CB_NEVER_SELF); - } - } - - BKE_modifiers_foreach_ID_link(object, library_foreach_modifiersForeachIDLink, &data); - BKE_gpencil_modifiers_foreach_ID_link( - object, library_foreach_gpencil_modifiersForeachIDLink, &data); - BKE_constraints_id_loop( - &object->constraints, library_foreach_constraintObjectLooper, &data); - BKE_shaderfx_foreach_ID_link(object, library_foreach_shaderfxForeachIDLink, &data); - - LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) { - BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, &data); - } - - if (object->soft) { - CALLBACK_INVOKE(object->soft->collision_group, IDWALK_CB_NOP); - - if (object->soft->effector_weights) { - CALLBACK_INVOKE(object->soft->effector_weights->group, IDWALK_CB_NOP); - } - } - break; - } - - case ID_AR: { - BLI_assert(0); - break; - } - - case ID_ME: { - BLI_assert(0); - break; - } - - case ID_CU: { - BLI_assert(0); - break; - } - - case ID_MB: { - BLI_assert(0); - break; - } - - case ID_MA: { - BLI_assert(0); - break; - } - - case ID_TE: { - BLI_assert(0); - break; - } - - case ID_LT: { - BLI_assert(0); - break; - } - - case ID_LA: { - break; - } - - case ID_CA: { - BLI_assert(0); - break; - } - - case ID_KE: { - break; - } - - case ID_WO: { - BLI_assert(0); - break; - } - - case ID_SPK: { - BLI_assert(0); - break; - } - - case ID_LP: { - BLI_assert(0); - break; - } - - case ID_GR: { - Collection *collection = (Collection *)id; - library_foreach_collection(&data, collection); - break; - } - - case ID_NT: { - BLI_assert(0); - break; - } - - case ID_BR: { - BLI_assert(0); - break; - } - - case ID_PA: { - ParticleSettings *psett = (ParticleSettings *)id; - CALLBACK_INVOKE(psett->instance_collection, IDWALK_CB_USER); - CALLBACK_INVOKE(psett->instance_object, IDWALK_CB_NOP); - CALLBACK_INVOKE(psett->bb_ob, IDWALK_CB_NOP); - CALLBACK_INVOKE(psett->collision_group, IDWALK_CB_NOP); - - for (i = 0; i < MAX_MTEX; i++) { - if (psett->mtex[i]) { - BKE_texture_mtex_foreach_id(&data, psett->mtex[i]); - } - } - - if (psett->effector_weights) { - CALLBACK_INVOKE(psett->effector_weights->group, IDWALK_CB_NOP); - } - - if (psett->pd) { - CALLBACK_INVOKE(psett->pd->tex, IDWALK_CB_USER); - CALLBACK_INVOKE(psett->pd->f_source, IDWALK_CB_NOP); - } - if (psett->pd2) { - CALLBACK_INVOKE(psett->pd2->tex, IDWALK_CB_USER); - CALLBACK_INVOKE(psett->pd2->f_source, IDWALK_CB_NOP); - } - - if (psett->boids) { - LISTBASE_FOREACH (BoidState *, state, &psett->boids->states) { - LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { - if (rule->type == eBoidRuleType_Avoid) { - BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule; - CALLBACK_INVOKE(gabr->ob, IDWALK_CB_NOP); - } - else if (rule->type == eBoidRuleType_FollowLeader) { - BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule; - CALLBACK_INVOKE(flbr->ob, IDWALK_CB_NOP); - } - } - } - } - - LISTBASE_FOREACH (ParticleDupliWeight *, dw, &psett->instance_weights) { - CALLBACK_INVOKE(dw->ob, IDWALK_CB_NOP); - } - break; - } - - case ID_MC: { - MovieClip *clip = (MovieClip *)id; - MovieTracking *tracking = &clip->tracking; - - CALLBACK_INVOKE(clip->gpd, IDWALK_CB_USER); - - LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) { - CALLBACK_INVOKE(track->gpd, IDWALK_CB_USER); - } - LISTBASE_FOREACH (MovieTrackingObject *, object, &tracking->objects) { - LISTBASE_FOREACH (MovieTrackingTrack *, track, &object->tracks) { - CALLBACK_INVOKE(track->gpd, IDWALK_CB_USER); - } - } - - LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, &tracking->plane_tracks) { - CALLBACK_INVOKE(plane_track->image, IDWALK_CB_USER); - } - break; - } - - case ID_MSK: { - Mask *mask = (Mask *)id; - - LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - LISTBASE_FOREACH (MaskSpline *, mask_spline, &mask_layer->splines) { - for (i = 0; i < mask_spline->tot_point; i++) { - MaskSplinePoint *point = &mask_spline->points[i]; - CALLBACK_INVOKE_ID(point->parent.id, IDWALK_CB_USER); - } - } - } - break; - } - - case ID_LS: { - FreestyleLineStyle *linestyle = (FreestyleLineStyle *)id; - - for (i = 0; i < MAX_MTEX; i++) { - if (linestyle->mtex[i]) { - BKE_texture_mtex_foreach_id(&data, linestyle->mtex[i]); - } - } - if (linestyle->nodetree) { - /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - BKE_library_foreach_ID_embedded(&data, (ID **)&linestyle->nodetree); - } - - LISTBASE_FOREACH (LineStyleModifier *, lsm, &linestyle->color_modifiers) { - if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { - LineStyleColorModifier_DistanceFromObject *p = - (LineStyleColorModifier_DistanceFromObject *)lsm; - if (p->target) { - CALLBACK_INVOKE(p->target, IDWALK_CB_NOP); - } - } - } - LISTBASE_FOREACH (LineStyleModifier *, lsm, &linestyle->alpha_modifiers) { - if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { - LineStyleAlphaModifier_DistanceFromObject *p = - (LineStyleAlphaModifier_DistanceFromObject *)lsm; - if (p->target) { - CALLBACK_INVOKE(p->target, IDWALK_CB_NOP); - } - } - } - LISTBASE_FOREACH (LineStyleModifier *, lsm, &linestyle->thickness_modifiers) { - if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { - LineStyleThicknessModifier_DistanceFromObject *p = - (LineStyleThicknessModifier_DistanceFromObject *)lsm; - if (p->target) { - CALLBACK_INVOKE(p->target, IDWALK_CB_NOP); - } - } - } - break; - } - - case ID_AC: { - bAction *act = (bAction *)id; - - LISTBASE_FOREACH (TimeMarker *, marker, &act->markers) { - CALLBACK_INVOKE(marker->camera, IDWALK_CB_NOP); - } - break; - } - - case ID_WM: { - wmWindowManager *wm = (wmWindowManager *)id; - - LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { - CALLBACK_INVOKE(win->scene, IDWALK_CB_USER_ONE); - - /* This pointer can be NULL during old files reading, better be safe than sorry. */ - if (win->workspace_hook != NULL) { - ID *workspace = (ID *)BKE_workspace_active_get(win->workspace_hook); - CALLBACK_INVOKE_ID(workspace, IDWALK_CB_NOP); - /* allow callback to set a different workspace */ - BKE_workspace_active_set(win->workspace_hook, (WorkSpace *)workspace); - } - if (data.flag & IDWALK_INCLUDE_UI) { - LISTBASE_FOREACH (ScrArea *, area, &win->global_areas.areabase) { - library_foreach_screen_area(&data, area); - } - } - } - break; - } - - case ID_WS: { - WorkSpace *workspace = (WorkSpace *)id; - ListBase *layouts = BKE_workspace_layouts_get(workspace); - - LISTBASE_FOREACH (WorkSpaceLayout *, layout, layouts) { - bScreen *screen = BKE_workspace_layout_screen_get(layout); - - /* CALLBACK_INVOKE expects an actual pointer, not a variable holding the pointer. - * However we can't access layout->screen here - * since we are outside the workspace project. */ - CALLBACK_INVOKE(screen, IDWALK_CB_USER); - /* allow callback to set a different screen */ - BKE_workspace_layout_screen_set(layout, screen); - } - break; - } - - case ID_GD: { - bGPdata *gpencil = (bGPdata *)id; - /* materials */ - for (i = 0; i < gpencil->totcol; i++) { - CALLBACK_INVOKE(gpencil->mat[i], IDWALK_CB_USER); - } - - LISTBASE_FOREACH (bGPDlayer *, gplayer, &gpencil->layers) { - CALLBACK_INVOKE(gplayer->parent, IDWALK_CB_NOP); - } - - break; - } - case ID_HA: { - Hair *hair = (Hair *)id; - for (i = 0; i < hair->totcol; i++) { - CALLBACK_INVOKE(hair->mat[i], IDWALK_CB_USER); - } - break; - } - case ID_PT: { - PointCloud *pointcloud = (PointCloud *)id; - for (i = 0; i < pointcloud->totcol; i++) { - CALLBACK_INVOKE(pointcloud->mat[i], IDWALK_CB_USER); - } - break; - } - case ID_VO: { - Volume *volume = (Volume *)id; - for (i = 0; i < volume->totcol; i++) { - CALLBACK_INVOKE(volume->mat[i], IDWALK_CB_USER); - } - break; - } - - case ID_SCR: { - if (data.flag & IDWALK_INCLUDE_UI) { - bScreen *screen = (bScreen *)id; - - LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { - library_foreach_screen_area(&data, area); - } - } - break; - } - case ID_SIM: { - Simulation *simulation = (Simulation *)id; - if (simulation->nodetree) { - /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - BKE_library_foreach_ID_embedded(&data, (ID **)&simulation->nodetree); - } - break; - } - - /* Nothing needed for those... */ - case ID_IM: - case ID_VF: - case ID_TXT: - case ID_SO: - case ID_PAL: - case ID_PC: - case ID_CF: - break; - - /* Deprecated. */ - case ID_IP: - break; } } -FOREACH_FINALIZE: if (data.ids_handled) { BLI_gset_free(data.ids_handled, NULL); BLI_LINKSTACK_FREE(data.ids_todo); @@ -1214,9 +363,6 @@ FOREACH_FINALIZE: #undef CALLBACK_INVOKE } -#undef FOREACH_CALLBACK_INVOKE_ID -#undef FOREACH_CALLBACK_INVOKE - /** * Loop over all of the ID's this data-block links to. */ diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c index 9dc338ce580..aa1005c663f 100644 --- a/source/blender/blenkernel/intern/light.c +++ b/source/blender/blenkernel/intern/light.c @@ -48,6 +48,8 @@ #include "BLT_translation.h" +#include "DEG_depsgraph.h" + static void light_init_data(ID *id) { Light *la = (Light *)id; @@ -178,3 +180,8 @@ Light *BKE_light_localize(Light *la) return lan; } + +void BKE_light_eval(struct Depsgraph *depsgraph, Light *la) +{ + DEG_debug_print_eval(depsgraph, __func__, la->id.name, la); +} diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index 0401ae48b5c..a389af5c47f 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -45,9 +45,11 @@ #include "BKE_freestyle.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_linestyle.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_texture.h" static void linestyle_init_data(ID *id) { @@ -144,6 +146,49 @@ static void linestyle_free_data(ID *id) } } +static void linestyle_foreach_id(ID *id, LibraryForeachIDData *data) +{ + FreestyleLineStyle *linestyle = (FreestyleLineStyle *)id; + + for (int i = 0; i < MAX_MTEX; i++) { + if (linestyle->mtex[i]) { + BKE_texture_mtex_foreach_id(data, linestyle->mtex[i]); + } + } + if (linestyle->nodetree) { + /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ + BKE_library_foreach_ID_embedded(data, (ID **)&linestyle->nodetree); + } + + LISTBASE_FOREACH (LineStyleModifier *, lsm, &linestyle->color_modifiers) { + if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { + LineStyleColorModifier_DistanceFromObject *p = (LineStyleColorModifier_DistanceFromObject *) + lsm; + if (p->target) { + BKE_LIB_FOREACHID_PROCESS(data, p->target, IDWALK_CB_NOP); + } + } + } + LISTBASE_FOREACH (LineStyleModifier *, lsm, &linestyle->alpha_modifiers) { + if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { + LineStyleAlphaModifier_DistanceFromObject *p = (LineStyleAlphaModifier_DistanceFromObject *) + lsm; + if (p->target) { + BKE_LIB_FOREACHID_PROCESS(data, p->target, IDWALK_CB_NOP); + } + } + } + LISTBASE_FOREACH (LineStyleModifier *, lsm, &linestyle->thickness_modifiers) { + if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { + LineStyleThicknessModifier_DistanceFromObject *p = + (LineStyleThicknessModifier_DistanceFromObject *)lsm; + if (p->target) { + BKE_LIB_FOREACHID_PROCESS(data, p->target, IDWALK_CB_NOP); + } + } + } +} + IDTypeInfo IDType_ID_LS = { .id_code = ID_LS, .id_filter = FILTER_ID_LS, @@ -158,6 +203,7 @@ IDTypeInfo IDType_ID_LS = { .copy_data = linestyle_copy_data, .free_data = linestyle_free_data, .make_local = NULL, + .foreach_id = linestyle_foreach_id, }; static const char *modifier_name[LS_MODIFIER_NUM] = { diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 6c835dc5fb2..49c909850de 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -45,6 +45,7 @@ #include "BKE_image.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_mask.h" #include "BKE_movieclip.h" @@ -79,6 +80,20 @@ static void mask_free_data(ID *id) BKE_mask_layer_free_list(&mask->masklayers); } +static void mask_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Mask *mask = (Mask *)id; + + LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { + LISTBASE_FOREACH (MaskSpline *, mask_spline, &mask_layer->splines) { + for (int i = 0; i < mask_spline->tot_point; i++) { + MaskSplinePoint *point = &mask_spline->points[i]; + BKE_LIB_FOREACHID_PROCESS_ID(data, point->parent.id, IDWALK_CB_USER); + } + } + } +} + IDTypeInfo IDType_ID_MSK = { .id_code = ID_MSK, .id_filter = FILTER_ID_MSK, @@ -93,6 +108,7 @@ IDTypeInfo IDType_ID_MSK = { .copy_data = mask_copy_data, .free_data = mask_free_data, .make_local = NULL, + .foreach_id = mask_foreach_id, }; static struct { diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 4c7b791f103..fe7c2055aef 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -36,6 +36,7 @@ #include "MEM_guardedalloc.h" #include "DNA_constraint_types.h" +#include "DNA_gpencil_types.h" #include "DNA_movieclip_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" @@ -58,6 +59,7 @@ #include "BKE_idtype.h" #include "BKE_image.h" /* openanim */ #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_movieclip.h" #include "BKE_node.h" @@ -106,6 +108,27 @@ static void movie_clip_free_data(ID *id) BKE_tracking_free(&movie_clip->tracking); } +static void movie_clip_foreach_id(ID *id, LibraryForeachIDData *data) +{ + MovieClip *movie_clip = (MovieClip *)id; + MovieTracking *tracking = &movie_clip->tracking; + + BKE_LIB_FOREACHID_PROCESS(data, movie_clip->gpd, IDWALK_CB_USER); + + LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) { + BKE_LIB_FOREACHID_PROCESS(data, track->gpd, IDWALK_CB_USER); + } + LISTBASE_FOREACH (MovieTrackingObject *, object, &tracking->objects) { + LISTBASE_FOREACH (MovieTrackingTrack *, track, &object->tracks) { + BKE_LIB_FOREACHID_PROCESS(data, track->gpd, IDWALK_CB_USER); + } + } + + LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, &tracking->plane_tracks) { + BKE_LIB_FOREACHID_PROCESS(data, plane_track->image, IDWALK_CB_USER); + } +} + IDTypeInfo IDType_ID_MC = { .id_code = ID_MC, .id_filter = FILTER_ID_MC, @@ -120,6 +143,7 @@ IDTypeInfo IDType_ID_MC = { .copy_data = movie_clip_copy_data, .free_data = movie_clip_free_data, .make_local = NULL, + .foreach_id = movie_clip_foreach_id, }; /*********************** movieclip buffer loaders *************************/ diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c index e59b19638f8..64cc9130e25 100644 --- a/source/blender/blenkernel/intern/multires_reshape.c +++ b/source/blender/blenkernel/intern/multires_reshape.c @@ -197,7 +197,16 @@ void multiresModifier_subdivide_to_level(struct Object *object, if (!has_mdisps) { CustomData_add_layer(&coarse_mesh->ldata, CD_MDISPS, CD_CALLOC, NULL, coarse_mesh->totloop); } - if (!has_mdisps || top_level == 1) { + + /* NOTE: Subdivision happens from the top level of the existing multires modifier. If it is set + * to 0 and there is mdisps layer it would mean that the modifier went out of sync with the data. + * This happens when, for example, linking modifiers from one object to another. + * + * In such cases simply ensure grids to be the proper level. + * + * If something smarter is needed it is up to the operators which does data synchronization, so + * that the mdisps layer is also synchronized. */ + if (!has_mdisps || top_level == 1 || mmd->totlvl == 0) { multires_reshape_ensure_grids(coarse_mesh, top_level); if (ELEM(mode, MULTIRES_SUBDIVIDE_LINEAR, MULTIRES_SUBDIVIDE_SIMPLE)) { multires_subdivide_create_tangent_displacement_linear_grids(object, mmd); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 6bd841ca8e5..d17575195e3 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -375,6 +375,153 @@ static void object_make_local(Main *bmain, ID *id, const int flags) } } +static void library_foreach_modifiersForeachIDLink(void *user_data, + Object *UNUSED(object), + ID **id_pointer, + int cb_flag) +{ + LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; + BKE_lib_query_foreachid_process(data, id_pointer, cb_flag); +} + +static void library_foreach_gpencil_modifiersForeachIDLink(void *user_data, + Object *UNUSED(object), + ID **id_pointer, + int cb_flag) +{ + LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; + BKE_lib_query_foreachid_process(data, id_pointer, cb_flag); +} + +static void library_foreach_shaderfxForeachIDLink(void *user_data, + Object *UNUSED(object), + ID **id_pointer, + int cb_flag) +{ + LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; + BKE_lib_query_foreachid_process(data, id_pointer, cb_flag); +} + +static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con), + ID **id_pointer, + bool is_reference, + void *user_data) +{ + LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; + const int cb_flag = is_reference ? IDWALK_CB_USER : IDWALK_CB_NOP; + BKE_lib_query_foreachid_process(data, id_pointer, cb_flag); +} + +static void library_foreach_particlesystemsObjectLooper(ParticleSystem *UNUSED(psys), + ID **id_pointer, + void *user_data, + int cb_flag) +{ + LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; + BKE_lib_query_foreachid_process(data, id_pointer, cb_flag); +} + +static void object_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Object *object = (Object *)id; + + /* Object is special, proxies make things hard... */ + const int proxy_cb_flag = ((BKE_lib_query_foreachid_process_flags_get(data) & + IDWALK_NO_INDIRECT_PROXY_DATA_USAGE) == 0 && + (object->proxy || object->proxy_group)) ? + IDWALK_CB_INDIRECT_USAGE : + 0; + + /* object data special case */ + if (object->type == OB_EMPTY) { + /* empty can have NULL or Image */ + BKE_LIB_FOREACHID_PROCESS_ID(data, object->data, proxy_cb_flag | IDWALK_CB_USER); + } + else { + /* when set, this can't be NULL */ + if (object->data) { + BKE_LIB_FOREACHID_PROCESS_ID( + data, object->data, proxy_cb_flag | IDWALK_CB_USER | IDWALK_CB_NEVER_NULL); + } + } + + BKE_LIB_FOREACHID_PROCESS(data, object->parent, IDWALK_CB_NEVER_SELF); + BKE_LIB_FOREACHID_PROCESS(data, object->track, IDWALK_CB_NEVER_SELF); + /* object->proxy is refcounted, but not object->proxy_group... *sigh* */ + BKE_LIB_FOREACHID_PROCESS(data, object->proxy, IDWALK_CB_USER | IDWALK_CB_NEVER_SELF); + BKE_LIB_FOREACHID_PROCESS(data, object->proxy_group, IDWALK_CB_NOP); + + /* Special case! + * Since this field is set/owned by 'user' of this ID (and not ID itself), + * it is only indirect usage if proxy object is linked... Twisted. */ + { + const int cb_flag_orig = BKE_lib_query_foreachid_process_callback_flag_override( + data, + (object->proxy_from != NULL && ID_IS_LINKED(object->proxy_from)) ? + IDWALK_CB_INDIRECT_USAGE : + 0, + true); + BKE_LIB_FOREACHID_PROCESS(data, object->proxy_from, IDWALK_CB_LOOPBACK | IDWALK_CB_NEVER_SELF); + BKE_lib_query_foreachid_process_callback_flag_override(data, cb_flag_orig, true); + } + + BKE_LIB_FOREACHID_PROCESS(data, object->poselib, IDWALK_CB_USER); + + for (int i = 0; i < object->totcol; i++) { + BKE_LIB_FOREACHID_PROCESS(data, object->mat[i], proxy_cb_flag | IDWALK_CB_USER); + } + + /* Note that ob->gpd is deprecated, so no need to handle it here. */ + BKE_LIB_FOREACHID_PROCESS(data, object->instance_collection, IDWALK_CB_USER); + + if (object->pd) { + BKE_LIB_FOREACHID_PROCESS(data, object->pd->tex, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, object->pd->f_source, IDWALK_CB_NOP); + } + /* Note that ob->effect is deprecated, so no need to handle it here. */ + + if (object->pose) { + const int cb_flag_orig = BKE_lib_query_foreachid_process_callback_flag_override( + data, proxy_cb_flag, false); + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + IDP_foreach_property( + pchan->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data); + BKE_LIB_FOREACHID_PROCESS(data, pchan->custom, IDWALK_CB_USER); + BKE_constraints_id_loop(&pchan->constraints, library_foreach_constraintObjectLooper, data); + } + BKE_lib_query_foreachid_process_callback_flag_override(data, cb_flag_orig, true); + } + + if (object->rigidbody_constraint) { + BKE_LIB_FOREACHID_PROCESS(data, object->rigidbody_constraint->ob1, IDWALK_CB_NEVER_SELF); + BKE_LIB_FOREACHID_PROCESS(data, object->rigidbody_constraint->ob2, IDWALK_CB_NEVER_SELF); + } + + if (object->lodlevels.first) { + LISTBASE_FOREACH (LodLevel *, level, &object->lodlevels) { + BKE_LIB_FOREACHID_PROCESS(data, level->source, IDWALK_CB_NEVER_SELF); + } + } + + BKE_modifiers_foreach_ID_link(object, library_foreach_modifiersForeachIDLink, data); + BKE_gpencil_modifiers_foreach_ID_link( + object, library_foreach_gpencil_modifiersForeachIDLink, data); + BKE_constraints_id_loop(&object->constraints, library_foreach_constraintObjectLooper, data); + BKE_shaderfx_foreach_ID_link(object, library_foreach_shaderfxForeachIDLink, data); + + LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) { + BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, data); + } + + if (object->soft) { + BKE_LIB_FOREACHID_PROCESS(data, object->soft->collision_group, IDWALK_CB_NOP); + + if (object->soft->effector_weights) { + BKE_LIB_FOREACHID_PROCESS(data, object->soft->effector_weights->group, IDWALK_CB_NOP); + } + } +} + IDTypeInfo IDType_ID_OB = { .id_code = ID_OB, .id_filter = FILTER_ID_OB, @@ -389,6 +536,7 @@ IDTypeInfo IDType_ID_OB = { .copy_data = object_copy_data, .free_data = object_free_data, .make_local = object_make_local, + .foreach_id = object_foreach_id, }; void BKE_object_workob_clear(Object *workob) @@ -3887,6 +4035,10 @@ bool BKE_object_is_child_recursive(const Object *ob_parent, const Object *ob_chi * cases false positives are hard to avoid (shape keys for example) */ int BKE_object_is_modified(Scene *scene, Object *ob) { + /* Always test on original object since evaluated object may no longer + * have shape keys or modifiers that were used to evaluate it. */ + ob = DEG_get_original_object(ob); + int flag = 0; if (BKE_key_from_object(ob)) { @@ -4017,6 +4169,10 @@ static bool modifiers_has_animation_check(const Object *ob) * and we can still if there was actual deformation afterwards */ int BKE_object_is_deform_modified(Scene *scene, Object *ob) { + /* Always test on original object since evaluated object may no longer + * have shape keys or modifiers that were used to evaluate it. */ + ob = DEG_get_original_object(ob); + ModifierData *md; VirtualModifierData virtualModifierData; int flag = 0; diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 5b608d579e8..f26b478c680 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -116,6 +116,7 @@ IDTypeInfo IDType_ID_PAL = { .copy_data = palette_copy_data, .free_data = palette_free_data, .make_local = NULL, + .foreach_id = NULL, }; static void paint_curve_copy_data(Main *UNUSED(bmain), @@ -153,6 +154,7 @@ IDTypeInfo IDType_ID_PC = { .copy_data = paint_curve_copy_data, .free_data = paint_curve_free_data, .make_local = NULL, + .foreach_id = NULL, }; const char PAINT_CURSOR_SCULPT[3] = {255, 100, 100}; @@ -547,35 +549,35 @@ void BKE_paint_runtime_init(const ToolSettings *ts, Paint *paint) paint->runtime.tool_offset = offsetof(Brush, imagepaint_tool); paint->runtime.ob_mode = OB_MODE_TEXTURE_PAINT; } - else if (paint == &ts->sculpt->paint) { + else if (ts->sculpt && paint == &ts->sculpt->paint) { paint->runtime.tool_offset = offsetof(Brush, sculpt_tool); paint->runtime.ob_mode = OB_MODE_SCULPT; } - else if (paint == &ts->vpaint->paint) { + else if (ts->vpaint && paint == &ts->vpaint->paint) { paint->runtime.tool_offset = offsetof(Brush, vertexpaint_tool); paint->runtime.ob_mode = OB_MODE_VERTEX_PAINT; } - else if (paint == &ts->wpaint->paint) { + else if (ts->wpaint && paint == &ts->wpaint->paint) { paint->runtime.tool_offset = offsetof(Brush, weightpaint_tool); paint->runtime.ob_mode = OB_MODE_WEIGHT_PAINT; } - else if (paint == &ts->uvsculpt->paint) { + else if (ts->uvsculpt && paint == &ts->uvsculpt->paint) { paint->runtime.tool_offset = offsetof(Brush, uv_sculpt_tool); paint->runtime.ob_mode = OB_MODE_EDIT; } - else if (paint == &ts->gp_paint->paint) { + else if (ts->gp_paint && paint == &ts->gp_paint->paint) { paint->runtime.tool_offset = offsetof(Brush, gpencil_tool); paint->runtime.ob_mode = OB_MODE_PAINT_GPENCIL; } - else if (paint == &ts->gp_vertexpaint->paint) { + else if (ts->gp_vertexpaint && paint == &ts->gp_vertexpaint->paint) { paint->runtime.tool_offset = offsetof(Brush, gpencil_vertex_tool); paint->runtime.ob_mode = OB_MODE_VERTEX_GPENCIL; } - else if (paint == &ts->gp_sculptpaint->paint) { + else if (ts->gp_sculptpaint && paint == &ts->gp_sculptpaint->paint) { paint->runtime.tool_offset = offsetof(Brush, gpencil_sculpt_tool); paint->runtime.ob_mode = OB_MODE_SCULPT_GPENCIL; } - else if (paint == &ts->gp_weightpaint->paint) { + else if (ts->gp_weightpaint && paint == &ts->gp_weightpaint->paint) { paint->runtime.tool_offset = offsetof(Brush, gpencil_weight_tool); paint->runtime.ob_mode = OB_MODE_WEIGHT_GPENCIL; } @@ -1480,6 +1482,7 @@ static void sculpt_update_object( SculptSession *ss = ob->sculpt; Mesh *me = BKE_object_get_original_mesh(ob); MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob); + const bool use_face_sets = (ob->mode & OB_MODE_SCULPT) != 0; ss->deform_modifiers_active = sculpt_modifiers_active(scene, sd, ob); ss->show_mask = (sd->flags & SCULPT_HIDE_MASK) == 0; @@ -1535,17 +1538,22 @@ static void sculpt_update_object( } /* Sculpt Face Sets. */ - if (!CustomData_has_layer(&me->pdata, CD_SCULPT_FACE_SETS)) { - ss->face_sets = CustomData_add_layer( - &me->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, NULL, me->totpoly); - for (int i = 0; i < me->totpoly; i++) { - ss->face_sets[i] = 1; - } + if (use_face_sets) { + if (!CustomData_has_layer(&me->pdata, CD_SCULPT_FACE_SETS)) { + ss->face_sets = CustomData_add_layer( + &me->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, NULL, me->totpoly); + for (int i = 0; i < me->totpoly; i++) { + ss->face_sets[i] = 1; + } - /* Set the default face set color if the datalayer did not exist. */ - me->face_sets_color_default = 1; + /* Set the default face set color if the datalayer did not exist. */ + me->face_sets_color_default = 1; + } + ss->face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS); + } + else { + ss->face_sets = NULL; } - ss->face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS); ss->subdiv_ccg = me_eval->runtime.subdiv_ccg; @@ -1805,11 +1813,12 @@ static PBVH *build_pbvh_for_dynamic_topology(Object *ob) return pbvh; } -static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform) +static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool respect_hide) { Mesh *me = BKE_object_get_original_mesh(ob); const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop); PBVH *pbvh = BKE_pbvh_new(); + BKE_pbvh_respect_hide_set(pbvh, respect_hide); MLoopTri *looptri = MEM_malloc_arrayN(looptris_num, sizeof(*looptri), __func__); @@ -1841,11 +1850,12 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform) return pbvh; } -static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg) +static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect_hide) { CCGKey key; BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg); PBVH *pbvh = BKE_pbvh_new(); + BKE_pbvh_respect_hide_set(pbvh, respect_hide); BKE_pbvh_build_grids(pbvh, subdiv_ccg->grids, subdiv_ccg->num_grids, @@ -1863,6 +1873,14 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob) if (ob == NULL || ob->sculpt == NULL) { return NULL; } + + bool respect_hide = true; + if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) { + if (!(BKE_paint_select_vert_test(ob) || BKE_paint_select_face_test(ob))) { + respect_hide = false; + } + } + PBVH *pbvh = ob->sculpt->pbvh; if (pbvh != NULL) { /* NOTE: It is possible that grids were re-allocated due to modifier @@ -1886,11 +1904,11 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob) Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); Mesh *mesh_eval = object_eval->data; if (mesh_eval->runtime.subdiv_ccg != NULL) { - pbvh = build_pbvh_from_ccg(ob, mesh_eval->runtime.subdiv_ccg); + pbvh = build_pbvh_from_ccg(ob, mesh_eval->runtime.subdiv_ccg, respect_hide); } else if (ob->type == OB_MESH) { Mesh *me_eval_deform = object_eval->runtime.mesh_deform_eval; - pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform); + pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform, respect_hide); } } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 2f2d3aded31..015c67806c6 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -55,21 +55,22 @@ #include "BKE_cloth.h" #include "BKE_collection.h" #include "BKE_colortools.h" -#include "BKE_effect.h" -#include "BKE_idtype.h" -#include "BKE_lattice.h" -#include "BKE_main.h" - #include "BKE_deform.h" #include "BKE_displist.h" +#include "BKE_effect.h" +#include "BKE_idtype.h" #include "BKE_key.h" +#include "BKE_lattice.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" +#include "BKE_main.h" #include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_scene.h" +#include "BKE_texture.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" @@ -146,6 +147,53 @@ static void particle_settings_free_data(ID *id) fluid_free_settings(particle_settings->fluid); } +static void particle_settings_foreach_id(ID *id, LibraryForeachIDData *data) +{ + ParticleSettings *psett = (ParticleSettings *)id; + BKE_LIB_FOREACHID_PROCESS(data, psett->instance_collection, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, psett->instance_object, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, psett->bb_ob, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, psett->collision_group, IDWALK_CB_NOP); + + for (int i = 0; i < MAX_MTEX; i++) { + if (psett->mtex[i]) { + BKE_texture_mtex_foreach_id(data, psett->mtex[i]); + } + } + + if (psett->effector_weights) { + BKE_LIB_FOREACHID_PROCESS(data, psett->effector_weights->group, IDWALK_CB_NOP); + } + + if (psett->pd) { + BKE_LIB_FOREACHID_PROCESS(data, psett->pd->tex, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, psett->pd->f_source, IDWALK_CB_NOP); + } + if (psett->pd2) { + BKE_LIB_FOREACHID_PROCESS(data, psett->pd2->tex, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, psett->pd2->f_source, IDWALK_CB_NOP); + } + + if (psett->boids) { + LISTBASE_FOREACH (BoidState *, state, &psett->boids->states) { + LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { + if (rule->type == eBoidRuleType_Avoid) { + BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule; + BKE_LIB_FOREACHID_PROCESS(data, gabr->ob, IDWALK_CB_NOP); + } + else if (rule->type == eBoidRuleType_FollowLeader) { + BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule; + BKE_LIB_FOREACHID_PROCESS(data, flbr->ob, IDWALK_CB_NOP); + } + } + } + } + + LISTBASE_FOREACH (ParticleDupliWeight *, dw, &psett->instance_weights) { + BKE_LIB_FOREACHID_PROCESS(data, dw->ob, IDWALK_CB_NOP); + } +} + IDTypeInfo IDType_ID_PA = { .id_code = ID_PA, .id_filter = FILTER_ID_PA, @@ -160,6 +208,7 @@ IDTypeInfo IDType_ID_PA = { .copy_data = particle_settings_copy_data, .free_data = particle_settings_free_data, .make_local = NULL, + .foreach_id = particle_settings_foreach_id, }; unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT]; diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 21bbdf46104..e31d2a8e005 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -295,6 +295,10 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node) node->face_vert_indices = (const int(*)[3])face_vert_indices; + if (bvh->respect_hide == false) { + has_visible = true; + } + for (int i = 0; i < totface; i++) { const MLoopTri *lt = &bvh->looptri[node->prim_indices[i]]; for (int j = 0; j < 3; j++) { @@ -302,8 +306,10 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node) bvh, map, &node->face_verts, &node->uniq_verts, bvh->mloop[lt->tri[j]].v); } - if (!paint_is_face_hidden(lt, bvh->verts, bvh->mloop)) { - has_visible = true; + if (has_visible == false) { + if (!paint_is_face_hidden(lt, bvh->verts, bvh->mloop)) { + has_visible = true; + } } } @@ -666,7 +672,7 @@ void BKE_pbvh_build_grids(PBVH *bvh, PBVH *BKE_pbvh_new(void) { PBVH *bvh = MEM_callocN(sizeof(PBVH), "pbvh"); - + bvh->respect_hide = true; return bvh; } @@ -2117,7 +2123,7 @@ static bool pbvh_faces_node_raycast(PBVH *bvh, const MLoopTri *lt = &bvh->looptri[faces[i]]; const int *face_verts = node->face_vert_indices[i]; - if (paint_is_face_hidden(lt, vert, mloop)) { + if (bvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) { continue; } @@ -2426,7 +2432,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *bvh, const MLoopTri *lt = &bvh->looptri[faces[i]]; const int *face_verts = node->face_vert_indices[i]; - if (paint_is_face_hidden(lt, vert, mloop)) { + if (bvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) { continue; } @@ -2900,6 +2906,12 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo vi->fno = NULL; vi->mvert = NULL; + vi->respect_hide = bvh->respect_hide; + if (bvh->respect_hide == false) { + /* The same value for all vertices. */ + vi->visible = true; + } + BKE_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids); BKE_pbvh_node_num_verts(bvh, node, &uniq_verts, &totvert); BKE_pbvh_node_get_verts(bvh, node, &vert_indices, &verts); @@ -3014,3 +3026,8 @@ void BKE_pbvh_face_sets_set(PBVH *bvh, int *face_sets) { bvh->face_sets = face_sets; } + +void BKE_pbvh_respect_hide_set(PBVH *bvh, bool respect_hide) +{ + bvh->respect_hide = respect_hide; +} diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h index d3e42ac7705..7397f939894 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -160,6 +160,7 @@ struct PBVH { bool deformed; bool show_mask; bool show_face_sets; + bool respect_hide; /* Dynamic topology */ BMesh *bm; diff --git a/source/blender/blenkernel/intern/pointcloud.c b/source/blender/blenkernel/intern/pointcloud.c index 79b16443122..e03888dcad7 100644 --- a/source/blender/blenkernel/intern/pointcloud.c +++ b/source/blender/blenkernel/intern/pointcloud.c @@ -21,6 +21,7 @@ #include "MEM_guardedalloc.h" #include "DNA_defaults.h" +#include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_pointcloud_types.h" @@ -48,23 +49,7 @@ /* PointCloud datablock */ -static void pointcloud_random(PointCloud *pointcloud) -{ - pointcloud->totpoint = 400; - CustomData_realloc(&pointcloud->pdata, pointcloud->totpoint); - BKE_pointcloud_update_customdata_pointers(pointcloud); - - RNG *rng = BLI_rng_new(0); - - for (int i = 0; i < pointcloud->totpoint; i++) { - pointcloud->co[i][0] = 2.0f * BLI_rng_get_float(rng) - 1.0f; - pointcloud->co[i][1] = 2.0f * BLI_rng_get_float(rng) - 1.0f; - pointcloud->co[i][2] = 2.0f * BLI_rng_get_float(rng) - 1.0f; - pointcloud->radius[i] = 0.05f * BLI_rng_get_float(rng); - } - - BLI_rng_free(rng); -} +static void pointcloud_random(PointCloud *pointcloud); static void pointcloud_init_data(ID *id) { @@ -81,15 +66,6 @@ static void pointcloud_init_data(ID *id) pointcloud_random(pointcloud); } -void *BKE_pointcloud_add(Main *bmain, const char *name) -{ - PointCloud *pointcloud = BKE_libblock_alloc(bmain, ID_PT, name, 0); - - pointcloud_init_data(&pointcloud->id); - - return pointcloud; -} - static void pointcloud_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag) { PointCloud *pointcloud_dst = (PointCloud *)id_dst; @@ -105,18 +81,6 @@ static void pointcloud_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_s BKE_pointcloud_update_customdata_pointers(pointcloud_dst); } -PointCloud *BKE_pointcloud_copy(Main *bmain, const PointCloud *pointcloud) -{ - PointCloud *pointcloud_copy; - BKE_id_copy(bmain, &pointcloud->id, (ID **)&pointcloud_copy); - return pointcloud_copy; -} - -static void pointcloud_make_local(Main *bmain, ID *id, const int flags) -{ - BKE_lib_id_make_local_generic(bmain, id, flags); -} - static void pointcloud_free_data(ID *id) { PointCloud *pointcloud = (PointCloud *)id; @@ -126,6 +90,14 @@ static void pointcloud_free_data(ID *id) MEM_SAFE_FREE(pointcloud->mat); } +static void pointcloud_foreach_id(ID *id, LibraryForeachIDData *data) +{ + PointCloud *pointcloud = (PointCloud *)id; + for (int i = 0; i < pointcloud->totcol; i++) { + BKE_LIB_FOREACHID_PROCESS(data, pointcloud->mat[i], IDWALK_CB_USER); + } +} + IDTypeInfo IDType_ID_PT = { .id_code = ID_PT, .id_filter = FILTER_ID_PT, @@ -139,9 +111,44 @@ IDTypeInfo IDType_ID_PT = { .init_data = pointcloud_init_data, .copy_data = pointcloud_copy_data, .free_data = pointcloud_free_data, - .make_local = pointcloud_make_local, + .make_local = NULL, + .foreach_id = pointcloud_foreach_id, }; +static void pointcloud_random(PointCloud *pointcloud) +{ + pointcloud->totpoint = 400; + CustomData_realloc(&pointcloud->pdata, pointcloud->totpoint); + BKE_pointcloud_update_customdata_pointers(pointcloud); + + RNG *rng = BLI_rng_new(0); + + for (int i = 0; i < pointcloud->totpoint; i++) { + pointcloud->co[i][0] = 2.0f * BLI_rng_get_float(rng) - 1.0f; + pointcloud->co[i][1] = 2.0f * BLI_rng_get_float(rng) - 1.0f; + pointcloud->co[i][2] = 2.0f * BLI_rng_get_float(rng) - 1.0f; + pointcloud->radius[i] = 0.05f * BLI_rng_get_float(rng); + } + + BLI_rng_free(rng); +} + +void *BKE_pointcloud_add(Main *bmain, const char *name) +{ + PointCloud *pointcloud = BKE_libblock_alloc(bmain, ID_PT, name, 0); + + pointcloud_init_data(&pointcloud->id); + + return pointcloud; +} + +PointCloud *BKE_pointcloud_copy(Main *bmain, const PointCloud *pointcloud) +{ + PointCloud *pointcloud_copy; + BKE_id_copy(bmain, &pointcloud->id, (ID **)&pointcloud_copy); + return pointcloud_copy; +} + BoundBox *BKE_pointcloud_boundbox_get(Object *ob) { BLI_assert(ob->type == OB_POINTCLOUD); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index be6a4e4022b..34249e0a8f7 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -33,6 +33,7 @@ #include "DNA_defaults.h" #include "DNA_gpencil_types.h" #include "DNA_linestyle_types.h" +#include "DNA_mask_types.h" #include "DNA_mesh_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" @@ -42,6 +43,7 @@ #include "DNA_sequence_types.h" #include "DNA_sound_types.h" #include "DNA_space_types.h" +#include "DNA_text_types.h" #include "DNA_view3d_types.h" #include "DNA_windowmanager_types.h" #include "DNA_workspace_types.h" @@ -77,6 +79,7 @@ #include "BKE_image.h" #include "BKE_layer.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_linestyle.h" #include "BKE_main.h" @@ -418,6 +421,155 @@ static void scene_free_data(ID *id) BLI_assert(scene->layer_properties == NULL); } +static void library_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSED(rbw), + ID **id_pointer, + void *user_data, + int cb_flag) +{ + LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; + BKE_lib_query_foreachid_process(data, id_pointer, cb_flag); +} + +static void library_foreach_paint(LibraryForeachIDData *data, Paint *paint) +{ + BKE_LIB_FOREACHID_PROCESS(data, paint->brush, IDWALK_CB_USER); + for (int i = 0; i < paint->tool_slots_len; i++) { + BKE_LIB_FOREACHID_PROCESS(data, paint->tool_slots[i].brush, IDWALK_CB_USER); + } + BKE_LIB_FOREACHID_PROCESS(data, paint->palette, IDWALK_CB_USER); +} + +static void library_foreach_layer_collection(LibraryForeachIDData *data, ListBase *lb) +{ + LISTBASE_FOREACH (LayerCollection *, lc, lb) { + /* XXX This is very weak. The whole idea of keeping pointers to private IDs is very bad + * anyway... */ + const int cb_flag = (lc->collection != NULL && + (lc->collection->id.flag & LIB_EMBEDDED_DATA) != 0) ? + IDWALK_CB_EMBEDDED : + IDWALK_CB_NOP; + BKE_LIB_FOREACHID_PROCESS(data, lc->collection, cb_flag); + library_foreach_layer_collection(data, &lc->layer_collections); + } +} + +static void scene_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Scene *scene = (Scene *)id; + + BKE_LIB_FOREACHID_PROCESS(data, scene->camera, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, scene->world, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, scene->set, IDWALK_CB_NEVER_SELF); + BKE_LIB_FOREACHID_PROCESS(data, scene->clip, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, scene->gpd, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, scene->r.bake.cage_object, IDWALK_CB_NOP); + if (scene->nodetree) { + /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ + BKE_library_foreach_ID_embedded(data, (ID **)&scene->nodetree); + } + if (scene->ed) { + Sequence *seq; + SEQP_BEGIN (scene->ed, seq) { + BKE_LIB_FOREACHID_PROCESS(data, seq->scene, IDWALK_CB_NEVER_SELF); + BKE_LIB_FOREACHID_PROCESS(data, seq->scene_camera, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, seq->clip, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, seq->mask, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, seq->sound, IDWALK_CB_USER); + IDP_foreach_property( + seq->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data); + LISTBASE_FOREACH (SequenceModifierData *, smd, &seq->modifiers) { + BKE_LIB_FOREACHID_PROCESS(data, smd->mask_id, IDWALK_CB_USER); + } + + if (seq->type == SEQ_TYPE_TEXT && seq->effectdata) { + TextVars *text_data = seq->effectdata; + BKE_LIB_FOREACHID_PROCESS(data, text_data->text_font, IDWALK_CB_USER); + } + } + SEQ_END; + } + + /* This pointer can be NULL during old files reading, better be safe than sorry. */ + if (scene->master_collection != NULL) { + BKE_library_foreach_ID_embedded(data, (ID **)&scene->master_collection); + } + + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + BKE_LIB_FOREACHID_PROCESS(data, view_layer->mat_override, IDWALK_CB_USER); + + LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_LIB_FOREACHID_PROCESS(data, base->object, IDWALK_CB_NOP); + } + + library_foreach_layer_collection(data, &view_layer->layer_collections); + + LISTBASE_FOREACH (FreestyleModuleConfig *, fmc, &view_layer->freestyle_config.modules) { + if (fmc->script) { + BKE_LIB_FOREACHID_PROCESS(data, fmc->script, IDWALK_CB_NOP); + } + } + + LISTBASE_FOREACH (FreestyleLineSet *, fls, &view_layer->freestyle_config.linesets) { + if (fls->group) { + BKE_LIB_FOREACHID_PROCESS(data, fls->group, IDWALK_CB_USER); + } + + if (fls->linestyle) { + BKE_LIB_FOREACHID_PROCESS(data, fls->linestyle, IDWALK_CB_USER); + } + } + } + + LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) { + BKE_LIB_FOREACHID_PROCESS(data, marker->camera, IDWALK_CB_NOP); + } + + ToolSettings *toolsett = scene->toolsettings; + if (toolsett) { + BKE_LIB_FOREACHID_PROCESS(data, toolsett->particle.scene, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, toolsett->particle.object, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, toolsett->particle.shape_object, IDWALK_CB_NOP); + + library_foreach_paint(data, &toolsett->imapaint.paint); + BKE_LIB_FOREACHID_PROCESS(data, toolsett->imapaint.stencil, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, toolsett->imapaint.clone, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, toolsett->imapaint.canvas, IDWALK_CB_USER); + + if (toolsett->vpaint) { + library_foreach_paint(data, &toolsett->vpaint->paint); + } + if (toolsett->wpaint) { + library_foreach_paint(data, &toolsett->wpaint->paint); + } + if (toolsett->sculpt) { + library_foreach_paint(data, &toolsett->sculpt->paint); + BKE_LIB_FOREACHID_PROCESS(data, toolsett->sculpt->gravity_object, IDWALK_CB_NOP); + } + if (toolsett->uvsculpt) { + library_foreach_paint(data, &toolsett->uvsculpt->paint); + } + if (toolsett->gp_paint) { + library_foreach_paint(data, &toolsett->gp_paint->paint); + } + if (toolsett->gp_vertexpaint) { + library_foreach_paint(data, &toolsett->gp_vertexpaint->paint); + } + if (toolsett->gp_sculptpaint) { + library_foreach_paint(data, &toolsett->gp_sculptpaint->paint); + } + if (toolsett->gp_weightpaint) { + library_foreach_paint(data, &toolsett->gp_weightpaint->paint); + } + + BKE_LIB_FOREACHID_PROCESS(data, toolsett->gp_sculpt.guide.reference_object, IDWALK_CB_NOP); + } + + if (scene->rigidbody_world) { + BKE_rigidbody_world_id_loop( + scene->rigidbody_world, library_foreach_rigidbodyworldSceneLooper, data); + } +} + IDTypeInfo IDType_ID_SCE = { .id_code = ID_SCE, .id_filter = FILTER_ID_SCE, @@ -434,6 +586,7 @@ IDTypeInfo IDType_ID_SCE = { /* For now default `BKE_lib_id_make_local_generic()` should work, may need more work though to * support all possible corner cases. */ .make_local = NULL, + .foreach_id = scene_foreach_id, }; const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE"; @@ -1175,34 +1328,6 @@ int BKE_scene_orientation_slot_get_index(const TransformOrientationSlot *orient_ /** \} */ -/* That's like really a bummer, because currently animation data for armatures - * might want to use pose, and pose might be missing on the object. - * This happens when changing visible layers, which leads to situations when - * pose is missing or marked for recalc, animation will change it and then - * object update will restore the pose. - * - * This could be solved by the new dependency graph, but for until then we'll - * do an extra pass on the objects to ensure it's all fine. - */ -#define POSE_ANIMATION_WORKAROUND - -#ifdef POSE_ANIMATION_WORKAROUND -static void scene_armature_depsgraph_workaround(Main *bmain, Depsgraph *depsgraph) -{ - Object *ob; - if (BLI_listbase_is_empty(&bmain->armatures) || !DEG_id_type_updated(depsgraph, ID_OB)) { - return; - } - for (ob = bmain->objects.first; ob; ob = ob->id.next) { - if (ob->type == OB_ARMATURE && ob->adt) { - if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) { - BKE_pose_rebuild(bmain, ob, ob->data, true); - } - } - } -} -#endif - static bool check_rendered_viewport_visible(Main *bmain) { wmWindowManager *wm = bmain->wm.first; @@ -1387,9 +1512,6 @@ void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph, Main *bmain) BKE_image_editors_update_frame(bmain, scene->r.cfra); BKE_sound_set_cfra(scene->r.cfra); DEG_graph_relations_update(depsgraph, bmain, scene, view_layer); -#ifdef POSE_ANIMATION_WORKAROUND - scene_armature_depsgraph_workaround(bmain, depsgraph); -#endif /* Update all objects: drivers, matrices, displists, etc. flags set * by depgraph or manual, no layer check here, gets correct flushed. * diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 997e807a253..bfc0d437994 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -32,14 +32,18 @@ #include "MEM_guardedalloc.h" #include "DNA_defaults.h" +#include "DNA_gpencil_types.h" +#include "DNA_mask_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" +#include "DNA_text_types.h" #include "DNA_view3d_types.h" #include "DNA_workspace_types.h" #include "BLI_listbase.h" #include "BLI_math_vector.h" +#include "BLI_mempool.h" #include "BLI_rect.h" #include "BLI_utildefines.h" @@ -48,6 +52,8 @@ #include "BKE_icons.h" #include "BKE_idprop.h" #include "BKE_idtype.h" +#include "BKE_lib_query.h" +#include "BKE_node.h" #include "BKE_screen.h" #include "BKE_workspace.h" @@ -72,6 +78,158 @@ static void screen_free_data(ID *id) MEM_SAFE_FREE(screen->tool_tip); } +static void screen_foreach_id_dopesheet(LibraryForeachIDData *data, bDopeSheet *ads) +{ + if (ads != NULL) { + BKE_LIB_FOREACHID_PROCESS_ID(data, ads->source, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, ads->filter_grp, IDWALK_CB_NOP); + } +} + +void BKE_screen_foreach_id_screen_area(LibraryForeachIDData *data, ScrArea *area) +{ + BKE_LIB_FOREACHID_PROCESS(data, area->full, IDWALK_CB_NOP); + + /* TODO this should be moved to a callback in `SpaceType`, defined in each editor's own code. + * Will be for a later round of cleanup though... */ + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + switch (sl->spacetype) { + case SPACE_VIEW3D: { + View3D *v3d = (View3D *)sl; + + BKE_LIB_FOREACHID_PROCESS(data, v3d->camera, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, v3d->ob_center, IDWALK_CB_NOP); + + if (v3d->localvd) { + BKE_LIB_FOREACHID_PROCESS(data, v3d->localvd->camera, IDWALK_CB_NOP); + } + break; + } + case SPACE_GRAPH: { + SpaceGraph *sipo = (SpaceGraph *)sl; + + screen_foreach_id_dopesheet(data, sipo->ads); + break; + } + case SPACE_PROPERTIES: { + SpaceProperties *sbuts = (SpaceProperties *)sl; + + BKE_LIB_FOREACHID_PROCESS_ID(data, sbuts->pinid, IDWALK_CB_NOP); + break; + } + case SPACE_FILE: + break; + case SPACE_ACTION: { + SpaceAction *saction = (SpaceAction *)sl; + + screen_foreach_id_dopesheet(data, &saction->ads); + BKE_LIB_FOREACHID_PROCESS(data, saction->action, IDWALK_CB_NOP); + break; + } + case SPACE_IMAGE: { + SpaceImage *sima = (SpaceImage *)sl; + + BKE_LIB_FOREACHID_PROCESS(data, sima->image, IDWALK_CB_USER_ONE); + BKE_LIB_FOREACHID_PROCESS(data, sima->mask_info.mask, IDWALK_CB_USER_ONE); + BKE_LIB_FOREACHID_PROCESS(data, sima->gpd, IDWALK_CB_USER); + break; + } + case SPACE_SEQ: { + SpaceSeq *sseq = (SpaceSeq *)sl; + + BKE_LIB_FOREACHID_PROCESS(data, sseq->gpd, IDWALK_CB_USER); + break; + } + case SPACE_NLA: { + SpaceNla *snla = (SpaceNla *)sl; + + screen_foreach_id_dopesheet(data, snla->ads); + break; + } + case SPACE_TEXT: { + SpaceText *st = (SpaceText *)sl; + + BKE_LIB_FOREACHID_PROCESS(data, st->text, IDWALK_CB_NOP); + break; + } + case SPACE_SCRIPT: { + SpaceScript *scpt = (SpaceScript *)sl; + + BKE_LIB_FOREACHID_PROCESS(data, scpt->script, IDWALK_CB_NOP); + break; + } + case SPACE_OUTLINER: { + SpaceOutliner *so = (SpaceOutliner *)sl; + + BKE_LIB_FOREACHID_PROCESS_ID(data, so->search_tse.id, IDWALK_CB_NOP); + + if (so->treestore != NULL) { + TreeStoreElem *tselem; + BLI_mempool_iter iter; + + BLI_mempool_iternew(so->treestore, &iter); + while ((tselem = BLI_mempool_iterstep(&iter))) { + BKE_LIB_FOREACHID_PROCESS_ID(data, tselem->id, IDWALK_CB_NOP); + } + } + break; + } + case SPACE_NODE: { + SpaceNode *snode = (SpaceNode *)sl; + + const bool is_private_nodetree = snode->id != NULL && + ntreeFromID(snode->id) == snode->nodetree; + + BKE_LIB_FOREACHID_PROCESS_ID(data, snode->id, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS_ID(data, snode->from, IDWALK_CB_NOP); + + BKE_LIB_FOREACHID_PROCESS( + data, snode->nodetree, is_private_nodetree ? IDWALK_CB_EMBEDDED : IDWALK_CB_USER_ONE); + + LISTBASE_FOREACH (bNodeTreePath *, path, &snode->treepath) { + if (path == snode->treepath.first) { + /* first nodetree in path is same as snode->nodetree */ + BKE_LIB_FOREACHID_PROCESS(data, + path->nodetree, + is_private_nodetree ? IDWALK_CB_EMBEDDED : + IDWALK_CB_USER_ONE); + } + else { + BKE_LIB_FOREACHID_PROCESS(data, path->nodetree, IDWALK_CB_USER_ONE); + } + + if (path->nodetree == NULL) { + break; + } + } + + BKE_LIB_FOREACHID_PROCESS(data, snode->edittree, IDWALK_CB_NOP); + break; + } + case SPACE_CLIP: { + SpaceClip *sclip = (SpaceClip *)sl; + + BKE_LIB_FOREACHID_PROCESS(data, sclip->clip, IDWALK_CB_USER_ONE); + BKE_LIB_FOREACHID_PROCESS(data, sclip->mask_info.mask, IDWALK_CB_USER_ONE); + break; + } + default: + break; + } + } +} + +static void screen_foreach_id(ID *id, LibraryForeachIDData *data) +{ + if (BKE_lib_query_foreachid_process_flags_get(data) & IDWALK_INCLUDE_UI) { + bScreen *screen = (bScreen *)id; + + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + BKE_screen_foreach_id_screen_area(data, area); + } + } +} + IDTypeInfo IDType_ID_SCR = { .id_code = ID_SCR, .id_filter = 0, @@ -86,6 +244,7 @@ IDTypeInfo IDType_ID_SCR = { .copy_data = NULL, .free_data = screen_free_data, .make_local = NULL, + .foreach_id = screen_foreach_id, }; /* ************ Spacetype/regiontype handling ************** */ diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c index a08bbf182fa..5c2d5b0087f 100644 --- a/source/blender/blenkernel/intern/seqcache.c +++ b/source/blender/blenkernel/intern/seqcache.c @@ -1217,6 +1217,11 @@ void BKE_sequencer_cache_cleanup_sequence(Scene *scene, struct ImBuf *BKE_sequencer_cache_get( const SeqRenderData *context, Sequence *seq, float cfra, int type, bool skip_disk_cache) { + + if (context->skip_cache || context->is_proxy_render || !seq) { + return NULL; + } + Scene *scene = context->scene; if (context->is_prefetch_render) { @@ -1314,6 +1319,10 @@ void BKE_sequencer_cache_put(const SeqRenderData *context, float cost, bool skip_disk_cache) { + if (i == NULL || context->skip_cache || context->is_proxy_render || !seq) { + return; + } + Scene *scene = context->scene; if (context->is_prefetch_render) { @@ -1322,10 +1331,6 @@ void BKE_sequencer_cache_put(const SeqRenderData *context, seq = BKE_sequencer_prefetch_get_original_sequence(seq, scene); } - if (i == NULL || context->skip_cache || context->is_proxy_render || !seq) { - return; - } - /* Prevent reinserting, it breaks cache key linking. */ ImBuf *test = BKE_sequencer_cache_get(context, seq, cfra, type, true); if (test) { diff --git a/source/blender/blenkernel/intern/seqprefetch.c b/source/blender/blenkernel/intern/seqprefetch.c index f00d517940a..dc75e2b9098 100644 --- a/source/blender/blenkernel/intern/seqprefetch.c +++ b/source/blender/blenkernel/intern/seqprefetch.c @@ -179,12 +179,17 @@ static bool seq_prefetch_is_cache_full(Scene *scene) return BKE_sequencer_cache_recycle_item(pfjob->scene) == false; } +static float seq_prefetch_cfra(PrefetchJob *pfjob) +{ + return pfjob->cfra + pfjob->num_frames_prefetched; +} + void BKE_sequencer_prefetch_get_time_range(Scene *scene, int *start, int *end) { PrefetchJob *pfjob = seq_prefetch_job_get(scene); *start = pfjob->cfra; - *end = pfjob->cfra + pfjob->num_frames_prefetched; + *end = seq_prefetch_cfra(pfjob); } static void seq_prefetch_free_depsgraph(PrefetchJob *pfjob) @@ -198,8 +203,7 @@ static void seq_prefetch_free_depsgraph(PrefetchJob *pfjob) static void seq_prefetch_update_depsgraph(PrefetchJob *pfjob) { - DEG_evaluate_on_framechange( - pfjob->bmain_eval, pfjob->depsgraph, pfjob->cfra + pfjob->num_frames_prefetched); + DEG_evaluate_on_framechange(pfjob->bmain_eval, pfjob->depsgraph, seq_prefetch_cfra(pfjob)); } static void seq_prefetch_init_depsgraph(PrefetchJob *pfjob) @@ -347,7 +351,7 @@ static bool seq_prefetch_do_skip_frame(Scene *scene) { Editing *ed = scene->ed; PrefetchJob *pfjob = seq_prefetch_job_get(scene); - float cfra = pfjob->cfra + pfjob->num_frames_prefetched; + float cfra = seq_prefetch_cfra(pfjob); Sequence *seq_arr[MAXSEQ + 1]; int count = BKE_sequencer_get_shown_sequences(ed->seqbasep, cfra, 0, seq_arr); SeqRenderData *ctx = &pfjob->context_cpy; @@ -403,18 +407,37 @@ static bool seq_prefetch_do_skip_frame(Scene *scene) return false; } +static bool seq_prefetch_need_suspend(PrefetchJob *pfjob) +{ + return seq_prefetch_is_cache_full(pfjob->scene) || seq_prefetch_is_scrubbing(pfjob->bmain) || + (seq_prefetch_cfra(pfjob) >= pfjob->scene->r.efra); +} + +static void seq_prefetch_do_suspend(PrefetchJob *pfjob) +{ + BLI_mutex_lock(&pfjob->prefetch_suspend_mutex); + while (seq_prefetch_need_suspend(pfjob) && + (pfjob->scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) && !pfjob->stop) { + pfjob->waiting = true; + BLI_condition_wait(&pfjob->prefetch_suspend_cond, &pfjob->prefetch_suspend_mutex); + seq_prefetch_update_area(pfjob); + } + pfjob->waiting = false; + BLI_mutex_unlock(&pfjob->prefetch_suspend_mutex); +} + static void *seq_prefetch_frames(void *job) { PrefetchJob *pfjob = (PrefetchJob *)job; - while (pfjob->cfra + pfjob->num_frames_prefetched <= pfjob->scene->r.efra) { + while (seq_prefetch_cfra(pfjob) <= pfjob->scene->r.efra) { pfjob->scene_eval->ed->prefetch_job = NULL; seq_prefetch_update_depsgraph(pfjob); AnimData *adt = BKE_animdata_from_id(&pfjob->context_cpy.scene->id); BKE_animsys_evaluate_animdata(&pfjob->context_cpy.scene->id, adt, - pfjob->cfra + pfjob->num_frames_prefetched, + seq_prefetch_cfra(pfjob), ADT_RECALC_ALL, false); @@ -431,26 +454,17 @@ static void *seq_prefetch_frames(void *job) continue; } - ImBuf *ibuf = BKE_sequencer_give_ibuf( - &pfjob->context_cpy, pfjob->cfra + pfjob->num_frames_prefetched, 0); + ImBuf *ibuf = BKE_sequencer_give_ibuf(&pfjob->context_cpy, seq_prefetch_cfra(pfjob), 0); BKE_sequencer_cache_free_temp_cache( - pfjob->scene, pfjob->context.task_id, pfjob->cfra + pfjob->num_frames_prefetched); + pfjob->scene, pfjob->context.task_id, seq_prefetch_cfra(pfjob)); IMB_freeImBuf(ibuf); - /* suspend thread */ - BLI_mutex_lock(&pfjob->prefetch_suspend_mutex); - while ((seq_prefetch_is_cache_full(pfjob->scene) || seq_prefetch_is_scrubbing(pfjob->bmain)) && - pfjob->scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE && !pfjob->stop) { - pfjob->waiting = true; - BLI_condition_wait(&pfjob->prefetch_suspend_cond, &pfjob->prefetch_suspend_mutex); - seq_prefetch_update_area(pfjob); - } - pfjob->waiting = false; - BLI_mutex_unlock(&pfjob->prefetch_suspend_mutex); + /* Suspend thread if there is nothing to be prefetched. */ + seq_prefetch_do_suspend(pfjob); /* Avoid "collision" with main thread, but make sure to fetch at least few frames */ if (pfjob->num_frames_prefetched > 5 && - (pfjob->cfra + pfjob->num_frames_prefetched - pfjob->scene->r.cfra) < 2) { + (seq_prefetch_cfra(pfjob) - pfjob->scene->r.cfra) < 2) { break; } @@ -463,7 +477,7 @@ static void *seq_prefetch_frames(void *job) } BKE_sequencer_cache_free_temp_cache( - pfjob->scene, pfjob->context.task_id, pfjob->cfra + pfjob->num_frames_prefetched); + pfjob->scene, pfjob->context.task_id, seq_prefetch_cfra(pfjob)); pfjob->running = false; pfjob->scene_eval->ed->prefetch_job = NULL; @@ -520,10 +534,12 @@ void BKE_sequencer_prefetch_start(const SeqRenderData *context, float cfra, floa seq_prefetch_resume(scene); /* conditions to start: * prefetch enabled, prefetch not running, not scrubbing, - * not playing and rendering-expensive footage, cache storage enabled, has strips to render + * not playing and rendering-expensive footage, cache storage enabled, has strips to render, + * not rendering, not doing modal transform - important, see D7820. */ if ((ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) && !running && !scrubbing && - !(playing && cost > 0.9) && ed->cache_flag & SEQ_CACHE_ALL_TYPES && has_strips) { + !(playing && cost > 0.9) && ed->cache_flag & SEQ_CACHE_ALL_TYPES && has_strips && + !G.is_rendering && !G.moving) { seq_prefetch_start(context, cfra); } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index a14db79ffc6..954dca0f679 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1910,9 +1910,10 @@ static bool seq_proxy_get_fname(Editing *ed, static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int cfra) { char name[PROXY_MAXFILE]; - IMB_Proxy_Size psize = seq_rendersize_to_proxysize(context->preview_render_size); - int size_flags; StripProxy *proxy = seq->strip->proxy; + const eSpaceSeq_Proxy_RenderSize psize = context->preview_render_size; + const IMB_Proxy_Size psize_flag = seq_rendersize_to_proxysize(psize); + int size_flags; Editing *ed = context->scene->ed; StripAnim *sanim; @@ -1923,7 +1924,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c size_flags = proxy->build_size_flags; /* only use proxies, if they are enabled (even if present!) */ - if (psize == IMB_PROXY_NONE || (size_flags & psize) == 0) { + if (psize_flag == IMB_PROXY_NONE || (size_flags & psize_flag) == 0) { return NULL; } diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc index b4cfa7cf0ef..50770125a18 100644 --- a/source/blender/blenkernel/intern/simulation.cc +++ b/source/blender/blenkernel/intern/simulation.cc @@ -87,13 +87,13 @@ static void simulation_free_data(ID *id) } } -void *BKE_simulation_add(Main *bmain, const char *name) +static void simulation_foreach_id(ID *id, LibraryForeachIDData *data) { - Simulation *simulation = (Simulation *)BKE_libblock_alloc(bmain, ID_SIM, name, 0); - - simulation_init_data(&simulation->id); - - return simulation; + Simulation *simulation = (Simulation *)id; + if (simulation->nodetree) { + /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ + BKE_library_foreach_ID_embedded(data, (ID **)&simulation->nodetree); + } } IDTypeInfo IDType_ID_SIM = { @@ -110,8 +110,18 @@ IDTypeInfo IDType_ID_SIM = { /* copy_data */ simulation_copy_data, /* free_data */ simulation_free_data, /* make_local */ nullptr, + /* foreach_id */ simulation_foreach_id, }; +void *BKE_simulation_add(Main *bmain, const char *name) +{ + Simulation *simulation = (Simulation *)BKE_libblock_alloc(bmain, ID_SIM, name, 0); + + simulation_init_data(&simulation->id); + + return simulation; +} + void BKE_simulation_data_update(Depsgraph *UNUSED(depsgraph), Scene *UNUSED(scene)) { } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 5500918428f..e8f31594cc0 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -127,6 +127,7 @@ IDTypeInfo IDType_ID_SO = { .copy_data = sound_copy_data, .free_data = sound_free_data, .make_local = NULL, + .foreach_id = NULL, }; #ifdef WITH_AUDASPACE diff --git a/source/blender/blenkernel/intern/subdiv.c b/source/blender/blenkernel/intern/subdiv.c index 1f7cb225fc7..fe1dd3835fd 100644 --- a/source/blender/blenkernel/intern/subdiv.c +++ b/source/blender/blenkernel/intern/subdiv.c @@ -38,6 +38,18 @@ #include "opensubdiv_evaluator_capi.h" #include "opensubdiv_topology_refiner_capi.h" +/* =================----====--===== MODULE ==========================------== */ + +void BKE_subdiv_init() +{ + openSubdiv_init(); +} + +void BKE_subdiv_exit() +{ + openSubdiv_cleanup(); +} + /* ========================== CONVERSION HELPERS ============================ */ eSubdivFVarLinearInterpolation BKE_subdiv_fvar_interpolation_from_uv_smooth(int uv_smooth) diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index c21d640a4c1..7a0a5645b80 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -71,18 +71,13 @@ #include "CCGSubSurf.h" -#ifdef WITH_OPENSUBDIV -# include "opensubdiv_capi.h" -#endif - /* assumes MLoop's are laid out 4 for each poly, in order */ #define USE_LOOP_LAYOUT_FAST static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int drawInteriorEdges, int useSubsurfUv, - DerivedMesh *dm, - bool use_gpu_backend); + DerivedMesh *dm); /// static void *arena_alloc(CCGAllocatorHDL a, int numBytes) @@ -404,82 +399,6 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, return 1; } -#ifdef WITH_OPENSUBDIV -static void UNUSED_FUNCTION(set_subsurf_osd_ccg_uv)(CCGSubSurf *ss, - DerivedMesh *dm, - DerivedMesh *result, - int layer_index) -{ - CCGFace **faceMap; - MTFace *tf; - MLoopUV *mluv; - CCGFaceIterator fi; - int index, gridSize, gridFaces, totface, x, y, S; - MLoopUV *dmloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, layer_index); - /* need to update both CD_MTFACE & CD_MLOOPUV, hrmf, we could get away with - * just tface except applying the modifier then looses subsurf UV */ - MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, layer_index); - MLoopUV *mloopuv = CustomData_get_layer_n(&result->loopData, CD_MLOOPUV, layer_index); - - if (dmloopuv == NULL || (tface == NULL && mloopuv == NULL)) { - return; - } - - ccgSubSurf_evaluatorSetFVarUV(ss, dm, layer_index); - - /* get some info from CCGSubSurf */ - totface = ccgSubSurf_getNumFaces(ss); - gridSize = ccgSubSurf_getGridSize(ss); - gridFaces = gridSize - 1; - - /* make a map from original faces to CCGFaces */ - faceMap = MEM_mallocN(totface * sizeof(*faceMap), "facemapuv"); - for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); - ccgFaceIterator_next(&fi)) { - CCGFace *f = ccgFaceIterator_getCurrent(&fi); - faceMap[POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f))] = f; - } - - /* load coordinates from uvss into tface */ - tf = tface; - mluv = mloopuv; - for (index = 0; index < totface; index++) { - CCGFace *f = faceMap[index]; - int numVerts = ccgSubSurf_getFaceNumVerts(f); - for (S = 0; S < numVerts; S++) { - for (y = 0; y < gridFaces; y++) { - for (x = 0; x < gridFaces; x++) { - const int delta[4][2] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}}; - float uv[4][2]; - int i; - for (i = 0; i < 4; i++) { - const int dx = delta[i][0], dy = delta[i][1]; - const float grid_u = ((float)(x + dx)) / (gridSize - 1), - grid_v = ((float)(y + dy)) / (gridSize - 1); - ccgSubSurf_evaluatorFVarUV(ss, index, S, grid_u, grid_v, uv[i]); - } - if (tf) { - copy_v2_v2(tf->uv[0], uv[0]); - copy_v2_v2(tf->uv[1], uv[1]); - copy_v2_v2(tf->uv[2], uv[2]); - copy_v2_v2(tf->uv[3], uv[3]); - tf++; - } - if (mluv) { - copy_v2_v2(mluv[0].uv, uv[0]); - copy_v2_v2(mluv[1].uv, uv[1]); - copy_v2_v2(mluv[2].uv, uv[2]); - copy_v2_v2(mluv[3].uv, uv[3]); - mluv += 4; - } - } - } - } - } - MEM_freeN(faceMap); -} -#endif /* WITH_OPENSUBDIV */ - static void set_subsurf_legacy_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int n) { CCGSubSurf *uvss; @@ -564,16 +483,7 @@ static void set_subsurf_legacy_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh * static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int layer_index) { -#ifdef WITH_OPENSUBDIV - if (!ccgSubSurf_needGrids(ss)) { - /* GPU backend is used, no need to evaluate UVs on CPU. */ - /* TODO(sergey): Think of how to support edit mode of UVs. */ - } - else -#endif - { - set_subsurf_legacy_uv(ss, dm, result, layer_index); - } + set_subsurf_legacy_uv(ss, dm, result, layer_index); } /* face weighting */ @@ -763,40 +673,13 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss, #endif } -#ifdef WITH_OPENSUBDIV -static void ss_sync_osd_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm) -{ - ccgSubSurf_initFullSync(ss); - ccgSubSurf_prepareTopologyRefiner(ss, dm); - ccgSubSurf_processSync(ss); -} -#endif /* WITH_OPENSUBDIV */ - static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, float (*vertexCos)[3], int use_flat_subdiv, - bool use_subdiv_uvs) + bool UNUSED(use_subdiv_uvs)) { -#ifndef WITH_OPENSUBDIV - UNUSED_VARS(use_subdiv_uvs); -#endif - -#ifdef WITH_OPENSUBDIV - /* Reset all related descriptors if actual mesh topology changed or if - * other evaluation-related settings changed. - */ - if (!ccgSubSurf_needGrids(ss)) { - /* TODO(sergey): Use vertex coordinates and flat subdiv flag. */ - ccgSubSurf__sync_subdivUvs(ss, use_subdiv_uvs); - ccgSubSurf_checkTopologyChanged(ss, dm); - ss_sync_osd_from_derivedmesh(ss, dm); - } - else -#endif - { - ss_sync_ccg_from_derivedmesh(ss, dm, vertexCos, use_flat_subdiv); - } + ss_sync_ccg_from_derivedmesh(ss, dm, vertexCos, use_flat_subdiv); } /***/ @@ -850,13 +733,6 @@ static void UNUSED_FUNCTION(ccgDM_getMinMax)(DerivedMesh *dm, float r_min[3], fl int i, edgeSize = ccgSubSurf_getEdgeSize(ss); int gridSize = ccgSubSurf_getGridSize(ss); -#ifdef WITH_OPENSUBDIV - if (ccgdm->useGpuBackend) { - ccgSubSurf_getMinMax(ccgdm->ss, r_min, r_max); - return; - } -#endif - CCG_key_top_level(&key, ss); if (!ccgSubSurf_getNumVerts(ss)) { @@ -1642,11 +1518,9 @@ static void ccgDM_release(DerivedMesh *dm) } MEM_freeN(ccgdm->edgeFlags); MEM_freeN(ccgdm->faceFlags); - if (ccgdm->useGpuBackend == false) { - MEM_freeN(ccgdm->vertMap); - MEM_freeN(ccgdm->edgeMap); - MEM_freeN(ccgdm->faceMap); - } + MEM_freeN(ccgdm->vertMap); + MEM_freeN(ccgdm->edgeMap); + MEM_freeN(ccgdm->faceMap); BLI_mutex_end(&ccgdm->loops_cache_lock); BLI_rw_mutex_end(&ccgdm->origindex_cache_rwlock); @@ -2417,76 +2291,44 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm, BLI_assert(faceNum == ccgSubSurf_getNumFinalFaces(ss)); } -/* Fill in only geometry arrays needed for the GPU tessellation. */ -static void set_ccgdm_gpu_geometry(CCGDerivedMesh *ccgdm, DerivedMesh *dm) -{ - const int totface = dm->getNumPolys(dm); - MPoly *mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); - int index; - DMFlagMat *faceFlags = ccgdm->faceFlags; - - for (index = 0; index < totface; index++) { - faceFlags->flag = mpoly ? mpoly[index].flag : 0; - faceFlags->mat_nr = mpoly ? mpoly[index].mat_nr : 0; - faceFlags++; - } - - /* TODO(sergey): Fill in edge flags. */ -} - -static CCGDerivedMesh *getCCGDerivedMesh( - CCGSubSurf *ss, int drawInteriorEdges, int useSubsurfUv, DerivedMesh *dm, bool use_gpu_backend) +static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, + int drawInteriorEdges, + int useSubsurfUv, + DerivedMesh *dm) { -#ifdef WITH_OPENSUBDIV - const int totedge = dm->getNumEdges(dm); - const int totface = dm->getNumPolys(dm); -#else const int totedge = ccgSubSurf_getNumEdges(ss); const int totface = ccgSubSurf_getNumFaces(ss); -#endif CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm"); - if (use_gpu_backend == false) { - BLI_assert(totedge == ccgSubSurf_getNumEdges(ss)); - BLI_assert(totface == ccgSubSurf_getNumFaces(ss)); - DM_from_template(&ccgdm->dm, - dm, - DM_TYPE_CCGDM, - ccgSubSurf_getNumFinalVerts(ss), - ccgSubSurf_getNumFinalEdges(ss), - 0, - ccgSubSurf_getNumFinalFaces(ss) * 4, - ccgSubSurf_getNumFinalFaces(ss)); + BLI_assert(totedge == ccgSubSurf_getNumEdges(ss)); + BLI_assert(totface == ccgSubSurf_getNumFaces(ss)); + DM_from_template(&ccgdm->dm, + dm, + DM_TYPE_CCGDM, + ccgSubSurf_getNumFinalVerts(ss), + ccgSubSurf_getNumFinalEdges(ss), + 0, + ccgSubSurf_getNumFinalFaces(ss) * 4, + ccgSubSurf_getNumFinalFaces(ss)); - CustomData_free_layer_active(&ccgdm->dm.polyData, CD_NORMAL, ccgdm->dm.numPolyData); + CustomData_free_layer_active(&ccgdm->dm.polyData, CD_NORMAL, ccgdm->dm.numPolyData); - ccgdm->reverseFaceMap = MEM_callocN(sizeof(int) * ccgSubSurf_getNumFinalFaces(ss), - "reverseFaceMap"); + ccgdm->reverseFaceMap = MEM_callocN(sizeof(int) * ccgSubSurf_getNumFinalFaces(ss), + "reverseFaceMap"); - create_ccgdm_maps(ccgdm, ss); - } - else { - DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM, 0, 0, 0, 0, dm->getNumPolys(dm)); - CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, 0, 0, dm->getNumPolys(dm)); - } + create_ccgdm_maps(ccgdm, ss); set_default_ccgdm_callbacks(ccgdm); ccgdm->ss = ss; ccgdm->drawInteriorEdges = drawInteriorEdges; ccgdm->useSubsurfUv = useSubsurfUv; - ccgdm->useGpuBackend = use_gpu_backend; /* CDDM hack. */ ccgdm->edgeFlags = MEM_callocN(sizeof(short) * totedge, "edgeFlags"); ccgdm->faceFlags = MEM_callocN(sizeof(DMFlagMat) * totface, "faceFlags"); - if (use_gpu_backend == false) { - set_ccgdm_all_geometry(ccgdm, ss, dm, useSubsurfUv != 0); - } - else { - set_ccgdm_gpu_geometry(ccgdm, dm); - } + set_ccgdm_all_geometry(ccgdm, ss, dm, useSubsurfUv != 0); ccgdm->dm.numVertData = ccgSubSurf_getNumFinalVerts(ss); ccgdm->dm.numEdgeData = ccgSubSurf_getNumFinalEdges(ss); @@ -2502,21 +2344,6 @@ static CCGDerivedMesh *getCCGDerivedMesh( /***/ -static bool subsurf_use_gpu_backend(SubsurfFlags flags) -{ -#ifdef WITH_OPENSUBDIV - /* Use GPU backend if it's a last modifier in the stack - * and user chose to use any of the OSD compute devices, - * but also check if GPU has all needed features. - */ - return (flags & SUBSURF_USE_GPU_BACKEND) != 0 && - (U.opensubdiv_compute_type != USER_OPENSUBDIV_COMPUTE_NONE); -#else - (void)flags; - return false; -#endif -} - struct DerivedMesh *subsurf_make_derived_from_derived(struct DerivedMesh *dm, struct SubsurfModifierData *smd, const struct Scene *scene, @@ -2527,7 +2354,6 @@ struct DerivedMesh *subsurf_make_derived_from_derived(struct DerivedMesh *dm, const CCGFlags useAging = (smd->flags & eSubsurfModifierFlag_DebugIncr) ? CCG_USE_AGING : 0; const int useSubsurfUv = (smd->uv_smooth != SUBSURF_UV_SMOOTH_NONE); const int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges); - const bool use_gpu_backend = subsurf_use_gpu_backend(flags); const bool ignore_simplify = (flags & SUBSURF_IGNORE_SIMPLIFY); CCGDerivedMesh *result; @@ -2546,11 +2372,8 @@ struct DerivedMesh *subsurf_make_derived_from_derived(struct DerivedMesh *dm, smd->emCache = _getSubSurf(smd->emCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS); -#ifdef WITH_OPENSUBDIV - ccgSubSurf_setSkipGrids(smd->emCache, use_gpu_backend); -#endif ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple, useSubsurfUv); - result = getCCGDerivedMesh(smd->emCache, drawInteriorEdges, useSubsurfUv, dm, use_gpu_backend); + result = getCCGDerivedMesh(smd->emCache, drawInteriorEdges, useSubsurfUv, dm); } else if (flags & SUBSURF_USE_RENDER_PARAMS) { /* Do not use cache in render mode. */ @@ -2567,7 +2390,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(struct DerivedMesh *dm, ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple, useSubsurfUv); - result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm, false); + result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm); result->freeSS = 1; } @@ -2600,32 +2423,15 @@ struct DerivedMesh *subsurf_make_derived_from_derived(struct DerivedMesh *dm, ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple, useSubsurfUv); - result = getCCGDerivedMesh(smd->mCache, drawInteriorEdges, useSubsurfUv, dm, false); + result = getCCGDerivedMesh(smd->mCache, drawInteriorEdges, useSubsurfUv, dm); } else { CCGFlags ccg_flags = useSimple | CCG_USE_ARENA | CCG_CALC_NORMALS; CCGSubSurf *prevSS = NULL; if (smd->mCache && (flags & SUBSURF_IS_FINAL_CALC)) { -#ifdef WITH_OPENSUBDIV - /* With OpenSubdiv enabled we always tries to re-use previous - * subsurf structure in order to save computation time since - * re-creation is rather a complicated business. - * - * TODO(sergey): There was a good reason why final calculation - * used to free entirely cached subsurf structure. reason of - * this is to be investigated still to be sure we don't have - * regressions here. - */ - if (use_gpu_backend) { - prevSS = smd->mCache; - } - else -#endif - { - ccgSubSurf_free(smd->mCache); - smd->mCache = NULL; - } + ccgSubSurf_free(smd->mCache); + smd->mCache = NULL; } if (flags & SUBSURF_ALLOC_PAINT_MASK) { @@ -2633,12 +2439,9 @@ struct DerivedMesh *subsurf_make_derived_from_derived(struct DerivedMesh *dm, } ss = _getSubSurf(prevSS, levels, 3, ccg_flags); -#ifdef WITH_OPENSUBDIV - ccgSubSurf_setSkipGrids(ss, use_gpu_backend); -#endif ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple, useSubsurfUv); - result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm, use_gpu_backend); + result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm); if (flags & SUBSURF_IS_FINAL_CALC) { smd->mCache = ss; @@ -2710,26 +2513,10 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*r_positions)[3]) bool subsurf_has_edges(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; -#ifdef WITH_OPENSUBDIV - if (ccgdm->useGpuBackend) { - return true; - } -#else - (void)ccgdm; -#endif return dm->getNumEdges(dm) != 0; } bool subsurf_has_faces(DerivedMesh *dm) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; -#ifdef WITH_OPENSUBDIV - if (ccgdm->useGpuBackend) { - return true; - } -#else - (void)ccgdm; -#endif return dm->getNumPolys(dm) != 0; } diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 3cdf3b40ce3..527b54a1aa2 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -206,6 +206,7 @@ IDTypeInfo IDType_ID_TXT = { .copy_data = text_copy_data, .free_data = text_free_data, .make_local = NULL, + .foreach_id = NULL, }; /***/ diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c index dffc703c943..e09e92588c6 100644 --- a/source/blender/blenkernel/intern/tracking_stabilize.c +++ b/source/blender/blenkernel/intern/tracking_stabilize.c @@ -42,6 +42,7 @@ #include "BKE_movieclip.h" #include "BKE_tracking.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "MEM_guardedalloc.h" @@ -1399,7 +1400,7 @@ ImBuf *BKE_tracking_stabilize_frame( return ibuf; } - /* Allocate frame for stabilization result. */ + /* Allocate frame for stabilization result, copy alpha mode and colorspace. */ ibuf_flags = 0; if (ibuf->rect) { ibuf_flags |= IB_rect; @@ -1409,6 +1410,7 @@ ImBuf *BKE_tracking_stabilize_frame( } tmpibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, ibuf_flags); + IMB_colormanagegent_copy_settings(ibuf, tmpibuf); /* Calculate stabilization matrix. */ BKE_tracking_stabilization_data_get(clip, framenr, width, height, tloc, &tscale, &tangle); diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c index 629c01ec298..dcaa9082026 100644 --- a/source/blender/blenkernel/intern/tracking_util.c +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -713,7 +713,7 @@ static ImBuf *make_grayscale_ibuf_copy(ImBuf *ibuf) */ const size_t size = (size_t)grayscale->x * (size_t)grayscale->y * sizeof(float); grayscale->channels = 1; - if ((grayscale->rect_float = MEM_mapallocN(size, "tracking grayscale image")) != NULL) { + if ((grayscale->rect_float = MEM_callocN(size, "tracking grayscale image")) != NULL) { grayscale->mall |= IB_rectfloat; grayscale->flags |= IB_rectfloat; @@ -741,7 +741,7 @@ static ImBuf *float_image_to_ibuf(libmv_FloatImage *float_image) ImBuf *ibuf = IMB_allocImBuf(float_image->width, float_image->height, 32, 0); size_t size = (size_t)ibuf->x * (size_t)ibuf->y * float_image->channels * sizeof(float); ibuf->channels = float_image->channels; - if ((ibuf->rect_float = MEM_mapallocN(size, "tracking grayscale image")) != NULL) { + if ((ibuf->rect_float = MEM_callocN(size, "tracking grayscale image")) != NULL) { ibuf->mall |= IB_rectfloat; ibuf->flags |= IB_rectfloat; diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index 9e636c0ee8b..26c5810aefa 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -21,6 +21,7 @@ #include "MEM_guardedalloc.h" #include "DNA_defaults.h" +#include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_volume_types.h" @@ -442,26 +443,6 @@ static void volume_init_data(ID *id) BKE_volume_init_grids(volume); } -void BKE_volume_init_grids(Volume *volume) -{ -#ifdef WITH_OPENVDB - if (volume->runtime.grids == NULL) { - volume->runtime.grids = OBJECT_GUARDED_NEW(VolumeGridVector); - } -#else - UNUSED_VARS(volume); -#endif -} - -void *BKE_volume_add(Main *bmain, const char *name) -{ - Volume *volume = (Volume *)BKE_libblock_alloc(bmain, ID_VO, name, 0); - - volume_init_data(&volume->id); - - return volume; -} - static void volume_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, @@ -483,18 +464,6 @@ static void volume_copy_data(Main *UNUSED(bmain), #endif } -Volume *BKE_volume_copy(Main *bmain, const Volume *volume) -{ - Volume *volume_copy; - BKE_id_copy(bmain, &volume->id, (ID **)&volume_copy); - return volume_copy; -} - -static void volume_make_local(Main *bmain, ID *id, const int flags) -{ - BKE_lib_id_make_local_generic(bmain, id, flags); -} - static void volume_free_data(ID *id) { Volume *volume = (Volume *)id; @@ -506,6 +475,14 @@ static void volume_free_data(ID *id) #endif } +static void volume_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Volume *volume = (Volume *)id; + for (int i = 0; i < volume->totcol; i++) { + BKE_LIB_FOREACHID_PROCESS(data, volume->mat[i], IDWALK_CB_USER); + } +} + IDTypeInfo IDType_ID_VO = { /* id_code */ ID_VO, /* id_filter */ FILTER_ID_VO, @@ -519,9 +496,37 @@ IDTypeInfo IDType_ID_VO = { /* init_data */ volume_init_data, /* copy_data */ volume_copy_data, /* free_data */ volume_free_data, - /* make_local */ volume_make_local, + /* make_local */ nullptr, + /* foreach_id */ volume_foreach_id, }; +void BKE_volume_init_grids(Volume *volume) +{ +#ifdef WITH_OPENVDB + if (volume->runtime.grids == NULL) { + volume->runtime.grids = OBJECT_GUARDED_NEW(VolumeGridVector); + } +#else + UNUSED_VARS(volume); +#endif +} + +void *BKE_volume_add(Main *bmain, const char *name) +{ + Volume *volume = (Volume *)BKE_libblock_alloc(bmain, ID_VO, name, 0); + + volume_init_data(&volume->id); + + return volume; +} + +Volume *BKE_volume_copy(Main *bmain, const Volume *volume) +{ + Volume *volume_copy; + BKE_id_copy(bmain, &volume->id, (ID **)&volume_copy); + return volume_copy; +} + /* Sequence */ static int volume_sequence_frame(const Depsgraph *depsgraph, const Volume *volume) diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c index c65d55785c1..3a69b95c114 100644 --- a/source/blender/blenkernel/intern/workspace.c +++ b/source/blender/blenkernel/intern/workspace.c @@ -32,6 +32,7 @@ #include "BKE_idprop.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_scene.h" @@ -65,6 +66,23 @@ static void workspace_free_data(ID *id) MEM_SAFE_FREE(workspace->status_text); } +static void workspace_foreach_id(ID *id, LibraryForeachIDData *data) +{ + WorkSpace *workspace = (WorkSpace *)id; + ListBase *layouts = BKE_workspace_layouts_get(workspace); + + LISTBASE_FOREACH (WorkSpaceLayout *, layout, layouts) { + bScreen *screen = BKE_workspace_layout_screen_get(layout); + + /* CALLBACK_INVOKE expects an actual pointer, not a variable holding the pointer. + * However we can't access layout->screen here + * since we are outside the workspace project. */ + BKE_LIB_FOREACHID_PROCESS(data, screen, IDWALK_CB_USER); + /* allow callback to set a different screen */ + BKE_workspace_layout_screen_set(layout, screen); + } +} + IDTypeInfo IDType_ID_WS = { .id_code = ID_WS, .id_filter = FILTER_ID_WS, @@ -79,6 +97,7 @@ IDTypeInfo IDType_ID_WS = { .copy_data = NULL, .free_data = workspace_free_data, .make_local = NULL, + .foreach_id = workspace_foreach_id, }; /** \name Internal Utils diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 16e56200131..724c4ab93b2 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -606,7 +606,10 @@ static AVStream *alloc_video_stream(FFMpegContext *context, c->gop_size = context->ffmpeg_gop_size; c->max_b_frames = context->ffmpeg_max_b_frames; - if (context->ffmpeg_crf >= 0) { + if (context->ffmpeg_type == FFMPEG_WEBM && context->ffmpeg_crf == 0) { + ffmpeg_dict_set_int(&opts, "lossless", 1); + } + else if (context->ffmpeg_crf >= 0) { ffmpeg_dict_set_int(&opts, "crf", context->ffmpeg_crf); } else { |