diff options
Diffstat (limited to 'source')
244 files changed, 3213 insertions, 4889 deletions
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 5238853a105..c22e7a24afe 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -90,7 +90,7 @@ void BKE_armature_bone_hash_free(struct bArmature *arm); bool BKE_armature_bone_flag_test_recursive(const struct Bone *bone, int flag); -void BKE_armature_refresh_layer_used(struct bArmature *arm); +void BKE_armature_refresh_layer_used(struct Depsgraph *depsgraph, struct bArmature *arm); float distfactor_to_bone( const float vec[3], const float b1[3], const float b2[3], float r1, float r2, float rdist); diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 5510f3c3d2e..ddebf50691f 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -31,7 +31,7 @@ extern "C" { * \note Use #STRINGIFY() rather than defining with quotes. */ #define BLENDER_VERSION 290 -#define BLENDER_SUBVERSION 2 +#define BLENDER_SUBVERSION 3 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index a97263a6523..4e9430ab3e1 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -57,10 +57,18 @@ struct Brush *BKE_brush_copy(struct Main *bmain, const struct Brush *brush); void BKE_brush_sculpt_reset(struct Brush *brush); -void BKE_brush_gpencil_paint_presets(struct Main *bmain, struct ToolSettings *ts); -void BKE_brush_gpencil_vertex_presets(struct Main *bmain, struct ToolSettings *ts); -void BKE_brush_gpencil_sculpt_presets(struct Main *bmain, struct ToolSettings *ts); -void BKE_brush_gpencil_weight_presets(struct Main *bmain, struct ToolSettings *ts); +void BKE_brush_gpencil_paint_presets(struct Main *bmain, + struct ToolSettings *ts, + const bool reset); +void BKE_brush_gpencil_vertex_presets(struct Main *bmain, + struct ToolSettings *ts, + const bool reset); +void BKE_brush_gpencil_sculpt_presets(struct Main *bmain, + struct ToolSettings *ts, + const bool reset); +void BKE_brush_gpencil_weight_presets(struct Main *bmain, + struct ToolSettings *ts, + const bool reset); void BKE_gpencil_brush_preset_set(struct Main *bmain, struct Brush *brush, const short type); /* image icon function */ diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 2b17cb7a875..bf270f2c06f 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -261,8 +261,9 @@ void BKE_nurb_handles_calc(struct Nurb *nu); void BKE_nurb_handles_autocalc(struct Nurb *nu, int flag); void BKE_nurb_bezt_handle_test(struct BezTriple *bezt, const eBezTriple_Flag__Alias sel_flag, - const bool use_handle); -void BKE_nurb_handles_test(struct Nurb *nu, const bool use_handles); + const bool use_handle, + const bool use_around_local); +void BKE_nurb_handles_test(struct Nurb *nu, const bool use_handles, const bool use_around_local); /* **** Depsgraph evaluation **** */ diff --git a/source/blender/blenkernel/BKE_lib_query.h b/source/blender/blenkernel/BKE_lib_query.h index 353ee3bbf5a..fac1852eafe 100644 --- a/source/blender/blenkernel/BKE_lib_query.h +++ b/source/blender/blenkernel/BKE_lib_query.h @@ -132,6 +132,10 @@ typedef struct LibraryForeachIDData LibraryForeachIDData; bool BKE_lib_query_foreachid_process(struct LibraryForeachIDData *data, struct ID **id_pp, int cb_flag); +int BKE_lib_query_foreachid_process_flags_get(struct LibraryForeachIDData *data); +int BKE_lib_query_foreachid_process_callback_flag_override(struct LibraryForeachIDData *data, + const int cb_flag, + const bool do_replace); #define BKE_LIB_FOREACHID_PROCESS_ID(_data, _id, _cb_flag) \ { \ diff --git a/source/blender/blenkernel/BKE_light.h b/source/blender/blenkernel/BKE_light.h index 17f7a8596bf..ead27ec8002 100644 --- a/source/blender/blenkernel/BKE_light.h +++ b/source/blender/blenkernel/BKE_light.h @@ -31,6 +31,7 @@ extern "C" { #endif +struct Depsgraph; struct Light; struct Main; @@ -38,6 +39,8 @@ struct Light *BKE_light_add(struct Main *bmain, const char *name) ATTR_WARN_UNUS struct Light *BKE_light_copy(struct Main *bmain, const struct Light *la) ATTR_WARN_UNUSED_RESULT; struct Light *BKE_light_localize(struct Light *la) ATTR_WARN_UNUSED_RESULT; +void BKE_light_eval(struct Depsgraph *depsgraph, struct Light *la); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 409afcd9f75..2bf16e38716 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -309,6 +309,8 @@ void BKE_pbvh_face_sets_set(PBVH *bvh, int *face_sets); void BKE_pbvh_face_sets_color_set(PBVH *bvh, int seed, int color_default); +void BKE_pbvh_respect_hide_set(PBVH *bvh, bool respect_hide); + /* vertex deformer */ float (*BKE_pbvh_vert_coords_alloc(struct PBVH *pbvh))[3]; void BKE_pbvh_vert_coords_apply(struct PBVH *pbvh, const float (*vertCos)[3], const int totvert); @@ -334,6 +336,7 @@ typedef struct PBVHVertexIter { int gy; int i; int index; + bool respect_hide; /* grid */ struct CCGKey key; @@ -402,9 +405,15 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo } \ else if (vi.mverts) { \ vi.mvert = &vi.mverts[vi.vert_indices[vi.gx]]; \ - vi.visible = !(vi.mvert->flag & ME_HIDE); \ - if (mode == PBVH_ITER_UNIQUE && !vi.visible) \ - continue; \ + if (vi.respect_hide) { \ + vi.visible = !(vi.mvert->flag & ME_HIDE); \ + if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \ + continue; \ + } \ + } \ + else { \ + BLI_assert(vi.visible); \ + } \ vi.co = vi.mvert->co; \ vi.no = vi.mvert->no; \ vi.index = vi.vert_indices[vi.i]; \ diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index c49b6e27bba..0d8f5ed550c 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -48,6 +48,7 @@ struct WorkSpace; struct bContext; struct bContextDataResult; struct bScreen; +struct LibraryForeachIDData; struct uiLayout; struct uiList; struct wmGizmoMap; @@ -389,6 +390,8 @@ float BKE_screen_view3d_zoom_from_fac(float zoomfac); void BKE_screen_view3d_shading_init(struct View3DShading *shading); /* screen */ +void BKE_screen_foreach_id_screen_area(struct LibraryForeachIDData *data, struct ScrArea *area); + void BKE_screen_free(struct bScreen *screen); void BKE_screen_area_map_free(struct ScrAreaMap *area_map) ATTR_NONNULL(); diff --git a/source/blender/blenkernel/BKE_subdiv.h b/source/blender/blenkernel/BKE_subdiv.h index 0333d52a464..1323938e479 100644 --- a/source/blender/blenkernel/BKE_subdiv.h +++ b/source/blender/blenkernel/BKE_subdiv.h @@ -194,6 +194,12 @@ typedef struct Subdiv { } cache_; } Subdiv; +/* =================----====--===== MODULE ==========================------== */ + +/* (De)initialize the entire subdivision surface module. */ +void BKE_subdiv_init(void); +void BKE_subdiv_exit(void); + /* ========================== CONVERSION HELPERS ============================ */ /* NOTE: uv_smooth is eSubsurfUVSmooth. */ diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h index 16013034823..2dee8de4dc7 100644 --- a/source/blender/blenkernel/BKE_subsurf.h +++ b/source/blender/blenkernel/BKE_subsurf.h @@ -103,7 +103,7 @@ typedef struct CCGDerivedMesh { struct CCGSubSurf *ss; int freeSS; - int drawInteriorEdges, useSubsurfUv, useGpuBackend; + int drawInteriorEdges, useSubsurfUv; struct { int startVert; @@ -156,13 +156,6 @@ typedef struct CCGDerivedMesh { ThreadRWMutex origindex_cache_rwlock; } CCGDerivedMesh; -#ifdef WITH_OPENSUBDIV -/* TODO(sergey): Not really ideal place, but we don't currently have better one. */ -void BKE_subsurf_osd_init(void); -void BKE_subsurf_free_unused_buffers(void); -void BKE_subsurf_osd_cleanup(void); -#endif - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 9716e5f5d3f..220bafa2187 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -64,8 +64,6 @@ set(SRC ${CMAKE_SOURCE_DIR}/release/datafiles/userdef/userdef_default.c intern/CCGSubSurf.c intern/CCGSubSurf_legacy.c - intern/CCGSubSurf_opensubdiv.c - intern/CCGSubSurf_opensubdiv_converter.c intern/CCGSubSurf_util.c intern/DerivedMesh.c intern/action.c 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 { diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index c199417017b..03fe27c10ed 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -58,9 +58,6 @@ void BLI_threadpool_clear(struct ListBase *threadbase); void BLI_threadpool_end(struct ListBase *threadbase); int BLI_thread_is_main(void); -void BLI_threaded_malloc_begin(void); -void BLI_threaded_malloc_end(void); - /* System Information */ int BLI_system_thread_count(void); /* gets the number of threads the system can make use of */ diff --git a/source/blender/blenlib/BLI_vector_set.hh b/source/blender/blenlib/BLI_vector_set.hh index 9f887513816..f402f47c357 100644 --- a/source/blender/blenlib/BLI_vector_set.hh +++ b/source/blender/blenlib/BLI_vector_set.hh @@ -140,7 +140,7 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { VectorSet(const VectorSet &other) : m_array(other.m_array) { m_elements = this->allocate_elements_array(m_array.slots_usable()); - copy_n(other.m_elements, m_array.slots_set(), m_elements); + uninitialized_copy_n(other.m_elements, m_array.slots_set(), m_elements); } VectorSet(VectorSet &&other) : m_array(std::move(other.m_array)), m_elements(other.m_elements) diff --git a/source/blender/blenlib/intern/boxpack_2d.c b/source/blender/blenlib/intern/boxpack_2d.c index 6ecadeecec5..83866f766df 100644 --- a/source/blender/blenlib/intern/boxpack_2d.c +++ b/source/blender/blenlib/intern/boxpack_2d.c @@ -705,7 +705,7 @@ void BLI_box_pack_2d_fixedarea(ListBase *boxes, int width, int height, ListBase LISTBASE_FOREACH_MUTABLE (FixedSizeBoxPack *, box, boxes) { LISTBASE_FOREACH (FixedSizeBoxPack *, space, &spaces) { /* Skip this space if it's too small. */ - if (box->w > space->w || box->h > space->w) { + if (box->w > space->w || box->h > space->h) { continue; } diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 154fc966ca2..87536ea8116 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -233,8 +233,9 @@ eFileAttributes BLI_file_attributes(const char *path) # ifdef WIN32 WCHAR wline[FILE_MAXDIR]; - size_t bsize = count_utf_16_from_8(path); - conv_utf_8_to_16(path, wline, bsize); + if (conv_utf_8_to_16(path, wline, ARRAY_SIZE(wline)) != 0) { + return ret; + } DWORD attr = GetFileAttributesW(wline); if (attr & FILE_ATTRIBUTE_READONLY) { ret |= FILE_ATTR_READONLY; diff --git a/source/blender/blenlib/intern/task_pool.cc b/source/blender/blenlib/intern/task_pool.cc index 670787697a3..cf328ec407c 100644 --- a/source/blender/blenlib/intern/task_pool.cc +++ b/source/blender/blenlib/intern/task_pool.cc @@ -364,14 +364,6 @@ static void background_task_pool_free(TaskPool *pool) static TaskPool *task_pool_create_ex(void *userdata, TaskPoolType type, TaskPriority priority) { - /* Ensure malloc will go fine from threads, - * - * This is needed because we could be in main thread here - * and malloc could be non-thread safe at this point because - * no other jobs are running. - */ - BLI_threaded_malloc_begin(); - const bool use_threads = BLI_task_scheduler_num_threads() > 1 && type != TASK_POOL_NO_THREADS; /* Background task pool uses regular TBB scheduling if available. Only when @@ -475,8 +467,6 @@ void BLI_task_pool_free(TaskPool *pool) BLI_mutex_end(&pool->user_mutex); MEM_freeN(pool); - - BLI_threaded_malloc_end(); } void BLI_task_pool_push(TaskPool *pool, diff --git a/source/blender/blenlib/intern/task_range.cc b/source/blender/blenlib/intern/task_range.cc index 55de35f0060..67d8960434e 100644 --- a/source/blender/blenlib/intern/task_range.cc +++ b/source/blender/blenlib/intern/task_range.cc @@ -128,7 +128,6 @@ void BLI_task_parallel_range(const int start, else { parallel_for(range, task); } - return; } #endif diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index f535798f86d..be43c27e945 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -104,7 +104,6 @@ static void *thread_tls_data; * BLI_threadpool_end(&lb); * ************************************************ */ -static SpinLock _malloc_lock; static pthread_mutex_t _image_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _image_draw_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _viewer_lock = PTHREAD_MUTEX_INITIALIZER; @@ -132,21 +131,9 @@ typedef struct ThreadSlot { int avail; } ThreadSlot; -static void BLI_lock_malloc_thread(void) -{ - BLI_spin_lock(&_malloc_lock); -} - -static void BLI_unlock_malloc_thread(void) -{ - BLI_spin_unlock(&_malloc_lock); -} - void BLI_threadapi_init(void) { mainid = pthread_self(); - - BLI_spin_init(&_malloc_lock); if (numaAPI_Initialize() == NUMAAPI_SUCCESS) { is_numa_available = true; } @@ -154,7 +141,6 @@ void BLI_threadapi_init(void) void BLI_threadapi_exit(void) { - BLI_spin_end(&_malloc_lock); } /* tot = 0 only initializes malloc mutex in a safe way (see sequence.c) @@ -185,8 +171,6 @@ void BLI_threadpool_init(ListBase *threadbase, void *(*do_thread)(void *), int t unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1); if (level == 0) { - MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); - #ifdef USE_APPLE_OMP_FIX /* workaround for Apple gcc 4.2.1 omp vs background thread bug, * we copy gomp thread local storage pointer to setting it again @@ -313,11 +297,6 @@ void BLI_threadpool_end(ListBase *threadbase) } BLI_freelistN(threadbase); } - - unsigned int level = atomic_sub_and_fetch_u(&thread_levels, 1); - if (level == 0) { - MEM_set_lock_callback(NULL, NULL); - } } /* System Information */ @@ -811,24 +790,6 @@ void BLI_thread_queue_wait_finish(ThreadQueue *queue) pthread_mutex_unlock(&queue->mutex); } -/* ************************************************ */ - -void BLI_threaded_malloc_begin(void) -{ - unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1); - if (level == 0) { - MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); - } -} - -void BLI_threaded_malloc_end(void) -{ - unsigned int level = atomic_sub_and_fetch_u(&thread_levels, 1); - if (level == 0) { - MEM_set_lock_callback(NULL, NULL); - } -} - /* **** Special functions to help performance on crazy NUMA setups. **** */ #if 0 /* UNUSED */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9cbe6056dc4..b661a1e7696 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2721,7 +2721,7 @@ static void lib_link_id(FileData *fd, Main *bmain, ID *id); static void lib_link_nodetree(FileData *fd, Main *bmain, bNodeTree *ntree); static void lib_link_collection(FileData *fd, Main *bmain, Collection *collection); -static void lib_link_id_private_id(FileData *fd, Main *bmain, ID *id) +static void lib_link_id_embedded_id(FileData *fd, Main *bmain, ID *id) { /* Handle 'private IDs'. */ bNodeTree *nodetree = ntreeFromID(id); @@ -2755,7 +2755,7 @@ static void lib_link_id(FileData *fd, Main *bmain, ID *id) id->override_library->storage = newlibadr(fd, id->lib, id->override_library->storage); } - lib_link_id_private_id(fd, bmain, id); + lib_link_id_embedded_id(fd, bmain, id); } static void direct_link_id_override_property_operation_cb(FileData *fd, void *data) @@ -2779,18 +2779,22 @@ static void direct_link_id_override_property_cb(FileData *fd, void *data) link_list_ex(fd, &op->operations, direct_link_id_override_property_operation_cb); } -static void direct_link_id_common(FileData *fd, ID *id, ID *id_old, const int tag); +static void direct_link_id_common( + FileData *fd, Library *current_library, ID *id, ID *id_old, const int tag); static void direct_link_nodetree(FileData *fd, bNodeTree *ntree); static void direct_link_collection(FileData *fd, Collection *collection); -static void direct_link_id_private_id(FileData *fd, ID *id, ID *id_old) +static void direct_link_id_embedded_id(FileData *fd, Library *current_library, ID *id, ID *id_old) { /* Handle 'private IDs'. */ bNodeTree **nodetree = BKE_ntree_ptr_from_id(id); if (nodetree != NULL && *nodetree != NULL) { *nodetree = newdataadr(fd, *nodetree); - direct_link_id_common( - fd, (ID *)*nodetree, id_old != NULL ? (ID *)ntreeFromID(id_old) : NULL, 0); + direct_link_id_common(fd, + current_library, + (ID *)*nodetree, + id_old != NULL ? (ID *)ntreeFromID(id_old) : NULL, + 0); direct_link_nodetree(fd, *nodetree); } @@ -2799,6 +2803,7 @@ static void direct_link_id_private_id(FileData *fd, ID *id, ID *id_old) if (scene->master_collection != NULL) { scene->master_collection = newdataadr(fd, scene->master_collection); direct_link_id_common(fd, + current_library, &scene->master_collection->id, id_old != NULL ? &((Scene *)id_old)->master_collection->id : NULL, 0); @@ -2863,18 +2868,40 @@ static int direct_link_id_restore_recalc(const FileData *fd, return recalc; } -static void direct_link_id_common(FileData *fd, ID *id, ID *id_old, const int tag) +static void direct_link_id_common( + FileData *fd, Library *current_library, ID *id, ID *id_old, const int tag) { + if (fd->memfile == NULL) { + /* When actually reading a file , we do want to reset/re-generate session uuids. + * In undo case, we want to re-use existing ones. */ + id->session_uuid = MAIN_ID_SESSION_UUID_UNSET; + } + + BKE_lib_libblock_session_uuid_ensure(id); + + id->lib = current_library; + id->us = ID_FAKE_USERS(id); + id->icon_id = 0; + id->newid = NULL; /* Needed because .blend may have been saved with crap value here... */ + id->orig_id = NULL; + id->py_instance = NULL; + + /* Initialize with provided tag. */ + id->tag = tag; + + if (tag & LIB_TAG_ID_LINK_PLACEHOLDER) { + /* For placeholder we only need to set the tag and properly init generic ID fieds above, no + * further data to read. */ + return; + } + /*link direct data of ID properties*/ if (id->properties) { id->properties = newdataadr(fd, id->properties); /* this case means the data was written incorrectly, it should not happen */ IDP_DirectLinkGroup_OrFree(&id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); } - id->py_instance = NULL; - /* Initialize with provided tag. */ - id->tag = tag; id->flag &= ~LIB_INDIRECT_WEAK_LINK; /* NOTE: It is important to not clear the recalc flags for undo/redo. @@ -2907,7 +2934,7 @@ static void direct_link_id_common(FileData *fd, ID *id, ID *id_old, const int ta } /* Handle 'private IDs'. */ - direct_link_id_private_id(fd, id, id_old); + direct_link_id_embedded_id(fd, current_library, id, id_old); } /** \} */ @@ -8177,23 +8204,9 @@ static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map, LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { if (sl->spacetype == SPACE_VIEW3D) { View3D *v3d = (View3D *)sl; - ARegion *region; v3d->camera = restore_pointer_by_name(id_map, (ID *)v3d->camera, USER_REAL); v3d->ob_center = restore_pointer_by_name(id_map, (ID *)v3d->ob_center, USER_REAL); - - /* Free render engines for now. */ - ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase : - &sl->regionbase; - for (region = regionbase->first; region; region = region->next) { - if (region->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3d = region->regiondata; - if (rv3d && rv3d->render_engine) { - RE_engine_free(rv3d->render_engine); - rv3d->render_engine = NULL; - } - } - } } else if (sl->spacetype == SPACE_GRAPH) { SpaceGraph *sipo = (SpaceGraph *)sl; @@ -9361,19 +9374,8 @@ static const char *dataname(short id_code) static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID *id_old) { - if (fd->memfile == NULL) { - /* When actually reading a file , we do want to reset/re-generate session uuids. - * In undo case, we want to re-use existing ones. */ - id->session_uuid = MAIN_ID_SESSION_UUID_UNSET; - } - - BKE_lib_libblock_session_uuid_ensure(id); - - id->lib = main->curlib; - id->us = ID_FAKE_USERS(id); - id->icon_id = 0; - id->newid = NULL; /* Needed because .blend may have been saved with crap value here... */ - id->orig_id = NULL; + /* Read part of datablock that is common between real and embedded datablocks. */ + direct_link_id_common(fd, main->curlib, id, id_old, tag); if (tag & LIB_TAG_ID_LINK_PLACEHOLDER) { /* For placeholder we only need to set the tag, no further data to read. */ @@ -9381,9 +9383,6 @@ static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID * return true; } - /* Read part of datablock that is common between real and embedded datablocks. */ - direct_link_id_common(fd, id, id_old, tag); - /* XXX Very weakly handled currently, see comment in read_libblock() before trying to * use it for anything new. */ bool success = true; @@ -9634,7 +9633,8 @@ static void read_libblock_undo_restore_identical( BLI_assert((fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0); BLI_assert(id_old != NULL); - id_old->tag = tag; + /* Some tags need to be preserved here. */ + id_old->tag = tag | (id_old->tag & LIB_TAG_EXTRAUSER); id_old->lib = main->curlib; id_old->us = ID_FAKE_USERS(id_old); /* Do not reset id->icon_id here, memory allocated for it remains valid. */ @@ -10920,7 +10920,7 @@ static void expand_id(FileData *fd, Main *mainvar, ID *id); static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree); static void expand_collection(FileData *fd, Main *mainvar, Collection *collection); -static void expand_id_private_id(FileData *fd, Main *mainvar, ID *id) +static void expand_id_embedded_id(FileData *fd, Main *mainvar, ID *id) { /* Handle 'private IDs'. */ bNodeTree *nodetree = ntreeFromID(id); @@ -10952,7 +10952,7 @@ static void expand_id(FileData *fd, Main *mainvar, ID *id) expand_animdata(fd, mainvar, adt); } - expand_id_private_id(fd, mainvar, id); + expand_id_embedded_id(fd, mainvar, id); } static void expand_action(FileData *fd, Main *mainvar, bAction *act) diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 07551f3ea2b..e32a40e1ad5 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -5192,6 +5192,15 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + /* Set Brush default color for grease pencil. */ + LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { + if (brush->gpencil_settings) { + brush->rgb[0] = 0.498f; + brush->rgb[1] = 1.0f; + brush->rgb[2] = 0.498f; + } + } } /** diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index a00cef745e5..665771cce1e 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -202,6 +202,8 @@ static void blo_update_defaults_screen(bScreen *screen, if (v3d->shading.background_type != V3D_SHADING_BACKGROUND_VIEWPORT) { copy_v3_fl(v3d->shading.background_color, 0.05f); } + /* Disable Curve Normals. */ + v3d->overlay.edit_flag &= ~V3D_OVERLAY_EDIT_CU_NORMALS; } else if (area->spacetype == SPACE_CLIP) { SpaceClip *sclip = area->spacedata.first; @@ -463,7 +465,7 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) /* Reset all grease pencil brushes. */ Scene *scene = bmain->scenes.first; - BKE_brush_gpencil_paint_presets(bmain, scene->toolsettings); + BKE_brush_gpencil_paint_presets(bmain, scene->toolsettings, true); /* Ensure new Paint modes. */ BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_VERTEX_GPENCIL); diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index de32d7881b0..b8508f7e12c 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -893,6 +893,10 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh j = bm_to_mesh_shape_layer_index_from_kb(bm, currkey); cd_shape_offset = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, j); + if (cd_shape_offset < 0) { + /* The target Mesh has more shapekeys than the BMesh. */ + continue; + } fp = newkey = MEM_callocN(me->key->elemsize * bm->totvert, "currkey->data"); oldkey = currkey->data; diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 255a52971bb..04cdc0020d9 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -122,6 +122,11 @@ static BMO_FlagSet bmo_enum_falloff_type[] = { {0, NULL}, }; +/* Quiet 'enum-conversion' warning. */ +#define BM_FACE ((int)BM_FACE) +#define BM_EDGE ((int)BM_EDGE) +#define BM_VERT ((int)BM_VERT) + /* * Vertex Smooth. * @@ -2074,6 +2079,10 @@ static BMOpDefine bmo_symmetrize_def = { /* clang-format on */ +#undef BM_FACE +#undef BM_EDGE +#undef BM_VERT + const BMOpDefine *bmo_opdefines[] = { &bmo_average_vert_facedata_def, &bmo_beautify_fill_def, diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index d1ddceb00b0..720eb34bda7 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -4167,6 +4167,10 @@ static int tri_corner_test(BevelParams *bp, BevVert *bv) if (bv->vmesh->count != 3) { return 0; } + + /* Only use the tri-corner special case if the offset is the same for every edge. */ + float offset = bv->edges[0].offset_l; + totang = 0.0f; for (i = 0; i < bv->edgecount; i++) { e = &bv->edges[i]; @@ -4178,6 +4182,11 @@ static int tri_corner_test(BevelParams *bp, BevVert *bv) else if (absang >= 3.0f * (float)M_PI_4) { return -1; } + + if (e->is_bev && !compare_ff(e->offset_l, offset, BEVEL_EPSILON)) { + return -1; + } + totang += ang; } if (in_plane_e != bv->edgecount - 3) { diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp index 7a34c84827e..ee1bb0739b9 100644 --- a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp @@ -570,15 +570,15 @@ void zbuf_accumulate_vecblur(NodeBlurData *nbd, zspan.zofsy = 0.0f; /* the buffers */ - rectz = (float *)MEM_mapallocN(sizeof(float) * xsize * ysize, "zbuf accum"); + rectz = (float *)MEM_callocN(sizeof(float) * xsize * ysize, "zbuf accum"); zspan.rectz = (int *)rectz; - rectmove = (char *)MEM_mapallocN(xsize * ysize, "rectmove"); - rectdraw = (DrawBufPixel *)MEM_mapallocN(sizeof(DrawBufPixel) * xsize * ysize, "rect draw"); + rectmove = (char *)MEM_callocN(xsize * ysize, "rectmove"); + rectdraw = (DrawBufPixel *)MEM_callocN(sizeof(DrawBufPixel) * xsize * ysize, "rect draw"); zspan.rectdraw = rectdraw; - rectweight = (float *)MEM_mapallocN(sizeof(float) * xsize * ysize, "rect weight"); - rectmax = (float *)MEM_mapallocN(sizeof(float) * xsize * ysize, "rect max"); + rectweight = (float *)MEM_callocN(sizeof(float) * xsize * ysize, "rect weight"); + rectmax = (float *)MEM_callocN(sizeof(float) * xsize * ysize, "rect max"); /* debug... check if PASS_VECTOR_MAX still is in buffers */ dvec1 = vecbufrect; @@ -597,7 +597,7 @@ void zbuf_accumulate_vecblur(NodeBlurData *nbd, float minspeed = (float)nbd->minspeed; float minspeedsq = minspeed * minspeed; - minvecbufrect = (float *)MEM_mapallocN(4 * sizeof(float) * xsize * ysize, "minspeed buf"); + minvecbufrect = (float *)MEM_callocN(4 * sizeof(float) * xsize * ysize, "minspeed buf"); dvec1 = vecbufrect; dvec2 = minvecbufrect; @@ -623,7 +623,7 @@ void zbuf_accumulate_vecblur(NodeBlurData *nbd, } /* make vertex buffer with averaged speed and zvalues */ - rectvz = (float *)MEM_mapallocN(4 * sizeof(float) * (xsize + 1) * (ysize + 1), "vertices"); + rectvz = (float *)MEM_callocN(4 * sizeof(float) * (xsize + 1) * (ysize + 1), "vertices"); dvz = rectvz; for (y = 0; y <= ysize; y++) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 44ddd9522e0..f76af5bdda5 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -83,6 +83,7 @@ #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_layer.h" +#include "BKE_light.h" #include "BKE_mask.h" #include "BKE_material.h" #include "BKE_mball.h" @@ -1402,7 +1403,11 @@ void DepsgraphNodeBuilder::build_armature(bArmature *armature) build_animdata(&armature->id); build_parameters(&armature->id); /* Make sure pose is up-to-date with armature updates. */ - add_operation_node(&armature->id, NodeType::ARMATURE, OperationCode::ARMATURE_EVAL); + bArmature *armature_cow = (bArmature *)get_cow_id(&armature->id); + add_operation_node(&armature->id, + NodeType::ARMATURE, + OperationCode::ARMATURE_EVAL, + function_bind(BKE_armature_refresh_layer_used, _1, armature_cow)); build_armature_bones(&armature->bonebase); } @@ -1437,6 +1442,12 @@ void DepsgraphNodeBuilder::build_light(Light *lamp) build_parameters(&lamp->id); /* light's nodetree */ build_nodetree(lamp->nodetree); + + Light *lamp_cow = get_cow_datablock(lamp); + add_operation_node(&lamp->id, + NodeType::SHADING, + OperationCode::LIGHT_UPDATE, + function_bind(BKE_light_eval, _1, lamp_cow)); } void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index ae90ad8a281..db8d9ed516a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -2245,14 +2245,20 @@ void DepsgraphRelationBuilder::build_light(Light *lamp) build_idproperties(lamp->id.properties); build_animdata(&lamp->id); build_parameters(&lamp->id); + + ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS); + /* light's nodetree */ if (lamp->nodetree != nullptr) { build_nodetree(lamp->nodetree); - ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS); ComponentKey nodetree_key(&lamp->nodetree->id, NodeType::SHADING); add_relation(nodetree_key, lamp_parameters_key, "NTree->Light Parameters"); build_nested_nodetree(&lamp->id, lamp->nodetree); } + + /* For allowing drivers on lamp properties. */ + ComponentKey shading_key(&lamp->id, NodeType::SHADING); + add_relation(lamp_parameters_key, shading_key, "Light Shading Parameters"); } void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc index 2381076161f..91bd0117f6c 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.cc +++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc @@ -172,6 +172,8 @@ const char *operationCodeAsString(OperationCode opcode) return "SHADING"; case OperationCode::MATERIAL_UPDATE: return "MATERIAL_UPDATE"; + case OperationCode::LIGHT_UPDATE: + return "LIGHT_UPDATE"; case OperationCode::WORLD_UPDATE: return "WORLD_UPDATE"; /* Movie clip. */ diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h index 865a25d2124..6b14e6af02f 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.h +++ b/source/blender/depsgraph/intern/node/deg_node_operation.h @@ -170,6 +170,7 @@ enum class OperationCode { /* Shading. ------------------------------------------------------------- */ SHADING, MATERIAL_UPDATE, + LIGHT_UPDATE, WORLD_UPDATE, /* Batch caches. -------------------------------------------------------- */ diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 6f932bf8797..0214a8e1887 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -401,4 +401,6 @@ if(WITH_XR_OPENXR) add_definitions(-DWITH_XR_OPENXR) endif() +add_definitions(${GL_DEFINITIONS}) + blender_add_lib(bf_draw "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index 3f4008eb8b9..ebd45ef8e67 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -350,23 +350,15 @@ void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) if (!DRW_pass_is_empty(psl->sss_translucency_ps)) { /* We sample the shadow-maps using normal sampler. We need to disable Comparison mode. * TODO(fclem) avoid this by using sampler objects.*/ - GPU_texture_bind(sldata->shadow_cube_pool, 0); GPU_texture_compare_mode(sldata->shadow_cube_pool, false); - GPU_texture_unbind(sldata->shadow_cube_pool); - GPU_texture_bind(sldata->shadow_cascade_pool, 0); GPU_texture_compare_mode(sldata->shadow_cascade_pool, false); - GPU_texture_unbind(sldata->shadow_cascade_pool); GPU_framebuffer_bind(fbl->sss_translucency_fb); DRW_draw_pass(psl->sss_translucency_ps); /* Reset original state. */ - GPU_texture_bind(sldata->shadow_cube_pool, 0); GPU_texture_compare_mode(sldata->shadow_cube_pool, true); - GPU_texture_unbind(sldata->shadow_cube_pool); - GPU_texture_bind(sldata->shadow_cascade_pool, 0); GPU_texture_compare_mode(sldata->shadow_cascade_pool, true); - GPU_texture_unbind(sldata->shadow_cascade_pool); } /* 1. horizontal pass */ diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index ad90c52b08e..55e7b0eb0e3 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -486,8 +486,7 @@ static bool eevee_volume_object_mesh_init(Scene *scene, ModifierData *md = NULL; /* Smoke Simulation */ - if (((ob->base_flag & BASE_FROM_DUPLI) == 0) && - (md = BKE_modifiers_findby_type(ob, eModifierType_Fluid)) && + if ((md = BKE_modifiers_findby_type(ob, eModifierType_Fluid)) && (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) && ((FluidModifierData *)md)->domain != NULL) { FluidModifierData *mmd = (FluidModifierData *)md; @@ -776,12 +775,8 @@ void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) /* We sample the shadow-maps using shadow sampler. We need to enable Comparison mode. * TODO(fclem) avoid this by using sampler objects.*/ - GPU_texture_bind(sldata->shadow_cube_pool, 0); GPU_texture_compare_mode(sldata->shadow_cube_pool, true); - GPU_texture_unbind(sldata->shadow_cube_pool); - GPU_texture_bind(sldata->shadow_cascade_pool, 0); GPU_texture_compare_mode(sldata->shadow_cascade_pool, true); - GPU_texture_unbind(sldata->shadow_cascade_pool); GPU_framebuffer_bind(fbl->volumetric_fb); DRW_draw_pass(psl->volumetric_world_ps); diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c index 7dddbd07623..6e636e4dc93 100644 --- a/source/blender/draw/engines/external/external_engine.c +++ b/source/blender/draw/engines/external/external_engine.c @@ -215,7 +215,7 @@ static void external_draw_scene_do(void *vedata) return; } - RenderEngine *engine = RE_engine_create_ex(engine_type, true); + RenderEngine *engine = RE_engine_create(engine_type); engine->tile_x = scene->r.tilex; engine->tile_y = scene->r.tiley; engine_type->view_update(engine, draw_ctx->evil_C, draw_ctx->depsgraph); diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl index e2606473d07..fb5073b3dc7 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl @@ -473,8 +473,8 @@ void stroke_vertex() float miter_dot = dot(miter_tan, line_adj); /* Break corners after a certain angle to avoid really thick corners. */ const float miter_limit = 0.5; /* cos(60°) */ - bool miter_break = (miter_dot < miter_limit) || is_stroke_start || is_stroke_end; - miter_tan = (miter_break) ? line : (miter_tan / miter_dot); + bool miter_break = (miter_dot < miter_limit); + miter_tan = (miter_break || is_stroke_start || is_stroke_end) ? line : (miter_tan / miter_dot); vec2 miter = rotate_90deg(miter_tan); @@ -487,7 +487,7 @@ void stroke_vertex() /* Reminder: we packed the cap flag into the sign of stength and thickness sign. */ if ((is_stroke_start && strength1 > 0.0) || (is_stroke_end && thickness1 > 0.0) || - miter_break) { + (miter_break && !is_stroke_start && !is_stroke_end)) { screen_ofs += line * x; } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl index 8c2032f834a..d81c6f4fe0b 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl @@ -99,8 +99,10 @@ void main() discard; } + vec2 fb_size = max(vec2(textureSize(gpSceneDepthTexture, 0).xy), + vec2(textureSize(gpMaskTexture, 0).xy)); + vec2 uvs = gl_FragCoord.xy / fb_size; /* Manual depth test */ - vec2 uvs = gl_FragCoord.xy / vec2(textureSize(gpSceneDepthTexture, 0).xy); float scene_depth = texture(gpSceneDepthTexture, uvs).r; if (gl_FragCoord.z > scene_depth) { discard; diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl index c6cfee5ef2d..225601eb9ba 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl @@ -2,4 +2,4 @@ void main() { gpencil_vertex(); -}
\ No newline at end of file +} diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c index 624eef8fa47..a538b7ffd5f 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.c +++ b/source/blender/draw/engines/overlay/overlay_armature.c @@ -137,9 +137,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) pd->armature.do_pose_fade_geom = pd->armature.do_pose_xray && ((draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) == 0) && draw_ctx->object_pose != NULL; - - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ADD; - DRW_PASS_CREATE(psl->armature_transp_ps, state | pd->clipping_state); + DRWState state; if (pd->armature.do_pose_fade_geom) { state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA; @@ -163,17 +161,21 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) OVERLAY_InstanceFormats *formats = OVERLAY_shader_instance_formats_get(); OVERLAY_ArmatureCallBuffers *cb = &pd->armature_call_buffers[i]; - DRWPass **p_armature_ps = &psl->armature_ps[i]; cb->custom_shapes_ghash = BLI_ghash_ptr_new(__func__); cb->custom_shapes_transp_ghash = BLI_ghash_ptr_new(__func__); + DRWPass **p_armature_ps = &psl->armature_ps[i]; DRWState infront_state = (DRW_state_is_select() && (i == 1)) ? DRW_STATE_IN_FRONT_SELECT : 0; state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_DEPTH; DRW_PASS_CREATE(*p_armature_ps, state | pd->clipping_state | infront_state); - DRWPass *armature_ps = *p_armature_ps; + DRWPass **p_armature_trans_ps = &psl->armature_transp_ps[i]; + state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ADD; + DRW_PASS_CREATE(*p_armature_trans_ps, state | pd->clipping_state); + DRWPass *armature_transp_ps = *p_armature_trans_ps; + #define BUF_INSTANCE DRW_shgroup_call_buffer_instance #define BUF_LINE(grp, format) DRW_shgroup_call_buffer(grp, format, GPU_PRIM_LINES) @@ -231,7 +233,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); cb->dof_lines = BUF_INSTANCE(grp, format, DRW_cache_bone_dof_lines_get()); - grp = DRW_shgroup_create(sh, psl->armature_transp_ps); + grp = DRW_shgroup_create(sh, armature_transp_ps); DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); cb->dof_sphere = BUF_INSTANCE(grp, format, DRW_cache_bone_dof_sphere_get()); } @@ -270,7 +272,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) format = formats->instance_bone_envelope_distance; sh = OVERLAY_shader_armature_envelope(false); - grp = DRW_shgroup_create(sh, psl->armature_transp_ps); + grp = DRW_shgroup_create(sh, armature_transp_ps); DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_bool_copy(grp, "isDistance", true); DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT); @@ -2255,7 +2257,7 @@ void OVERLAY_armature_draw(OVERLAY_Data *vedata) { OVERLAY_PassList *psl = vedata->psl; - DRW_draw_pass(psl->armature_transp_ps); + DRW_draw_pass(psl->armature_transp_ps[0]); DRW_draw_pass(psl->armature_ps[0]); } @@ -2264,6 +2266,7 @@ void OVERLAY_armature_in_front_draw(OVERLAY_Data *vedata) OVERLAY_PassList *psl = vedata->psl; if (psl->armature_bone_select_ps == NULL || DRW_state_is_select()) { + DRW_draw_pass(psl->armature_transp_ps[1]); DRW_draw_pass(psl->armature_ps[1]); } } @@ -2285,6 +2288,7 @@ void OVERLAY_pose_draw(OVERLAY_Data *vedata) GPU_framebuffer_clear_depth(fbl->overlay_line_in_front_fb, 1.0f); } + DRW_draw_pass(psl->armature_transp_ps[1]); DRW_draw_pass(psl->armature_ps[1]); } } diff --git a/source/blender/draw/engines/overlay/overlay_background.c b/source/blender/draw/engines/overlay/overlay_background.c index f1ffa9035e0..f52ae691a35 100644 --- a/source/blender/draw/engines/overlay/overlay_background.c +++ b/source/blender/draw/engines/overlay/overlay_background.c @@ -71,15 +71,16 @@ void OVERLAY_background_cache_init(OVERLAY_Data *vedata) } else { switch (UI_GetThemeValue(TH_BACKGROUND_TYPE)) { - case TH_BACKGROUND_SINGLE_COLOR: - background_type = BG_SOLID; - break; case TH_BACKGROUND_GRADIENT_LINEAR: background_type = BG_GRADIENT; break; case TH_BACKGROUND_GRADIENT_RADIAL: background_type = BG_RADIAL; break; + default: + case TH_BACKGROUND_SINGLE_COLOR: + background_type = BG_SOLID; + break; } } diff --git a/source/blender/draw/engines/overlay/overlay_image.c b/source/blender/draw/engines/overlay/overlay_image.c index c592f11a855..be3510967b6 100644 --- a/source/blender/draw/engines/overlay/overlay_image.c +++ b/source/blender/draw/engines/overlay/overlay_image.c @@ -287,6 +287,9 @@ static void image_camera_background_matrix_get(const Camera *cam, translate[3][0] = bgpic->offset[0]; translate[3][1] = bgpic->offset[1]; translate[3][2] = cam_corners[0][2]; + if (cam->type == CAM_ORTHO) { + mul_v2_fl(translate[3], cam->ortho_scale); + } /* These lines are for keeping 2.80 behavior and could be removed to keep 2.79 behavior. */ translate[3][0] *= min_ff(1.0f, cam_aspect); translate[3][1] /= max_ff(1.0f, cam_aspect) * (image_aspect / cam_aspect); diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h index 0c29fe9d2e4..fa7c7f6d090 100644 --- a/source/blender/draw/engines/overlay/overlay_private.h +++ b/source/blender/draw/engines/overlay/overlay_private.h @@ -54,7 +54,7 @@ typedef struct OVERLAY_PassList { DRWPass *antialiasing_ps; DRWPass *armature_ps[2]; DRWPass *armature_bone_select_ps; - DRWPass *armature_transp_ps; + DRWPass *armature_transp_ps[2]; DRWPass *background_ps; DRWPass *clipping_frustum_ps; DRWPass *edit_curve_wire_ps[2]; @@ -253,8 +253,9 @@ typedef struct OVERLAY_PrivateData { DRWShadingGroup *particle_shapes_grp; DRWShadingGroup *pointcloud_dots_grp; DRWShadingGroup *sculpt_mask_grp; - DRWShadingGroup *wires_grp[2][2]; /* With and without coloring. */ - DRWShadingGroup *wires_all_grp[2][2]; /* With and without coloring. */ + DRWShadingGroup *wires_grp[2][2]; /* With and without coloring. */ + DRWShadingGroup *wires_all_grp[2][2]; /* With and without coloring. */ + DRWShadingGroup *wires_hair_grp[2][2]; /* With and without coloring. */ DRWShadingGroup *wires_sculpt_grp[2]; DRWView *view_default; diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c index 99ff7f67d49..309c7c1021a 100644 --- a/source/blender/draw/engines/overlay/overlay_wireframe.c +++ b/source/blender/draw/engines/overlay/overlay_wireframe.c @@ -21,15 +21,18 @@ */ #include "DNA_mesh_types.h" +#include "DNA_particle_types.h" #include "DNA_view3d_types.h" #include "DNA_volume_types.h" #include "BKE_curve.h" #include "BKE_displist.h" +#include "BKE_duplilist.h" #include "BKE_editmesh.h" #include "BKE_global.h" #include "BKE_object.h" #include "BKE_paint.h" +#include "BKE_particle.h" #include "BLI_hash.h" @@ -95,16 +98,24 @@ void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata) DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0); DRW_shgroup_uniform_bool_copy(grp, "isObjectColor", is_object_color); DRW_shgroup_uniform_bool_copy(grp, "isRandomColor", is_random_color); + DRW_shgroup_uniform_bool_copy(grp, "isHair", false); pd->wires_all_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass); DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx); DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 1.0f); + + pd->wires_hair_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass); + /* TODO(fclem) texture ref persist */ + DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx); + DRW_shgroup_uniform_bool_copy(grp, "isHair", true); + DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 10.0f); } pd->wires_sculpt_grp[xray] = grp = DRW_shgroup_create(wires_sh, pass); DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx); DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 10.0f); DRW_shgroup_uniform_bool_copy(grp, "useColoring", false); + DRW_shgroup_uniform_bool_copy(grp, "isHair", false); } if (is_material_shmode) { @@ -112,19 +123,53 @@ void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata) for (int use_coloring = 0; use_coloring < 2; use_coloring++) { pd->wires_grp[1][use_coloring] = pd->wires_grp[0][use_coloring]; pd->wires_all_grp[1][use_coloring] = pd->wires_all_grp[0][use_coloring]; + pd->wires_hair_grp[1][use_coloring] = pd->wires_hair_grp[0][use_coloring]; } pd->wires_sculpt_grp[1] = pd->wires_sculpt_grp[0]; psl->wireframe_xray_ps = NULL; } } +static void wireframe_hair_cache_populate(OVERLAY_Data *vedata, Object *ob, ParticleSystem *psys) +{ + OVERLAY_PrivateData *pd = vedata->stl->pd; + const bool is_xray = (ob->dtx & OB_DRAWXRAY) != 0; + + Object *dupli_parent = DRW_object_get_dupli_parent(ob); + DupliObject *dupli_object = DRW_object_get_dupli(ob); + + float dupli_mat[4][4]; + if ((dupli_parent != NULL) && (dupli_object != NULL)) { + if (dupli_object->type & OB_DUPLICOLLECTION) { + copy_m4_m4(dupli_mat, dupli_parent->obmat); + } + else { + copy_m4_m4(dupli_mat, dupli_object->ob->obmat); + invert_m4(dupli_mat); + mul_m4_m4m4(dupli_mat, ob->obmat, dupli_mat); + } + } + else { + unit_m4(dupli_mat); + } + + struct GPUBatch *hairs = DRW_cache_particles_get_hair(ob, psys, NULL); + + const bool use_coloring = true; + DRWShadingGroup *shgrp = DRW_shgroup_create_sub(pd->wires_hair_grp[is_xray][use_coloring]); + DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[0]", dupli_mat[0]); + DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[1]", dupli_mat[1]); + DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[2]", dupli_mat[2]); + DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[3]", dupli_mat[3]); + DRW_shgroup_call_no_cull(shgrp, hairs, ob); +} + void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, Object *ob, OVERLAY_DupliData *dupli, bool init_dupli) { - OVERLAY_Data *data = vedata; - OVERLAY_PrivateData *pd = data->stl->pd; + OVERLAY_PrivateData *pd = vedata->stl->pd; const DRWContextState *draw_ctx = DRW_context_state_get(); const bool all_wires = (ob->dtx & OB_DRAW_ALL_EDGES) != 0; const bool is_xray = (ob->dtx & OB_DRAWXRAY) != 0; @@ -134,6 +179,19 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, const bool use_wire = !is_mesh_verts_only && ((pd->overlay.flag & V3D_OVERLAY_WIREFRAMES) || (ob->dtx & OB_DRAWWIRE) || (ob->dt == OB_WIRE)); + if (use_wire && pd->wireframe_mode && ob->particlesystem.first) { + for (ParticleSystem *psys = ob->particlesystem.first; psys != NULL; psys = psys->next) { + if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) { + continue; + } + ParticleSettings *part = psys->part; + const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; + if (draw_as == PART_DRAW_PATH) { + wireframe_hair_cache_populate(vedata, ob, psys); + } + } + } + if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) { OVERLAY_ExtraCallBuffers *cb = OVERLAY_extra_call_buffer_get(vedata, ob); float *color; diff --git a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl index 7e71f4ae587..f7467aa3bf4 100644 --- a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl @@ -4,6 +4,8 @@ uniform bool useColoring; uniform bool isTransform; uniform bool isObjectColor; uniform bool isRandomColor; +uniform bool isHair; +uniform vec4 hairDupliMatrix[4]; in vec3 pos; in vec3 nor; @@ -103,9 +105,16 @@ void main() { bool no_attr = all(equal(nor, vec3(0))); vec3 wnor = no_attr ? ViewMatrixInverse[2].xyz : normalize(normal_object_to_world(nor)); - vec3 wpos = point_object_to_world(pos); + if (isHair) { + mat4 obmat = mat4( + hairDupliMatrix[0], hairDupliMatrix[1], hairDupliMatrix[2], hairDupliMatrix[3]); + + wpos = (obmat * vec4(pos, 1.0)).xyz; + wnor = -normalize(mat3(obmat) * nor); + } + bool is_persp = (ProjectionMatrix[3][3] == 0.0); vec3 V = (is_persp) ? normalize(ViewMatrixInverse[3].xyz - wpos) : ViewMatrixInverse[2].xyz; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl index e6bc4c7bbc6..a4d81393dbc 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl @@ -26,6 +26,10 @@ void curvature_compute(vec2 uv, if ((object_up != object_down) || (object_right != object_left)) { return; } + /* Avoid shading background pixels. */ + if ((object_up == object_right) && (object_right == 0u)) { + return; + } float normal_up = workbench_normal_decode(texture(normalBuffer, uv + offset.zy)).g; float normal_down = workbench_normal_decode(texture(normalBuffer, uv - offset.zy)).g; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl index 6f99739f259..e45f7a7b9e3 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl @@ -24,11 +24,17 @@ bool node_tex_tile_lookup(inout vec3 co, sampler2DArray ima, sampler1DArray map) vec4 workbench_sample_texture(sampler2D image, vec2 coord, bool nearest_sampling) { - vec2 tex_size = vec2(textureSize(image, 0).xy); /* TODO(fclem) We could do the same with sampler objects. * But this is a quick workaround instead of messing with the GPUTexture itself. */ - vec2 uv = nearest_sampling ? (floor(coord * tex_size) + 0.5) / tex_size : coord; - return texture(image, uv); + if (nearest_sampling) { + /* Use texelFetch for nearest_sampling to reduce glitches. See: T73726 */ + vec2 tex_size = vec2(textureSize(image, 0).xy); + ivec2 uv = ivec2(floor(coord * tex_size) + 0.5); + return texelFetch(image, uv, 0); + } + else { + return texture(image, coord); + } } vec4 workbench_sample_texture_array(sampler2DArray tile_array, @@ -36,7 +42,6 @@ vec4 workbench_sample_texture_array(sampler2DArray tile_array, vec2 coord, bool nearest_sampling) { - vec2 tex_size = vec2(textureSize(tile_array, 0).xy); vec3 uv = vec3(coord, 0); if (!node_tex_tile_lookup(uv, tile_array, tile_data)) @@ -44,8 +49,15 @@ vec4 workbench_sample_texture_array(sampler2DArray tile_array, /* TODO(fclem) We could do the same with sampler objects. * But this is a quick workaround instead of messing with the GPUTexture itself. */ - uv.xy = nearest_sampling ? (floor(uv.xy * tex_size) + 0.5) / tex_size : uv.xy; - return texture(tile_array, uv); + if (nearest_sampling) { + /* Use texelFetch for nearest_sampling to reduce glitches. See: T73726 */ + vec3 tex_size = vec3(textureSize(tile_array, 0)); + uv.xy = floor(uv.xy * tex_size.xy) + 0.5; + return texelFetch(tile_array, ivec3(uv), 0); + } + else { + return texture(tile_array, uv); + } } uniform sampler2DArray imageTileArray; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_merge_infront_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_merge_infront_frag.glsl index 58becb03290..b77e168889f 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_merge_infront_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_merge_infront_frag.glsl @@ -15,4 +15,4 @@ void main() /* Make this fragment occlude any fragment that will try to * render over it in the normal passes. */ gl_FragDepth = 0.0; -}
\ No newline at end of file +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl index 81f6e651be0..41ef516ee4d 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl @@ -128,4 +128,4 @@ float get_shadow(vec3 N) float shadow_mix = smoothstep(world_data.shadow_shift, world_data.shadow_focus, light_factor); shadow_mix *= forceShadowing ? 0.0 : world_data.shadow_mul; return shadow_mix + world_data.shadow_add; -}
\ No newline at end of file +} diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c index 72ee7fe17c1..5642ffba4f1 100644 --- a/source/blender/draw/intern/draw_cache_impl_curve.c +++ b/source/blender/draw/intern/draw_cache_impl_curve.c @@ -1034,7 +1034,7 @@ void DRW_curve_batch_cache_create_requested(Object *ob) } if (DRW_vbo_requested(cache->ordered.loop_pos_nor) || - DRW_vbo_requested(cache->ordered.loop_uv)) { + DRW_vbo_requested(cache->ordered.loop_uv) || DRW_vbo_requested(cache->ordered.loop_tan)) { DRW_displist_vertbuf_create_loop_pos_and_nor_and_uv_and_tan( lb, cache->ordered.loop_pos_nor, cache->ordered.loop_uv, cache->ordered.loop_tan); } diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c index 62ce34fe556..ee148e0934d 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.c +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c @@ -291,7 +291,7 @@ static void gpencil_buffer_add_point(gpStrokeVert *verts, vert->u_stroke = pt->uv_fac; vert->stroke_id = gps->runtime.stroke_start; vert->point_id = v; - vert->thickness = max_ff(0.0f, gps->thickness * pt->pressure) * (round_cap1 ? 1.0 : -1.0); + vert->thickness = max_ff(0.0f, gps->thickness * pt->pressure) * (round_cap1 ? 1.0f : -1.0f); /* Tag endpoint material to -1 so they get discarded by vertex shader. */ vert->mat = (is_endpoint) ? -1 : (gps->mat_nr % GP_MATERIAL_BUFFER_LEN); diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 95b204ac004..ff27fa958ef 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -2000,7 +2000,10 @@ void DRW_pass_sort_shgroup_z(DRWPass *pass) } } /* To be sorted a shgroup needs to have at least one draw command. */ - BLI_assert(handle != 0); + /* FIXME(fclem) In some case, we can still have empty shading group to sort. However their + * final order is not well defined. + * (see T76730 & D7729). */ + // BLI_assert(handle != 0); DRWObjectMatrix *obmats = DRW_memblock_elem_from_handle(DST.vmempool->obmats, &handle); diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c index 7eac082a9e1..0d6527421d0 100644 --- a/source/blender/draw/intern/draw_manager_shader.c +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -241,6 +241,9 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred) WM_jobs_timer(wm_job, 0.1, NC_MATERIAL | ND_SHADING_DRAW, 0); WM_jobs_delay_start(wm_job, 0.1); WM_jobs_callbacks(wm_job, drw_deferred_shader_compilation_exec, NULL, NULL, NULL); + + G.is_break = false; + WM_jobs_start(wm, wm_job); } diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index e795cb6e3ef..eadaa449b92 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -717,28 +717,31 @@ static void draw_modifier__envelope(uiLayout *layout, /* control points list */ for (i = 0, fed = env->data; i < env->totvert; i++, fed++) { + PointerRNA ctrl_ptr; + RNA_pointer_create(fcurve_owner_id, &RNA_FModifierEnvelopeControlPoint, fed, &ctrl_ptr); + /* get a new row to operate on */ row = uiLayoutRow(layout, true); block = uiLayoutGetBlock(row); UI_block_align_begin(block); - but = uiDefButF(block, - UI_BTYPE_NUM, - B_FMODIFIER_REDRAW, - IFACE_("Fra:"), - 0, - 0, - 4.5 * UI_UNIT_X, - UI_UNIT_Y, - &fed->time, - -MAXFRAMEF, - MAXFRAMEF, - 10, - 1, - TIP_("Frame that envelope point occurs")); - UI_but_func_set(but, validate_fmodifier_cb, fcm, NULL); - - uiDefButF(block, + uiDefButR(block, + UI_BTYPE_NUM, + B_FMODIFIER_REDRAW, + IFACE_("Fra:"), + 0, + 0, + 4.5 * UI_UNIT_X, + UI_UNIT_Y, + &ctrl_ptr, + "frame", + -1, + -MAXFRAMEF, + MAXFRAMEF, + 10, + 1, + NULL); + uiDefButR(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, IFACE_("Min:"), @@ -746,13 +749,15 @@ static void draw_modifier__envelope(uiLayout *layout, 0, 5 * UI_UNIT_X, UI_UNIT_Y, - &fed->min, + &ctrl_ptr, + "min", + -1, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, - TIP_("Minimum bound of envelope at this point")); - uiDefButF(block, + NULL); + uiDefButR(block, UI_BTYPE_NUM, B_FMODIFIER_REDRAW, IFACE_("Max:"), @@ -760,12 +765,14 @@ static void draw_modifier__envelope(uiLayout *layout, 0, 5 * UI_UNIT_X, UI_UNIT_Y, - &fed->max, + &ctrl_ptr, + "max", + -1, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, - TIP_("Maximum bound of envelope at this point")); + NULL); but = uiDefIconBut(block, UI_BTYPE_BUT, diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index 5f3b876efaf..d3d00fc44f2 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -432,7 +432,6 @@ int join_armature_exec(bContext *C, wmOperator *op) ED_armature_from_edit(bmain, arm); ED_armature_edit_free(arm); - BKE_armature_refresh_layer_used(arm); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); @@ -689,9 +688,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op) /* 5) restore original conditions */ ED_armature_to_edit(ob_old->data); - ED_armature_edit_refresh_layer_used(ob_old->data); - BKE_armature_refresh_layer_used(ob_new->data); /* parents tips remain selected when connected children are removed. */ ED_armature_edit_deselect_all(ob_old); diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index daab945c106..0cd3afc9cf9 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -906,8 +906,6 @@ static int pose_bone_layers_exec(bContext *C, wmOperator *op) RNA_boolean_set_array(&ptr, "layers", layers); if (prev_ob != ob) { - BKE_armature_refresh_layer_used(ob->data); - /* Note, notifier might evolve. */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); DEG_id_tag_update((ID *)ob->data, ID_RECALC_COPY_ON_WRITE); diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index 481282d6df3..d9621dba730 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -1239,51 +1239,60 @@ static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso return OPERATOR_FINISHED; } -/* common code for defining RNA properties */ -/* TODO: Skip save on these? */ +/** + * Common code for defining RNA properties. + */ static void pose_slide_opdef_properties(wmOperatorType *ot) { - RNA_def_float_percentage(ot->srna, - "percentage", - 0.5f, - 0.0f, - 1.0f, - "Percentage", - "Weighting factor for which keyframe is favored more", - 0.0, - 1.0); - - RNA_def_int(ot->srna, - "prev_frame", - 0, - MINAFRAME, - MAXFRAME, - "Previous Keyframe", - "Frame number of keyframe immediately before the current frame", - 0, - 50); - RNA_def_int(ot->srna, - "next_frame", - 0, - MINAFRAME, - MAXFRAME, - "Next Keyframe", - "Frame number of keyframe immediately after the current frame", - 0, - 50); - - RNA_def_enum(ot->srna, - "channels", - prop_channels_types, - PS_TFM_ALL, - "Channels", - "Set of properties that are affected"); - RNA_def_enum(ot->srna, - "axis_lock", - prop_axis_lock_types, - 0, - "Axis Lock", - "Transform axis to restrict effects to"); + PropertyRNA *prop; + + prop = RNA_def_float_percentage(ot->srna, + "percentage", + 0.5f, + 0.0f, + 1.0f, + "Percentage", + "Weighting factor for which keyframe is favored more", + 0.0, + 1.0); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_int(ot->srna, + "prev_frame", + 0, + MINAFRAME, + MAXFRAME, + "Previous Keyframe", + "Frame number of keyframe immediately before the current frame", + 0, + 50); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_int(ot->srna, + "next_frame", + 0, + MINAFRAME, + MAXFRAME, + "Next Keyframe", + "Frame number of keyframe immediately after the current frame", + 0, + 50); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_enum(ot->srna, + "channels", + prop_channels_types, + PS_TFM_ALL, + "Channels", + "Set of properties that are affected"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, + "axis_lock", + prop_axis_lock_types, + 0, + "Axis Lock", + "Transform axis to restrict effects to"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ------------------------------------ */ diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index a7e7246ee82..8c80334bf8a 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -1907,19 +1907,19 @@ static int gp_brush_reset_all_exec(bContext *C, wmOperator *UNUSED(op)) switch (mode) { case CTX_MODE_PAINT_GPENCIL: { - BKE_brush_gpencil_paint_presets(bmain, ts); + BKE_brush_gpencil_paint_presets(bmain, ts, true); break; } case CTX_MODE_SCULPT_GPENCIL: { - BKE_brush_gpencil_sculpt_presets(bmain, ts); + BKE_brush_gpencil_sculpt_presets(bmain, ts, true); break; } case CTX_MODE_WEIGHT_GPENCIL: { - BKE_brush_gpencil_weight_presets(bmain, ts); + BKE_brush_gpencil_weight_presets(bmain, ts, true); break; } case CTX_MODE_VERTEX_GPENCIL: { - BKE_brush_gpencil_vertex_presets(bmain, ts); + BKE_brush_gpencil_vertex_presets(bmain, ts, true); break; } default: { diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 2d53679b61a..151f4a930d0 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -369,12 +369,20 @@ static int gpencil_paintmode_toggle_exec(bContext *C, wmOperator *op) } if (mode == OB_MODE_PAINT_GPENCIL) { - /* be sure we have brushes */ + /* Be sure we have brushes and Paint settings. + * Need Draw and Vertex (used fro Tint). */ BKE_paint_ensure(ts, (Paint **)&ts->gp_paint); + BKE_paint_ensure(ts, (Paint **)&ts->gp_vertexpaint); + + BKE_brush_gpencil_paint_presets(bmain, ts, false); + + /* Ensure Palette by default. */ + BKE_gpencil_palette_ensure(bmain, CTX_data_scene(C)); + Paint *paint = &ts->gp_paint->paint; /* if not exist, create a new one */ if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) { - BKE_brush_gpencil_paint_presets(bmain, ts); + BKE_brush_gpencil_paint_presets(bmain, ts, true); } BKE_paint_toolslots_brush_validate(bmain, &ts->gp_paint->paint); } @@ -480,6 +488,8 @@ static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op) /* be sure we have brushes */ BKE_paint_ensure(ts, (Paint **)&ts->gp_sculptpaint); BKE_paint_toolslots_brush_validate(bmain, &ts->gp_sculptpaint->paint); + + BKE_brush_gpencil_sculpt_presets(bmain, ts, false); } /* setup other modes */ @@ -585,6 +595,8 @@ static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op) /* be sure we have brushes */ BKE_paint_ensure(ts, (Paint **)&ts->gp_weightpaint); BKE_paint_toolslots_brush_validate(bmain, &ts->gp_weightpaint->paint); + + BKE_brush_gpencil_weight_presets(bmain, ts, false); } /* setup other modes */ @@ -687,6 +699,11 @@ static int gpencil_vertexmode_toggle_exec(bContext *C, wmOperator *op) /* be sure we have brushes */ BKE_paint_ensure(ts, (Paint **)&ts->gp_vertexpaint); BKE_paint_toolslots_brush_validate(bmain, &ts->gp_vertexpaint->paint); + + BKE_brush_gpencil_vertex_presets(bmain, ts, false); + + /* Ensure Palette by default. */ + BKE_gpencil_palette_ensure(bmain, CTX_data_scene(C)); } /* setup other modes */ diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index a98ccb1cba6..473913c5459 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -699,16 +699,13 @@ struct GP_EditableStrokes_Iter { const bool is_multiedit_ = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_); \ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_->layers) { \ if (BKE_gpencil_layer_is_editable(gpl)) { \ - bGPDframe *init_gpf_ = gpl->actframe; \ - if (is_multiedit_) { \ - init_gpf_ = gpl->frames.first; \ - } \ + bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \ for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ /* loop over strokes */ \ - for (bGPDstroke *gps = gpf_->strokes.first; gps; gps = gps->next) { \ + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf_->strokes) { \ /* skip strokes that are invalid for current view */ \ if (ED_gpencil_stroke_can_use(C, gps) == false) \ continue; \ diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c index b80e8d6ac73..e71bf2098dd 100644 --- a/source/blender/editors/gpencil/gpencil_merge.c +++ b/source/blender/editors/gpencil/gpencil_merge.c @@ -117,7 +117,7 @@ static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpo /* if not exist, create a new one */ if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) { /* create new brushes */ - BKE_brush_gpencil_paint_presets(bmain, ts); + BKE_brush_gpencil_paint_presets(bmain, ts, false); } Brush *brush = paint->brush; diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index cb72553c68b..4e83c4fb11c 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1814,7 +1814,7 @@ static void gp_init_drawing_brush(bContext *C, tGPsdata *p) /* if not exist, create a new one */ if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) { /* create new brushes */ - BKE_brush_gpencil_paint_presets(bmain, ts); + BKE_brush_gpencil_paint_presets(bmain, ts, true); changed = true; } /* Be sure curves are initializated. */ @@ -2071,8 +2071,15 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps return; } - /* Eraser mode: If no active strokes, just return. */ + /* Eraser mode: If no active strokes, add one or just return. */ if (paintmode == GP_PAINTMODE_ERASER) { + /* Eraser mode: + * 1) Add new frames to all frames that we might touch, + * 2) Ensure that p->gpf refers to the frame used for the active layer + * (to avoid problems with other tools which expect it to exist) + * + * This is done only if additive drawing is enabled. + */ bool has_layer_to_erase = false; LISTBASE_FOREACH (bGPDlayer *, gpl, &p->gpd->layers) { @@ -2081,12 +2088,27 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps continue; } + /* Add a new frame if needed (and based off the active frame, + * as we need some existing strokes to erase) + * + * Note: We don't add a new frame if there's nothing there now, so + * -> If there are no frames at all, don't add one + * -> If there are no strokes in that frame, don't add a new empty frame + */ if (gpl->actframe && gpl->actframe->strokes.first) { + if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { + gpl->actframe = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_COPY); + } has_layer_to_erase = true; break; } } + /* Ensure this gets set. */ + if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { + p->gpf = p->gpl->actframe; + } + if (has_layer_to_erase == false) { p->status = GP_STATUS_ERROR; return; diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 1778162c1a3..875a6265497 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -1178,7 +1178,7 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op) /* if brush doesn't exist, create a new set (fix damaged files from old versions) */ if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) { - BKE_brush_gpencil_paint_presets(bmain, ts); + BKE_brush_gpencil_paint_presets(bmain, ts, true); } /* Set Draw brush. */ diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 407571d18c8..3cab26eab44 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -1365,7 +1365,7 @@ void ED_gpencil_add_defaults(bContext *C, Object *ob) /* if not exist, create a new one */ if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) { /* create new brushes */ - BKE_brush_gpencil_paint_presets(bmain, ts); + BKE_brush_gpencil_paint_presets(bmain, ts, true); } /* ensure a color exists and is assigned to object */ diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 32e62a6436c..e6d39d5f966 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -260,6 +260,7 @@ float ED_object_new_primitive_matrix(struct bContext *C, #define OBJECT_ADD_SIZE_MAXF 1.0e12f void ED_object_add_unit_props_size(struct wmOperatorType *ot); +void ED_object_add_unit_props_radius_ex(struct wmOperatorType *ot, float default_value); void ED_object_add_unit_props_radius(struct wmOperatorType *ot); void ED_object_add_generic_props(struct wmOperatorType *ot, bool do_editmode); void ED_object_add_mesh_props(struct wmOperatorType *ot); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 43f3a578bfe..bc6a4b23609 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -347,6 +347,7 @@ bool ED_operator_info_active(struct bContext *C); bool ED_operator_console_active(struct bContext *C); bool ED_operator_object_active(struct bContext *C); +bool ED_operator_object_active_editable_ex(struct bContext *C, const Object *ob); bool ED_operator_object_active_editable(struct bContext *C); bool ED_operator_object_active_editable_mesh(struct bContext *C); bool ED_operator_object_active_editable_font(struct bContext *C); diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 27b7511c8a2..9969acd04b7 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -158,7 +158,7 @@ int BIF_countTransformOrientation(const struct bContext *C); #define P_CURSOR_EDIT (1 << 14) #define P_CLNOR_INVALIDATE (1 << 15) /* For properties performed when confirming the transformation. */ -#define P_POST_TRANSFORM (1 << 16) +#define P_POST_TRANSFORM (1 << 19) void Transform_Properties(struct wmOperatorType *ot, int flags); diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 8c565536c71..f656aaf9c07 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -50,20 +50,17 @@ void ED_operatortypes_uvedit(void); void ED_keymap_uvedit(struct wmKeyConfig *keyconf); bool ED_uvedit_minmax(const struct Scene *scene, - struct Image *ima, struct Object *obedit, float min[2], float max[2]); void ED_uvedit_select_all(struct BMesh *bm); bool ED_uvedit_minmax_multi(const struct Scene *scene, - struct Image *ima, struct Object **objects_edit, uint objects_len, float r_min[2], float r_max[2]); bool ED_uvedit_center_multi(const struct Scene *scene, - Image *ima, struct Object **objects_edit, uint objects_len, float r_cent[2], @@ -95,11 +92,7 @@ void ED_object_assign_active_image(struct Main *bmain, bool ED_uvedit_test(struct Object *obedit); /* visibility and selection */ -bool uvedit_face_visible_nolocal_ex(const struct ToolSettings *ts, struct BMFace *efa); -bool uvedit_face_visible_test_ex(const struct ToolSettings *ts, - struct Object *obedit, - struct Image *ima, - struct BMFace *efa); +bool uvedit_face_visible_test_ex(const struct ToolSettings *ts, struct BMFace *efa); bool uvedit_face_select_test_ex(const struct ToolSettings *ts, struct BMFace *efa, const int cd_loop_uv_offset); @@ -110,11 +103,7 @@ bool uvedit_uv_select_test_ex(const struct ToolSettings *ts, struct BMLoop *l, const int cd_loop_uv_offset); -bool uvedit_face_visible_nolocal(const struct Scene *scene, struct BMFace *efa); -bool uvedit_face_visible_test(const struct Scene *scene, - struct Object *obedit, - struct Image *ima, - struct BMFace *efa); +bool uvedit_face_visible_test(const struct Scene *scene, struct BMFace *efa); bool uvedit_face_select_test(const struct Scene *scene, struct BMFace *efa, const int cd_loop_uv_offset); @@ -175,12 +164,10 @@ void uvedit_uv_select_disable(struct BMEditMesh *em, bool ED_uvedit_nearest_uv(const struct Scene *scene, struct Object *obedit, - struct Image *ima, const float co[2], float *dist_sq, float r_uv[2]); bool ED_uvedit_nearest_uv_multi(const struct Scene *scene, - struct Image *ima, struct Object **objects, const uint objects_len, const float co[2], diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 8b7b0430765..3ad1608b47b 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -2417,6 +2417,8 @@ uiBut *UI_context_active_but_prop_get(const struct bContext *C, struct PropertyRNA **r_prop, int *r_index); void UI_context_active_but_prop_handle(struct bContext *C); +void UI_context_active_but_clear(struct bContext *C, struct wmWindow *win, struct ARegion *region); + struct wmOperator *UI_context_active_operator_get(const struct bContext *C); void UI_context_update_anim_flag(const struct bContext *C); void UI_context_active_but_prop_get_filebrowser(const struct bContext *C, diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c index 7527a1e0662..ace367fd513 100644 --- a/source/blender/editors/interface/interface_eyedropper_color.c +++ b/source/blender/editors/interface/interface_eyedropper_color.c @@ -82,11 +82,13 @@ static bool eyedropper_init(bContext *C, wmOperator *op) eye->use_accum = RNA_boolean_get(op->ptr, "use_accumulate"); uiBut *but = UI_context_active_but_prop_get(C, &eye->ptr, &eye->prop, &eye->index); + const enum PropertySubType prop_subtype = eye->prop ? RNA_property_subtype(eye->prop) : 0; if ((eye->ptr.data == NULL) || (eye->prop == NULL) || (RNA_property_editable(&eye->ptr, eye->prop) == false) || (RNA_property_array_length(&eye->ptr, eye->prop) < 3) || - (RNA_property_type(eye->prop) != PROP_FLOAT)) { + (RNA_property_type(eye->prop) != PROP_FLOAT) || + (ELEM(prop_subtype, PROP_COLOR, PROP_COLOR_GAMMA) == 0)) { MEM_freeN(eye); return false; } @@ -96,7 +98,7 @@ static bool eyedropper_init(bContext *C, wmOperator *op) float col[4]; RNA_property_float_get_array(&eye->ptr, eye->prop, col); - if (RNA_property_subtype(eye->prop) != PROP_COLOR) { + if (prop_subtype != PROP_COLOR) { Scene *scene = CTX_data_scene(C); const char *display_device; @@ -290,7 +292,10 @@ static int eyedropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED( { /* init */ if (eyedropper_init(C, op)) { - WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_EYEDROPPER); + wmWindow *win = CTX_wm_window(C); + /* Workaround for de-activating the button clearing the cursor, see T76794 */ + UI_context_active_but_clear(C, win, CTX_wm_region(C)); + WM_cursor_modal_set(win, WM_CURSOR_EYEDROPPER); /* add temp handler */ WM_event_add_modal_handler(C, op); diff --git a/source/blender/editors/interface/interface_eyedropper_colorband.c b/source/blender/editors/interface/interface_eyedropper_colorband.c index be23eacafff..24d06361c54 100644 --- a/source/blender/editors/interface/interface_eyedropper_colorband.c +++ b/source/blender/editors/interface/interface_eyedropper_colorband.c @@ -304,7 +304,10 @@ static int eyedropper_colorband_invoke(bContext *C, wmOperator *op, const wmEven { /* init */ if (eyedropper_colorband_init(C, op)) { - WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_EYEDROPPER); + wmWindow *win = CTX_wm_window(C); + /* Workaround for de-activating the button clearing the cursor, see T76794 */ + UI_context_active_but_clear(C, win, CTX_wm_region(C)); + WM_cursor_modal_set(win, WM_CURSOR_EYEDROPPER); /* add temp handler */ WM_event_add_modal_handler(C, op); diff --git a/source/blender/editors/interface/interface_eyedropper_datablock.c b/source/blender/editors/interface/interface_eyedropper_datablock.c index d9c77c26941..f2217db9b7d 100644 --- a/source/blender/editors/interface/interface_eyedropper_datablock.c +++ b/source/blender/editors/interface/interface_eyedropper_datablock.c @@ -316,7 +316,10 @@ static int datadropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED { /* init */ if (datadropper_init(C, op)) { - WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_EYEDROPPER); + wmWindow *win = CTX_wm_window(C); + /* Workaround for de-activating the button clearing the cursor, see T76794 */ + UI_context_active_but_clear(C, win, CTX_wm_region(C)); + WM_cursor_modal_set(win, WM_CURSOR_EYEDROPPER); /* add temp handler */ WM_event_add_modal_handler(C, op); diff --git a/source/blender/editors/interface/interface_eyedropper_depth.c b/source/blender/editors/interface/interface_eyedropper_depth.c index 907da917e75..5c85edc94a1 100644 --- a/source/blender/editors/interface/interface_eyedropper_depth.c +++ b/source/blender/editors/interface/interface_eyedropper_depth.c @@ -311,7 +311,10 @@ static int depthdropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE { /* init */ if (depthdropper_init(C, op)) { - WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_EYEDROPPER); + wmWindow *win = CTX_wm_window(C); + /* Workaround for de-activating the button clearing the cursor, see T76794 */ + UI_context_active_but_clear(C, win, CTX_wm_region(C)); + WM_cursor_modal_set(win, WM_CURSOR_EYEDROPPER); /* add temp handler */ WM_event_add_modal_handler(C, op); diff --git a/source/blender/editors/interface/interface_eyedropper_driver.c b/source/blender/editors/interface/interface_eyedropper_driver.c index 89c087855bc..276cc70f2b5 100644 --- a/source/blender/editors/interface/interface_eyedropper_driver.c +++ b/source/blender/editors/interface/interface_eyedropper_driver.c @@ -180,7 +180,10 @@ static int driverdropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS { /* init */ if (driverdropper_init(C, op)) { - WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_EYEDROPPER); + wmWindow *win = CTX_wm_window(C); + /* Workaround for de-activating the button clearing the cursor, see T76794 */ + UI_context_active_but_clear(C, win, CTX_wm_region(C)); + WM_cursor_modal_set(win, WM_CURSOR_EYEDROPPER); /* add temp handler */ WM_event_add_modal_handler(C, op); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index ebde1d54c07..eb99d044e17 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -5559,7 +5559,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co } else if (but->type == UI_BTYPE_MENU) { if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { - const int direction = (event->type == WHEELDOWNMOUSE) ? -1 : 1; + const int direction = (event->type == WHEELDOWNMOUSE) ? 1 : -1; data->value = ui_but_menu_step(but, direction); @@ -8337,6 +8337,11 @@ void UI_context_active_but_prop_handle(bContext *C) } } +void UI_context_active_but_clear(bContext *C, wmWindow *win, ARegion *region) +{ + wm_event_handler_ui_cancel_ex(C, win, region, false); +} + wmOperator *UI_context_active_operator_get(const struct bContext *C) { ARegion *region_ctx = CTX_wm_region(C); @@ -8868,7 +8873,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) if (post_but) { button_activate_init(C, region, post_but, post_type); } - else { + else if (!((event->type == EVT_BUT_CANCEL) && (event->val == 1))) { /* XXX issue is because WM_event_add_mousemove(wm) is a bad hack and not reliable, * if that gets coded better this bypass can go away too. * diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index fbcac6079ae..974fec13bee 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -105,7 +105,6 @@ extern const char ui_radial_dir_to_numpad[8]; extern const short ui_radial_dir_to_angle[8]; /* internal panel drawing defines */ -#define PNL_GRID (UI_UNIT_Y / 5) /* 4 default */ #define PNL_HEADER (UI_UNIT_Y * 1.2) /* 24 default */ /* bit button defines */ diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 04179721305..c5f67e63bd3 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -1322,8 +1322,8 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel) return; } - dx = (event->x - data->startx) & ~(PNL_GRID - 1); - dy = (event->y - data->starty) & ~(PNL_GRID - 1); + dx = (event->x - data->startx); + dy = (event->y - data->starty); dx *= (float)BLI_rctf_size_x(®ion->v2d.cur) / (float)BLI_rcti_size_x(®ion->winrct); dy *= (float)BLI_rctf_size_y(®ion->v2d.cur) / (float)BLI_rcti_size_y(®ion->winrct); diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.c index 34ac58c1dca..1f8af7b9e6e 100644 --- a/source/blender/editors/interface/interface_region_hud.c +++ b/source/blender/editors/interface/interface_region_hud.c @@ -177,11 +177,13 @@ static void hud_region_layout(const bContext *C, ARegion *region) return; } + ScrArea *area = CTX_wm_area(C); int size_y = region->sizey; ED_region_panels_layout(C, region); - if (region->panels.first && (region->sizey != size_y)) { + if (region->panels.first && + ((area->flag & AREA_FLAG_REGION_SIZE_UPDATE) || (region->sizey != size_y))) { int winx_new = UI_DPI_FAC * (region->sizex + 0.5f); int winy_new = UI_DPI_FAC * (region->sizey + 0.5f); View2D *v2d = ®ion->v2d; @@ -339,6 +341,7 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *area) } else { if (region->flag & RGN_FLAG_HIDDEN) { + /* Also forces recalculating HUD size in hud_region_layout(). */ area->flag |= AREA_FLAG_REGION_SIZE_UPDATE; } region->flag &= ~RGN_FLAG_HIDDEN; diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c index 0a06f765c0e..2c6b09168f4 100644 --- a/source/blender/editors/interface/interface_template_search_menu.c +++ b/source/blender/editors/interface/interface_template_search_menu.c @@ -41,6 +41,7 @@ #include "BLI_math_matrix.h" #include "BLI_memarena.h" #include "BLI_string.h" +#include "BLI_string_utils.h" #include "BLI_utildefines.h" #include "BLT_translation.h" @@ -177,7 +178,19 @@ static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *d struct MenuSearch_Context *wm_context) { struct MenuSearch_Item *item = NULL; + + /* Use override if the name is empty, this can happen with popovers. */ + const char *drawstr_override = NULL; + const char *drawstr_sep = (but->flag & UI_BUT_HAS_SEP_CHAR) ? + strrchr(but->drawstr, UI_SEP_CHAR) : + NULL; + const bool drawstr_is_empty = (drawstr_sep == but->drawstr) || (but->drawstr[0] == '\0'); + if (but->optype != NULL) { + if (drawstr_is_empty) { + drawstr_override = WM_operatortype_name(but->optype, but->opptr); + } + item = BLI_memarena_calloc(memarena, sizeof(*item)); item->type = MENU_SEARCH_TYPE_OP; @@ -189,6 +202,25 @@ static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *d } else if (but->rnaprop != NULL) { const int prop_type = RNA_property_type(but->rnaprop); + + if (drawstr_is_empty) { + if (prop_type == PROP_ENUM) { + const int value_enum = (int)but->hardmax; + EnumPropertyItem enum_item; + if (RNA_property_enum_item_from_value_gettexted( + but->block->evil_C, &but->rnapoin, but->rnaprop, value_enum, &enum_item)) { + drawstr_override = enum_item.name; + } + else { + /* Should never happen. */ + drawstr_override = "Unknown"; + } + } + else { + drawstr_override = RNA_property_ui_name(but->rnaprop); + } + } + if (!ELEM(prop_type, PROP_BOOLEAN, PROP_ENUM)) { /* Note that these buttons are not prevented, * but aren't typically used in menus. */ @@ -213,7 +245,16 @@ static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *d if (item != NULL) { /* Handle shared settings. */ - item->drawstr = strdup_memarena(memarena, but->drawstr); + if (drawstr_override != NULL) { + const char *drawstr_suffix = drawstr_sep ? drawstr_sep : ""; + char *drawstr_alloc = BLI_string_joinN("(", drawstr_override, ")", drawstr_suffix); + item->drawstr = strdup_memarena(memarena, drawstr_alloc); + MEM_freeN(drawstr_alloc); + } + else { + item->drawstr = strdup_memarena(memarena, but->drawstr); + } + item->icon = ui_but_icon(but); item->state = (but->flag & (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT | UI_BUT_HAS_SEP_CHAR)); diff --git a/source/blender/editors/interface/view2d_draw.c b/source/blender/editors/interface/view2d_draw.c index 17a95ba3fff..36213f919a3 100644 --- a/source/blender/editors/interface/view2d_draw.c +++ b/source/blender/editors/interface/view2d_draw.c @@ -40,6 +40,7 @@ #include "GPU_immediate.h" #include "GPU_matrix.h" +#include "GPU_state.h" #include "WM_api.h" @@ -196,7 +197,19 @@ static void draw_parallel_lines(const ParallelLinesSet *lines, GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + if (U.pixelsize > 1.0f) { + float viewport[4]; + GPU_viewport_size_get_f(viewport); + + immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); + immUniform2fv("viewportSize", &viewport[2]); + /* -1.0f offset here is because the line is too fat due to the builtin antialiasing. + * TODO make a variant or a uniform to toggle it off. */ + immUniform1f("lineWidth", U.pixelsize - 1.0f); + } + else { + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + } immUniformColor3ubv(color); immBegin(GPU_PRIM_LINES, steps * 2); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 74fba4d0cf9..2ee98f39306 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -303,10 +303,15 @@ void ED_object_add_unit_props_size(wmOperatorType *ot) ot->srna, "size", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Size", "", 0.001, 100.00); } -void ED_object_add_unit_props_radius(wmOperatorType *ot) +void ED_object_add_unit_props_radius_ex(wmOperatorType *ot, float default_value) { RNA_def_float_distance( - ot->srna, "radius", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.001, 100.00); + ot->srna, "radius", default_value, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.001, 100.00); +} + +void ED_object_add_unit_props_radius(wmOperatorType *ot) +{ + ED_object_add_unit_props_radius_ex(ot, 1.0f); } void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode) @@ -814,7 +819,10 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op) } ED_object_new_primitive_matrix(C, obedit, loc, rot, mat); - dia = RNA_float_get(op->ptr, "radius"); + /* Halving here is done to account for constant values from #BKE_mball_element_add. + * While the default radius of the resulting meta element is 2, + * we want to pass in 1 so other values such as resolution are scaled by 1.0. */ + dia = RNA_float_get(op->ptr, "radius") / 2; ED_mball_add_primitive(C, obedit, mat, dia, RNA_enum_get(op->ptr, "type")); @@ -845,7 +853,7 @@ void OBJECT_OT_metaball_add(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_metaelem_type_items, 0, "Primitive", ""); - ED_object_add_unit_props_radius(ot); + ED_object_add_unit_props_radius_ex(ot, 2.0f); ED_object_add_generic_props(ot, true); } diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 46923b593b1..e84dbca2469 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -96,6 +96,7 @@ typedef struct BakeAPIRender { bool is_cage; float cage_extrusion; + float max_ray_distance; int normal_space; eBakeNormalSwizzle normal_swizzle[3]; @@ -737,6 +738,7 @@ static int bake(Render *re, const bool is_selected_to_active, const bool is_cage, const float cage_extrusion, + const float max_ray_distance, const int normal_space, const eBakeNormalSwizzle normal_swizzle[], const char *custom_cage, @@ -1010,6 +1012,7 @@ static int bake(Render *re, num_pixels, ob_cage != NULL, cage_extrusion, + max_ray_distance, ob_low_eval->obmat, (ob_cage ? ob_cage->obmat : ob_low_eval->obmat), me_cage)) { @@ -1024,7 +1027,7 @@ static int bake(Render *re, highpoly[i].ob, i, pixel_array_high, - num_pixels, + &bake_images, depth, pass_type, pass_filter, @@ -1046,7 +1049,7 @@ static int bake(Render *re, ob_low_eval, 0, pixel_array_low, - num_pixels, + &bake_images, depth, pass_type, pass_filter, @@ -1305,6 +1308,7 @@ static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr) bkr->is_selected_to_active = RNA_boolean_get(op->ptr, "use_selected_to_active"); bkr->is_cage = RNA_boolean_get(op->ptr, "use_cage"); bkr->cage_extrusion = RNA_float_get(op->ptr, "cage_extrusion"); + bkr->max_ray_distance = RNA_float_get(op->ptr, "max_ray_distance"); bkr->normal_space = RNA_enum_get(op->ptr, "normal_space"); bkr->normal_swizzle[0] = RNA_enum_get(op->ptr, "normal_r"); @@ -1394,6 +1398,7 @@ static int bake_exec(bContext *C, wmOperator *op) true, bkr.is_cage, bkr.cage_extrusion, + bkr.max_ray_distance, bkr.normal_space, bkr.normal_swizzle, bkr.custom_cage, @@ -1426,6 +1431,7 @@ static int bake_exec(bContext *C, wmOperator *op) false, bkr.is_cage, bkr.cage_extrusion, + bkr.max_ray_distance, bkr.normal_space, bkr.normal_swizzle, bkr.custom_cage, @@ -1495,6 +1501,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa true, bkr->is_cage, bkr->cage_extrusion, + bkr->max_ray_distance, bkr->normal_space, bkr->normal_swizzle, bkr->custom_cage, @@ -1527,6 +1534,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa false, bkr->is_cage, bkr->cage_extrusion, + bkr->max_ray_distance, bkr->normal_space, bkr->normal_swizzle, bkr->custom_cage, @@ -1586,6 +1594,11 @@ static void bake_set_props(wmOperator *op, Scene *scene) RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_TO_ACTIVE) != 0); } + prop = RNA_struct_find_property(op->ptr, "max_ray_distance"); + if (!RNA_property_is_set(op->ptr, prop)) { + RNA_property_float_set(op->ptr, prop, bake->max_ray_distance); + } + prop = RNA_struct_find_property(op->ptr, "cage_extrusion"); if (!RNA_property_is_set(op->ptr, prop)) { RNA_property_float_set(op->ptr, prop, bake->cage_extrusion); @@ -1766,12 +1779,23 @@ void OBJECT_OT_bake(wmOperatorType *ot) "Selected to Active", "Bake shading on the surface of selected objects to the active object"); RNA_def_float(ot->srna, + "max_ray_distance", + 0.0f, + 0.0f, + FLT_MAX, + "Max Ray Distance", + "The maximum ray distance for matching points between the active and selected " + "objects. If zero, there is no limit", + 0.0f, + 1.0f); + RNA_def_float(ot->srna, "cage_extrusion", 0.0f, 0.0f, FLT_MAX, "Cage Extrusion", - "Distance to use for the inward ray cast when using selected to active", + "Inflate the active object by the specified distance for baking. This helps " + "matching to points nearer to the outside of the selected object meshes", 0.0f, 1.0f); RNA_def_string(ot->srna, diff --git a/source/blender/editors/object/object_collection.c b/source/blender/editors/object/object_collection.c index 74ba94fbf4c..7a83d582299 100644 --- a/source/blender/editors/object/object_collection.c +++ b/source/blender/editors/object/object_collection.c @@ -483,17 +483,13 @@ static int collection_link_exec(bContext *C, wmOperator *op) /* Currently this should not be allowed (might be supported in the future though...). */ if (ID_IS_OVERRIDE_LIBRARY(&collection->id)) { - BKE_report(op->reports, - RPT_ERROR, - "Could not add the collection because it is overridden."); + BKE_report(op->reports, RPT_ERROR, "Could not add the collection because it is overridden."); return OPERATOR_CANCELLED; } /* Linked collections are already checked for by using RNA_collection_local_itemf * but operator can be called without invoke */ if (ID_IS_LINKED(&collection->id)) { - BKE_report(op->reports, - RPT_ERROR, - "Could not add the collection because it is linked."); + BKE_report(op->reports, RPT_ERROR, "Could not add the collection because it is linked."); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 690c63a2cbf..53a557c5871 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1466,6 +1466,13 @@ static const EnumPropertyItem *object_mode_set_itemsf(bContext *C, return item; } +static bool object_mode_set_poll(bContext *C) +{ + /* Needed as #ED_operator_object_active_editable doesn't call use 'active_object'. */ + Object *ob = CTX_data_active_object(C); + return ED_operator_object_active_editable_ex(C, ob); +} + static int object_mode_set_exec(bContext *C, wmOperator *op) { bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_with_submode"); @@ -1551,7 +1558,7 @@ void OBJECT_OT_mode_set(wmOperatorType *ot) /* api callbacks */ ot->exec = object_mode_set_exec; - ot->poll = ED_operator_object_active_editable; + ot->poll = object_mode_set_poll; /* flags */ ot->flag = 0; /* no register/undo here, leave it to operators being called */ diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 6cafc51231c..ca2dec75160 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -5251,9 +5251,6 @@ static bool particle_edit_toggle_poll(bContext *C) if (!ob->data || ID_IS_LINKED(ob->data)) { return 0; } - if (CTX_data_edit_object(C)) { - return 0; - } return (ob->particlesystem.first || BKE_modifiers_findby_type(ob, eModifierType_Cloth) || BKE_modifiers_findby_type(ob, eModifierType_Softbody)); diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index ceaac201da3..8524870c15e 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -52,6 +52,7 @@ #include "DEG_depsgraph.h" +#include "ED_object.h" #include "ED_screen.h" #include "PIL_time.h" @@ -154,7 +155,7 @@ static bool fluid_initjob( { FluidModifierData *mmd = NULL; FluidDomainSettings *mds; - Object *ob = CTX_data_active_object(C); + Object *ob = ED_object_active_context(C); mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); if (!mmd) { @@ -170,7 +171,7 @@ static bool fluid_initjob( job->bmain = CTX_data_main(C); job->scene = CTX_data_scene(C); job->depsgraph = CTX_data_depsgraph_pointer(C); - job->ob = CTX_data_active_object(C); + job->ob = ob; job->mmd = mmd; job->type = op->type->idname; job->name = op->type->name; @@ -616,7 +617,7 @@ static int fluid_free_exec(struct bContext *C, struct wmOperator *op) { FluidModifierData *mmd = NULL; FluidDomainSettings *mds; - Object *ob = CTX_data_active_object(C); + Object *ob = ED_object_active_context(C); Scene *scene = CTX_data_scene(C); /* @@ -679,7 +680,7 @@ static int fluid_pause_exec(struct bContext *C, struct wmOperator *op) { FluidModifierData *mmd = NULL; FluidDomainSettings *mds; - Object *ob = CTX_data_active_object(C); + Object *ob = ED_object_active_context(C); /* * Get modifier data diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 17049fdb28b..46827940b57 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -349,7 +349,6 @@ static int screen_render_exec(bContext *C, wmOperator *op) RE_SetReports(re, op->reports); - BLI_threaded_malloc_begin(); if (is_animation) { RE_RenderAnim(re, mainp, @@ -363,7 +362,6 @@ static int screen_render_exec(bContext *C, wmOperator *op) else { RE_RenderFrame(re, mainp, scene, single_layer, camera_override, scene->r.cfra, is_write_still); } - BLI_threaded_malloc_end(); RE_SetReports(re, NULL); @@ -391,16 +389,14 @@ static void make_renderinfo_string(const RenderStats *rs, char *str) { char info_time_str[32]; // used to be extern to header_info.c - uintptr_t mem_in_use, mmap_in_use, peak_memory; - float megs_used_memory, mmap_used_memory, megs_peak_memory; + uintptr_t mem_in_use, peak_memory; + float megs_used_memory, megs_peak_memory; char *spos = str; mem_in_use = MEM_get_memory_in_use(); - mmap_in_use = MEM_get_mapped_memory_in_use(); peak_memory = MEM_get_peak_memory(); - megs_used_memory = (mem_in_use - mmap_in_use) / (1024.0 * 1024.0); - mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0); + megs_used_memory = (mem_in_use) / (1024.0 * 1024.0); megs_peak_memory = (peak_memory) / (1024.0 * 1024.0); /* local view */ @@ -462,11 +458,7 @@ static void make_renderinfo_string(const RenderStats *rs, } if (rs->mem_peak == 0.0f) { - spos += sprintf(spos, - TIP_("| Mem:%.2fM (%.2fM, Peak %.2fM) "), - megs_used_memory, - mmap_used_memory, - megs_peak_memory); + spos += sprintf(spos, TIP_("| Mem:%.2fM (Peak %.2fM) "), megs_used_memory, megs_peak_memory); } else { spos += sprintf(spos, TIP_("| Mem:%.2fM, Peak: %.2fM "), rs->mem_used, rs->mem_peak); diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index f2e8209b099..2861e851282 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -494,7 +494,7 @@ static void screen_opengl_render_apply(const bContext *C, OGLRender *oglrender) scene, oglrender->sizex, oglrender->sizey, - 100.0f, + 100, false, &context); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 5b808206935..f2bfcb7a395 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -339,7 +339,7 @@ bool ED_operator_console_active(bContext *C) return ed_spacetype_test(C, SPACE_CONSOLE); } -static bool ed_object_hidden(Object *ob) +static bool ed_object_hidden(const Object *ob) { /* if hidden but in edit mode, we still display, can happen with animation */ return ((ob->restrictflag & OB_RESTRICT_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)); @@ -351,10 +351,15 @@ bool ED_operator_object_active(bContext *C) return ((ob != NULL) && !ed_object_hidden(ob)); } +bool ED_operator_object_active_editable_ex(bContext *UNUSED(C), const Object *ob) +{ + return ((ob != NULL) && !ID_IS_LINKED(ob) && !ed_object_hidden(ob)); +} + bool ED_operator_object_active_editable(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !ID_IS_LINKED(ob) && !ed_object_hidden(ob)); + return ED_operator_object_active_editable_ex(C, ob); } bool ED_operator_object_active_editable_mesh(bContext *C) @@ -4861,8 +4866,11 @@ static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot) /** \name Show User Preferences Operator * \{ */ -static int userpref_show_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static int userpref_show_exec(bContext *C, wmOperator *op) { + wmWindow *win_cur = CTX_wm_window(C); + /* Use eventstate, not event from _invoke, so this can be called through exec(). */ + const wmEvent *event = win_cur->eventstate; int sizex = (500 + UI_NAVIGATION_REGION_WIDTH) * UI_DPI_FAC; int sizey = 520 * UI_DPI_FAC; @@ -4899,7 +4907,7 @@ static void SCREEN_OT_userpref_show(struct wmOperatorType *ot) ot->idname = "SCREEN_OT_userpref_show"; /* api callbacks */ - ot->invoke = userpref_show_invoke; + ot->exec = userpref_show_exec; ot->poll = ED_operator_screenactive; } @@ -4909,8 +4917,11 @@ static void SCREEN_OT_userpref_show(struct wmOperatorType *ot) /** \name Show Drivers Editor Operator * \{ */ -static int drivers_editor_show_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static int drivers_editor_show_exec(bContext *C, wmOperator *op) { + wmWindow *win_cur = CTX_wm_window(C); + /* Use eventstate, not event from _invoke, so this can be called through exec(). */ + const wmEvent *event = win_cur->eventstate; PointerRNA ptr = {NULL}; PropertyRNA *prop = NULL; int index = -1; @@ -4974,7 +4985,7 @@ static void SCREEN_OT_drivers_editor_show(struct wmOperatorType *ot) ot->idname = "SCREEN_OT_drivers_editor_show"; /* api callbacks */ - ot->invoke = drivers_editor_show_invoke; + ot->exec = drivers_editor_show_exec; ot->poll = ED_operator_screenactive; } @@ -4984,8 +4995,11 @@ static void SCREEN_OT_drivers_editor_show(struct wmOperatorType *ot) /** \name Show Info Log Operator * \{ */ -static int info_log_show_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static int info_log_show_exec(bContext *C, wmOperator *op) { + wmWindow *win_cur = CTX_wm_window(C); + /* Use eventstate, not event from _invoke, so this can be called through exec(). */ + const wmEvent *event = win_cur->eventstate; int sizex = 900 * UI_DPI_FAC; int sizey = 580 * UI_DPI_FAC; int shift_y = 480; @@ -5015,7 +5029,7 @@ static void SCREEN_OT_info_log_show(struct wmOperatorType *ot) ot->idname = "SCREEN_OT_info_log_show"; /* api callbacks */ - ot->invoke = info_log_show_invoke; + ot->exec = info_log_show_exec; ot->poll = ED_operator_screenactive; } diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index e227db1c644..fd5018f76ff 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -1130,9 +1130,6 @@ static bool texture_paint_toggle_poll(bContext *C) if (!ob->data || ID_IS_LINKED(ob->data)) { return 0; } - if (CTX_data_edit_object(C)) { - return 0; - } return 1; } diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index d607b6a9d6f..634e29ca400 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -731,7 +731,14 @@ static bool brush_generic_tool_set(bContext *C, WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush); /* Tool System - * This is needed for when there is a non-sculpt tool active (transform for e.g.) */ + * This is needed for when there is a non-sculpt tool active (transform for e.g.). + * In case we are toggling (and the brush changed to the toggle_brush), we need to get the + * tool_name again. */ + int tool_result = brush_tool(brush, paint->runtime.tool_offset); + ePaintMode paint_mode = BKE_paintmode_get_active_from_context(C); + const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode); + RNA_enum_name_from_value(items, tool_result, &tool_name); + char tool_id[MAX_NAME]; SNPRINTF(tool_id, "builtin_brush.%s", tool_name); WM_toolsystem_ref_set_by_id(C, tool_id); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 045fd54b46a..855e7503e3b 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -7389,7 +7389,7 @@ static bool sculpt_no_multires_poll(bContext *C) return false; } -static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op)) +static int sculpt_symmetrize_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); const Sculpt *sd = CTX_data_tool_settings(C)->sculpt; @@ -7440,7 +7440,7 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op)) MirrorModifierData mmd = {{0}}; int axis = 0; mmd.flag = 0; - mmd.tolerance = 0.005f; + mmd.tolerance = RNA_float_get(op->ptr, "merge_tolerance"); switch (sd->symmetrize_direction) { case BMO_SYMMETRIZE_NEGATIVE_X: axis = 0; @@ -7497,6 +7497,16 @@ static void SCULPT_OT_symmetrize(wmOperatorType *ot) /* API callbacks. */ ot->exec = sculpt_symmetrize_exec; ot->poll = sculpt_no_multires_poll; + + RNA_def_float(ot->srna, + "merge_tolerance", + 0.001f, + 0.0f, + FLT_MAX, + "Merge Limit", + "Distance within which symmetrical vertices are merged", + 0.0f, + 1.0f); } /**** Toggle operator for turning sculpt mode on or off ****/ diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 912a6e1aaf6..4a449e529d5 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -847,6 +847,7 @@ static void sculpt_undo_free_list(ListBase *lb) sculpt_undo_geometry_free_data(&unode->geometry_original); sculpt_undo_geometry_free_data(&unode->geometry_modified); + sculpt_undo_geometry_free_data(&unode->geometry_bmesh_enter); if (unode->face_sets) { MEM_freeN(unode->face_sets); @@ -913,7 +914,7 @@ static void sculpt_undo_alloc_and_store_hidden(PBVH *pbvh, SculptUndoNode *unode BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, NULL, NULL, NULL); - unode->grid_hidden = MEM_mapallocN(sizeof(*unode->grid_hidden) * totgrid, "unode->grid_hidden"); + unode->grid_hidden = MEM_callocN(sizeof(*unode->grid_hidden) * totgrid, "unode->grid_hidden"); for (i = 0; i < totgrid; i++) { if (grid_hidden[grid_indices[i]]) { @@ -974,13 +975,11 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt maxgrid = 0; } - /* We will use this while sculpting, is mapalloc slow to access then? */ - /* General TODO, fix count_alloc. */ switch (type) { case SCULPT_UNDO_COORDS: - unode->co = MEM_mapallocN(sizeof(float[3]) * allvert, "SculptUndoNode.co"); - unode->no = MEM_mapallocN(sizeof(short[3]) * allvert, "SculptUndoNode.no"); + unode->co = MEM_callocN(sizeof(float[3]) * allvert, "SculptUndoNode.co"); + unode->no = MEM_callocN(sizeof(short[3]) * allvert, "SculptUndoNode.no"); usculpt->undo_size = (sizeof(float[3]) + sizeof(short[3]) + sizeof(int)) * allvert; break; @@ -994,7 +993,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt break; case SCULPT_UNDO_MASK: - unode->mask = MEM_mapallocN(sizeof(float) * allvert, "SculptUndoNode.mask"); + unode->mask = MEM_callocN(sizeof(float) * allvert, "SculptUndoNode.mask"); usculpt->undo_size += (sizeof(float) * sizeof(int)) * allvert; @@ -1013,12 +1012,12 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt unode->maxgrid = maxgrid; unode->totgrid = totgrid; unode->gridsize = gridsize; - unode->grids = MEM_mapallocN(sizeof(int) * totgrid, "SculptUndoNode.grids"); + unode->grids = MEM_callocN(sizeof(int) * totgrid, "SculptUndoNode.grids"); } else { /* Regular mesh. */ unode->maxvert = ss->totvert; - unode->index = MEM_mapallocN(sizeof(int) * allvert, "SculptUndoNode.index"); + unode->index = MEM_callocN(sizeof(int) * allvert, "SculptUndoNode.index"); } if (ss->deform_modifiers_active) { diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index a1094dde749..d6b259c9ac0 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -548,8 +548,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm if (do_island_optimization) { UvElement *element; UvNearestHit hit = UV_NEAREST_HIT_INIT; - Image *ima = CTX_data_edit_image(C); - uv_find_nearest_vert(scene, ima, obedit, co, 0.0f, &hit); + uv_find_nearest_vert(scene, obedit, co, 0.0f, &hit); element = BM_uv_element_get(data->elementMap, hit.efa, hit.l); island_index = element->island; diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c index 6c56e8dfb79..805e9608fec 100644 --- a/source/blender/editors/space_console/console_draw.c +++ b/source/blender/editors/space_console/console_draw.c @@ -91,7 +91,6 @@ void console_scrollback_prompt_end(SpaceConsole *sc, ConsoleLine *cl_dummy) static int console_textview_begin(TextViewContext *tvc) { SpaceConsole *sc = (SpaceConsole *)tvc->arg1; - tvc->lheight = sc->lheight * UI_DPI_FAC; tvc->sel_start = sc->sel_start; tvc->sel_end = sc->sel_end; @@ -143,10 +142,7 @@ static void console_cursor_wrap_offset( return; } -static void console_textview_draw_cursor(TextViewContext *tvc, - int cwidth, - int columns, - int descender) +static void console_textview_draw_cursor(TextViewContext *tvc, int cwidth, int columns) { int pen[2]; { @@ -157,10 +153,10 @@ static void console_textview_draw_cursor(TextViewContext *tvc, console_cursor_wrap_offset(sc->prompt, columns, &offl, &offc, NULL); console_cursor_wrap_offset(cl->line, columns, &offl, &offc, cl->line + cl->cursor); pen[0] = cwidth * offc; - pen[1] = -2 - (tvc->lheight + descender) * offl; + pen[1] = -tvc->lheight * offl; console_cursor_wrap_offset(cl->line + cl->cursor, columns, &offl, &offc, NULL); - pen[1] += (tvc->lheight + descender) * offl; + pen[1] += tvc->lheight * offl; pen[0] += tvc->draw_rect.xmin; pen[1] += tvc->draw_rect.ymin; @@ -172,8 +168,7 @@ static void console_textview_draw_cursor(TextViewContext *tvc, immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); immUniformThemeColor(TH_CONSOLE_CURSOR); - immRectf( - pos, pen[0] - U.pixelsize, pen[1], pen[0] + U.pixelsize, pen[1] + tvc->lheight + descender); + immRectf(pos, pen[0] - U.pixelsize, pen[1], pen[0] + U.pixelsize, pen[1] + tvc->lheight); immUnbindProgram(); } @@ -229,7 +224,7 @@ static int console_textview_main__internal(SpaceConsole *sc, /* view */ tvc.sel_start = sc->sel_start; tvc.sel_end = sc->sel_end; - tvc.lheight = sc->lheight * 1.2f * UI_DPI_FAC; + tvc.lheight = sc->lheight * UI_DPI_FAC; tvc.scroll_ymin = v2d->cur.ymin; tvc.scroll_ymax = v2d->cur.ymax; diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index 66157296064..dc258157afd 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -848,6 +848,10 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) CFRelease(volEnum); + /* kLSSharedFileListFavoriteItems is deprecated, but available till macOS 10.15. + * Will have to find a new method to sync the Finder Favorites with File Browser. */ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" /* Finally get user favorite places */ if (read_bookmarks) { UInt32 seed; @@ -891,6 +895,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) CFRelease(pathesArray); CFRelease(list); } +# pragma GCC diagnostic pop } # else /* unix */ diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 6c984860efc..185bf029f1a 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -295,7 +295,7 @@ static void graphedit_activekey_handles_cb(bContext *C, void *fcu_ptr, void *bez bezt->h2 = HD_ALIGN; } else { - BKE_nurb_bezt_handle_test(bezt, SELECT, true); + BKE_nurb_bezt_handle_test(bezt, SELECT, true, false); } /* now call standard updates */ @@ -423,8 +423,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) col = uiLayoutColumn(layout, true); /* keyframe itself */ { - - uiItemL_respect_property_split(col, IFACE_("Key Value"), ICON_NONE); + uiItemL_respect_property_split(col, IFACE_("Key Frame"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, @@ -435,16 +434,14 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) UI_UNIT_Y, &bezt_ptr, "co", - 1, + 0, 0, 0, -1, -1, NULL); - UI_but_func_set(but, graphedit_activekey_update_cb, fcu, bezt); - UI_but_unit_type_set(but, unit); - uiItemL_respect_property_split(col, IFACE_("Frame"), ICON_NONE); + uiItemL_respect_property_split(col, IFACE_("Value"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, @@ -455,21 +452,42 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) UI_UNIT_Y, &bezt_ptr, "co", - 0, + 1, 0, 0, -1, -1, NULL); UI_but_func_set(but, graphedit_activekey_update_cb, fcu, bezt); + UI_but_unit_type_set(but, unit); + + UI_but_func_set(but, graphedit_activekey_update_cb, fcu, bezt); } /* previous handle - only if previous was Bezier interpolation */ if ((prevbezt) && (prevbezt->ipo == BEZT_IPO_BEZ)) { col = uiLayoutColumn(layout, true); + uiItemL_respect_property_split(col, IFACE_("Left Handle Type"), ICON_NONE); + but = uiDefButR(block, + UI_BTYPE_MENU, + B_REDR, + NULL, + 0, + 0, + but_max_width, + UI_UNIT_Y, + &bezt_ptr, + "handle_left_type", + 0, + 0, + 0, + -1, + -1, + "Type of left handle"); + UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt); - uiItemL_respect_property_split(col, IFACE_("Left Handle X"), ICON_NONE); + uiItemL_respect_property_split(col, IFACE_("Frame"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, @@ -488,7 +506,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) NULL); UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt); - uiItemL_respect_property_split(col, IFACE_("Y"), ICON_NONE); + uiItemL_respect_property_split(col, IFACE_("Value"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, @@ -507,8 +525,14 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) NULL); UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt); UI_but_unit_type_set(but, unit); + } + + /* next handle - only if current is Bezier interpolation */ + if (bezt->ipo == BEZT_IPO_BEZ) { + /* NOTE: special update callbacks are needed on the coords here due to T39911 */ - uiItemL_respect_property_split(col, IFACE_("Type"), ICON_NONE); + col = uiLayoutColumn(layout, true); + uiItemL_respect_property_split(col, IFACE_("Right Handle Type"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_MENU, B_REDR, @@ -518,22 +542,16 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) but_max_width, UI_UNIT_Y, &bezt_ptr, - "handle_left_type", + "handle_right_type", 0, 0, 0, -1, -1, - "Type of left handle"); + "Type of right handle"); UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt); - } - /* next handle - only if current is Bezier interpolation */ - if (bezt->ipo == BEZT_IPO_BEZ) { - /* NOTE: special update callbacks are needed on the coords here due to T39911 */ - - col = uiLayoutColumn(layout, true); - uiItemL_respect_property_split(col, IFACE_("Right Handle X"), ICON_NONE); + uiItemL_respect_property_split(col, IFACE_("Frame"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, @@ -552,7 +570,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) NULL); UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt); - uiItemL_respect_property_split(col, IFACE_("Y"), ICON_NONE); + uiItemL_respect_property_split(col, IFACE_("Value"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, @@ -571,25 +589,6 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) NULL); UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt); UI_but_unit_type_set(but, unit); - - uiItemL_respect_property_split(col, IFACE_("Type"), ICON_NONE); - but = uiDefButR(block, - UI_BTYPE_MENU, - B_REDR, - NULL, - 0, - 0, - but_max_width, - UI_UNIT_Y, - &bezt_ptr, - "handle_right_type", - 0, - 0, - 0, - -1, - -1, - "Type of right handle"); - UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt); } } else { diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index eac87caf777..68fef5e921f 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -343,6 +343,10 @@ static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu) uint color = GPU_vertformat_attr_add( format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { + GPU_line_smooth(true); + } + GPU_blend(true); immBeginAtMost(GPU_PRIM_LINES, 4 * 2 * fcu->totvert); @@ -419,6 +423,10 @@ static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu) immEnd(); immUnbindProgram(); + GPU_blend(false); + if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) { + GPU_line_smooth(false); + } } /* Samples ---------------- */ @@ -1181,9 +1189,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, shor if (do_handles) { /* only draw handles/vertices on keyframes */ - GPU_blend(true); draw_fcurve_handles(sipo, fcu); - GPU_blend(false); } draw_fcurve_vertices(region, fcu, do_handles, (sipo->flag & SIPO_SELVHANDLESONLY)); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index eb97077f77a..8cb85ce9800 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -885,7 +885,6 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) Scene *scene; ViewLayer *view_layer; Object *obedit; - Image *ima; /* retrieve state */ sima = CTX_wm_space_image(C); @@ -894,15 +893,13 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) view_layer = CTX_data_view_layer(C); obedit = CTX_data_edit_object(C); - ima = ED_space_image(sima); - /* get bounds */ float min[2], max[2]; if (ED_space_image_show_uvedit(sima, obedit)) { uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( view_layer, ((View3D *)NULL), &objects_len); - bool success = ED_uvedit_minmax_multi(scene, ima, objects, objects_len, min, max); + bool success = ED_uvedit_minmax_multi(scene, objects, objects_len, min, max); MEM_freeN(objects); if (!success) { return OPERATOR_CANCELLED; diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c index eb1c46240cb..5668b88826e 100644 --- a/source/blender/editors/space_image/image_undo.c +++ b/source/blender/editors/space_image/image_undo.c @@ -225,9 +225,9 @@ void *ED_image_paint_tile_push(ListBase *paint_tiles, "PaintTile.mask"); } - ptile->rect.pt = MEM_mapallocN((ibuf->rect_float ? sizeof(float[4]) : sizeof(char[4])) * - square_i(ED_IMAGE_UNDO_TILE_SIZE), - "PaintTile.rect"); + ptile->rect.pt = MEM_callocN((ibuf->rect_float ? sizeof(float[4]) : sizeof(char[4])) * + square_i(ED_IMAGE_UNDO_TILE_SIZE), + "PaintTile.rect"); ptile->use_float = has_float; ptile->valid = true; diff --git a/source/blender/editors/space_info/info_draw.c b/source/blender/editors/space_info/info_draw.c index 2a3f6d6e365..3685e5de852 100644 --- a/source/blender/editors/space_info/info_draw.c +++ b/source/blender/editors/space_info/info_draw.c @@ -141,7 +141,6 @@ static int report_textview_begin(TextViewContext *tvc) { const ReportList *reports = tvc->arg2; - tvc->lheight = 14 * UI_DPI_FAC; tvc->sel_start = 0; tvc->sel_end = 0; diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index f8c0e66873f..dbd3b65857a 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -414,17 +414,11 @@ static const char *footer_string(ViewLayer *view_layer) size_t ofs = 0; uintptr_t mem_in_use = MEM_get_memory_in_use(); - uintptr_t mmap_in_use = MEM_get_mapped_memory_in_use(); /* get memory statistics */ - BLI_str_format_byte_unit(formatted_mem, mem_in_use - mmap_in_use, false); + BLI_str_format_byte_unit(formatted_mem, mem_in_use, false); ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, TIP_("Mem: %s"), formatted_mem); - if (mmap_in_use) { - BLI_str_format_byte_unit(formatted_mem, mmap_in_use, false); - BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, TIP_(" (%s)"), formatted_mem); - } - if (GPU_mem_stats_supported()) { int gpu_free_mem, gpu_tot_memory; diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index c842fa8b4ac..8076d3d7eaf 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -394,25 +394,26 @@ int textview_draw(TextViewContext *tvc, tvc->line_get(tvc, &ext_line, &ext_len); - if (!textview_draw_string(&tds, - ext_line, - ext_len, - (data_flag & TVC_LINE_FG) ? fg : NULL, - (data_flag & TVC_LINE_BG) ? bg : NULL, - (data_flag & TVC_LINE_ICON) ? icon : 0, - (data_flag & TVC_LINE_ICON_FG) ? icon_fg : NULL, - (data_flag & TVC_LINE_ICON_BG) ? icon_bg : NULL, - bg_sel)) { - /* When drawing, if we pass v2d->cur.ymax, then quit. */ - if (do_draw) { - /* Past the y limits. */ - break; - } - } + const bool is_out_of_view_y = !textview_draw_string( + &tds, + ext_line, + ext_len, + (data_flag & TVC_LINE_FG) ? fg : NULL, + (data_flag & TVC_LINE_BG) ? bg : NULL, + (data_flag & TVC_LINE_ICON) ? icon : 0, + (data_flag & TVC_LINE_ICON_FG) ? icon_fg : NULL, + (data_flag & TVC_LINE_ICON_BG) ? icon_bg : NULL, + bg_sel); if (do_draw) { + /* We always want the cursor to draw. */ if (tvc->draw_cursor && iter_index == 0) { - tvc->draw_cursor(tvc, tds.cwidth, tds.columns, tds.lofs); + tvc->draw_cursor(tvc, tds.cwidth, tds.columns); + } + + /* When drawing, if we pass v2d->cur.ymax, then quit. */ + if (is_out_of_view_y) { + break; } } @@ -428,6 +429,11 @@ int textview_draw(TextViewContext *tvc, tvc->end(tvc); + /* Sanity checks (bugs here can be tricky to track down). */ + BLI_assert(tds.lheight == tvc->lheight); + BLI_assert(tds.row_vpadding == tvc->row_vpadding); + BLI_assert(tds.do_draw == do_draw); + xy[1] += tvc->lheight * 2; return xy[1] - y_orig; diff --git a/source/blender/editors/space_info/textview.h b/source/blender/editors/space_info/textview.h index 8eef4ef5d56..41f8baf634e 100644 --- a/source/blender/editors/space_info/textview.h +++ b/source/blender/editors/space_info/textview.h @@ -60,7 +60,7 @@ typedef struct TextViewContext { int *r_icon, uchar r_icon_fg[4], uchar r_icon_bg[4]); - void (*draw_cursor)(struct TextViewContext *tvc, int cwidth, int columns, int descender); + void (*draw_cursor)(struct TextViewContext *tvc, int cwidth, int columns); /* constant theme colors */ void (*const_colors)(struct TextViewContext *tvc, unsigned char bg_sel[4]); const void *iter; diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index 740d090e641..e879e01ecc4 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -209,6 +209,7 @@ static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, const wmEvent *e ED_region_tag_redraw(region); WM_main_add_notifier(NC_NODE | ND_DISPLAY, NULL); + WM_main_add_notifier(NC_SPACE | ND_SPACE_NODE_VIEW, NULL); break; @@ -354,6 +355,7 @@ static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op)) ED_region_tag_redraw(region); WM_main_add_notifier(NC_NODE | ND_DISPLAY, NULL); + WM_main_add_notifier(NC_SPACE | ND_SPACE_NODE_VIEW, NULL); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 13cbda5aad7..7d3b95721c6 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -178,20 +178,13 @@ static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *UNUSED(poin2) WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, poin); } -static void restrictbutton_bone_visibility_cb(bContext *C, void *poin, void *poin2) +static void restrictbutton_bone_visibility_cb(bContext *C, void *poin, void *UNUSED(poin2)) { - bArmature *arm = (bArmature *)poin; - Bone *bone = (Bone *)poin2; - if (bone->flag & BONE_HIDDEN_P) { - bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - } + Bone *bone = (Bone *)poin; if (CTX_wm_window(C)->eventstate->ctrl) { restrictbutton_recursive_bone(bone, BONE_HIDDEN_P, (bone->flag & BONE_HIDDEN_P) != 0); } - - WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); - DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE); } static void restrictbutton_bone_select_cb(bContext *C, void *UNUSED(poin), void *poin2) @@ -859,6 +852,7 @@ typedef struct RestrictProperties { *layer_collection_hide_viewport; PropertyRNA *modifier_show_viewport, *modifier_show_render; PropertyRNA *constraint_enable; + PropertyRNA *bone_hide_viewport; } RestrictProperties; /* We don't care about the value of the property @@ -877,6 +871,7 @@ typedef struct RestrictPropertiesActive { bool modifier_show_viewport; bool modifier_show_render; bool constraint_enable; + bool bone_hide_viewport; } RestrictPropertiesActive; static void outliner_restrict_properties_enable_collection_set( @@ -1011,6 +1006,8 @@ static void outliner_draw_restrictbuts(uiBlock *block, props.constraint_enable = RNA_struct_type_find_property(&RNA_Constraint, "mute"); + props.bone_hide_viewport = RNA_struct_type_find_property(&RNA_Bone, "hide"); + props.initialized = true; } @@ -1279,27 +1276,32 @@ static void outliner_draw_restrictbuts(uiBlock *block, } } else if (tselem->type == TSE_POSE_CHANNEL) { + PointerRNA ptr; bPoseChannel *pchan = (bPoseChannel *)te->directdata; Bone *bone = pchan->bone; Object *ob = (Object *)tselem->id; + bArmature *arm = ob->data; + + RNA_pointer_create(&arm->id, &RNA_Bone, bone, &ptr); if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) { - bt = uiDefIconButBitI(block, - UI_BTYPE_ICON_TOGGLE, - BONE_HIDDEN_P, - 0, - ICON_RESTRICT_VIEW_OFF, - (int)(region->v2d.cur.xmax - restrict_offsets.viewport), - te->ys, - UI_UNIT_X, - UI_UNIT_Y, - &(bone->flag), - 0, - 0, - 0, - 0, - TIP_("Restrict visibility in the 3D View")); - UI_but_func_set(bt, restrictbutton_bone_visibility_cb, ob->data, bone); + bt = uiDefIconButR_prop(block, + UI_BTYPE_ICON_TOGGLE, + 0, + 0, + (int)(region->v2d.cur.xmax - restrict_offsets.viewport), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + &ptr, + props.bone_hide_viewport, + -1, + 0, + 0, + -1, + -1, + TIP_("Restrict visibility in the 3D View")); + UI_but_func_set(bt, restrictbutton_bone_visibility_cb, bone, NULL); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE); } diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 97ce9ad549f..3db75d9288b 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -460,6 +460,9 @@ void OUTLINER_OT_item_rename(wmOperatorType *ot) ot->invoke = outliner_item_rename; ot->poll = ED_operator_outliner_active; + + /* Flags. */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /** \} */ @@ -578,6 +581,9 @@ void OUTLINER_OT_id_delete(wmOperatorType *ot) ot->invoke = outliner_id_delete_invoke; ot->poll = ED_operator_outliner_active; + + /* Flags. */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /** \} */ @@ -715,7 +721,8 @@ void OUTLINER_OT_id_remap(wmOperatorType *ot) ot->exec = outliner_id_remap_exec; ot->poll = ED_operator_outliner_active; - ot->flag = 0; + /* Flags. */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; prop = RNA_def_enum(ot->srna, "id_type", rna_enum_id_type_items, ID_OB, "ID Type", ""); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID); @@ -823,6 +830,7 @@ void OUTLINER_OT_id_copy(wmOperatorType *ot) ot->exec = outliner_id_copy_exec; ot->poll = ED_operator_outliner_active; + /* Flags, don't need any undo here (this operator does not change anything in Blender data). */ ot->flag = 0; } @@ -863,7 +871,8 @@ void OUTLINER_OT_id_paste(wmOperatorType *ot) ot->exec = outliner_id_paste_exec; ot->poll = ED_operator_outliner_active; - ot->flag = 0; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /** \} */ @@ -974,6 +983,9 @@ void OUTLINER_OT_lib_relocate(wmOperatorType *ot) ot->invoke = outliner_lib_relocate_invoke; ot->poll = ED_operator_outliner_active; + + /* Flags. */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* XXX This does not work with several items @@ -1028,6 +1040,9 @@ void OUTLINER_OT_lib_reload(wmOperatorType *ot) ot->invoke = outliner_lib_reload_invoke; ot->poll = ED_operator_outliner_active; + + /* Flags. */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } void lib_reload_cb(bContext *C, diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 0ccf982fd29..53f2c6a90d4 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -1450,7 +1450,8 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) } else if (event == OL_OP_REMAP) { outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL); - str = "Remap ID"; + /* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth trick + * does not work here). */ } else if (event == OL_OP_LOCALIZED) { /* disabled, see above enum (ton) */ outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb); @@ -1481,7 +1482,9 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) ED_outliner_select_sync_from_object_tag(C); } - ED_undo_push(C, str); + if (str != NULL) { + ED_undo_push(C, str); + } return OPERATOR_FINISHED; } @@ -1681,6 +1684,7 @@ static const EnumPropertyItem *outliner_id_operation_itemf(bContext *C, static int outliner_id_operation_exec(bContext *C, wmOperator *op) { + wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = CTX_data_scene(C); SpaceOutliner *soops = CTX_wm_space_outliner(C); int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0; @@ -1801,16 +1805,22 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op) if (idlevel > 0) { outliner_do_libdata_operation( C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL); - ED_undo_push(C, "Remap"); + /* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth + * trick does not work here). */ } break; } case OUTLINER_IDOP_COPY: { + wm->op_undo_depth++; WM_operator_name_call(C, "OUTLINER_OT_id_copy", WM_OP_INVOKE_DEFAULT, NULL); + wm->op_undo_depth--; + /* No need for undo, this operation does not change anything... */ break; } case OUTLINER_IDOP_PASTE: { + wm->op_undo_depth++; WM_operator_name_call(C, "OUTLINER_OT_id_paste", WM_OP_INVOKE_DEFAULT, NULL); + wm->op_undo_depth--; ED_outliner_select_sync_from_all_tag(C); ED_undo_push(C, "Paste"); break; @@ -1929,7 +1939,6 @@ static int outliner_lib_operation_exec(bContext *C, wmOperator *op) switch (event) { case OL_LIB_RENAME: { - /* rename */ outliner_do_libdata_operation( C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL); @@ -1944,16 +1953,17 @@ static int outliner_lib_operation_exec(bContext *C, wmOperator *op) break; } case OL_LIB_RELOCATE: { - /* rename */ outliner_do_libdata_operation( C, op->reports, scene, soops, &soops->tree, lib_relocate_cb, NULL); - ED_undo_push(C, "Relocate Library"); + /* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth + * trick does not work here). */ break; } case OL_LIB_RELOAD: { - /* rename */ outliner_do_libdata_operation( C, op->reports, scene, soops, &soops->tree, lib_reload_cb, NULL); + /* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth + * trick does not work here). */ break; } default: @@ -2102,7 +2112,7 @@ void OUTLINER_OT_action_set(wmOperatorType *ot) ot->poll = ED_operator_outliner_active; /* flags */ - ot->flag = 0; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* props */ // TODO: this would be nicer as an ID-pointer... @@ -2150,6 +2160,7 @@ static const EnumPropertyItem prop_animdata_op_types[] = { static int outliner_animdata_operation_exec(bContext *C, wmOperator *op) { + wmWindowManager *wm = CTX_wm_manager(C); SpaceOutliner *soops = CTX_wm_space_outliner(C); int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0; eOutliner_AnimDataOps event; @@ -2178,7 +2189,10 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op) case OUTLINER_ANIMOP_SET_ACT: /* delegate once again... */ + wm->op_undo_depth++; WM_operator_name_call(C, "OUTLINER_OT_action_set", WM_OP_INVOKE_REGION_WIN, NULL); + wm->op_undo_depth--; + ED_undo_push(C, "Set active action"); break; case OUTLINER_ANIMOP_CLEAR_ACT: diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 7965422c117..f81b4bb09e2 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -1005,7 +1005,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } } BKE_nurb_test_2d(nu); - BKE_nurb_handles_test(nu, true); /* test for bezier too */ + BKE_nurb_handles_test(nu, true, false); /* test for bezier too */ nu = nu->next; } @@ -1577,9 +1577,7 @@ static void view3d_panel_transform(const bContext *C, Panel *panel) } else { View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const float lim = 10000.0f * max_ff(1.0f, ED_view3d_grid_scale(scene, v3d, NULL)); - v3d_editvertex_buts(col, v3d, ob, lim); + v3d_editvertex_buts(col, v3d, ob, FLT_MAX); } } else if (ob->mode & OB_MODE_POSE) { diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index 08e68c9174e..2ad7797f6c8 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -126,7 +126,7 @@ void meshobject_foreachScreenVert( Scene *scene_eval = DEG_get_evaluated_scene(vc->depsgraph); Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact); - me = mesh_get_eval_deform(vc->depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); + me = mesh_get_eval_final(vc->depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); ED_view3d_check_mats_rv3d(vc->rv3d); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 8e3ad55bae1..5fc65522fe6 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -825,17 +825,17 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, bool is } } else if (!edit_2d) { - if (t->orientation.index == 0 || ELEM(cmode, '\0', axis)) { + if (t->orient_curr == 0 || ELEM(cmode, '\0', axis)) { /* Successive presses on existing axis, cycle orientation modes. */ - t->orientation.index = (t->orientation.index + 1) % ARRAY_SIZE(t->orientation.types); - initTransformOrientation(t->context, t, t->orientation.types[t->orientation.index]); + t->orient_curr = (short)((t->orient_curr + 1) % (int)ARRAY_SIZE(t->orient)); + transform_orientations_current_set(t, t->orient_curr); } - if (t->orientation.index == 0) { + if (t->orient_curr == 0) { stopConstraint(t); } else { - const short orientation = t->orientation.types[t->orientation.index]; + const short orientation = t->orient[t->orient_curr].type; if (is_plane == false) { setUserConstraint(t, orientation, constraint_axis, msg2); } @@ -896,74 +896,59 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; case TFM_MODAL_TRANSLATE: /* only switch when... */ - if (ELEM(t->mode, - TFM_ROTATION, - TFM_RESIZE, - TFM_TRACKBALL, - TFM_EDGE_SLIDE, - TFM_VERT_SLIDE)) { - restoreTransObjects(t); - resetTransModal(t); - resetTransRestrictions(t); - transform_mode_init(t, NULL, TFM_TRANSLATION); - initSnapping(t, NULL); // need to reinit after mode change - t->redraw |= TREDRAW_HARD; - handled = true; - } - else if (t->mode == TFM_SEQ_SLIDE) { - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - handled = true; - } - else { - if (t->obedit_type == OB_MESH) { - if ((t->mode == TFM_TRANSLATION) && (t->spacetype == SPACE_VIEW3D)) { - restoreTransObjects(t); + if (t->mode == TFM_TRANSLATION) { + if ((t->obedit_type == OB_MESH) && (t->spacetype == SPACE_VIEW3D)) { + restoreTransObjects(t); + resetTransModal(t); + resetTransRestrictions(t); + + /* first try edge slide */ + transform_mode_init(t, NULL, TFM_EDGE_SLIDE); + /* if that fails, do vertex slide */ + if (t->state == TRANS_CANCEL) { resetTransModal(t); + t->state = TRANS_STARTING; + transform_mode_init(t, NULL, TFM_VERT_SLIDE); + } + /* vert slide can fail on unconnected vertices (rare but possible) */ + if (t->state == TRANS_CANCEL) { + resetTransModal(t); + t->state = TRANS_STARTING; + restoreTransObjects(t); resetTransRestrictions(t); - - /* first try edge slide */ - transform_mode_init(t, NULL, TFM_EDGE_SLIDE); - /* if that fails, do vertex slide */ - if (t->state == TRANS_CANCEL) { - resetTransModal(t); - t->state = TRANS_STARTING; - transform_mode_init(t, NULL, TFM_VERT_SLIDE); - } - /* vert slide can fail on unconnected vertices (rare but possible) */ - if (t->state == TRANS_CANCEL) { - resetTransModal(t); - t->state = TRANS_STARTING; - restoreTransObjects(t); - resetTransRestrictions(t); - transform_mode_init(t, NULL, TFM_TRANSLATION); - } - initSnapping(t, NULL); // need to reinit after mode change - t->redraw |= TREDRAW_HARD; - handled = true; + transform_mode_init(t, NULL, TFM_TRANSLATION); } + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + handled = true; } else if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { - if (t->mode == TFM_TRANSLATION) { - restoreTransObjects(t); + restoreTransObjects(t); - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - handled = true; - } + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + handled = true; } } + else if (t->mode == TFM_SEQ_SLIDE) { + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + handled = true; + } + else if (transform_mode_is_changeable(t->mode)) { + restoreTransObjects(t); + resetTransModal(t); + resetTransRestrictions(t); + transform_mode_init(t, NULL, TFM_TRANSLATION); + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + handled = true; + } break; case TFM_MODAL_ROTATE: /* only switch when... */ if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) { - if (ELEM(t->mode, - TFM_ROTATION, - TFM_RESIZE, - TFM_TRACKBALL, - TFM_TRANSLATION, - TFM_EDGE_SLIDE, - TFM_VERT_SLIDE)) { + if (transform_mode_is_changeable(t->mode)) { restoreTransObjects(t); resetTransModal(t); resetTransRestrictions(t); @@ -982,15 +967,23 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; case TFM_MODAL_RESIZE: /* only switch when... */ - if (ELEM(t->mode, - TFM_ROTATION, - TFM_TRANSLATION, - TFM_TRACKBALL, - TFM_EDGE_SLIDE, - TFM_VERT_SLIDE)) { + if (t->mode == TFM_RESIZE) { + if (t->options & CTX_MOVIECLIP) { + restoreTransObjects(t); + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + handled = true; + } + } + else if (t->mode == TFM_SHRINKFATTEN) { + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + handled = true; + } + else if (transform_mode_is_changeable(t->mode)) { /* Scale isn't normally very useful after extrude along normals, see T39756 */ - if ((t->con.mode & CON_APPLY) && (t->con.orientation == V3D_ORIENT_NORMAL)) { + if ((t->con.mode & CON_APPLY) && (t->orient[t->orient_curr].type == V3D_ORIENT_NORMAL)) { stopConstraint(t); } @@ -1002,20 +995,6 @@ int transformEvent(TransInfo *t, const wmEvent *event) t->redraw |= TREDRAW_HARD; handled = true; } - else if (t->mode == TFM_SHRINKFATTEN) { - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - handled = true; - } - else if (t->mode == TFM_RESIZE) { - if (t->options & CTX_MOVIECLIP) { - restoreTransObjects(t); - - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - handled = true; - } - } break; case TFM_MODAL_SNAP_INV_ON: @@ -1229,7 +1208,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; } /* only switch when... */ - if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) { + if (t->mode != TFM_TRANSLATION && transform_mode_is_changeable(t->mode)) { restoreTransObjects(t); resetTransModal(t); resetTransRestrictions(t); @@ -1244,7 +1223,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; } /* only switch when... */ - if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL)) { + if (t->mode != TFM_RESIZE && transform_mode_is_changeable(t->mode)) { restoreTransObjects(t); resetTransModal(t); resetTransRestrictions(t); @@ -1260,7 +1239,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) } /* only switch when... */ if (!(t->options & CTX_TEXTURE)) { - if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION)) { + if (transform_mode_is_changeable(t->mode)) { restoreTransObjects(t); resetTransModal(t); resetTransRestrictions(t); @@ -1615,6 +1594,17 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) int proportional = 0; PropertyRNA *prop; + if (!(t->con.mode & CON_APPLY) && (t->flag & T_MODAL) && + ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE)) { + /* When redoing these modes the first time, it's more convenient to save + * the Global orientation. */ + mul_m3_v3(t->spacemtx, t->values_final); + unit_m3(t->spacemtx); + + BLI_assert(t->orient_curr == 0); + t->orient[0].type = V3D_ORIENT_GLOBAL; + } + // Save back mode in case we're in the generic operator if ((prop = RNA_struct_find_property(op->ptr, "mode"))) { RNA_property_enum_set(op->ptr, prop, t->mode); @@ -1723,19 +1713,20 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } if ((prop = RNA_struct_find_property(op->ptr, "orient_type"))) { - short orient_set, orient_cur; - orient_set = RNA_property_is_set(op->ptr, prop) ? RNA_property_enum_get(op->ptr, prop) : -1; - orient_cur = t->orientation.types[t->orientation.index]; + short orient_type_set, orient_type_curr; + orient_type_set = RNA_property_is_set(op->ptr, prop) ? RNA_property_enum_get(op->ptr, prop) : + -1; + orient_type_curr = t->orient[t->orient_curr].type; - if (!ELEM(orient_cur, orient_set, V3D_ORIENT_CUSTOM_MATRIX)) { - RNA_property_enum_set(op->ptr, prop, orient_cur); - orient_set = orient_cur; + if (!ELEM(orient_type_curr, orient_type_set, V3D_ORIENT_CUSTOM_MATRIX)) { + RNA_property_enum_set(op->ptr, prop, orient_type_curr); + orient_type_set = orient_type_curr; } if (((prop = RNA_struct_find_property(op->ptr, "orient_matrix_type")) && !RNA_property_is_set(op->ptr, prop))) { /* Set the first time to register on redo. */ - RNA_property_enum_set(op->ptr, prop, orient_set); + RNA_property_enum_set(op->ptr, prop, orient_type_set); RNA_float_set_array(op->ptr, "orient_matrix", &t->spacemtx[0][0]); } } @@ -1883,11 +1874,8 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve initTransInfo(C, t, op, event); /* Use the custom orientation when it is set. */ - short orientation = t->orientation.types[0] == V3D_ORIENT_CUSTOM_MATRIX ? - V3D_ORIENT_CUSTOM_MATRIX : - t->orientation.types[t->orientation.index]; - - initTransformOrientation(C, t, orientation); + short orient_index = t->orient[0].type == V3D_ORIENT_CUSTOM_MATRIX ? 0 : t->orient_curr; + transform_orientations_current_set(t, orient_index); if (t->spacetype == SPACE_VIEW3D) { t->draw_handle_apply = ED_region_draw_cb_activate( @@ -2043,7 +2031,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve /* Constraint init from operator */ if (t->con.mode & CON_APPLY) { - setUserConstraint(t, t->orientation.types[t->orientation.index], t->con.mode, "%s"); + setUserConstraint(t, t->orient[t->orient_curr].type, t->con.mode, "%s"); } /* Don't write into the values when non-modal because they are already set from operator redo diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 503e7bd4691..7720660e2e8 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -113,13 +113,8 @@ typedef struct TransSnap { } TransSnap; typedef struct TransCon { - short orientation; /** Description of the constraint for header_print. */ char text[50]; - /** Matrix of the constraint space. */ - float mtx[3][3]; - /** Inverse matrix of the constraint space. */ - float imtx[3][3]; /** Projection constraint matrix (same as #imtx with some axis == 0). */ float pmtx[3][3]; /** Initial mouse value for visual calculation @@ -139,8 +134,7 @@ typedef struct TransCon { struct TransDataContainer *tc, struct TransData *td, const float in[3], - float out[3], - float pvec[3]); + float out[3]); /** Apply function pointer for size transformation. */ void (*applySize)(struct TransInfo *t, struct TransDataContainer *tc, @@ -520,6 +514,7 @@ typedef struct TransInfo { /** orientation matrix of the current space. */ float spacemtx[3][3]; + float spacemtx_inv[3][3]; /** name of the current space, MAX_NAME. */ char spacename[64]; @@ -531,13 +526,11 @@ typedef struct TransInfo { bool is_launch_event_tweak; struct { - short index; - short types[3]; - /* this gets used when orientation.type[x] is V3D_ORIENT_CUSTOM */ - struct TransformOrientation *custom; - /* this gets used when orientation.type[0] is V3D_ORIENT_CUSTOM_MATRIX */ - float custom_matrix[3][3]; - } orientation; + short type; + float matrix[3][3]; + } orient[3]; + short orient_curr; + /** backup from view3d, to restore on end. */ short gizmo_flag; @@ -911,8 +904,13 @@ void getViewVector(const TransInfo *t, const float coord[3], float vec[3]); void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot); /*********************** Transform Orientations ******************************/ - -void initTransformOrientation(struct bContext *C, TransInfo *t, short orientation); +short transform_orientation_matrix_get(struct bContext *C, + TransInfo *t, + const short orientation, + const float custom[3][3], + float r_spacemtx[3][3]); +const char *transform_orientations_spacename_get(TransInfo *t, const short orient_type); +void transform_orientations_current_set(struct TransInfo *t, const short orient_index); /* Those two fill in mat and return non-zero on success */ bool createSpaceNormal(float mat[3][3], const float normal[3]); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index b07eb6edf5a..0a6e0d6b7f5 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -42,6 +42,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_scene.h" #include "ED_view3d.h" @@ -57,6 +58,27 @@ static void drawObjectConstraint(TransInfo *t); +static void projection_matrix_calc(const TransInfo *t, float r_pmtx[3][3]) +{ + unit_m3(r_pmtx); + + if (!(t->con.mode & CON_AXIS0)) { + zero_v3(r_pmtx[0]); + } + + if (!(t->con.mode & CON_AXIS1)) { + zero_v3(r_pmtx[1]); + } + + if (!(t->con.mode & CON_AXIS2)) { + zero_v3(r_pmtx[2]); + } + + float mat[3][3]; + mul_m3_m3m3(mat, r_pmtx, t->spacemtx_inv); + mul_m3_m3m3(r_pmtx, t->spacemtx, mat); +} + /* ************************** CONSTRAINTS ************************* */ static void constraintValuesFinal(TransInfo *t, float vec[3]) { @@ -121,11 +143,9 @@ void constraintNumInput(TransInfo *t, float vec[3]) } } -static void postConstraintChecks(TransInfo *t, float vec[3], float pvec[3]) +static void postConstraintChecks(TransInfo *t, float vec[3]) { - int i = 0; - - mul_m3_v3(t->con.imtx, vec); + mul_m3_v3(t->spacemtx_inv, vec); snapGridIncrement(t, vec); @@ -155,17 +175,7 @@ static void postConstraintChecks(TransInfo *t, float vec[3], float pvec[3]) /* inverse transformation at the end */ } - if (t->con.mode & CON_AXIS0) { - pvec[i++] = vec[0]; - } - if (t->con.mode & CON_AXIS1) { - pvec[i++] = vec[1]; - } - if (t->con.mode & CON_AXIS2) { - pvec[i++] = vec[2]; - } - - mul_m3_v3(t->con.mtx, vec); + mul_m3_v3(t->spacemtx, vec); } static void viewAxisCorrectCenter(const TransInfo *t, float t_con_center[3]) @@ -298,7 +308,7 @@ static bool isPlaneProjectionViewAligned(const TransInfo *t) int n = 0; for (int i = 0; i < 3; i++) { if (t->con.mode & (CON_AXIS0 << i)) { - constraint_vector[n++] = t->con.mtx[i]; + constraint_vector[n++] = t->spacemtx[i]; if (n == 2) { break; } @@ -346,12 +356,8 @@ static void planeProjection(const TransInfo *t, const float in[3], float out[3]) * (in perspective mode, the view vector is relative to the position on screen) */ -static void applyAxisConstraintVec(TransInfo *t, - TransDataContainer *UNUSED(tc), - TransData *td, - const float in[3], - float out[3], - float pvec[3]) +static void applyAxisConstraintVec( + TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, const float in[3], float out[3]) { copy_v3_v3(out, in); if (!td && t->con.mode & CON_APPLY) { @@ -371,25 +377,25 @@ static void applyAxisConstraintVec(TransInfo *t, float c[3]; if (t->con.mode & CON_AXIS0) { - copy_v3_v3(c, t->con.mtx[0]); + copy_v3_v3(c, t->spacemtx[0]); } else if (t->con.mode & CON_AXIS1) { - copy_v3_v3(c, t->con.mtx[1]); + copy_v3_v3(c, t->spacemtx[1]); } else if (t->con.mode & CON_AXIS2) { - copy_v3_v3(c, t->con.mtx[2]); + copy_v3_v3(c, t->spacemtx[2]); } axisProjection(t, c, in, out); } } - postConstraintChecks(t, out, pvec); + postConstraintChecks(t, out); } } /* * Generic callback for object based spatial constraints applied to linear motion * - * At first, the following is applied to the first data in the array + * At first, the following is applied without orientation * The IN vector in projected into the constrained space and then further * projected along the view vector. * (in perspective mode, the view vector is relative to the position on screen) @@ -397,61 +403,19 @@ static void applyAxisConstraintVec(TransInfo *t, * Further down, that vector is mapped to each data's space. */ -static void applyObjectConstraintVec(TransInfo *t, - TransDataContainer *tc, - TransData *td, - const float in[3], - float out[3], - float pvec[3]) +static void applyObjectConstraintVec( + TransInfo *t, TransDataContainer *tc, TransData *td, const float in[3], float out[3]) { - copy_v3_v3(out, in); - if (t->con.mode & CON_APPLY) { - if (!td) { - mul_m3_v3(t->con.pmtx, out); - - const int dims = getConstraintSpaceDimension(t); - if (dims == 2) { - if (!is_zero_v3(out)) { - if (!isPlaneProjectionViewAligned(t)) { - planeProjection(t, in, out); - } - } - } - else if (dims == 1) { - float c[3]; - - if (t->con.mode & CON_AXIS0) { - copy_v3_v3(c, t->con.mtx[0]); - } - else if (t->con.mode & CON_AXIS1) { - copy_v3_v3(c, t->con.mtx[1]); - } - else if (t->con.mode & CON_AXIS2) { - copy_v3_v3(c, t->con.mtx[2]); - } - axisProjection(t, c, in, out); - } - postConstraintChecks(t, out, pvec); - copy_v3_v3(out, pvec); - } - else { - int i = 0; - - out[0] = out[1] = out[2] = 0.0f; - if (t->con.mode & CON_AXIS0) { - out[0] = in[i++]; - } - if (t->con.mode & CON_AXIS1) { - out[1] = in[i++]; - } - if (t->con.mode & CON_AXIS2) { - out[2] = in[i++]; - } - - mul_m3_v3(td->axismtx, out); - if (t->flag & T_EDIT) { - mul_m3_v3(tc->mat3_unit, out); - } + if (!td) { + applyAxisConstraintVec(t, tc, td, in, out); + } + else { + /* Specific TransData's space. */ + copy_v3_v3(out, in); + mul_m3_v3(t->spacemtx_inv, out); + mul_m3_v3(td->axismtx, out); + if (t->flag & T_EDIT) { + mul_m3_v3(tc->mat3_unit, out); } } } @@ -478,8 +442,8 @@ static void applyAxisConstraintSize(TransInfo *t, smat[2][2] = 1.0f; } - mul_m3_m3m3(tmat, smat, t->con.imtx); - mul_m3_m3m3(smat, t->con.mtx, tmat); + mul_m3_m3m3(tmat, smat, t->spacemtx_inv); + mul_m3_m3m3(smat, t->spacemtx, tmat); } } @@ -539,15 +503,15 @@ static void applyAxisConstraintRot( switch (mode) { case CON_AXIS0: case (CON_AXIS1 | CON_AXIS2): - copy_v3_v3(vec, t->con.mtx[0]); + copy_v3_v3(vec, t->spacemtx[0]); break; case CON_AXIS1: case (CON_AXIS0 | CON_AXIS2): - copy_v3_v3(vec, t->con.mtx[1]); + copy_v3_v3(vec, t->spacemtx[1]); break; case CON_AXIS2: case (CON_AXIS0 | CON_AXIS1): - copy_v3_v3(vec, t->con.mtx[2]); + copy_v3_v3(vec, t->spacemtx[2]); break; } /* don't flip axis if asked to or if num input */ @@ -620,12 +584,11 @@ static void applyObjectConstraintRot( /*--------------------- INTERNAL SETUP CALLS ------------------*/ -void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[]) +void setConstraint(TransInfo *t, int mode, const char text[]) { BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1); - copy_m3_m3(t->con.mtx, space); t->con.mode = mode; - getConstraintMatrix(t); + projection_matrix_calc(t, t->con.pmtx); startConstraint(t); @@ -639,41 +602,25 @@ void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[]) /* applies individual td->axismtx constraints */ void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[]) { - TransDataContainer *tc = t->data_container; - if (t->data_len_all == 1) { - float axismtx[3][3]; - if (t->flag & T_EDIT) { - mul_m3_m3m3(axismtx, tc->mat3_unit, tc->data->axismtx); - } - else { - copy_m3_m3(axismtx, tc->data->axismtx); - } - - setConstraint(t, axismtx, mode, text); - } - else { - BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1); - copy_m3_m3(t->con.mtx, tc->data->axismtx); - t->con.mode = mode; - getConstraintMatrix(t); + BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1); + t->con.mode = mode; + projection_matrix_calc(t, t->con.pmtx); - startConstraint(t); + startConstraint(t); - t->con.drawExtra = drawObjectConstraint; - t->con.applyVec = applyObjectConstraintVec; - t->con.applySize = applyObjectConstraintSize; - t->con.applyRot = applyObjectConstraintRot; - t->redraw = TREDRAW_HARD; - } + t->con.drawExtra = drawObjectConstraint; + t->con.applyVec = applyObjectConstraintVec; + t->con.applySize = applyObjectConstraintSize; + t->con.applyRot = applyObjectConstraintRot; + t->redraw = TREDRAW_HARD; } void setLocalConstraint(TransInfo *t, int mode, const char text[]) { - /* edit-mode now allows local transforms too */ if (t->flag & T_EDIT) { - /* Use the active (first) edit object. */ - TransDataContainer *tc = t->data_container; - setConstraint(t, tc->mat3_unit, mode, text); + /* Although in edit-mode each object has its local space, use the + * orientation of the active object. */ + setConstraint(t, mode, text); } else { setAxisMatrixConstraint(t, mode, text); @@ -689,64 +636,30 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[]) void setUserConstraint(TransInfo *t, short orientation, int mode, const char ftext[]) { char text[256]; + const char *spacename = transform_orientations_spacename_get(t, orientation); + BLI_snprintf(text, sizeof(text), ftext, spacename); switch (orientation) { - case V3D_ORIENT_GLOBAL: { - float mtx[3][3]; - BLI_snprintf(text, sizeof(text), ftext, TIP_("global")); - unit_m3(mtx); - setConstraint(t, mtx, mode, text); - break; - } case V3D_ORIENT_LOCAL: - BLI_snprintf(text, sizeof(text), ftext, TIP_("local")); setLocalConstraint(t, mode, text); break; case V3D_ORIENT_NORMAL: - BLI_snprintf(text, sizeof(text), ftext, TIP_("normal")); if (checkUseAxisMatrix(t)) { setAxisMatrixConstraint(t, mode, text); + break; } - else { - setConstraint(t, t->spacemtx, mode, text); - } - break; + ATTR_FALLTHROUGH; + case V3D_ORIENT_GLOBAL: case V3D_ORIENT_VIEW: - BLI_snprintf(text, sizeof(text), ftext, TIP_("view")); - float mtx[3][3]; - copy_m3_m3(mtx, t->spacemtx); - negate_v3(mtx[2]); - setConstraint(t, mtx, mode, text); - break; case V3D_ORIENT_CURSOR: - BLI_snprintf(text, sizeof(text), ftext, TIP_("cursor")); - setConstraint(t, t->spacemtx, mode, text); - break; case V3D_ORIENT_GIMBAL: - BLI_snprintf(text, sizeof(text), ftext, TIP_("gimbal")); - setConstraint(t, t->spacemtx, mode, text); - break; case V3D_ORIENT_CUSTOM_MATRIX: - BLI_snprintf(text, sizeof(text), ftext, TIP_("custom matrix")); - setConstraint(t, t->spacemtx, mode, text); - break; case V3D_ORIENT_CUSTOM: default: { - BLI_assert(orientation >= V3D_ORIENT_CUSTOM); - char orientation_str[128]; - BLI_snprintf(orientation_str, - sizeof(orientation_str), - "%s \"%s\"", - TIP_("custom orientation"), - t->orientation.custom->name); - BLI_snprintf(text, sizeof(text), ftext, orientation_str); - setConstraint(t, t->spacemtx, mode, text); + setConstraint(t, mode, text); break; } } - - t->con.orientation = orientation; - t->con.mode |= CON_USER; } @@ -777,9 +690,9 @@ void drawConstraint(TransInfo *t) convertViewVec(t, vec, (t->mval[0] - t->con.imval[0]), (t->mval[1] - t->con.imval[1])); add_v3_v3(vec, t->center_global); - drawLine(t, t->center_global, tc->mtx[0], 'X', 0); - drawLine(t, t->center_global, tc->mtx[1], 'Y', 0); - drawLine(t, t->center_global, tc->mtx[2], 'Z', 0); + drawLine(t, t->center_global, t->spacemtx[0], 'X', 0); + drawLine(t, t->center_global, t->spacemtx[1], 'Y', 0); + drawLine(t, t->center_global, t->spacemtx[2], 'Z', 0); depth_test_enabled = GPU_depth_test_enabled(); if (depth_test_enabled) { @@ -813,13 +726,13 @@ void drawConstraint(TransInfo *t) } if (tc->mode & CON_AXIS0) { - drawLine(t, t->center_global, tc->mtx[0], 'X', DRAWLIGHT); + drawLine(t, t->center_global, t->spacemtx[0], 'X', DRAWLIGHT); } if (tc->mode & CON_AXIS1) { - drawLine(t, t->center_global, tc->mtx[1], 'Y', DRAWLIGHT); + drawLine(t, t->center_global, t->spacemtx[1], 'Y', DRAWLIGHT); } if (tc->mode & CON_AXIS2) { - drawLine(t, t->center_global, tc->mtx[2], 'Z', DRAWLIGHT); + drawLine(t, t->center_global, t->spacemtx[2], 'Z', DRAWLIGHT); } } } @@ -965,28 +878,6 @@ void stopConstraint(TransInfo *t) t->num.idx_max = t->idx_max; } -void getConstraintMatrix(TransInfo *t) -{ - float mat[3][3]; - invert_m3_m3(t->con.imtx, t->con.mtx); - unit_m3(t->con.pmtx); - - if (!(t->con.mode & CON_AXIS0)) { - zero_v3(t->con.pmtx[0]); - } - - if (!(t->con.mode & CON_AXIS1)) { - zero_v3(t->con.pmtx[1]); - } - - if (!(t->con.mode & CON_AXIS2)) { - zero_v3(t->con.pmtx[2]); - } - - mul_m3_m3m3(mat, t->con.pmtx, t->con.imtx); - mul_m3_m3m3(t->con.pmtx, t->con.mtx, mat); -} - /*------------------------- MMB Select -------------------------------*/ void initSelectConstraint(TransInfo *t, bool force_global) @@ -996,11 +887,11 @@ void initSelectConstraint(TransInfo *t, bool force_global) orientation = V3D_ORIENT_GLOBAL; } else { - if (t->orientation.index == 0) { - t->orientation.index = 1; - initTransformOrientation(t->context, t, t->orientation.types[t->orientation.index]); + if (t->orient_curr == 0) { + t->orient_curr = 1; + transform_orientations_current_set(t, t->orient_curr); } - orientation = t->orientation.types[t->orientation.index]; + orientation = t->orient[t->orient_curr].type; } setUserConstraint(t, orientation, CON_APPLY | CON_SELECT, ""); @@ -1070,7 +961,7 @@ static void setNearestAxis3d(TransInfo *t) for (i = 0; i < 3; i++) { float axis[3], axis_2d[2]; - copy_v3_v3(axis, t->con.mtx[i]); + copy_v3_v3(axis, t->spacemtx[i]); mul_v3_fl(axis, zfac); /* now we can project to get window coordinate */ @@ -1139,7 +1030,7 @@ void setNearestAxis(TransInfo *t) setNearestAxis2d(t); } - getConstraintMatrix(t); + projection_matrix_calc(t, t->con.pmtx); } /*-------------- HELPER FUNCTIONS ----------------*/ diff --git a/source/blender/editors/transform/transform_constraints.h b/source/blender/editors/transform/transform_constraints.h index c98234c83da..b57a7599321 100644 --- a/source/blender/editors/transform/transform_constraints.h +++ b/source/blender/editors/transform/transform_constraints.h @@ -27,7 +27,7 @@ struct TransInfo; void constraintNumInput(TransInfo *t, float vec[3]); -void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[]); +void setConstraint(TransInfo *t, int mode, const char text[]); void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[]); void setLocalConstraint(TransInfo *t, int mode, const char text[]); void setUserConstraint(TransInfo *t, short orientation, int mode, const char text[]); @@ -35,7 +35,6 @@ void drawConstraint(TransInfo *t); void drawPropCircle(const struct bContext *C, TransInfo *t); void startConstraint(TransInfo *t); void stopConstraint(TransInfo *t); -void getConstraintMatrix(TransInfo *t); void initSelectConstraint(TransInfo *t, bool force_global); void selectConstraint(TransInfo *t); void postSelectConstraint(TransInfo *t); diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index b2d87272203..7295a8623d9 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -83,16 +83,45 @@ #include "transform_convert.h" #include "transform_mode.h" +bool transform_mode_use_local_origins(const TransInfo *t) +{ + return ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL); +} + /** * Transforming around ourselves is no use, fallback to individual origins, * useful for curve/armatures. */ void transform_around_single_fallback(TransInfo *t) { - if ((t->data_len_all == 1) && - (ELEM(t->around, V3D_AROUND_CENTER_BOUNDS, V3D_AROUND_CENTER_MEDIAN, V3D_AROUND_ACTIVE)) && - (ELEM(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL))) { - t->around = V3D_AROUND_LOCAL_ORIGINS; + if ((ELEM(t->around, V3D_AROUND_CENTER_BOUNDS, V3D_AROUND_CENTER_MEDIAN, V3D_AROUND_ACTIVE)) && + transform_mode_use_local_origins(t)) { + + bool is_data_single = false; + if (t->data_len_all == 1) { + is_data_single = true; + } + else if (t->data_len_all == 3) { + if (t->obedit_type == OB_CURVE) { + /* Special case check for curve, if we have a single curve bezier triple selected + * treat */ + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + if (!tc->data_len) { + continue; + } + if (tc->data_len == 3) { + const TransData *td = tc->data; + if ((td[0].loc == td[1].loc) && (td[1].loc == td[2].loc)) { + is_data_single = true; + } + } + break; + } + } + } + if (is_data_single) { + t->around = V3D_AROUND_LOCAL_ORIGINS; + } } } @@ -1840,6 +1869,7 @@ static void special_aftertrans_update__node(bContext *C, TransInfo *t) nodeRemoveNode(bmain, ntree, node, true); } } + ntreeUpdateTree(bmain, ntree); } } } diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h index fccaeb994e9..e5d758135e2 100644 --- a/source/blender/editors/transform/transform_convert.h +++ b/source/blender/editors/transform/transform_convert.h @@ -100,6 +100,7 @@ void flushTransTracking(TransInfo *t); /********************* intern **********************/ /* transform_convert.c */ +bool transform_mode_use_local_origins(const TransInfo *t); void transform_around_single_fallback(TransInfo *t); bool constraints_list_needinv(TransInfo *t, ListBase *list); void calc_distanceCurveVerts(TransData *head, TransData *tail); diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c index 908cf7707f2..42ffe675dc5 100644 --- a/source/blender/editors/transform/transform_convert_curve.c +++ b/source/blender/editors/transform/transform_convert_curve.c @@ -167,6 +167,8 @@ void createTransCurveVerts(TransInfo *t) ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) : false; + bool use_around_origins_for_handles_test = ((t->around == V3D_AROUND_LOCAL_ORIGINS) && + transform_mode_use_local_origins(t)); float mtx[3][3], smtx[3][3]; copy_m3_m4(mtx, tc->obedit->obmat); @@ -342,7 +344,7 @@ void createTransCurveVerts(TransInfo *t) if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT, TFM_DUMMY) == 0) { /* sets the handles based on their selection, * do this after the data is copied to the TransData */ - BKE_nurb_handles_test(nu, !hide_handles); + BKE_nurb_handles_test(nu, !hide_handles, use_around_origins_for_handles_test); } } else { diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index 24dda8c8464..07b2f07bf2c 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -1450,7 +1450,6 @@ static void UVsToTransData(const float aspect[2], void createTransUVs(bContext *C, TransInfo *t) { SpaceImage *sima = CTX_wm_space_image(C); - Image *ima = CTX_data_edit_image(C); Scene *scene = t->scene; ToolSettings *ts = CTX_data_tool_settings(C); @@ -1500,7 +1499,7 @@ void createTransUVs(bContext *C, TransInfo *t) BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BMLoop *l; - if (!uvedit_face_visible_test(scene, tc->obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { BM_elem_flag_disable(efa, BM_ELEM_TAG); continue; } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 4472facf183..069e49088de 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1650,25 +1650,21 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve { TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT]; - TransformOrientation *custom_orientation = NULL; short orient_type_set = -1; short orient_type_matrix_set = -1; short orient_type_scene = orient_slot->type; if (orient_type_scene == V3D_ORIENT_CUSTOM) { const int index_custom = orient_slot->index_custom; - custom_orientation = BKE_scene_transform_orientation_find(t->scene, index_custom); orient_type_scene += index_custom; } - short orient_type_default = V3D_ORIENT_GLOBAL; - short orient_type_constraint[2]; + short orient_types[3]; + float custom_matrix[3][3]; + bool use_orient_axis = false; if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) { t->orient_axis = RNA_property_enum_get(op->ptr, prop); - - /* For transfor modes that require "orient_axis" use - * `V3D_ORIENT_VIEW` as default. */ - orient_type_default = V3D_ORIENT_VIEW; + use_orient_axis = true; } if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) { t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop); @@ -1681,26 +1677,28 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve if (orient_type_set >= V3D_ORIENT_CUSTOM + BIF_countTransformOrientation(C)) { orient_type_set = V3D_ORIENT_GLOBAL; } - else { - custom_orientation = BKE_scene_transform_orientation_find( - t->scene, orient_type_default - V3D_ORIENT_CUSTOM); - } } /* Change the default orientation to be used when redoing. */ - orient_type_default = orient_type_set; - orient_type_constraint[0] = orient_type_set; - orient_type_constraint[1] = orient_type_scene; + orient_types[0] = orient_type_set; + orient_types[1] = orient_type_set; + orient_types[2] = orient_type_scene; } else { - orient_type_constraint[0] = orient_type_scene; - orient_type_constraint[1] = orient_type_scene != V3D_ORIENT_GLOBAL ? V3D_ORIENT_GLOBAL : - V3D_ORIENT_LOCAL; + if ((t->flag & T_MODAL) && (use_orient_axis || transform_mode_is_changeable(t->mode))) { + orient_types[0] = V3D_ORIENT_VIEW; + } + else { + orient_types[0] = orient_type_scene; + } + orient_types[1] = orient_type_scene; + orient_types[2] = orient_type_scene != V3D_ORIENT_GLOBAL ? V3D_ORIENT_GLOBAL : + V3D_ORIENT_LOCAL; } if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_matrix")) && RNA_property_is_set(op->ptr, prop))) { - RNA_property_float_get_array(op->ptr, prop, &t->orientation.custom_matrix[0][0]); + RNA_property_float_get_array(op->ptr, prop, &custom_matrix[0][0]); if ((prop = RNA_struct_find_property(op->ptr, "orient_matrix_type")) && RNA_property_is_set(op->ptr, prop)) { @@ -1715,18 +1713,30 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve if (orient_type_matrix_set == orient_type_set) { /* Constraints are forced to use the custom matrix when redoing. */ - orient_type_default = V3D_ORIENT_CUSTOM_MATRIX; + orient_types[0] = V3D_ORIENT_CUSTOM_MATRIX; } } - t->orientation.types[0] = orient_type_default; - t->orientation.types[1] = orient_type_constraint[0]; - t->orientation.types[2] = orient_type_constraint[1]; - t->orientation.custom = custom_orientation; - if (t->con.mode & CON_APPLY) { - t->orientation.index = 1; + t->orient_curr = 1; } + + /* For efficiency, avoid calculating the same orientation twice. */ + for (int i = 1; i < 3; i++) { + t->orient[i].type = transform_orientation_matrix_get( + C, t, orient_types[i], custom_matrix, t->orient[i].matrix); + } + + if (orient_types[0] != orient_types[1]) { + t->orient[0].type = transform_orientation_matrix_get( + C, t, orient_types[0], custom_matrix, t->orient[0].matrix); + } + else { + memcpy(&t->orient[0], &t->orient[1], sizeof(t->orient[0])); + } + + const char *spacename = transform_orientations_spacename_get(t, orient_types[0]); + BLI_strncpy(t->spacename, spacename, sizeof(t->spacename)); } if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) && diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c index 50317d8b395..c63e90ac2b7 100644 --- a/source/blender/editors/transform/transform_gizmo_2d.c +++ b/source/blender/editors/transform/transform_gizmo_2d.c @@ -217,14 +217,12 @@ static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min ScrArea *area = CTX_wm_area(C); bool changed = false; if (area->spacetype == SPACE_IMAGE) { - SpaceImage *sima = area->spacedata.first; Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = ED_space_image(sima); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( view_layer, NULL, &objects_len); - if (ED_uvedit_minmax_multi(scene, ima, objects, objects_len, r_min, r_max)) { + if (ED_uvedit_minmax_multi(scene, objects, objects_len, r_min, r_max)) { changed = true; } MEM_freeN(objects); diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index b575030778f..ddeba206e4a 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -1390,21 +1390,21 @@ void drawDial3d(const TransInfo *t) if (tc->mode & CON_APPLY) { if (tc->mode & CON_AXIS0) { axis_idx = MAN_AXIS_ROT_X; - negate_v3_v3(mat_basis[2], tc->mtx[0]); + negate_v3_v3(mat_basis[2], t->spacemtx[0]); } else if (tc->mode & CON_AXIS1) { axis_idx = MAN_AXIS_ROT_Y; - negate_v3_v3(mat_basis[2], tc->mtx[1]); + negate_v3_v3(mat_basis[2], t->spacemtx[1]); } else { BLI_assert((tc->mode & CON_AXIS2) != 0); axis_idx = MAN_AXIS_ROT_Z; - negate_v3_v3(mat_basis[2], tc->mtx[2]); + negate_v3_v3(mat_basis[2], t->spacemtx[2]); } } else { axis_idx = MAN_AXIS_ROT_C; - negate_v3_v3(mat_basis[2], t->spacemtx[t->orient_axis]); + copy_v3_v3(mat_basis[2], t->spacemtx[t->orient_axis]); scale *= 1.2f; line_with -= 1.0f; } @@ -2201,6 +2201,15 @@ static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *gzgr WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true); } else { + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + if (ob && ob->mode & OB_MODE_EDIT) { + copy_m4_m4(gz->matrix_space, ob->obmat); + } + else { + unit_m4(gz->matrix_space); + } + gizmo_prepare_mat(C, rv3d, &tbounds); WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); @@ -2258,15 +2267,6 @@ static void WIDGETGROUP_xform_cage_message_subscribe(const bContext *C, static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) { struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata; - wmGizmo *gz = xgzgroup->gizmo; - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - if (ob && ob->mode & OB_MODE_EDIT) { - copy_m4_m4(gz->matrix_space, ob->obmat); - } - else { - unit_m4(gz->matrix_space); - } RegionView3D *rv3d = CTX_wm_region_view3d(C); { diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index 4c14c3aebd7..c2c880b03ff 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -61,6 +61,18 @@ bool transdata_check_local_center(TransInfo *t, short around) (t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE)))); } +/* Informs if the mode can be switched during modal. */ +bool transform_mode_is_changeable(const int mode) +{ + return ELEM(mode, + TFM_ROTATION, + TFM_RESIZE, + TFM_TRACKBALL, + TFM_TRANSLATION, + TFM_EDGE_SLIDE, + TFM_VERT_SLIDE); +} + /* -------------------------------------------------------------------- */ /** \name Transform Locks * \{ */ diff --git a/source/blender/editors/transform/transform_mode.h b/source/blender/editors/transform/transform_mode.h index 6180f6d3477..074e89390c2 100644 --- a/source/blender/editors/transform/transform_mode.h +++ b/source/blender/editors/transform/transform_mode.h @@ -41,6 +41,7 @@ typedef struct TransDataGenericSlideVert { /* transform_mode.c */ bool transdata_check_local_center(TransInfo *t, short around); +bool transform_mode_is_changeable(const int mode); void protectedTransBits(short protectflag, float vec[3]); void constraintTransLim(TransInfo *t, TransData *td); void postInputRotation(TransInfo *t, float values[3]); diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c index ee91459dcdd..8690cd54a3b 100644 --- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c @@ -101,9 +101,8 @@ static void applySeqSlide(TransInfo *t, const int mval[2]) snapSequenceBounds(t, mval); if (t->con.mode & CON_APPLY) { - float pvec[3] = {0.0f, 0.0f, 0.0f}; float tvec[3]; - t->con.applyVec(t, NULL, NULL, t->values, tvec, pvec); + t->con.applyVec(t, NULL, NULL, t->values, tvec); copy_v3_v3(t->values_final, tvec); } else { diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c index f52bfda0d14..55c97630487 100644 --- a/source/blender/editors/transform/transform_mode_rotate.c +++ b/source/blender/editors/transform/transform_mode_rotate.c @@ -146,7 +146,8 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) snapGridIncrement(t, &final); float axis_final[3]; - copy_v3_v3(axis_final, t->spacemtx[t->orient_axis]); + /* Use the negative axis to match the default Z axis of the view matrix. */ + negate_v3_v3(axis_final, t->spacemtx[t->orient_axis]); if ((t->con.mode & CON_APPLY) && t->con.applyRot) { t->con.applyRot(t, NULL, NULL, axis_final, NULL); diff --git a/source/blender/editors/transform/transform_mode_shear.c b/source/blender/editors/transform/transform_mode_shear.c index da34bf50ba3..3eeb8a1e758 100644 --- a/source/blender/editors/transform/transform_mode_shear.c +++ b/source/blender/editors/transform/transform_mode_shear.c @@ -56,14 +56,14 @@ static void initShear_mouseInputMode(TransInfo *t) copy_v3_v3(dir, t->spacemtx[t->orient_axis_ortho]); /* Needed for axis aligned view gizmo. */ - if (t->orientation.types[t->orientation.index] == V3D_ORIENT_VIEW) { + if (t->orient[t->orient_curr].type == V3D_ORIENT_VIEW) { if (t->orient_axis_ortho == 0) { - if (t->center2d[1] < t->mouse.imval[1]) { + if (t->center2d[1] > t->mouse.imval[1]) { dir_flip = !dir_flip; } } else if (t->orient_axis_ortho == 1) { - if (t->center2d[0] < t->mouse.imval[0]) { + if (t->center2d[0] > t->mouse.imval[0]) { dir_flip = !dir_flip; } } diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index 0a7d8bd90d3..69552eda5bf 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -277,8 +277,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) } if (t->con.applyVec) { - float pvec[3]; - t->con.applyVec(t, tc, td, vec, tvec, pvec); + t->con.applyVec(t, tc, td, vec, tvec); } else { copy_v3_v3(tvec, vec); @@ -319,45 +318,39 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) { char str[UI_MAX_DRAW_STR]; - float values_final[3]; + float global_dir[3]; if (t->flag & T_INPUT_IS_VALUES_FINAL) { - copy_v3_v3(t->values_final, t->values); + mul_v3_m3v3(global_dir, t->spacemtx, t->values); } else { - copy_v3_v3(t->values_final, t->values); + copy_v3_v3(global_dir, t->values); if ((t->con.mode & CON_APPLY) == 0) { - snapGridIncrement(t, t->values_final); + snapGridIncrement(t, global_dir); } - if (applyNumInput(&t->num, t->values_final)) { - removeAspectRatio(t, t->values_final); + if (applyNumInput(&t->num, global_dir)) { + removeAspectRatio(t, global_dir); } - applySnapping(t, t->values_final); + applySnapping(t, global_dir); } - copy_v3_v3(values_final, t->values_final); if (t->con.mode & CON_APPLY) { - float pvec[3] = {0.0f, 0.0f, 0.0f}; - t->con.applyVec(t, NULL, NULL, t->values_final, values_final, pvec); - headerTranslation(t, pvec, str); - - /* only so we have re-usable value with redo, see T46741. */ - mul_v3_m3v3(t->values_final, t->con.imtx, values_final); + float in[3]; + copy_v3_v3(in, global_dir); + t->con.applyVec(t, NULL, NULL, in, global_dir); + headerTranslation(t, global_dir, str); } else { - headerTranslation(t, t->values_final, str); - copy_v3_v3(values_final, t->values_final); + headerTranslation(t, global_dir, str); } - /* don't use 't->values' now on */ - - applyTranslationValue(t, values_final); + applyTranslationValue(t, global_dir); /* evil hack - redo translation if clipping needed */ - if (t->flag & T_CLIP_UV && clipUVTransform(t, values_final, 0)) { - applyTranslationValue(t, values_final); + if (t->flag & T_CLIP_UV && clipUVTransform(t, global_dir, 0)) { + applyTranslationValue(t, global_dir); /* In proportional edit it can happen that */ /* vertices in the radius of the brush end */ @@ -368,8 +361,10 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) } } - recalcData(t); + /* Set the redo value. */ + mul_v3_m3v3(t->values_final, t->spacemtx_inv, global_dir); + recalcData(t); ED_area_status_text(t->area, str); } diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 81c63278366..4cddb9d3b4a 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -438,79 +438,148 @@ static int armature_bone_transflags_update_recursive(bArmature *arm, return total; } -void initTransformOrientation(bContext *C, TransInfo *t, short orientation) +/* Sets the matrix of the specified space orientation. + * If the matrix cannot be obtained, an orientation different from the one + * informed is returned */ +short transform_orientation_matrix_get(bContext *C, + TransInfo *t, + const short orientation, + const float custom[3][3], + float r_spacemtx[3][3]) { Object *ob = CTX_data_active_object(C); Object *obedit = CTX_data_active_object(C); switch (orientation) { case V3D_ORIENT_GLOBAL: - unit_m3(t->spacemtx); - BLI_strncpy(t->spacename, TIP_("global"), sizeof(t->spacename)); - break; + unit_m3(r_spacemtx); + return V3D_ORIENT_GLOBAL; case V3D_ORIENT_GIMBAL: - unit_m3(t->spacemtx); - if (ob && gimbal_axis(ob, t->spacemtx)) { - BLI_strncpy(t->spacename, TIP_("gimbal"), sizeof(t->spacename)); - break; + unit_m3(r_spacemtx); + if (ob && gimbal_axis(ob, r_spacemtx)) { + return V3D_ORIENT_GIMBAL; } ATTR_FALLTHROUGH; /* no gimbal fallthrough to normal */ + case V3D_ORIENT_NORMAL: if (obedit || (ob && ob->mode & OB_MODE_POSE)) { - BLI_strncpy(t->spacename, TIP_("normal"), sizeof(t->spacename)); - ED_getTransformOrientationMatrix(C, t->spacemtx, t->around); - break; + ED_getTransformOrientationMatrix(C, r_spacemtx, t->around); + return V3D_ORIENT_NORMAL; } ATTR_FALLTHROUGH; /* we define 'normal' as 'local' in Object mode */ - case V3D_ORIENT_LOCAL: - BLI_strncpy(t->spacename, TIP_("local"), sizeof(t->spacename)); + case V3D_ORIENT_LOCAL: if (ob) { - copy_m3_m4(t->spacemtx, ob->obmat); - normalize_m3(t->spacemtx); + copy_m3_m4(r_spacemtx, ob->obmat); + normalize_m3(r_spacemtx); + return V3D_ORIENT_LOCAL; } - else { - unit_m3(t->spacemtx); - } - - break; + unit_m3(r_spacemtx); + return V3D_ORIENT_GLOBAL; case V3D_ORIENT_VIEW: { float mat[3][3]; if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { - BLI_strncpy(t->spacename, TIP_("view"), sizeof(t->spacename)); - copy_m3_m4(mat, t->viewinv); + RegionView3D *rv3d = t->region->regiondata; + copy_m3_m4(mat, rv3d->viewinv); normalize_m3(mat); } else { unit_m3(mat); } - negate_v3(mat[2]); - copy_m3_m3(t->spacemtx, mat); - break; - } - case V3D_ORIENT_CURSOR: { - BLI_strncpy(t->spacename, TIP_("cursor"), sizeof(t->spacename)); - BKE_scene_cursor_rot_to_mat3(&t->scene->cursor, t->spacemtx); - break; + copy_m3_m3(r_spacemtx, mat); + return V3D_ORIENT_VIEW; } + case V3D_ORIENT_CURSOR: + BKE_scene_cursor_rot_to_mat3(&t->scene->cursor, r_spacemtx); + return V3D_ORIENT_CURSOR; + case V3D_ORIENT_CUSTOM_MATRIX: - BLI_strncpy(t->spacename, TIP_("custom"), sizeof(t->spacename)); - copy_m3_m3(t->spacemtx, t->orientation.custom_matrix); - break; + copy_m3_m3(r_spacemtx, custom); + return V3D_ORIENT_CUSTOM_MATRIX; + case V3D_ORIENT_CUSTOM: default: BLI_assert(orientation >= V3D_ORIENT_CUSTOM); - BLI_strncpy(t->spacename, t->orientation.custom->name, sizeof(t->spacename)); - if (applyTransformOrientation(t->orientation.custom, t->spacemtx, t->spacename)) { + TransformOrientation *ts = BKE_scene_transform_orientation_find( + t->scene, orientation - V3D_ORIENT_CUSTOM); + if (applyTransformOrientation(ts, r_spacemtx, t->spacename)) { /* pass */ } else { - unit_m3(t->spacemtx); + unit_m3(r_spacemtx); } break; } + + return orientation; +} + +const char *transform_orientations_spacename_get(TransInfo *t, const short orient_type) +{ + switch (orient_type) { + case V3D_ORIENT_GLOBAL: + return TIP_("global"); + case V3D_ORIENT_GIMBAL: + return TIP_("gimbal"); + case V3D_ORIENT_NORMAL: + return TIP_("normal"); + case V3D_ORIENT_LOCAL: + return TIP_("local"); + case V3D_ORIENT_VIEW: + return TIP_("view"); + case V3D_ORIENT_CURSOR: + return TIP_("cursor"); + case V3D_ORIENT_CUSTOM_MATRIX: + return TIP_("custom"); + case V3D_ORIENT_CUSTOM: + default: + BLI_assert(orient_type >= V3D_ORIENT_CUSTOM); + TransformOrientation *ts = BKE_scene_transform_orientation_find( + t->scene, orient_type - V3D_ORIENT_CUSTOM); + return ts->name; + } +} + +void transform_orientations_current_set(TransInfo *t, const short orient_index) +{ + const short orientation = t->orient[orient_index].type; + const char *spacename; + switch (orientation) { + case V3D_ORIENT_GLOBAL: + spacename = TIP_("global"); + break; + case V3D_ORIENT_GIMBAL: + spacename = TIP_("gimbal"); + break; + case V3D_ORIENT_NORMAL: + spacename = TIP_("normal"); + break; + case V3D_ORIENT_LOCAL: + spacename = TIP_("local"); + break; + case V3D_ORIENT_VIEW: + spacename = TIP_("view"); + break; + case V3D_ORIENT_CURSOR: + spacename = TIP_("cursor"); + break; + case V3D_ORIENT_CUSTOM_MATRIX: + spacename = TIP_("custom"); + break; + case V3D_ORIENT_CUSTOM: + default: + BLI_assert(orientation >= V3D_ORIENT_CUSTOM); + TransformOrientation *ts = BKE_scene_transform_orientation_find( + t->scene, orientation - V3D_ORIENT_CUSTOM); + spacename = ts->name; + break; + } + + BLI_strncpy(t->spacename, spacename, sizeof(t->spacename)); + copy_m3_m3(t->spacemtx, t->orient[orient_index].matrix); + invert_m3_m3(t->spacemtx_inv, t->spacemtx); } /** diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index cb4446deb99..d3df68b21da 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -1106,7 +1106,6 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) } else if (t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH) { if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) { - Image *ima = ED_space_image(t->area->spacedata.first); float co[2]; UI_view2d_region_to_view(&t->region->v2d, t->mval[0], t->mval[1], &co[0], &co[1]); @@ -1117,7 +1116,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) float dist_sq = FLT_MAX; if (ED_uvedit_nearest_uv_multi( - t->scene, ima, objects, objects_len, co, &dist_sq, t->tsnap.snapPoint)) { + t->scene, objects, objects_len, co, &dist_sq, t->tsnap.snapPoint)) { t->tsnap.snapPoint[0] *= t->aspect[0]; t->tsnap.snapPoint[1] *= t->aspect[1]; @@ -1750,8 +1749,8 @@ static void applyGridIncrement( float local_axis[3]; float pos_on_axis[3]; - copy_v3_v3(local_axis, t->con.mtx[i]); - copy_v3_v3(pos_on_axis, t->con.mtx[i]); + copy_v3_v3(local_axis, t->spacemtx[i]); + copy_v3_v3(pos_on_axis, t->spacemtx[i]); /* amount of movement on axis from initial pos */ mul_v3_fl(pos_on_axis, val[i]); diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 2cfeedbb346..acd76a2e3f5 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -1707,8 +1707,14 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, &nearest.dist_sq, nearest.co)) { nearest.index = vindex[v_id]; - nearest2d.copy_vert_no(vindex[v_id], nearest.no, nearest2d.userdata); elem = SCE_SNAP_MODE_VERTEX; + if (r_no) { + float imat[4][4]; + invert_m4_m4(imat, obmat); + nearest2d.copy_vert_no(vindex[v_id], r_no, nearest2d.userdata); + mul_transposed_mat3_m4_v3(imat, r_no); + normalize_v3(r_no); + } } } } @@ -1726,10 +1732,6 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, vmid, &nearest.dist_sq, nearest.co)) { - float v_nor[2][3]; - nearest2d.copy_vert_no(vindex[0], v_nor[0], nearest2d.userdata); - nearest2d.copy_vert_no(vindex[1], v_nor[1], nearest2d.userdata); - mid_v3_v3v3(nearest.no, v_nor[0], v_nor[1]); nearest.index = *r_index; elem = SCE_SNAP_MODE_EDGE_MIDPOINT; } @@ -1757,11 +1759,6 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, v_near, &nearest.dist_sq, nearest.co)) { - float v_nor[2][3]; - nearest2d.copy_vert_no(vindex[0], v_nor[0], nearest2d.userdata); - nearest2d.copy_vert_no(vindex[1], v_nor[1], nearest2d.userdata); - mid_v3_v3v3(nearest.no, v_nor[0], v_nor[1]); - nearest.index = *r_index; elem = SCE_SNAP_MODE_EDGE_PERPENDICULAR; } @@ -1778,15 +1775,6 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, mul_m4_v3(obmat, r_loc); } - if (r_no) { - float imat[4][4]; - invert_m4_m4(imat, obmat); - - copy_v3_v3(r_no, nearest.no); - mul_transposed_mat3_m4_v3(imat, r_no); - normalize_v3(r_no); - } - *r_index = nearest.index; } diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c index 67a62473dc0..1c56ad878e2 100644 --- a/source/blender/editors/util/ed_transverts.c +++ b/source/blender/editors/util/ed_transverts.c @@ -111,7 +111,7 @@ void ED_transverts_update_obedit(TransVertStore *tvs, Object *obedit) } BKE_nurb_test_2d(nu); - BKE_nurb_handles_test(nu, true); /* test for bezier too */ + BKE_nurb_handles_test(nu, true, false); /* test for bezier too */ nu = nu->next; } } diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c index c072220842e..edfbfd0cdc3 100644 --- a/source/blender/editors/uvedit/uvedit_buttons.c +++ b/source/blender/editors/uvedit/uvedit_buttons.c @@ -58,8 +58,7 @@ /* UV Utilities */ -static int uvedit_center( - Scene *scene, Object **objects, uint objects_len, Image *ima, float center[2]) +static int uvedit_center(Scene *scene, Object **objects, uint objects_len, float center[2]) { BMFace *f; BMLoop *l; @@ -75,7 +74,7 @@ static int uvedit_center( const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, f)) { + if (!uvedit_face_visible_test(scene, f)) { continue; } @@ -97,8 +96,10 @@ static int uvedit_center( return tot; } -static void uvedit_translate( - Scene *scene, Object **objects, uint objects_len, Image *ima, const float delta[2]) +static void uvedit_translate(Scene *scene, + Object **objects, + uint objects_len, + const float delta[2]) { BMFace *f; BMLoop *l; @@ -112,7 +113,7 @@ static void uvedit_translate( const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, f)) { + if (!uvedit_face_visible_test(scene, f)) { continue; } @@ -134,7 +135,6 @@ static void uvedit_vertex_buttons(const bContext *C, uiBlock *block) { SpaceImage *sima = CTX_wm_space_image(C); Scene *scene = CTX_data_scene(C); - Image *ima = sima->image; float center[2]; int imx, imy, step, digits; float width = 8 * UI_UNIT_X; @@ -144,7 +144,7 @@ static void uvedit_vertex_buttons(const bContext *C, uiBlock *block) ED_space_image_get_size(sima, &imx, &imy); - if (uvedit_center(scene, objects, objects_len, ima, center)) { + if (uvedit_center(scene, objects, objects_len, center)) { float range_xy[2][2] = { {-10.0f, 10.0f}, {-10.0f, 10.0f}, @@ -212,7 +212,6 @@ static void do_uvedit_vertex(bContext *C, void *UNUSED(arg), int event) { SpaceImage *sima = CTX_wm_space_image(C); Scene *scene = CTX_data_scene(C); - Image *ima = sima->image; float center[2], delta[2]; int imx, imy; @@ -225,7 +224,7 @@ static void do_uvedit_vertex(bContext *C, void *UNUSED(arg), int event) CTX_data_view_layer(C), CTX_wm_view3d(C), &objects_len); ED_space_image_get_size(sima, &imx, &imy); - uvedit_center(scene, objects, objects_len, ima, center); + uvedit_center(scene, objects, objects_len, center); if (sima->flag & SI_COORDFLOATS) { delta[0] = uvedit_old_center[0] - center[0]; @@ -236,7 +235,7 @@ static void do_uvedit_vertex(bContext *C, void *UNUSED(arg), int event) delta[1] = uvedit_old_center[1] / imy - center[1]; } - uvedit_translate(scene, objects, objects_len, ima, delta); + uvedit_translate(scene, objects, objects_len, delta); WM_event_add_notifier(C, NC_IMAGE, sima->image); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 959ca1eeef1..f8cef95c776 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -216,13 +216,14 @@ static void uvedit_get_batches(Object *ob, } } -static void draw_uvs_shadow(SpaceImage *UNUSED(sima), +static void draw_uvs_shadow(SpaceImage *sima, const Scene *scene, Object *obedit, Depsgraph *depsgraph) { Object *ob_eval = DEG_get_evaluated_object(depsgraph, obedit); Mesh *me = ob_eval->data; + const float overlay_alpha = sima->uv_opacity; float col[4]; UI_GetThemeColor4fv(TH_UV_SHADOW, col); @@ -231,9 +232,26 @@ static void draw_uvs_shadow(SpaceImage *UNUSED(sima), DRW_mesh_batch_cache_create_requested(ob_eval, me, scene, false, false); if (edges) { + if (sima->flag & SI_SMOOTH_UV) { + GPU_line_smooth(true); + GPU_blend(true); + } + else if (overlay_alpha < 1.0f) { + GPU_blend(true); + } + + col[3] = overlay_alpha; GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UV_UNIFORM_COLOR); GPU_batch_uniform_4fv(edges, "color", col); GPU_batch_draw(edges); + + if (sima->flag & SI_SMOOTH_UV) { + GPU_line_smooth(false); + GPU_blend(false); + } + else if (overlay_alpha < 1.0f) { + GPU_blend(false); + } } } diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index ffab5bd094f..31384d6df17 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -57,13 +57,11 @@ typedef struct UvNearestHit { } bool uv_find_nearest_vert(struct Scene *scene, - struct Image *ima, struct Object *obedit, const float co[2], const float penalty_dist, struct UvNearestHit *hit_final); bool uv_find_nearest_vert_multi(struct Scene *scene, - struct Image *ima, struct Object **objects, const uint objects_len, const float co[2], @@ -71,24 +69,20 @@ bool uv_find_nearest_vert_multi(struct Scene *scene, struct UvNearestHit *hit_final); bool uv_find_nearest_edge(struct Scene *scene, - struct Image *ima, struct Object *obedit, const float co[2], struct UvNearestHit *hit_final); bool uv_find_nearest_edge_multi(struct Scene *scene, - struct Image *ima, struct Object **objects, const uint objects_len, const float co[2], struct UvNearestHit *hit_final); bool uv_find_nearest_face(struct Scene *scene, - struct Image *ima, struct Object *obedit, const float co[2], struct UvNearestHit *hit_final); bool uv_find_nearest_face_multi(struct Scene *scene, - struct Image *ima, struct Object **objects, const uint objects_len, const float co[2], @@ -116,14 +110,11 @@ void UV_OT_stitch(struct wmOperatorType *ot); /* uvedit_select.c */ -bool uvedit_select_is_any_selected(struct Scene *scene, struct Image *ima, struct Object *obedit); +bool uvedit_select_is_any_selected(struct Scene *scene, struct Object *obedit); bool uvedit_select_is_any_selected_multi(struct Scene *scene, - struct Image *ima, struct Object **objects, const uint objects_len); const float *uvedit_first_selected_uv_from_vertex(struct Scene *scene, - struct Object *obedit, - struct Image *ima, struct BMVert *eve, const int cd_loop_uv_offset); diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index a99e05cb52b..78b6cfc44ac 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -252,12 +252,8 @@ void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float as } } -bool ED_uvedit_minmax_multi(const Scene *scene, - Image *ima, - Object **objects_edit, - uint objects_len, - float r_min[2], - float r_max[2]) +bool ED_uvedit_minmax_multi( + const Scene *scene, Object **objects_edit, uint objects_len, float r_min[2], float r_max[2]) { bool changed = false; INIT_MINMAX2(r_min, r_max); @@ -274,7 +270,7 @@ bool ED_uvedit_minmax_multi(const Scene *scene, const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -290,10 +286,9 @@ bool ED_uvedit_minmax_multi(const Scene *scene, return changed; } -bool ED_uvedit_minmax( - const Scene *scene, Image *ima, Object *obedit, float r_min[2], float r_max[2]) +bool ED_uvedit_minmax(const Scene *scene, Object *obedit, float r_min[2], float r_max[2]) { - return ED_uvedit_minmax_multi(scene, ima, &obedit, 1, r_min, r_max); + return ED_uvedit_minmax_multi(scene, &obedit, 1, r_min, r_max); } /* Be careful when using this, it bypasses all synchronization options */ @@ -314,8 +309,10 @@ void ED_uvedit_select_all(BMesh *bm) } } -static bool ED_uvedit_median_multi( - const Scene *scene, Image *ima, Object **objects_edit, uint objects_len, float co[2]) +static bool ED_uvedit_median_multi(const Scene *scene, + Object **objects_edit, + uint objects_len, + float co[2]) { uint sel = 0; zero_v2(co); @@ -332,7 +329,7 @@ static bool ED_uvedit_median_multi( const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -351,24 +348,20 @@ static bool ED_uvedit_median_multi( return (sel != 0); } -bool ED_uvedit_center_multi(const Scene *scene, - Image *ima, - Object **objects_edit, - uint objects_len, - float cent[2], - char mode) +bool ED_uvedit_center_multi( + const Scene *scene, Object **objects_edit, uint objects_len, float cent[2], char mode) { bool changed = false; if (mode == V3D_AROUND_CENTER_BOUNDS) { /* bounding box */ float min[2], max[2]; - if (ED_uvedit_minmax_multi(scene, ima, objects_edit, objects_len, min, max)) { + if (ED_uvedit_minmax_multi(scene, objects_edit, objects_len, min, max)) { mid_v2_v2v2(cent, min, max); changed = true; } } else { - if (ED_uvedit_median_multi(scene, ima, objects_edit, objects_len, cent)) { + if (ED_uvedit_median_multi(scene, objects_edit, objects_len, cent)) { changed = true; } } @@ -392,8 +385,7 @@ bool ED_uvedit_center_from_pivot_ex(SpaceImage *sima, uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( view_layer, ((View3D *)NULL), &objects_len); - *r_has_select = uvedit_select_is_any_selected_multi( - scene, sima->image, objects, objects_len); + *r_has_select = uvedit_select_is_any_selected_multi(scene, objects, objects_len); MEM_freeN(objects); } break; @@ -402,7 +394,7 @@ bool ED_uvedit_center_from_pivot_ex(SpaceImage *sima, uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( view_layer, ((View3D *)NULL), &objects_len); - changed = ED_uvedit_center_multi(scene, sima->image, objects, objects_len, r_center, mode); + changed = ED_uvedit_center_multi(scene, objects, objects_len, r_center, mode); MEM_freeN(objects); if (r_has_select != NULL) { *r_has_select = changed; @@ -440,7 +432,6 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); SpaceImage *sima = CTX_wm_space_image(C); - Image *ima = CTX_data_edit_image(C); const ToolSettings *ts = scene->toolsettings; const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0; float cent[2], min[2], max[2]; @@ -467,7 +458,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool) BMLoop *l; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -482,7 +473,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool) tool = (max[0] - min[0] >= max[1] - min[1]) ? UV_ALIGN_Y : UV_ALIGN_X; } - ED_uvedit_center_multi(scene, ima, objects, objects_len, cent, 0); + ED_uvedit_center_multi(scene, objects, objects_len, cent, 0); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -501,7 +492,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool) BMLoop *l; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -521,7 +512,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool) BMLoop *l; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -548,7 +539,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool) /* tag verts with a selected UV */ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) { - if (!uvedit_face_visible_test(scene, obedit, ima, l->f)) { + if (!uvedit_face_visible_test(scene, l->f)) { continue; } @@ -619,9 +610,9 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool) /* we know the returns from these must be valid */ const float *uv_start = uvedit_first_selected_uv_from_vertex( - scene, obedit, ima, eve_line[0], cd_loop_uv_offset); + scene, eve_line[0], cd_loop_uv_offset); const float *uv_end = uvedit_first_selected_uv_from_vertex( - scene, obedit, ima, eve_line[BLI_array_len(eve_line) - 1], cd_loop_uv_offset); + scene, eve_line[BLI_array_len(eve_line) - 1], cd_loop_uv_offset); /* For UV_STRAIGHTEN_X & UV_STRAIGHTEN_Y modes */ float a = 0.0f; eUVWeldAlign tool_local = tool; @@ -646,7 +637,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool) /* go over all verts except for endpoints */ for (i = 0; i < BLI_array_len(eve_line); i++) { BM_ITER_ELEM (l, &liter, eve_line[i], BM_LOOPS_OF_VERT) { - if (!uvedit_face_visible_test(scene, obedit, ima, l->f)) { + if (!uvedit_face_visible_test(scene, l->f)) { continue; } @@ -754,7 +745,6 @@ static int uv_remove_doubles_to_selected(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); SpaceImage *sima = CTX_wm_space_image(C); - Image *ima = CTX_data_edit_image(C); const ToolSettings *ts = scene->toolsettings; const float threshold = RNA_float_get(op->ptr, "threshold"); @@ -808,7 +798,7 @@ static int uv_remove_doubles_to_selected(bContext *C, wmOperator *op) const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -899,7 +889,6 @@ static int uv_remove_doubles_to_unselected(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); SpaceImage *sima = CTX_wm_space_image(C); - Image *ima = CTX_data_edit_image(C); const ToolSettings *ts = scene->toolsettings; const float threshold = RNA_float_get(op->ptr, "threshold"); @@ -939,7 +928,7 @@ static int uv_remove_doubles_to_unselected(bContext *C, wmOperator *op) const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -972,7 +961,7 @@ static int uv_remove_doubles_to_unselected(bContext *C, wmOperator *op) const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -1086,10 +1075,12 @@ static void uv_snap_cursor_to_pixels(SpaceImage *sima) uv_snap_to_pixel(sima->cursor, width, height); } -static bool uv_snap_cursor_to_selection( - Scene *scene, Image *ima, Object **objects_edit, uint objects_len, SpaceImage *sima) +static bool uv_snap_cursor_to_selection(Scene *scene, + Object **objects_edit, + uint objects_len, + SpaceImage *sima) { - return ED_uvedit_center_multi(scene, ima, objects_edit, objects_len, sima->cursor, sima->around); + return ED_uvedit_center_multi(scene, objects_edit, objects_len, sima->cursor, sima->around); } static int uv_snap_cursor_exec(bContext *C, wmOperator *op) @@ -1105,13 +1096,12 @@ static int uv_snap_cursor_exec(bContext *C, wmOperator *op) break; case 1: { Scene *scene = CTX_data_scene(C); - Image *ima = CTX_data_edit_image(C); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( view_layer, ((View3D *)NULL), &objects_len); - changed = uv_snap_cursor_to_selection(scene, ima, objects, objects_len, sima); + changed = uv_snap_cursor_to_selection(scene, objects, objects_len, sima); MEM_freeN(objects); break; } @@ -1155,7 +1145,7 @@ static void UV_OT_snap_cursor(wmOperatorType *ot) /** \name Snap Selection Operator * \{ */ -static bool uv_snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, const float cursor[2]) +static bool uv_snap_uvs_to_cursor(Scene *scene, Object *obedit, const float cursor[2]) { BMEditMesh *em = BKE_editmesh_from_object(obedit); BMFace *efa; @@ -1167,7 +1157,7 @@ static bool uv_snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, cons const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -1183,7 +1173,7 @@ static bool uv_snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, cons return changed; } -static bool uv_snap_uvs_offset(Scene *scene, Image *ima, Object *obedit, const float offset[2]) +static bool uv_snap_uvs_offset(Scene *scene, Object *obedit, const float offset[2]) { BMEditMesh *em = BKE_editmesh_from_object(obedit); BMFace *efa; @@ -1195,7 +1185,7 @@ static bool uv_snap_uvs_offset(Scene *scene, Image *ima, Object *obedit, const f const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -1211,7 +1201,7 @@ static bool uv_snap_uvs_offset(Scene *scene, Image *ima, Object *obedit, const f return changed; } -static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obedit) +static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Object *obedit) { BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm = em->bm; @@ -1225,7 +1215,7 @@ static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object /* index every vert that has a selected UV using it, but only once so as to * get unique indices and to count how much to malloc */ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (uvedit_face_visible_test(scene, obedit, ima, f)) { + if (uvedit_face_visible_test(scene, f)) { BM_elem_flag_enable(f, BM_ELEM_TAG); BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { BM_elem_flag_set(l, BM_ELEM_TAG, uvedit_uv_select_test(scene, l, cd_loop_uv_offset)); @@ -1269,7 +1259,6 @@ static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object static bool uv_snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit) { BMEditMesh *em = BKE_editmesh_from_object(obedit); - Image *ima = sima->image; BMFace *efa; BMLoop *l; BMIter iter, liter; @@ -1285,7 +1274,7 @@ static bool uv_snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit h = (float)height; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -1307,7 +1296,6 @@ static int uv_snap_selection_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); SpaceImage *sima = CTX_wm_space_image(C); - Image *ima = CTX_data_edit_image(C); const ToolSettings *ts = scene->toolsettings; const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0; const int target = RNA_enum_get(op->ptr, "target"); @@ -1319,7 +1307,7 @@ static int uv_snap_selection_exec(bContext *C, wmOperator *op) if (target == 2) { float center[2]; - if (!ED_uvedit_center_multi(scene, ima, objects, objects_len, center, sima->around)) { + if (!ED_uvedit_center_multi(scene, objects, objects_len, center, sima->around)) { MEM_freeN(objects); return OPERATOR_CANCELLED; } @@ -1341,13 +1329,13 @@ static int uv_snap_selection_exec(bContext *C, wmOperator *op) changed = uv_snap_uvs_to_pixels(sima, scene, obedit); break; case 1: - changed = uv_snap_uvs_to_cursor(scene, ima, obedit, sima->cursor); + changed = uv_snap_uvs_to_cursor(scene, obedit, sima->cursor); break; case 2: - changed = uv_snap_uvs_offset(scene, ima, obedit, offset); + changed = uv_snap_uvs_offset(scene, obedit, offset); break; case 3: - changed = uv_snap_uvs_to_adjacent_unselected(scene, ima, obedit); + changed = uv_snap_uvs_to_adjacent_unselected(scene, obedit); break; } @@ -1398,7 +1386,6 @@ static int uv_pin_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); BMFace *efa; BMLoop *l; BMIter iter, liter; @@ -1423,7 +1410,7 @@ static int uv_pin_exec(bContext *C, wmOperator *op) } BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -1501,11 +1488,9 @@ static bool bm_face_is_all_uv_sel(BMFace *f, bool select_test, const int cd_loop static int uv_hide_exec(bContext *C, wmOperator *op) { ViewLayer *view_layer = CTX_data_view_layer(C); - SpaceImage *sima = CTX_wm_space_image(C); Scene *scene = CTX_data_scene(C); const ToolSettings *ts = scene->toolsettings; const bool swap = RNA_boolean_get(op->ptr, "unselected"); - Image *ima = sima ? sima->image : NULL; const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE); uint objects_len = 0; @@ -1532,7 +1517,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op) BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { int hide = 0; - if (!uvedit_face_visible_test(scene, ob, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -2006,8 +1991,6 @@ static void UV_OT_seams_from_islands(wmOperatorType *ot) static int uv_mark_seam_exec(bContext *C, wmOperator *op) { - SpaceImage *sima = CTX_wm_space_image(C); - Image *ima = sima ? sima->image : NULL; Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const ToolSettings *ts = scene->toolsettings; @@ -2038,7 +2021,7 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *op) const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - if (uvedit_face_visible_test(scene, ob, ima, efa)) { + if (uvedit_face_visible_test(scene, efa)) { BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_edge_select_test(scene, loop, cd_loop_uv_offset)) { BM_elem_flag_set(loop->e, BM_ELEM_SEAM, flag_set); diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index 6e931b56a85..cc9be9d48c1 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -70,9 +70,11 @@ #include "uvedit_intern.h" -static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action); -static void uv_select_all_perform_multi( - Scene *scene, Image *ima, Object **objects, const uint objects_len, int action); +static void uv_select_all_perform(Scene *scene, Object *obedit, int action); +static void uv_select_all_perform_multi(Scene *scene, + Object **objects, + const uint objects_len, + int action); static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object *obedit, @@ -112,7 +114,7 @@ static void uvedit_vertex_select_tagged(BMEditMesh *em, } } -bool uvedit_face_visible_nolocal_ex(const ToolSettings *ts, BMFace *efa) +bool uvedit_face_visible_test_ex(const ToolSettings *ts, BMFace *efa) { if (ts->uv_flag & UV_SYNC_SELECTION) { return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0); @@ -121,25 +123,9 @@ bool uvedit_face_visible_nolocal_ex(const ToolSettings *ts, BMFace *efa) return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0 && BM_elem_flag_test(efa, BM_ELEM_SELECT)); } } -bool uvedit_face_visible_nolocal(const Scene *scene, BMFace *efa) +bool uvedit_face_visible_test(const Scene *scene, BMFace *efa) { - return uvedit_face_visible_nolocal_ex(scene->toolsettings, efa); -} - -bool uvedit_face_visible_test_ex(const ToolSettings *ts, Object *obedit, Image *ima, BMFace *efa) -{ - if (ts->uv_flag & UV_SHOW_SAME_IMAGE) { - Image *face_image; - ED_object_get_active_image(obedit, efa->mat_nr + 1, &face_image, NULL, NULL, NULL); - return (face_image == ima) ? uvedit_face_visible_nolocal_ex(ts, efa) : false; - } - else { - return uvedit_face_visible_nolocal_ex(ts, efa); - } -} -bool uvedit_face_visible_test(const Scene *scene, Object *obedit, Image *ima, BMFace *efa) -{ - return uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa); + return uvedit_face_visible_test_ex(scene->toolsettings, efa); } bool uvedit_face_select_test_ex(const ToolSettings *ts, BMFace *efa, const int cd_loop_uv_offset) @@ -437,8 +423,7 @@ void uvedit_uv_select_disable(BMEditMesh *em, /** \name Find Nearest Elements * \{ */ -bool uv_find_nearest_edge( - Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit) +bool uv_find_nearest_edge(Scene *scene, Object *obedit, const float co[2], UvNearestHit *hit) { BMEditMesh *em = BKE_editmesh_from_object(obedit); BMFace *efa; @@ -453,7 +438,7 @@ bool uv_find_nearest_edge( BM_mesh_elem_index_ensure(em->bm, BM_VERT); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { @@ -479,7 +464,6 @@ bool uv_find_nearest_edge( } bool uv_find_nearest_edge_multi(Scene *scene, - Image *ima, Object **objects, const uint objects_len, const float co[2], @@ -488,7 +472,7 @@ bool uv_find_nearest_edge_multi(Scene *scene, bool found = false; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; - if (uv_find_nearest_edge(scene, ima, obedit, co, hit_final)) { + if (uv_find_nearest_edge(scene, obedit, co, hit_final)) { hit_final->ob = obedit; found = true; } @@ -496,8 +480,7 @@ bool uv_find_nearest_edge_multi(Scene *scene, return found; } -bool uv_find_nearest_face( - Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit_final) +bool uv_find_nearest_face(Scene *scene, Object *obedit, const float co[2], UvNearestHit *hit_final) { BMEditMesh *em = BKE_editmesh_from_object(obedit); bool found = false; @@ -507,7 +490,7 @@ bool uv_find_nearest_face( /* this will fill in hit.vert1 and hit.vert2 */ float dist_sq_init = hit_final->dist_sq; UvNearestHit hit = *hit_final; - if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) { + if (uv_find_nearest_edge(scene, obedit, co, &hit)) { hit.dist_sq = dist_sq_init; hit.l = NULL; hit.luv = hit.luv_next = NULL; @@ -516,7 +499,7 @@ bool uv_find_nearest_face( BMFace *efa; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -539,7 +522,6 @@ bool uv_find_nearest_face( } bool uv_find_nearest_face_multi(Scene *scene, - Image *ima, Object **objects, const uint objects_len, const float co[2], @@ -548,7 +530,7 @@ bool uv_find_nearest_face_multi(Scene *scene, bool found = false; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; - if (uv_find_nearest_face(scene, ima, obedit, co, hit_final)) { + if (uv_find_nearest_face(scene, obedit, co, hit_final)) { hit_final->ob = obedit; found = true; } @@ -567,7 +549,6 @@ static bool uv_nearest_between(const BMLoop *l, const float co[2], const int cd_ } bool uv_find_nearest_vert(Scene *scene, - Image *ima, Object *obedit, float const co[2], const float penalty_dist, @@ -578,7 +559,7 @@ bool uv_find_nearest_vert(Scene *scene, /* this will fill in hit.vert1 and hit.vert2 */ float dist_sq_init = hit_final->dist_sq; UvNearestHit hit = *hit_final; - if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) { + if (uv_find_nearest_edge(scene, obedit, co, &hit)) { hit.dist_sq = dist_sq_init; hit.l = NULL; @@ -593,7 +574,7 @@ bool uv_find_nearest_vert(Scene *scene, const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -639,7 +620,6 @@ bool uv_find_nearest_vert(Scene *scene, } bool uv_find_nearest_vert_multi(Scene *scene, - Image *ima, Object **objects, const uint objects_len, float const co[2], @@ -649,7 +629,7 @@ bool uv_find_nearest_vert_multi(Scene *scene, bool found = false; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; - if (uv_find_nearest_vert(scene, ima, obedit, co, penalty_dist, hit_final)) { + if (uv_find_nearest_vert(scene, obedit, co, penalty_dist, hit_final)) { hit_final->ob = obedit; found = true; } @@ -657,12 +637,8 @@ bool uv_find_nearest_vert_multi(Scene *scene, return found; } -bool ED_uvedit_nearest_uv(const Scene *scene, - Object *obedit, - Image *ima, - const float co[2], - float *dist_sq, - float r_uv[2]) +bool ED_uvedit_nearest_uv( + const Scene *scene, Object *obedit, const float co[2], float *dist_sq, float r_uv[2]) { BMEditMesh *em = BKE_editmesh_from_object(obedit); BMIter iter; @@ -671,7 +647,7 @@ bool ED_uvedit_nearest_uv(const Scene *scene, float dist_best = *dist_sq; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } BMLoop *l_iter, *l_first; @@ -697,7 +673,6 @@ bool ED_uvedit_nearest_uv(const Scene *scene, } bool ED_uvedit_nearest_uv_multi(const Scene *scene, - Image *ima, Object **objects, const uint objects_len, const float co[2], @@ -707,7 +682,7 @@ bool ED_uvedit_nearest_uv_multi(const Scene *scene, bool found = false; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; - if (ED_uvedit_nearest_uv(scene, obedit, ima, co, dist_sq, r_uv)) { + if (ED_uvedit_nearest_uv(scene, obedit, co, dist_sq, r_uv)) { found = true; } } @@ -817,12 +792,8 @@ static bool uv_select_edgeloop_edge_tag_faces(BMEditMesh *em, return true; } -static int uv_select_edgeloop(Scene *scene, - Image *ima, - Object *obedit, - UvNearestHit *hit, - const float limit[2], - const bool extend) +static int uv_select_edgeloop( + Scene *scene, Object *obedit, UvNearestHit *hit, const float limit[2], const bool extend) { BMEditMesh *em = BKE_editmesh_from_object(obedit); BMFace *efa; @@ -843,7 +814,7 @@ static int uv_select_edgeloop(Scene *scene, BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); if (!extend) { - uv_select_all_perform(scene, ima, obedit, SEL_DESELECT); + uv_select_all_perform(scene, obedit, SEL_DESELECT); } BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); @@ -867,8 +838,7 @@ static int uv_select_edgeloop(Scene *scene, /* find correct valence edges which are not tagged yet, but connect to tagged one */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && - uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && uvedit_face_visible_test(scene, efa)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { /* check face not hidden and not tagged */ if (!(iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l))) { @@ -930,7 +900,6 @@ static int uv_select_edgeloop(Scene *scene, * \{ */ static void uv_select_linked_multi(Scene *scene, - Image *ima, Object **objects, const uint objects_len, const float limit[2], @@ -980,7 +949,7 @@ static void uv_select_linked_multi(Scene *scene, if (hit_final == NULL) { /* Use existing selection */ BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { - if (uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (uvedit_face_visible_test(scene, efa)) { if (select_faces) { if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { stack[stacksize] = a; @@ -1121,14 +1090,15 @@ static void uv_select_linked_multi(Scene *scene, * \warning This returns first selected UV, * not ideal in many cases since there could be multiple. */ -const float *uvedit_first_selected_uv_from_vertex( - Scene *scene, Object *obedit, Image *ima, BMVert *eve, const int cd_loop_uv_offset) +const float *uvedit_first_selected_uv_from_vertex(Scene *scene, + BMVert *eve, + const int cd_loop_uv_offset) { BMIter liter; BMLoop *l; BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) { - if (!uvedit_face_visible_test(scene, obedit, ima, l->f)) { + if (!uvedit_face_visible_test(scene, l->f)) { continue; } @@ -1151,7 +1121,6 @@ static int uv_select_more_less(bContext *C, const bool select) { Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); SpaceImage *sima = CTX_wm_space_image(C); BMFace *efa; @@ -1193,7 +1162,7 @@ static int uv_select_more_less(bContext *C, const bool select) /* mark loops to be selected */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (uvedit_face_visible_test(scene, efa)) { #define IS_SEL 1 #define IS_UNSEL 2 @@ -1233,7 +1202,7 @@ static int uv_select_more_less(bContext *C, const bool select) /* mark loops to be selected */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (uvedit_face_visible_test(scene, efa)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); @@ -1308,7 +1277,7 @@ void UV_OT_select_less(wmOperatorType *ot) /** \name (De)Select All Operator * \{ */ -bool uvedit_select_is_any_selected(Scene *scene, Image *ima, Object *obedit) +bool uvedit_select_is_any_selected(Scene *scene, Object *obedit) { const ToolSettings *ts = scene->toolsettings; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -1323,7 +1292,7 @@ bool uvedit_select_is_any_selected(Scene *scene, Image *ima, Object *obedit) else { const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { @@ -1337,15 +1306,12 @@ bool uvedit_select_is_any_selected(Scene *scene, Image *ima, Object *obedit) return false; } -bool uvedit_select_is_any_selected_multi(Scene *scene, - Image *ima, - Object **objects, - const uint objects_len) +bool uvedit_select_is_any_selected_multi(Scene *scene, Object **objects, const uint objects_len) { bool found = false; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; - if (uvedit_select_is_any_selected(scene, ima, obedit)) { + if (uvedit_select_is_any_selected(scene, obedit)) { found = true; break; } @@ -1353,7 +1319,7 @@ bool uvedit_select_is_any_selected_multi(Scene *scene, return found; } -static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action) +static void uv_select_all_perform(Scene *scene, Object *obedit, int action) { const ToolSettings *ts = scene->toolsettings; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -1365,7 +1331,7 @@ static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); if (action == SEL_TOGGLE) { - action = uvedit_select_is_any_selected(scene, ima, obedit) ? SEL_DESELECT : SEL_SELECT; + action = uvedit_select_is_any_selected(scene, obedit) ? SEL_DESELECT : SEL_SELECT; } if (ts->uv_flag & UV_SYNC_SELECTION) { @@ -1387,7 +1353,7 @@ static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int } else { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -1410,17 +1376,19 @@ static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int } } -static void uv_select_all_perform_multi( - Scene *scene, Image *ima, Object **objects, const uint objects_len, int action) +static void uv_select_all_perform_multi(Scene *scene, + Object **objects, + const uint objects_len, + int action) { if (action == SEL_TOGGLE) { - action = uvedit_select_is_any_selected_multi(scene, ima, objects, objects_len) ? SEL_DESELECT : - SEL_SELECT; + action = uvedit_select_is_any_selected_multi(scene, objects, objects_len) ? SEL_DESELECT : + SEL_SELECT; } for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; - uv_select_all_perform(scene, ima, obedit, action); + uv_select_all_perform(scene, obedit, action); } } @@ -1429,7 +1397,6 @@ static int uv_select_all_exec(bContext *C, wmOperator *op) Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Scene *scene = CTX_data_scene(C); const ToolSettings *ts = scene->toolsettings; - Image *ima = CTX_data_edit_image(C); ViewLayer *view_layer = CTX_data_view_layer(C); int action = RNA_enum_get(op->ptr, "action"); @@ -1438,7 +1405,7 @@ static int uv_select_all_exec(bContext *C, wmOperator *op) Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( view_layer, ((View3D *)NULL), &objects_len); - uv_select_all_perform_multi(scene, ima, objects, objects_len, action); + uv_select_all_perform_multi(scene, objects, objects_len, action); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -1510,7 +1477,6 @@ static int uv_mouse_select_multi(bContext *C, SpaceImage *sima = CTX_wm_space_image(C); Scene *scene = CTX_data_scene(C); const ToolSettings *ts = scene->toolsettings; - Image *ima = CTX_data_edit_image(C); BMFace *efa; BMLoop *l; BMIter iter, liter; @@ -1563,12 +1529,11 @@ static int uv_mouse_select_multi(bContext *C, /* find nearest element */ if (loop) { /* find edge */ - found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit); + found_item = uv_find_nearest_edge_multi(scene, objects, objects_len, co, &hit); } else if (selectmode == UV_SELECT_VERTEX) { /* find vertex */ - found_item = uv_find_nearest_vert_multi( - scene, ima, objects, objects_len, co, penalty_dist, &hit); + found_item = uv_find_nearest_vert_multi(scene, objects, objects_len, co, penalty_dist, &hit); found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); if (found_item) { @@ -1585,7 +1550,7 @@ static int uv_mouse_select_multi(bContext *C, } else if (selectmode == UV_SELECT_EDGE) { /* find edge */ - found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit); + found_item = uv_find_nearest_edge_multi(scene, objects, objects_len, co, &hit); found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); if (found_item) { @@ -1604,7 +1569,7 @@ static int uv_mouse_select_multi(bContext *C, } else if (selectmode == UV_SELECT_FACE) { /* find face */ - found_item = uv_find_nearest_face_multi(scene, ima, objects, objects_len, co, &hit); + found_item = uv_find_nearest_face_multi(scene, objects, objects_len, co, &hit); found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); if (found_item) { @@ -1628,13 +1593,13 @@ static int uv_mouse_select_multi(bContext *C, } } else if (selectmode == UV_SELECT_ISLAND) { - found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit); + found_item = uv_find_nearest_edge_multi(scene, objects, objects_len, co, &hit); found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); } if (!found_item) { if (deselect_all) { - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -1654,19 +1619,18 @@ static int uv_mouse_select_multi(bContext *C, if (loop) { if (!extend) { /* TODO(MULTI_EDIT): We only need to de-select non-active */ - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); } - flush = uv_select_edgeloop(scene, ima, obedit, &hit, limit, extend); + flush = uv_select_edgeloop(scene, obedit, &hit, limit, extend); } else if (selectmode == UV_SELECT_ISLAND) { if (!extend) { /* TODO(MULTI_EDIT): We only need to de-select non-active */ - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); } /* Current behavior of 'extend' * is actually toggling, so pass extend flag as 'toggle' here */ - uv_select_linked_multi( - scene, ima, objects, objects_len, limit, &hit, false, false, extend, false); + uv_select_linked_multi(scene, objects, objects_len, limit, &hit, false, false, extend, false); } else if (extend) { if (selectmode == UV_SELECT_VERTEX) { @@ -1701,7 +1665,7 @@ static int uv_mouse_select_multi(bContext *C, BM_mesh_elem_index_ensure(em->bm, BM_VERT); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -1719,7 +1683,7 @@ static int uv_mouse_select_multi(bContext *C, } else { /* deselect all */ - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); if (selectmode == UV_SELECT_VERTEX) { /* select vertex */ @@ -1739,7 +1703,7 @@ static int uv_mouse_select_multi(bContext *C, /* select sticky uvs */ if (sticky != SI_STICKY_DISABLE) { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -1946,7 +1910,6 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent Scene *scene = CTX_data_scene(C); const ToolSettings *ts = scene->toolsettings; ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); float limit[2]; bool extend = true; bool deselect = false; @@ -1986,18 +1949,17 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent RNA_float_get_array(op->ptr, "location", co); } - if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) { + if (!uv_find_nearest_edge_multi(scene, objects, objects_len, co, &hit)) { MEM_freeN(objects); return OPERATOR_CANCELLED; } } if (!extend) { - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); } uv_select_linked_multi(scene, - ima, objects, objects_len, limit, @@ -2117,7 +2079,6 @@ static int uv_select_split_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const ToolSettings *ts = scene->toolsettings; - Image *ima = CTX_data_edit_image(C); BMFace *efa; BMLoop *l; @@ -2147,7 +2108,7 @@ static int uv_select_split_exec(bContext *C, wmOperator *op) bool is_sel = false; bool is_unsel = false; - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -2483,7 +2444,6 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); const ToolSettings *ts = scene->toolsettings; ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); const ARegion *region = CTX_wm_region(C); BMFace *efa; BMLoop *l; @@ -2518,7 +2478,7 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) view_layer, ((View3D *)NULL), &objects_len); if (use_pre_deselect) { - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); } /* don't indent to avoid diff noise! */ @@ -2539,7 +2499,7 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) /* assume not touched */ BM_elem_flag_disable(efa, BM_ELEM_TAG); - if (uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (uvedit_face_visible_test(scene, efa)) { uv_poly_center(efa, cent, cd_loop_uv_offset); if (BLI_rctf_isect_pt_v(&rectf, cent)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); @@ -2558,7 +2518,7 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -2594,7 +2554,7 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } bool has_selected = false; @@ -2623,7 +2583,7 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) .efa = efa, }; uv_select_linked_multi( - scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); + scene, objects, objects_len, limit, &hit, true, !select, false, false); } } @@ -2708,7 +2668,6 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); SpaceImage *sima = CTX_wm_space_image(C); - Image *ima = CTX_data_edit_image(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const ToolSettings *ts = scene->toolsettings; @@ -2757,7 +2716,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op); if (use_pre_deselect) { - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); } for (uint ob_index = 0; ob_index < objects_len; ob_index++) { @@ -2792,7 +2751,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -2826,7 +2785,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } bool has_selected = false; @@ -2847,7 +2806,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) .efa = efa, }; uv_select_linked_multi( - scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); + scene, objects, objects_len, limit, &hit, true, !select, false, false); } } @@ -2920,7 +2879,6 @@ static bool do_lasso_select_mesh_uv(bContext *C, { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); SpaceImage *sima = CTX_wm_space_image(C); - Image *ima = CTX_data_edit_image(C); const ARegion *region = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); const ToolSettings *ts = scene->toolsettings; @@ -2952,7 +2910,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, view_layer, ((View3D *)NULL), &objects_len); if (use_pre_deselect) { - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); } /* don't indent to avoid diff noise! */ @@ -2988,7 +2946,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -3025,7 +2983,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } bool has_selected = false; @@ -3047,7 +3005,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, .efa = efa, }; uv_select_linked_multi( - scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); + scene, objects, objects_len, limit, &hit, true, !select, false, false); } } @@ -3116,7 +3074,6 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op)) Scene *scene = CTX_data_scene(C); const ToolSettings *ts = scene->toolsettings; ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); BMFace *efa; BMLoop *l; BMIter iter, liter; @@ -3134,7 +3091,7 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op)) bool changed = false; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -3208,7 +3165,6 @@ static int uv_select_overlap(bContext *C, const bool extend) Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( @@ -3224,13 +3180,13 @@ static int uv_select_overlap(bContext *C, const bool extend) BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); if (!extend) { - uv_select_all_perform(scene, ima, obedit, SEL_DESELECT); + uv_select_all_perform(scene, obedit, SEL_DESELECT); } BMIter iter; BMFace *efa; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) { + if (!uvedit_face_visible_test_ex(scene->toolsettings, efa)) { continue; } uv_tri_len += efa->len - 2; @@ -3261,7 +3217,7 @@ static int uv_select_overlap(bContext *C, const bool extend) int face_index; BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, face_index) { - if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) { + if (!uvedit_face_visible_test_ex(scene->toolsettings, efa)) { continue; } diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 3a4f12acf9c..594847b7249 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -2550,12 +2550,11 @@ static StitchState *stitch_select(bContext *C, float co[2]; UvNearestHit hit = UV_NEAREST_HIT_INIT; ARegion *region = CTX_wm_region(C); - Image *ima = CTX_data_edit_image(C); UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); if (ssc->mode == STITCH_VERT) { - if (uv_find_nearest_vert_multi(scene, ima, ssc->objects, ssc->objects_len, co, 0.0f, &hit)) { + if (uv_find_nearest_vert_multi(scene, ssc->objects, ssc->objects_len, co, 0.0f, &hit)) { /* Add vertex to selection, deselect all common uv's of vert other than selected and * update the preview. This behavior was decided so that you can do stuff like deselect * the opposite stitchable vertex and the initial still gets deselected */ @@ -2576,7 +2575,7 @@ static StitchState *stitch_select(bContext *C, return state; } } - else if (uv_find_nearest_edge_multi(scene, ima, ssc->objects, ssc->objects_len, co, &hit)) { + else if (uv_find_nearest_edge_multi(scene, ssc->objects, ssc->objects_len, co, &hit)) { /* find StitchState from hit->ob */ StitchState *state = NULL; for (uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) { diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp index 66195745cbb..253d62ea3dc 100644 --- a/source/blender/freestyle/intern/application/Controller.cpp +++ b/source/blender/freestyle/intern/application/Controller.cpp @@ -923,19 +923,16 @@ Render *Controller::RenderStrokes(Render *re, bool render) cout << "Stroke rendering : " << d << endl; uintptr_t mem_in_use = MEM_get_memory_in_use(); - uintptr_t mmap_in_use = MEM_get_mapped_memory_in_use(); uintptr_t peak_memory = MEM_get_peak_memory(); - float megs_used_memory = (mem_in_use - mmap_in_use) / (1024.0 * 1024.0); - float mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0); + float megs_used_memory = (mem_in_use) / (1024.0 * 1024.0); float megs_peak_memory = (peak_memory) / (1024.0 * 1024.0); - printf("%d objs, %d verts, %d faces, mem %.2fM (%.2fM, peak %.2fM)\n", + printf("%d objs, %d verts, %d faces, mem %.2fM (peak %.2fM)\n", totmesh, freestyle_render->i.totvert, freestyle_render->i.totface, megs_used_memory, - mmap_used_memory, megs_peak_memory); } delete blenderRenderer; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c index 82f9d9a323d..73328d7dd31 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c @@ -170,9 +170,12 @@ static void deformStroke(GpencilModifierData *md, float *noise_table_thickness = (mmd->factor_thickness > 0.0f) ? noise_table(len, seed) : NULL; float *noise_table_uvs = (mmd->factor_uvs > 0.0f) ? noise_table(len, seed + 4) : NULL; - /* calculate stroke normal*/ + /* Calculate stroke normal. */ if (gps->totpoints > 2) { BKE_gpencil_stroke_normal(gps, normal); + if (is_zero_v3(normal)) { + copy_v3_fl(normal, 1.0f); + } } else { copy_v3_fl(normal, 1.0f); diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index e9061f1a029..cef90d57ef5 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -151,7 +151,10 @@ static bool gpu_pbvh_vert_buf_data_set(GPU_PBVH_Buffers *buffers, uint vert_len) /* Initialize vertex buffer (match 'VertexBufferFormat'). */ buffers->vert_buf = GPU_vertbuf_create_with_format_ex(&g_vbo_id.format, GPU_USAGE_STATIC); } - GPU_vertbuf_data_alloc(buffers->vert_buf, vert_len); + if (buffers->vert_buf->data == NULL || buffers->vert_buf->vertex_len != vert_len) { + /* Allocate buffer if not allocated yet or size changed. */ + GPU_vertbuf_data_alloc(buffers->vert_buf, vert_len); + } #endif return buffers->vert_buf->data != NULL; @@ -1083,13 +1086,24 @@ short GPU_pbvh_buffers_material_index_get(GPU_PBVH_Buffers *buffers) return buffers->material_index; } +static void gpu_pbvh_buffers_clear(GPU_PBVH_Buffers *buffers) +{ + GPU_BATCH_DISCARD_SAFE(buffers->lines); + GPU_BATCH_DISCARD_SAFE(buffers->lines_fast); + GPU_BATCH_DISCARD_SAFE(buffers->triangles); + GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); + GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf); +} + void GPU_pbvh_buffers_update_flush(GPU_PBVH_Buffers *buffers) { /* Free empty bmesh node buffers. */ if (buffers->clear_bmesh_on_flush) { - GPU_BATCH_DISCARD_SAFE(buffers->triangles); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); - GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf); + gpu_pbvh_buffers_clear(buffers); buffers->clear_bmesh_on_flush = false; } @@ -1102,16 +1116,7 @@ void GPU_pbvh_buffers_update_flush(GPU_PBVH_Buffers *buffers) void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers) { if (buffers) { - GPU_BATCH_DISCARD_SAFE(buffers->lines); - GPU_BATCH_DISCARD_SAFE(buffers->lines_fast); - GPU_BATCH_DISCARD_SAFE(buffers->triangles); - GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); - GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf); - + gpu_pbvh_buffers_clear(buffers); MEM_freeN(buffers); } } diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 2a8a4d416d8..7871907a7d4 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -905,7 +905,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, ImBuf *ibuf, bindcode = gpu_texture_create_tile_array(ima, ibuf_intern); } else if (textarget == GL_TEXTURE_1D_ARRAY) { - bindcode = gpu_texture_create_tile_mapping(ima, iuser->multiview_eye); + bindcode = gpu_texture_create_tile_mapping(ima, iuser ? iuser->multiview_eye : 0); } else { bindcode = gpu_texture_create_from_ibuf(ima, ibuf_intern, textarget); diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index e3632b82778..ff745787630 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -304,6 +304,14 @@ void gpu_extensions_init(void) GG.context_local_shaders_workaround = GLEW_ARB_get_program_binary; } + /* Special fix for theses specific GPUs. Without thoses workaround, blender crashes on strartup. + * (see T72098) */ + if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) && + (strstr(renderer, "HD Graphics 620") || strstr(renderer, "HD Graphics 630"))) { + GG.mip_render_workaround = true; + GG.context_local_shaders_workaround = GLEW_ARB_get_program_binary; + } + /* df/dy calculation factors, those are dependent on driver */ GG.dfdyfactors[0] = 1.0; GG.dfdyfactors[1] = 1.0; diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c index 1caa88d18ae..3218d12bc0d 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.c +++ b/source/blender/gpu/intern/gpu_shader_interface.c @@ -261,7 +261,9 @@ GPUShaderInterface *GPU_shaderinterface_create(int32_t program) continue; } - shaderface->enabled_attr_mask |= (1 << input->location); + if (input->location != -1) { + shaderface->enabled_attr_mask |= (1 << input->location); + } set_input_name(shaderface, input, name, name_len); diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 1639fb4715f..3158e3419b0 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -56,6 +56,7 @@ void IMB_colormanagement_validate_settings( const char *IMB_colormanagement_role_colorspace_name_get(int role); void IMB_colormanagement_check_is_data(struct ImBuf *ibuf, const char *name); +void IMB_colormanagegent_copy_settings(struct ImBuf *ibuf_src, struct ImBuf *ibuf_dst); void IMB_colormanagement_assign_float_colorspace(struct ImBuf *ibuf, const char *name); void IMB_colormanagement_assign_rect_colorspace(struct ImBuf *ibuf, const char *name); diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index 6c17254e697..4b3858e6d5a 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -380,7 +380,7 @@ void *imb_alloc_pixels( } size_t size = (size_t)x * (size_t)y * (size_t)channels * typesize; - return MEM_mapallocN(size, name); + return MEM_callocN(size, name); } bool imb_addrectfloatImBuf(ImBuf *ibuf) diff --git a/source/blender/imbuf/intern/cache.c b/source/blender/imbuf/intern/cache.c index 176b41d2706..23ce9bd7818 100644 --- a/source/blender/imbuf/intern/cache.c +++ b/source/blender/imbuf/intern/cache.c @@ -427,8 +427,8 @@ void IMB_tiles_to_rect(ImBuf *ibuf) /* don't call imb_addrectImBuf, it frees all mipmaps */ if (!mipbuf->rect) { - if ((mipbuf->rect = MEM_mapallocN(ibuf->x * ibuf->y * sizeof(unsigned int), - "imb_addrectImBuf"))) { + if ((mipbuf->rect = MEM_callocN(ibuf->x * ibuf->y * sizeof(unsigned int), + "imb_addrectImBuf"))) { mipbuf->mall |= IB_rect; mipbuf->flags |= IB_rect; } diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index c57ab70f4e6..3f5a0f25cc5 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1349,6 +1349,23 @@ void IMB_colormanagement_check_is_data(ImBuf *ibuf, const char *name) } } +void IMB_colormanagegent_copy_settings(ImBuf *ibuf_src, ImBuf *ibuf_dst) +{ + IMB_colormanagement_assign_rect_colorspace(ibuf_dst, + IMB_colormanagement_get_rect_colorspace(ibuf_src)); + IMB_colormanagement_assign_float_colorspace(ibuf_dst, + IMB_colormanagement_get_float_colorspace(ibuf_src)); + if (ibuf_src->flags & IB_alphamode_premul) { + ibuf_dst->flags |= IB_alphamode_premul; + } + else if (ibuf_src->flags & IB_alphamode_channel_packed) { + ibuf_dst->flags |= IB_alphamode_channel_packed; + } + else if (ibuf_src->flags & IB_alphamode_ignore) { + ibuf_dst->flags |= IB_alphamode_ignore; + } +} + void IMB_colormanagement_assign_float_colorspace(ImBuf *ibuf, const char *name) { ColorSpace *colorspace = colormanage_colorspace_get_named(name); diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index e068a84aab0..bcc8488089d 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -788,7 +788,7 @@ void IMB_float_from_rect(ImBuf *ibuf) size = size * 4 * sizeof(float); ibuf->channels = 4; - rect_float = MEM_mapallocN(size, "IMB_float_from_rect"); + rect_float = MEM_callocN(size, "IMB_float_from_rect"); if (rect_float == NULL) { return; diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 62cc2e605e5..882808cbc14 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -1598,8 +1598,8 @@ static ExrHandle *imb_exr_begin_read_mem(IStream &file_stream, for (lay = (ExrLayer *)data->layers.first; lay; lay = lay->next) { for (pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) { if (pass->totchan) { - pass->rect = (float *)MEM_mapallocN(width * height * pass->totchan * sizeof(float), - "pass rect"); + pass->rect = (float *)MEM_callocN(width * height * pass->totchan * sizeof(float), + "pass rect"); if (pass->totchan == 1) { echan = pass->chan[0]; echan->rect = pass->rect; diff --git a/source/blender/io/alembic/intern/abc_reader_nurbs.cc b/source/blender/io/alembic/intern/abc_reader_nurbs.cc index 10d9a35a8e1..5b9954b3ff6 100644 --- a/source/blender/io/alembic/intern/abc_reader_nurbs.cc +++ b/source/blender/io/alembic/intern/abc_reader_nurbs.cc @@ -71,7 +71,7 @@ bool AbcNurbsReader::valid() const static bool set_knots(const FloatArraySamplePtr &knots, float *&nu_knots) { - if (!knots || knots->size() == 0) { + if (!knots || knots->size() < 2) { return false; } diff --git a/source/blender/io/avi/intern/avi_mjpeg.c b/source/blender/io/avi/intern/avi_mjpeg.c index ac622d8b0e4..70ddca28060 100644 --- a/source/blender/io/avi/intern/avi_mjpeg.c +++ b/source/blender/io/avi/intern/avi_mjpeg.c @@ -30,6 +30,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_math_base.h" #include "IMB_imbuf.h" #include "jerror.h" @@ -45,14 +46,16 @@ static size_t numbytes; static void add_huff_table(j_decompress_ptr dinfo, JHUFF_TBL **htblptr, const UINT8 *bits, - const UINT8 *val) + const size_t bits_size, + const UINT8 *val, + const size_t val_size) { if (*htblptr == NULL) { *htblptr = jpeg_alloc_huff_table((j_common_ptr)dinfo); } - memcpy((*htblptr)->bits, bits, sizeof((*htblptr)->bits)); - memcpy((*htblptr)->huffval, val, sizeof((*htblptr)->huffval)); + memcpy((*htblptr)->bits, bits, min_zz(sizeof((*htblptr)->bits), bits_size)); + memcpy((*htblptr)->huffval, val, min_zz(sizeof((*htblptr)->huffval), val_size)); /* Initialize sent_table false so table will be written to JPEG file. */ (*htblptr)->sent_table = false; @@ -200,10 +203,30 @@ static void std_huff_tables(j_decompress_ptr dinfo) 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, }; - add_huff_table(dinfo, &dinfo->dc_huff_tbl_ptrs[0], bits_dc_luminance, val_dc_luminance); - add_huff_table(dinfo, &dinfo->ac_huff_tbl_ptrs[0], bits_ac_luminance, val_ac_luminance); - add_huff_table(dinfo, &dinfo->dc_huff_tbl_ptrs[1], bits_dc_chrominance, val_dc_chrominance); - add_huff_table(dinfo, &dinfo->ac_huff_tbl_ptrs[1], bits_ac_chrominance, val_ac_chrominance); + add_huff_table(dinfo, + &dinfo->dc_huff_tbl_ptrs[0], + bits_dc_luminance, + sizeof(bits_dc_luminance), + val_dc_luminance, + sizeof(val_dc_luminance)); + add_huff_table(dinfo, + &dinfo->ac_huff_tbl_ptrs[0], + bits_ac_luminance, + sizeof(bits_ac_luminance), + val_ac_luminance, + sizeof(val_ac_luminance)); + add_huff_table(dinfo, + &dinfo->dc_huff_tbl_ptrs[1], + bits_dc_chrominance, + sizeof(bits_dc_chrominance), + val_dc_chrominance, + sizeof(val_dc_chrominance)); + add_huff_table(dinfo, + &dinfo->ac_huff_tbl_ptrs[1], + bits_ac_chrominance, + sizeof(bits_ac_chrominance), + val_ac_chrominance, + sizeof(val_ac_chrominance)); } static int Decode_JPEG(unsigned char *inBuffer, diff --git a/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc b/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc index e382fa6bb1d..ab83ea2c3c4 100644 --- a/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc +++ b/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc @@ -53,7 +53,7 @@ bool HierarchyContext::operator<(const HierarchyContext &other) const if (object != other.object) { return object < other.object; } - if (duplicator != NULL && duplicator == other.duplicator) { + if (duplicator != nullptr && duplicator == other.duplicator) { // Only resort to string comparisons when both objects are created by the same duplicator. return export_name < other.export_name; } diff --git a/source/blender/io/usd/intern/usd_capi.cc b/source/blender/io/usd/intern/usd_capi.cc index f8e0a03abfa..890e2fd205f 100644 --- a/source/blender/io/usd/intern/usd_capi.cc +++ b/source/blender/io/usd/intern/usd_capi.cc @@ -185,7 +185,7 @@ bool USD_export(bContext *C, /* setup job */ WM_jobs_customdata_set(wm_job, job, MEM_freeN); WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME); - WM_jobs_callbacks(wm_job, USD::export_startjob, NULL, NULL, USD::export_endjob); + WM_jobs_callbacks(wm_job, USD::export_startjob, nullptr, nullptr, USD::export_endjob); WM_jobs_start(CTX_wm_manager(C), wm_job); } diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index 909869d2af1..841501bcf42 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -79,7 +79,7 @@ void USDGenericMeshWriter::do_write(HierarchyContext &context) bool needsfree = false; Mesh *mesh = get_export_mesh(object_eval, needsfree); - if (mesh == NULL) { + if (mesh == nullptr) { return; } @@ -100,7 +100,7 @@ void USDGenericMeshWriter::do_write(HierarchyContext &context) void USDGenericMeshWriter::free_export_mesh(Mesh *mesh) { - BKE_id_free(NULL, mesh); + BKE_id_free(nullptr, mesh); } struct USDMeshData { diff --git a/source/blender/io/usd/intern/usd_writer_transform.cc b/source/blender/io/usd/intern/usd_writer_transform.cc index 038f2b17b1a..0694d873002 100644 --- a/source/blender/io/usd/intern/usd_writer_transform.cc +++ b/source/blender/io/usd/intern/usd_writer_transform.cc @@ -50,7 +50,7 @@ void USDTransformWriter::do_write(HierarchyContext &context) bool USDTransformWriter::check_is_animated(const HierarchyContext &context) const { - if (context.duplicator != NULL) { + if (context.duplicator != nullptr) { /* This object is being duplicated, so could be emitted by a particle system and thus * influenced by forces. TODO(Sybren): Make this more strict. Probably better to get from the * depsgraph whether this object instance has a time source. */ diff --git a/source/blender/makesdna/DNA_fluid_types.h b/source/blender/makesdna/DNA_fluid_types.h index 6583aa2eeee..7da33a369f3 100644 --- a/source/blender/makesdna/DNA_fluid_types.h +++ b/source/blender/makesdna/DNA_fluid_types.h @@ -215,39 +215,54 @@ enum { #define FLUID_DOMAIN_SMOKE_SCRIPT "smoke_script.py" #define FLUID_DOMAIN_LIQUID_SCRIPT "liquid_script.py" -#define FLUID_DOMAIN_FILE_CONFIG "config_####" - -#define FLUID_DOMAIN_FILE_DENSITY "density_####" -#define FLUID_DOMAIN_FILE_SHADOW "shadow_####" -#define FLUID_DOMAIN_FILE_VEL "vel_####" -#define FLUID_DOMAIN_FILE_HEAT "heat_####" -#define FLUID_DOMAIN_FILE_COLORR "color_r_####" -#define FLUID_DOMAIN_FILE_COLORG "color_g_####" -#define FLUID_DOMAIN_FILE_COLORB "color_b_####" -#define FLUID_DOMAIN_FILE_FLAME "flame_####" -#define FLUID_DOMAIN_FILE_FUEL "fuel_####" -#define FLUID_DOMAIN_FILE_REACT "react_####" - -#define FLUID_DOMAIN_FILE_PHI "phi_####" -#define FLUID_DOMAIN_FILE_PP "pp_####" -#define FLUID_DOMAIN_FILE_PVEL "pVel_####" - -#define FLUID_DOMAIN_FILE_DENSITYNOISE "density_noise_####" -#define FLUID_DOMAIN_FILE_COLORRNOISE "color_r_noise_####" -#define FLUID_DOMAIN_FILE_COLORGNOISE "color_g_noise_####" -#define FLUID_DOMAIN_FILE_COLORBNOISE "color_b_noise_####" -#define FLUID_DOMAIN_FILE_FLAMENOISE "flame_noise_####" -#define FLUID_DOMAIN_FILE_FUELNOISE "fuel_noise_####" -#define FLUID_DOMAIN_FILE_REACTNOISE "react_noise_####" - -#define FLUID_DOMAIN_FILE_MESH "lMesh_####" -#define FLUID_DOMAIN_FILE_MESHVEL "lVelMesh_####" - -#define FLUID_DOMAIN_FILE_PPSND "ppSnd_####" -#define FLUID_DOMAIN_FILE_PVELSND "pVelSnd_####" -#define FLUID_DOMAIN_FILE_PLIFESND "pLifeSnd_####" - -#define FLUID_DOMAIN_FILE_GUIDEVEL "guidevel_####" +#define FLUID_FILENAME_CONFIG "config_####" + +#define FLUID_FILENAME_DATA "fluid_data_####" +#define FLUID_FILENAME_NOISE "fluid_noise_####" +#define FLUID_FILENAME_DENSITY "density_####" +#define FLUID_FILENAME_SHADOW "shadow_####" +#define FLUID_FILENAME_VELOCITY "vel_####" +#define FLUID_FILENAME_HEAT "heat_####" +#define FLUID_FILENAME_COLORR "color_r_####" +#define FLUID_FILENAME_COLORG "color_g_####" +#define FLUID_FILENAME_COLORB "color_b_####" +#define FLUID_FILENAME_FLAME "flame_####" +#define FLUID_FILENAME_FUEL "fuel_####" +#define FLUID_FILENAME_REACT "react_####" +#define FLUID_FILENAME_PHI "phi_####" +#define FLUID_FILENAME_PP "pp_####" +#define FLUID_FILENAME_PVEL "pVel_####" +#define FLUID_FILENAME_DENSITYNOISE "density_noise_####" +#define FLUID_FILENAME_COLORRNOISE "color_r_noise_####" +#define FLUID_FILENAME_COLORGNOISE "color_g_noise_####" +#define FLUID_FILENAME_COLORBNOISE "color_b_noise_####" +#define FLUID_FILENAME_FLAMENOISE "flame_noise_####" +#define FLUID_FILENAME_FUELNOISE "fuel_noise_####" +#define FLUID_FILENAME_REACTNOISE "react_noise_####" +#define FLUID_FILENAME_MESH "lMesh_####" +#define FLUID_FILENAME_MESHVEL "lVelMesh_####" +#define FLUID_FILENAME_PPSND "ppSnd_####" +#define FLUID_FILENAME_PVELSND "pVelSnd_####" +#define FLUID_FILENAME_PLIFESND "pLifeSnd_####" +#define FLUID_FILENAME_GUIDEVEL "guidevel_####" + +#define FLUID_GRIDNAME_DENSITY "density" +#define FLUID_GRIDNAME_SHADOW "shadow" +#define FLUID_GRIDNAME_VELOCITY "velocity" +#define FLUID_GRIDNAME_HEAT "heat" +#define FLUID_GRIDNAME_COLORR "color_r" +#define FLUID_GRIDNAME_COLORG "color_g" +#define FLUID_GRIDNAME_COLORB "color_b" +#define FLUID_GRIDNAME_FLAME "flame" +#define FLUID_GRIDNAME_FUEL "fuel" +#define FLUID_GRIDNAME_REACT "react" +#define FLUID_GRIDNAME_DENSITYNOISE "density_noise" +#define FLUID_GRIDNAME_COLORRNOISE "color_r_noise" +#define FLUID_GRIDNAME_COLORGNOISE "color_g_noise" +#define FLUID_GRIDNAME_COLORBNOISE "color_b_noise" +#define FLUID_GRIDNAME_FLAMENOISE "flame_noise" +#define FLUID_GRIDNAME_FUELNOISE "fuel_noise" +#define FLUID_GRIDNAME_REACTNOISE "react_noise" #define FLUID_DOMAIN_EXTENSION_UNI ".uni" #define FLUID_DOMAIN_EXTENSION_OPENVDB ".vdb" @@ -256,6 +271,17 @@ enum { #define FLUID_DOMAIN_EXTENSION_BINOBJ ".bobj.gz" enum { + FLUID_DOMAIN_GRID_FLOAT = 0, + FLUID_DOMAIN_GRID_INT = 1, + FLUID_DOMAIN_GRID_VEC3F = 2, +}; + +enum { + FLUID_DOMAIN_CACHE_FILES_SINGLE = 0, + FLUID_DOMAIN_CACHE_FILES_COMBINED = 1, +}; + +enum { FLUID_DOMAIN_CACHE_REPLAY = 0, FLUID_DOMAIN_CACHE_MODULAR = 1, FLUID_DOMAIN_CACHE_FINAL = 2, diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 1533b82ad4e..8c34a7cb0a1 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -555,13 +555,14 @@ typedef struct BakeData { short margin, flag; float cage_extrusion; + float max_ray_distance; int pass_filter; char normal_swizzle[3]; char normal_space; char save_mode; - char _pad[3]; + char _pad[7]; struct Object *cage_object; } BakeData; diff --git a/source/blender/makesdna/DNA_view3d_defaults.h b/source/blender/makesdna/DNA_view3d_defaults.h index afade37d0c8..20b491c47f2 100644 --- a/source/blender/makesdna/DNA_view3d_defaults.h +++ b/source/blender/makesdna/DNA_view3d_defaults.h @@ -65,7 +65,7 @@ V3D_OVERLAY_EDIT_SHARP | V3D_OVERLAY_EDIT_FREESTYLE_EDGE | \ V3D_OVERLAY_EDIT_FREESTYLE_FACE | V3D_OVERLAY_EDIT_EDGES | \ V3D_OVERLAY_EDIT_CREASES | V3D_OVERLAY_EDIT_BWEIGHTS | \ - V3D_OVERLAY_EDIT_CU_HANDLES | V3D_OVERLAY_EDIT_CU_NORMALS, \ + V3D_OVERLAY_EDIT_CU_HANDLES, \ \ .gpencil_paper_opacity = 0.5f, \ .gpencil_grid_opacity = 0.9f, \ diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt index 1b0bf086269..01e3971a216 100644 --- a/source/blender/makesdna/intern/CMakeLists.txt +++ b/source/blender/makesdna/intern/CMakeLists.txt @@ -58,6 +58,10 @@ setup_platform_linker_flags() add_executable(makesdna ${SRC} ${SRC_DNA_INC}) +if(WIN32 AND NOT UNIX) + target_link_libraries(makesdna ${PTHREADS_LIBRARIES}) +endif() + # Output dna.c add_custom_command( OUTPUT diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index cd05aba8794..024bdbe5ed5 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -394,6 +394,10 @@ add_executable(makesrna ${SRC} ${SRC_RNA_INC} ${SRC_DNA_INC}) target_link_libraries(makesrna bf_dna) target_link_libraries(makesrna bf_dna_blenlib) +if(WIN32 AND NOT UNIX) + target_link_libraries(makesrna ${PTHREADS_LIBRARIES}) +endif() + # Output rna_*_gen.c # note (linux only): with crashes try add this after COMMAND: valgrind --leak-check=full --track-origins=yes add_custom_command( diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 86a088f38ed..5506bfaaaf0 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -1823,6 +1823,10 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) case PROP_ENUM: { EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop; + if (!eprop->get && !eprop->set) { + rna_set_raw_property(dp, prop); + } + eprop->get = (void *)rna_def_property_get_func(f, srna, prop, dp, (const char *)eprop->get); eprop->set = (void *)rna_def_property_set_func(f, srna, prop, dp, (const char *)eprop->set); break; diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 85892758a88..f14e81a38df 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -4386,8 +4386,8 @@ static int rna_raw_access(ReportList *reports, /* check type */ itemtype = RNA_property_type(itemprop); - if (!ELEM(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) { - BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported"); + if (!ELEM(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT, PROP_ENUM)) { + BKE_report(reports, RPT_ERROR, "Only boolean, int float and enum properties supported"); return 0; } diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index a3a89db66be..facbf8d59cc 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -345,14 +345,14 @@ static void rna_def_dopesheet(BlenderRNA *brna) prop = RNA_def_property(srna, "show_only_selected", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_ONLYSEL); RNA_def_property_ui_text( - prop, "Only Selected", "Only include channels relating to selected objects and data"); + prop, "Only Show Selected", "Only include channels relating to selected objects and data"); RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_hidden", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_INCL_HIDDEN); RNA_def_property_ui_text( - prop, "Display Hidden", "Include channels from objects/bone that are not visible"); + prop, "Show Hidden", "Include channels from objects/bone that are not visible"); RNA_def_property_ui_icon(prop, ICON_OBJECT_HIDDEN, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); @@ -368,8 +368,9 @@ static void rna_def_dopesheet(BlenderRNA *brna) /* Debug Filtering Settings */ prop = RNA_def_property(srna, "show_only_errors", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_ONLY_ERRORS); - RNA_def_property_ui_text( - prop, "Show Errors", "Only include F-Curves and drivers that are disabled or have errors"); + RNA_def_property_ui_text(prop, + "Only Show Errors", + "Only include F-Curves and drivers that are disabled or have errors"); RNA_def_property_ui_icon(prop, ICON_ERROR, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 3afbd0405fe..cd7875d84e3 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -176,6 +176,20 @@ static void rna_Armature_redraw_data(Main *UNUSED(bmain), Scene *UNUSED(scene), WM_main_add_notifier(NC_GEOM | ND_DATA, id); } +/* Unselect bones when hidden */ +static void rna_Bone_hide_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + bArmature *arm = (bArmature *)ptr->owner_id; + Bone *bone = (Bone *)ptr->data; + + if (bone->flag & BONE_HIDDEN_P) { + bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + + WM_main_add_notifier(NC_OBJECT | ND_POSE, arm); + DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE); +} + /* called whenever a bone is renamed */ static void rna_Bone_update_renamed(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { @@ -301,8 +315,7 @@ static void rna_Bone_layer_set(PointerRNA *ptr, const bool *values) Bone *bone = (Bone *)ptr->data; rna_bone_layer_set(&bone->layer, values); - - BKE_armature_refresh_layer_used(arm); + BKE_armature_refresh_layer_used(NULL, arm); } /* TODO: remove the deprecation stubs. */ @@ -1144,7 +1157,8 @@ static void rna_def_bone(BlenderRNA *brna) prop, "Hide", "Bone is not visible when it is not in Edit Mode (i.e. in Object or Pose Modes)"); - RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1); + RNA_def_property_update(prop, 0, "rna_Bone_hide_update"); prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_SELECTED); diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index fff39326ada..93c7c1f3480 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -1725,7 +1725,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "resolution of the domain). For best meshing, it is recommended to " "adjust the mesh particle radius alongside this value"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_meshcache_reset"); prop = RNA_def_property(srna, "mesh_generator", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mesh_generator"); @@ -1754,7 +1754,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Caches velocities of mesh vertices. These will be used " "(automatically) when rendering with motion blur enabled"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_meshcache_reset"); prop = RNA_def_property(srna, "mesh_particle_radius", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 10.0); @@ -2516,7 +2516,7 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "use_inflow", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_USE_INFLOW); - RNA_def_property_ui_text(prop, "Enabled", "Control when to apply inflow"); + RNA_def_property_ui_text(prop, "Use Flow", "Control when to apply fluid flow"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "subframes", PROP_INT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 33bf174be79..5f1ff0d8745 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -1187,7 +1187,6 @@ static void rna_def_gpencil_stroke(BlenderRNA *brna) * (this is a special flag for fill brush). */ prop = RNA_def_property(srna, "is_nofill_stroke", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STROKE_NOFILL); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "No Fill", "Special stroke to use as boundary for filling areas"); RNA_def_property_update(prop, 0, "rna_GPencil_update"); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 30d1380417f..32999c91fad 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -960,12 +960,11 @@ static bool rna_NodeTree_check(bNodeTree *ntree, ReportList *reports) static void rna_NodeTree_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { bNodeTree *ntree = (bNodeTree *)ptr->owner_id; - bNode *node = (bNode *)ptr->data; WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); WM_main_add_notifier(NC_SCENE | ND_NODES, &ntree->id); - ED_node_tag_update_nodetree(bmain, ntree, node); + ED_node_tag_update_nodetree(bmain, ntree, NULL); } static bNode *rna_NodeTree_node_new(bNodeTree *ntree, diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index c2ee256ad58..a27d77df32a 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -2890,6 +2890,7 @@ static void rna_def_object(BlenderRNA *brna) prop = RNA_def_property(srna, "matrix_parent_inverse", PROP_FLOAT, PROP_MATRIX); RNA_def_property_float_sdna(prop, NULL, "parentinv"); RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Parent Inverse Matrix", "Inverse of object's parent matrix at time of parenting"); RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update"); diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 17e5f3d3649..8f28fc56712 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -295,6 +295,18 @@ static void rna_PoseChannel_name_set(PointerRNA *ptr, const char *value) ED_armature_bone_rename(G_MAIN, ob->data, oldname, newname); } +/* See rna_Bone_update_renamed() */ +static void rna_PoseChannel_name_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + ID *id = ptr->owner_id; + + /* redraw view */ + WM_main_add_notifier(NC_GEOM | ND_DATA, id); + + /* update animation channels */ + WM_main_add_notifier(NC_ANIMATION | ND_ANIMCHAN, id); +} + static PointerRNA rna_PoseChannel_bone_get(PointerRNA *ptr) { Object *ob = (Object *)ptr->owner_id; @@ -996,6 +1008,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Name", ""); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_struct_name_property(srna, prop); + RNA_def_property_update(prop, 0, "rna_PoseChannel_name_update"); /* Baked Bone Path cache data */ rna_def_motionpath_common(srna); diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 8322c7ad5f4..6c21e4ad01b 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -181,11 +181,8 @@ static void engine_bake(RenderEngine *engine, struct Object *object, const int pass_type, const int pass_filter, - const int object_id, - const struct BakePixel *pixel_array, - const int num_pixels, - const int depth, - void *result) + const int width, + const int height) { extern FunctionRNA rna_RenderEngine_bake_func; PointerRNA ptr; @@ -200,11 +197,8 @@ static void engine_bake(RenderEngine *engine, RNA_parameter_set_lookup(&list, "object", &object); RNA_parameter_set_lookup(&list, "pass_type", &pass_type); RNA_parameter_set_lookup(&list, "pass_filter", &pass_filter); - RNA_parameter_set_lookup(&list, "object_id", &object_id); - RNA_parameter_set_lookup(&list, "pixel_array", &pixel_array); - RNA_parameter_set_lookup(&list, "num_pixels", &num_pixels); - RNA_parameter_set_lookup(&list, "depth", &depth); - RNA_parameter_set_lookup(&list, "result", &result); + RNA_parameter_set_lookup(&list, "width", &width); + RNA_parameter_set_lookup(&list, "height", &height); engine->type->rna_ext.call(NULL, &ptr, func, &list); RNA_parameter_list_free(&list); @@ -461,12 +455,6 @@ void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values) memcpy(rpass->rect, values, sizeof(float) * rpass->rectx * rpass->recty * rpass->channels); } -static PointerRNA rna_BakePixel_next_get(PointerRNA *ptr) -{ - BakePixel *bp = ptr->data; - return rna_pointer_inherit_refine(ptr, &RNA_BakePixel, bp + 1); -} - static RenderPass *rna_RenderPass_find_by_type(RenderLayer *rl, int passtype, const char *view) { return RE_pass_find_by_type(rl, passtype, view); @@ -535,33 +523,9 @@ static void rna_def_render_engine(BlenderRNA *brna) 0, INT_MAX); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - parm = RNA_def_int(func, - "object_id", - 0, - 0, - INT_MAX, - "Object Id", - "Id of the current object being baked in relation to the others", - 0, - INT_MAX); - RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - parm = RNA_def_pointer(func, "pixel_array", "BakePixel", "", ""); - RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - parm = RNA_def_int(func, - "num_pixels", - 0, - 0, - INT_MAX, - "Number of Pixels", - "Size of the baking batch", - 0, - INT_MAX); - RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - parm = RNA_def_int( - func, "depth", 0, 0, INT_MAX, "Pixels depth", "Number of channels", 1, INT_MAX); + parm = RNA_def_int(func, "width", 0, 0, INT_MAX, "Width", "Image width", 0, INT_MAX); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - /* TODO, see how array size of 0 works, this shouldnt be used */ - parm = RNA_def_pointer(func, "result", "AnyType", "", ""); + parm = RNA_def_int(func, "height", 0, 0, INT_MAX, "Height", "Image height", 0, INT_MAX); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); /* viewport render callbacks */ @@ -1119,53 +1083,6 @@ static void rna_def_render_pass(BlenderRNA *brna) RNA_define_verify_sdna(1); } -static void rna_def_render_bake_pixel(BlenderRNA *brna) -{ - StructRNA *srna; - PropertyRNA *prop; - - srna = RNA_def_struct(brna, "BakePixel", NULL); - RNA_def_struct_ui_text(srna, "Bake Pixel", ""); - - RNA_define_verify_sdna(0); - - prop = RNA_def_property(srna, "primitive_id", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "primitive_id"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - - prop = RNA_def_property(srna, "object_id", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "object_id"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - - prop = RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE); - RNA_def_property_array(prop, 2); - RNA_def_property_float_sdna(prop, NULL, "uv"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - - prop = RNA_def_property(srna, "du_dx", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "du_dx"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - - prop = RNA_def_property(srna, "du_dy", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "du_dy"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - - prop = RNA_def_property(srna, "dv_dx", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "dv_dx"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - - prop = RNA_def_property(srna, "dv_dy", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "dv_dy"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - - prop = RNA_def_property(srna, "next", PROP_POINTER, PROP_NONE); - RNA_def_property_struct_type(prop, "BakePixel"); - RNA_def_property_pointer_funcs(prop, "rna_BakePixel_next_get", NULL, NULL, NULL); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - - RNA_define_verify_sdna(1); -} - void RNA_def_render(BlenderRNA *brna) { rna_def_render_engine(brna); @@ -1173,7 +1090,6 @@ void RNA_def_render(BlenderRNA *brna) rna_def_render_view(brna); rna_def_render_layer(brna); rna_def_render_pass(brna); - rna_def_render_bake_pixel(brna); } #endif /* RNA_RUNTIME */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 6423175e2f4..e3d779ce7fb 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -3374,14 +3374,15 @@ static void rna_def_tool_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "use_keyframe_insert_auto", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "autokey_mode", AUTOKEY_ON); RNA_def_property_ui_text( - prop, "Auto Keying", "Automatic keyframe insertion for Objects and Bones"); + prop, "Auto Keying", "Automatic keyframe insertion for Objects, Bones and Masks"); RNA_def_property_ui_icon(prop, ICON_REC, 0); prop = RNA_def_property(srna, "auto_keying_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "autokey_mode"); RNA_def_property_enum_items(prop, auto_key_items); - RNA_def_property_ui_text( - prop, "Auto-Keying Mode", "Mode of automatic keyframe insertion for Objects and Bones"); + RNA_def_property_ui_text(prop, + "Auto-Keying Mode", + "Mode of automatic keyframe insertion for Objects, Bones and Masks"); prop = RNA_def_property(srna, "use_record_with_nla", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "autokey_flag", ANIMRECORD_FLAG_WITHNLA); @@ -4884,13 +4885,23 @@ static void rna_def_bake_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Margin", "Extends the baked result as a post process filter"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + prop = RNA_def_property(srna, "max_ray_distance", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_range(prop, 0.0, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 3); + RNA_def_property_ui_text(prop, + "Max Ray Distance", + "The maximum ray distance for matching points between the active and " + "selected objects. If zero, there is no limit"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + prop = RNA_def_property(srna, "cage_extrusion", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_range(prop, 0.0, FLT_MAX); RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 3); RNA_def_property_ui_text( prop, "Cage Extrusion", - "Distance to use for the inward ray cast when using selected to active"); + "Inflate the active object by the specified distance for baking. This helps matching to " + "points nearer to the outside of the selected object meshes"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "normal_space", PROP_ENUM, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index 46b8d8647de..9184c54ae88 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -1565,7 +1565,11 @@ static void rna_def_texture(BlenderRNA *brna) prop = RNA_def_property(srna, "use_color_ramp", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", TEX_COLORBAND); RNA_def_property_boolean_funcs(prop, NULL, "rna_Texture_use_color_ramp_set"); - RNA_def_property_ui_text(prop, "Use Color Ramp", "Toggle color ramp operations"); + RNA_def_property_ui_text(prop, + "Use Color Ramp", + "Map the texture intensity to the color ramp. " + "Note that the alpha value is used for image textures, " + "enable \"Calculate Alpha\" for images without an alpha channel"); RNA_def_property_update(prop, 0, "rna_Texture_update"); prop = RNA_def_property(srna, "color_ramp", PROP_POINTER, PROP_NEVER_NULL); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 00d3189dcbe..aa138517209 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -5798,8 +5798,9 @@ static void rna_def_userdef_input(BlenderRNA *brna) prop = RNA_def_property(srna, "ndof_fly_helicopter", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_FLY_HELICOPTER); - RNA_def_property_ui_text( - prop, "Helicopter Mode", "Device up/down directly controls your Z position"); + RNA_def_property_ui_text(prop, + "Helicopter Mode", + "Device up/down directly controls the Z position of the 3D viewport"); /* let Python know whether NDOF is enabled */ prop = RNA_def_boolean(srna, "use_ndof", true, "", ""); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index deeb4f5789c..6749aa9495a 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -450,7 +450,7 @@ static const EnumPropertyItem operator_flag_items[] = { "UNDO_GROUPED", 0, "Grouped Undo", - "Push a single undo event for repetead instances of this operator"}, + "Push a single undo event for repeated instances of this operator"}, {OPTYPE_BLOCKING, "BLOCKING", 0, "Blocking", "Block anything else from using the cursor"}, {OPTYPE_MACRO, "MACRO", 0, "Macro", "Use to check if an operator is a macro"}, {OPTYPE_GRAB_CURSOR_XY, diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index a458e4dd8bc..18b88864926 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -366,6 +366,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * copy_masked_polys_to_new_mesh( *mesh, *result, vertex_map, edge_map, masked_poly_indices, new_loop_starts); + BKE_mesh_calc_edges_loose(result); /* Tag to recalculate normals later. */ result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 382459993b7..53ea02ff8a7 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -311,8 +311,7 @@ static void cmp_node_rlayer_create_outputs(bNodeTree *ntree, if ((scene->r.mode & R_EDGE_FRS) && (view_layer->freestyle_config.flags & FREESTYLE_AS_RENDER_PASS)) { - ntreeCompositRegisterPass( - scene->nodetree, scene, view_layer, RE_PASSNAME_FREESTYLE, SOCK_RGBA); + ntreeCompositRegisterPass(ntree, scene, view_layer, RE_PASSNAME_FREESTYLE, SOCK_RGBA); } MEM_freeN(data); diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index a1dd9b3d5b0..f49c68a258d 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -108,4 +108,6 @@ if(APPLE) endif() endif() +add_definitions(${GL_DEFINITIONS}) + blender_add_lib_nolist(bf_render "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/render/extern/include/RE_bake.h b/source/blender/render/extern/include/RE_bake.h index 372defbe8db..3bab9179f84 100644 --- a/source/blender/render/extern/include/RE_bake.h +++ b/source/blender/render/extern/include/RE_bake.h @@ -67,7 +67,7 @@ bool RE_bake_engine(struct Render *re, struct Object *object, const int object_id, const BakePixel pixel_array[], - const size_t num_pixels, + const BakeImages *bake_images, const int depth, const eScenePassType pass_type, const int pass_filter, @@ -84,6 +84,7 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low, const size_t num_pixels, const bool is_custom_cage, const float cage_extrusion, + const float max_ray_distance, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage); diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index fd55a2a01df..77a60854616 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -68,7 +68,6 @@ struct bNodeTree; #define RE_ENGINE_DO_UPDATE 8 #define RE_ENGINE_RENDERING 16 #define RE_ENGINE_HIGHLIGHT_TILES 32 -#define RE_ENGINE_USED_FOR_VIEWPORT 64 extern ListBase R_engines; @@ -87,11 +86,8 @@ typedef struct RenderEngineType { struct Object *object, const int pass_type, const int pass_filter, - const int object_id, - const struct BakePixel *pixel_array, - const int num_pixels, - const int depth, - void *result); + const int width, + const int height); void (*view_update)(struct RenderEngine *engine, const struct bContext *context, @@ -140,6 +136,13 @@ typedef struct RenderEngine { struct ReportList *reports; + struct { + const struct BakePixel *pixels; + float *result; + int width, height, depth; + int object_id; + } bake; + /* Depsgraph */ struct Depsgraph *depsgraph; @@ -155,7 +158,6 @@ typedef struct RenderEngine { } RenderEngine; RenderEngine *RE_engine_create(RenderEngineType *type); -RenderEngine *RE_engine_create_ex(RenderEngineType *type, bool use_for_viewport); void RE_engine_free(RenderEngine *engine); void RE_layer_load_from_file( diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h index fabbd5fb096..0ed8871b224 100644 --- a/source/blender/render/intern/include/render_result.h +++ b/source/blender/render/intern/include/render_result.h @@ -84,11 +84,12 @@ void render_result_exr_file_begin(struct Render *re, struct RenderEngine *engine void render_result_exr_file_end(struct Render *re, struct RenderEngine *engine); /* render pass wrapper for gpencil */ -struct RenderPass *gp_add_pass(struct RenderResult *rr, - struct RenderLayer *rl, - int channels, - const char *name, - const char *viewname); +struct RenderPass *render_layer_add_pass(struct RenderResult *rr, + struct RenderLayer *rl, + int channels, + const char *name, + const char *viewname, + const char *chanid); void render_result_exr_file_merge(struct RenderResult *rr, struct RenderResult *rrpart, diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c index e823a481d59..06f77854595 100644 --- a/source/blender/render/intern/source/bake_api.c +++ b/source/blender/render/intern/source/bake_api.c @@ -321,11 +321,16 @@ static bool cast_ray_highpoly(BVHTreeFromMesh *treeData, const float co[3], const float dir[3], const int pixel_id, - const int tot_highpoly) + const int tot_highpoly, + const float max_ray_distance) { int i; int hit_mesh = -1; - float hit_distance = FLT_MAX; + float hit_distance = max_ray_distance; + if (hit_distance == 0.0f) { + /* No ray distance set, use maximum. */ + hit_distance = FLT_MAX; + } BVHTreeRayHit *hits; hits = MEM_mallocN(sizeof(BVHTreeRayHit) * tot_highpoly, "Bake Highpoly to Lowpoly: BVH Rays"); @@ -520,6 +525,7 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low, const size_t num_pixels, const bool is_custom_cage, const float cage_extrusion, + const float max_ray_distance, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage) @@ -623,7 +629,8 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low, co, dir, i, - tot_highpoly)) { + tot_highpoly, + max_ray_distance)) { /* if it fails mask out the original pixel array */ pixel_array_from[i].primitive_id = -1; } diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 4770e98bd20..cc685610886 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -31,6 +31,7 @@ #include "BLI_ghash.h" #include "BLI_listbase.h" +#include "BLI_math_bits.h" #include "BLI_rect.h" #include "BLI_string.h" #include "BLI_utildefines.h" @@ -131,20 +132,9 @@ bool RE_engine_is_opengl(RenderEngineType *render_type) RenderEngine *RE_engine_create(RenderEngineType *type) { - return RE_engine_create_ex(type, false); -} - -RenderEngine *RE_engine_create_ex(RenderEngineType *type, bool use_for_viewport) -{ RenderEngine *engine = MEM_callocN(sizeof(RenderEngine), "RenderEngine"); engine->type = type; - if (use_for_viewport) { - engine->flag |= RE_ENGINE_USED_FOR_VIEWPORT; - - BLI_threaded_malloc_begin(); - } - BLI_mutex_init(&engine->update_render_passes_mutex); return engine; @@ -158,15 +148,94 @@ void RE_engine_free(RenderEngine *engine) } #endif - if (engine->flag & RE_ENGINE_USED_FOR_VIEWPORT) { - BLI_threaded_malloc_end(); - } - BLI_mutex_end(&engine->update_render_passes_mutex); MEM_freeN(engine); } +/* Bake Render Results */ + +static RenderResult *render_result_from_bake(RenderEngine *engine, int x, int y, int w, int h) +{ + /* Create render result with specified size. */ + RenderResult *rr = MEM_callocN(sizeof(RenderResult), __func__); + + rr->rectx = w; + rr->recty = h; + rr->tilerect.xmin = x; + rr->tilerect.ymin = y; + rr->tilerect.xmax = x + w; + rr->tilerect.ymax = y + h; + + /* Add single baking render layer. */ + RenderLayer *rl = MEM_callocN(sizeof(RenderLayer), "bake render layer"); + rl->rectx = w; + rl->recty = h; + BLI_addtail(&rr->layers, rl); + + /* Add render passes. */ + render_layer_add_pass(rr, rl, engine->bake.depth, RE_PASSNAME_COMBINED, "", "RGBA"); + RenderPass *primitive_pass = render_layer_add_pass(rr, rl, 4, "BakePrimitive", "", "RGBA"); + RenderPass *differential_pass = render_layer_add_pass(rr, rl, 4, "BakeDifferential", "", "RGBA"); + + /* Fill render passes from bake pixel array, to be read by the render engine. */ + for (int ty = 0; ty < h; ty++) { + size_t offset = ty * w * 4; + float *primitive = primitive_pass->rect + offset; + float *differential = differential_pass->rect + offset; + + size_t bake_offset = (y + ty) * engine->bake.width + x; + const BakePixel *bake_pixel = engine->bake.pixels + bake_offset; + + for (int tx = 0; tx < w; tx++) { + if (bake_pixel->object_id != engine->bake.object_id) { + primitive[0] = int_as_float(-1); + primitive[1] = int_as_float(-1); + } + else { + primitive[0] = int_as_float(bake_pixel->object_id); + primitive[1] = int_as_float(bake_pixel->primitive_id); + primitive[2] = bake_pixel->uv[0]; + primitive[3] = bake_pixel->uv[1]; + + differential[0] = bake_pixel->du_dx; + differential[1] = bake_pixel->du_dy; + differential[2] = bake_pixel->dv_dx; + differential[3] = bake_pixel->dv_dy; + } + + primitive += 4; + differential += 4; + bake_pixel++; + } + } + + return rr; +} + +static void render_result_to_bake(RenderEngine *engine, RenderResult *rr) +{ + RenderPass *rpass = RE_pass_find_by_name(rr->layers.first, RE_PASSNAME_COMBINED, ""); + + if (!rpass) { + return; + } + + /* Copy from tile render result to full image bake result. */ + int x = rr->tilerect.xmin; + int y = rr->tilerect.ymin; + int w = rr->tilerect.xmax - rr->tilerect.xmin; + int h = rr->tilerect.ymax - rr->tilerect.ymin; + + for (int ty = 0; ty < h; ty++) { + size_t offset = ty * w * engine->bake.depth; + size_t bake_offset = ((y + ty) * engine->bake.width + x) * engine->bake.depth; + size_t size = w * engine->bake.depth * sizeof(float); + + memcpy(engine->bake.result + bake_offset, rpass->rect + offset, size); + } +} + /* Render Results */ static RenderPart *get_part_from_result(Render *re, RenderResult *result) @@ -180,6 +249,12 @@ static RenderPart *get_part_from_result(Render *re, RenderResult *result) RenderResult *RE_engine_begin_result( RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname) { + if (engine->bake.pixels) { + RenderResult *result = render_result_from_bake(engine, x, y, w, h); + BLI_addtail(&engine->fullresult, result); + return result; + } + Render *re = engine->re; RenderResult *result; rcti disprect; @@ -237,6 +312,11 @@ RenderResult *RE_engine_begin_result( void RE_engine_update_result(RenderEngine *engine, RenderResult *result) { + if (engine->bake.pixels) { + /* No interactive baking updates for now. */ + return; + } + Render *re = engine->re; if (result) { @@ -270,6 +350,13 @@ void RE_engine_end_result( return; } + if (engine->bake.pixels) { + render_result_to_bake(engine, result); + BLI_remlink(&engine->fullresult, result); + render_result_free(result); + return; + } + /* merge. on break, don't merge in result for preview renders, looks nicer */ if (!highlight) { /* for exr tile render, detect tiles that are done */ @@ -574,7 +661,7 @@ bool RE_bake_engine(Render *re, Object *object, const int object_id, const BakePixel pixel_array[], - const size_t num_pixels, + const BakeImages *bake_images, const int depth, const eScenePassType pass_type, const int pass_filter, @@ -619,16 +706,21 @@ bool RE_bake_engine(Render *re, type->update(engine, re->main, engine->depsgraph); } - type->bake(engine, - engine->depsgraph, - object, - pass_type, - pass_filter, - object_id, - pixel_array, - num_pixels, - depth, - result); + for (int i = 0; i < bake_images->size; i++) { + const BakeImage *image = bake_images->data + i; + + engine->bake.pixels = pixel_array + image->offset; + engine->bake.result = result + image->offset * depth; + engine->bake.width = image->width; + engine->bake.height = image->height; + engine->bake.depth = depth; + engine->bake.object_id = object_id; + + type->bake( + engine, engine->depsgraph, object, pass_type, pass_filter, image->width, image->height); + + memset(&engine->bake, 0, sizeof(engine->bake)); + } engine->depsgraph = NULL; } diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 4a910d9e12c..e0c59596c2a 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -187,23 +187,20 @@ static int default_break(void *UNUSED(arg)) static void stats_background(void *UNUSED(arg), RenderStats *rs) { - uintptr_t mem_in_use, mmap_in_use, peak_memory; - float megs_used_memory, mmap_used_memory, megs_peak_memory; + uintptr_t mem_in_use, peak_memory; + float megs_used_memory, megs_peak_memory; char info_time_str[32]; mem_in_use = MEM_get_memory_in_use(); - mmap_in_use = MEM_get_mapped_memory_in_use(); peak_memory = MEM_get_peak_memory(); - megs_used_memory = (mem_in_use - mmap_in_use) / (1024.0 * 1024.0); - mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0); + megs_used_memory = (mem_in_use) / (1024.0 * 1024.0); megs_peak_memory = (peak_memory) / (1024.0 * 1024.0); fprintf(stdout, - TIP_("Fra:%d Mem:%.2fM (%.2fM, Peak %.2fM) "), + TIP_("Fra:%d Mem:%.2fM (Peak %.2fM) "), rs->cfra, megs_used_memory, - mmap_used_memory, megs_peak_memory); if (rs->curfield) { @@ -2955,5 +2952,5 @@ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const cha BLI_freelinkN(&rl->passes, rp); } /* create a totally new pass */ - return gp_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, viewname); + return render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, viewname, "RGBA"); } diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index b38c1b573f3..4b74bfb3e5c 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -213,12 +213,12 @@ static void set_pass_full_name( /********************************** New **************************************/ -static RenderPass *render_layer_add_pass(RenderResult *rr, - RenderLayer *rl, - int channels, - const char *name, - const char *viewname, - const char *chan_id) +RenderPass *render_layer_add_pass(RenderResult *rr, + RenderLayer *rl, + int channels, + const char *name, + const char *viewname, + const char *chan_id) { const int view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name)); RenderPass *rpass = MEM_callocN(sizeof(RenderPass), name); @@ -255,7 +255,7 @@ static RenderPass *render_layer_add_pass(RenderResult *rr, float *rect; int x; - rpass->rect = MEM_mapallocN(sizeof(float) * rectsize, name); + rpass->rect = MEM_callocN(sizeof(float) * rectsize, name); if (rpass->rect == NULL) { MEM_freeN(rpass); return NULL; @@ -280,12 +280,6 @@ static RenderPass *render_layer_add_pass(RenderResult *rr, return rpass; } -/* wrapper called from render_opengl */ -RenderPass *gp_add_pass( - RenderResult *rr, RenderLayer *rl, int channels, const char *name, const char *viewname) -{ - return render_layer_add_pass(rr, rl, channels, name, viewname, "RGBA"); -} /* called by main render as well for parts */ /* will read info from Render *re to define layers */ diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index 22fd55cd49a..7c749c60168 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -168,10 +168,6 @@ if(WITH_BUILDINFO) add_definitions(-DWITH_BUILDINFO) endif() -if(WITH_OPENSUBDIV) - add_definitions(-DWITH_OPENSUBDIV) -endif() - if(WITH_INPUT_NDOF) add_definitions(-DWITH_INPUT_NDOF) endif() diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 54e6735175d..9aaaa0e2c81 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -44,8 +44,10 @@ #include "BKE_idprop.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_report.h" +#include "BKE_screen.h" #include "BKE_workspace.h" #include "WM_api.h" @@ -73,6 +75,28 @@ static void window_manager_free_data(ID *id) wm_close_and_free(NULL, (wmWindowManager *)id); } +static void window_manager_foreach_id(ID *id, LibraryForeachIDData *data) +{ + wmWindowManager *wm = (wmWindowManager *)id; + + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { + BKE_LIB_FOREACHID_PROCESS(data, 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); + BKE_LIB_FOREACHID_PROCESS_ID(data, workspace, IDWALK_CB_NOP); + /* allow callback to set a different workspace */ + BKE_workspace_active_set(win->workspace_hook, (WorkSpace *)workspace); + } + if (BKE_lib_query_foreachid_process_flags_get(data) & IDWALK_INCLUDE_UI) { + LISTBASE_FOREACH (ScrArea *, area, &win->global_areas.areabase) { + BKE_screen_foreach_id_screen_area(data, area); + } + } + } +} + IDTypeInfo IDType_ID_WM = { .id_code = ID_WM, .id_filter = 0, @@ -87,6 +111,7 @@ IDTypeInfo IDType_ID_WM = { .copy_data = NULL, .free_data = window_manager_free_data, .make_local = NULL, + .foreach_id = window_manager_foreach_id, }; #define MAX_OP_REGISTERED 32 @@ -359,7 +384,7 @@ void wm_add_default(Main *bmain, bContext *C) WorkSpaceLayout *layout = BKE_workspace_layout_find_global(bmain, screen, &workspace); CTX_wm_manager_set(C, wm); - win = wm_window_new(bmain, wm, NULL); + win = wm_window_new(bmain, wm, NULL, false); win->scene = CTX_data_scene(C); STRNCPY(win->view_layer_name, CTX_data_view_layer(C)->name); BKE_workspace_active_set(win->workspace_hook, workspace); diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index a01ab1377c1..4cc9f4ee7d1 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -848,6 +848,7 @@ static void wm_draw_window(bContext *C, wmWindow *win) glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); + wmWindowViewport(win); if (win->stereo3d_format->display_mode == S3D_DISPLAY_SIDEBYSIDE) { wm_stereo3d_draw_sidebyside(win, view); } @@ -982,10 +983,6 @@ void wm_draw_update(bContext *C) wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win; -#ifdef WITH_OPENSUBDIV - BKE_subsurf_free_unused_buffers(); -#endif - GPU_free_unused_buffers(bmain); for (win = wm->windows.first; win; win = win->next) { diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 61c99d72695..c7bda0bdae0 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -563,7 +563,7 @@ void wm_event_do_notifiers(bContext *C) static int wm_event_always_pass(const wmEvent *event) { /* some events we always pass on, to ensure proper communication */ - return ISTIMER(event->type) || (event->type == WINDEACTIVATE); + return ISTIMER(event->type) || (event->type == WINDEACTIVATE) || (event->type == EVT_FILESELECT); } /** \} */ @@ -640,11 +640,11 @@ static int wm_handler_ui_call(bContext *C, return WM_HANDLER_CONTINUE; } -static void wm_handler_ui_cancel(bContext *C) +void wm_event_handler_ui_cancel_ex(bContext *C, + wmWindow *win, + ARegion *region, + bool reactivate_button) { - wmWindow *win = CTX_wm_window(C); - ARegion *region = CTX_wm_region(C); - if (!region) { return; } @@ -656,11 +656,19 @@ static void wm_handler_ui_cancel(bContext *C) wmEvent event; wm_event_init_from_window(win, &event); event.type = EVT_BUT_CANCEL; + event.val = reactivate_button ? 0 : 1; handler->handle_fn(C, &event, handler->user_data); } } } +static void wm_event_handler_ui_cancel(bContext *C) +{ + wmWindow *win = CTX_wm_window(C); + ARegion *region = CTX_wm_region(C); + wm_event_handler_ui_cancel_ex(C, win, region, true); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -1365,7 +1373,7 @@ static int wm_operator_invoke(bContext *C, * while dragging the view or worse, that stay there permanently * after the modal operator has swallowed all events and passed * none to the UI handler */ - wm_handler_ui_cancel(C); + wm_event_handler_ui_cancel(C); } else { WM_operator_free(op); @@ -2661,6 +2669,12 @@ static int wm_handlers_do_gizmo_handler(bContext *C, return action; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Handle Single Event (All Handler Types) + * \{ */ + static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers) { const bool do_debug_handler = @@ -2962,6 +2976,14 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) return action; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Event Queue Utilities + * + * Utilities used by #wm_event_do_handlers. + * \{ */ + static bool wm_event_inside_rect(const wmEvent *event, const rcti *rect) { if (wm_event_always_pass(event)) { @@ -3126,6 +3148,14 @@ static void wm_event_free_and_remove_from_queue_if_valid(wmEvent *event) } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Main Event Queue (Every Window) + * + * Handle events for all windows, run from the #WM_main event loop. + * \{ */ + /* called in main loop */ /* goes over entire hierarchy: events -> window -> screen -> area -> region */ void wm_event_do_handlers(bContext *C) @@ -3434,19 +3464,13 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op) wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); const bool is_temp_screen = WM_window_is_temp_screen(win); - const bool opens_window = (U.filebrowser_display_type == USER_TEMP_SPACE_DISPLAY_WINDOW); - /* Don't add the file handler to the temporary window if one is opened, or else it owns the - * handlers for itself, causing dangling pointers once it's destructed through a handler. It has - * a parent which should hold the handlers itself. */ - ListBase *modalhandlers = (is_temp_screen && opens_window) ? &win->parent->modalhandlers : - &win->modalhandlers; /* Close any popups, like when opening a file browser from the splash. */ - UI_popup_handlers_remove_all(C, modalhandlers); + UI_popup_handlers_remove_all(C, &win->modalhandlers); if (!is_temp_screen) { /* only allow 1 file selector open per window */ - LISTBASE_FOREACH_MUTABLE (wmEventHandler *, handler_base, modalhandlers) { + LISTBASE_FOREACH_MUTABLE (wmEventHandler *, handler_base, &win->modalhandlers) { if (handler_base->type == WM_HANDLER_TYPE_OP) { wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; if (handler->is_fileselect == false) { @@ -3487,7 +3511,7 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op) handler->context.area = CTX_wm_area(C); handler->context.region = CTX_wm_region(C); - BLI_addhead(modalhandlers, handler); + BLI_addhead(&win->modalhandlers, handler); /* check props once before invoking if check is available * ensures initial properties are valid */ diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index b9f0e3686db..cc81e4f2715 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -1212,6 +1212,7 @@ static ImBuf *blend_file_thumb(const bContext *C, ImBuf *ibuf; BlendThumbnail *thumb; wmWindowManager *wm = CTX_wm_manager(C); + const float pixelsize_old = U.pixelsize; wmWindow *windrawable_old = wm->windrawable; char err_out[256] = "unknown"; @@ -1246,6 +1247,10 @@ static ImBuf *blend_file_thumb(const bContext *C, /* gets scaled to BLEN_THUMB_SIZE */ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + /* Note that with scaling, this ends up being 0.5, + * as it's a thumbnail, we don't need object centers and friends to be 1:1 size. */ + U.pixelsize = 1.0f; + if (scene->camera) { ibuf = ED_view3d_draw_offscreen_imbuf_simple(depsgraph, scene, @@ -1276,6 +1281,8 @@ static ImBuf *blend_file_thumb(const bContext *C, err_out); } + U.pixelsize = pixelsize_old; + /* Reset to old drawable. */ if (windrawable_old) { wm_window_make_drawable(wm, windrawable_old); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index a93d4c7bf37..fc3f0c87b69 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -125,6 +125,8 @@ #include "GPU_material.h" #include "BKE_sound.h" +#include "BKE_subdiv.h" + #include "COM_compositor.h" #include "DEG_depsgraph.h" @@ -132,10 +134,6 @@ #include "DRW_engine.h" -#ifdef WITH_OPENSUBDIV -# include "BKE_subsurf.h" -#endif - CLG_LOGREF_DECLARE_GLOBAL(WM_LOG_OPERATORS, "wm.operator"); CLG_LOGREF_DECLARE_GLOBAL(WM_LOG_HANDLERS, "wm.handler"); CLG_LOGREF_DECLARE_GLOBAL(WM_LOG_EVENTS, "wm.event"); @@ -193,9 +191,8 @@ void WM_init_opengl(Main *bmain) GPU_pass_cache_init(); -#ifdef WITH_OPENSUBDIV - BKE_subsurf_osd_init(); -#endif + BKE_subdiv_init(); + opengl_is_init = true; } @@ -576,11 +573,9 @@ void WM_exit_ex(bContext *C, const bool do_python) COM_deinitialize(); #endif - if (opengl_is_init) { -#ifdef WITH_OPENSUBDIV - BKE_subsurf_osd_cleanup(); -#endif + BKE_subdiv_exit(); + if (opengl_is_init) { GPU_free_unused_buffers(G_MAIN); } diff --git a/source/blender/windowmanager/intern/wm_splash_screen.c b/source/blender/windowmanager/intern/wm_splash_screen.c index 8445fac0498..c821f5bfe89 100644 --- a/source/blender/windowmanager/intern/wm_splash_screen.c +++ b/source/blender/windowmanager/intern/wm_splash_screen.c @@ -129,6 +129,7 @@ static void get_version_string(char *ver, const int max_length) version_cycle_number); } +#ifndef WITH_HEADLESS static void wm_block_splash_image_roundcorners_add(ImBuf *ibuf) { uchar *rct = (uchar *)ibuf->rect; @@ -179,6 +180,7 @@ static void wm_block_splash_image_roundcorners_add(ImBuf *ibuf) } } } +#endif /* WITH_HEADLESS */ static ImBuf *wm_block_splash_image(int width, int *r_height) { @@ -219,6 +221,7 @@ static ImBuf *wm_block_splash_image(int width, int *r_height) return ibuf; #else + UNUSED_VARS(width, r_height); return NULL; #endif } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 70601ae5e42..fcb2be0a0bb 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -286,14 +286,15 @@ static int find_free_winid(wmWindowManager *wm) } /* don't change context itself */ -wmWindow *wm_window_new(const Main *bmain, wmWindowManager *wm, wmWindow *parent) +wmWindow *wm_window_new(const Main *bmain, wmWindowManager *wm, wmWindow *parent, bool dialog) { wmWindow *win = MEM_callocN(sizeof(wmWindow), "window"); BLI_addtail(&wm->windows, win); win->winid = find_free_winid(wm); - win->parent = (parent && parent->parent) ? parent->parent : parent; + /* Dialogs may have a child window as parent. Otherwise, a child must not be a parent too. */ + win->parent = (!dialog && parent && parent->parent) ? parent->parent : parent; win->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo 3D Format (window)"); win->workspace_hook = BKE_workspace_instance_hook_create(bmain); @@ -307,8 +308,9 @@ wmWindow *wm_window_copy(Main *bmain, const bool duplicate_layout, const bool child) { + const bool is_dialog = GHOST_IsDialogWindow(win_src->ghostwin); wmWindow *win_parent = (child) ? win_src : win_src->parent; - wmWindow *win_dst = wm_window_new(bmain, wm, win_parent); + wmWindow *win_dst = wm_window_new(bmain, wm, win_parent, is_dialog); WorkSpace *workspace = WM_window_get_active_workspace(win_src); WorkSpaceLayout *layout_old = WM_window_get_active_layout(win_src); WorkSpaceLayout *layout_new; @@ -417,7 +419,6 @@ void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win) void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) { wmWindow *win_other; - const bool is_dialog = (G.background == false) ? GHOST_IsDialogWindow(win->ghostwin) : false; /* First check if there is another main window remaining. */ for (win_other = wm->windows.first; win_other; win_other = win_other->next) { @@ -431,20 +432,11 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) return; } - /* Close child windows and bring windows back to front that dialogs have pushed behind the main - * window. */ - LISTBASE_FOREACH (wmWindow *, iter_win, &wm->windows) { + /* Close child windows */ + LISTBASE_FOREACH_MUTABLE (wmWindow *, iter_win, &wm->windows) { if (iter_win->parent == win) { wm_window_close(C, wm, iter_win); } - else { - if (G.background == false) { - if (is_dialog && iter_win != win && iter_win->parent && - (GHOST_GetWindowState(iter_win->ghostwin) != GHOST_kWindowStateMinimized)) { - wm_window_raise(iter_win); - } - } - } } bScreen *screen = WM_window_get_active_screen(win); @@ -834,7 +826,7 @@ wmWindow *WM_window_open(bContext *C, const rcti *rect) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win_prev = CTX_wm_window(C); - wmWindow *win = wm_window_new(CTX_data_main(C), wm, win_prev); + wmWindow *win = wm_window_new(CTX_data_main(C), wm, win_prev, false); win->posx = rect->xmin; win->posy = rect->ymin; @@ -905,7 +897,7 @@ wmWindow *WM_window_open_temp(bContext *C, /* add new window? */ if (win == NULL) { - win = wm_window_new(bmain, wm, win_prev); + win = wm_window_new(bmain, wm, win_prev, dialog); win->posx = rect.xmin; win->posy = rect.ymin; diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h index ffa5baae9f1..efcf40d03eb 100644 --- a/source/blender/windowmanager/wm_event_system.h +++ b/source/blender/windowmanager/wm_event_system.h @@ -149,6 +149,11 @@ void wm_event_do_depsgraph(bContext *C, bool is_after_open_file); void wm_event_do_refresh_wm_and_depsgraph(bContext *C); void wm_event_do_notifiers(bContext *C); +void wm_event_handler_ui_cancel_ex(bContext *C, + wmWindow *win, + ARegion *region, + bool reactivate_button); + /* wm_event_query.c */ float wm_pressure_curve(float raw_pressure); void wm_tablet_data_from_ghost(const struct GHOST_TabletData *tablet_data, wmTabletData *wmtab); diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index f16056cc91e..ffed86abfe7 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -333,6 +333,7 @@ enum { EVT_BUT_OPEN = 0x5021, /* 20513 */ EVT_MODAL_MAP = 0x5022, /* 20514 */ EVT_DROP = 0x5023, /* 20515 */ + /* When value is 0, re-activate, when 1, don't re-activate the button under the cursor. */ EVT_BUT_CANCEL = 0x5024, /* 20516 */ /* could become gizmo callback */ diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index 45cfe1431d7..5ca5711b4f2 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -33,7 +33,10 @@ void wm_ghost_exit(void); void wm_get_screensize(int *r_width, int *r_height); void wm_get_desktopsize(int *r_width, int *r_height); -wmWindow *wm_window_new(const struct Main *bmain, wmWindowManager *wm, wmWindow *parent); +wmWindow *wm_window_new(const struct Main *bmain, + wmWindowManager *wm, + wmWindow *parent, + bool dialog); wmWindow *wm_window_copy(struct Main *bmain, wmWindowManager *wm, wmWindow *win_src, diff --git a/source/blender/windowmanager/xr/intern/wm_xr.c b/source/blender/windowmanager/xr/intern/wm_xr.c index 69c9034d51f..90f30809136 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr.c +++ b/source/blender/windowmanager/xr/intern/wm_xr.c @@ -126,7 +126,12 @@ void wm_xr_exit(wmWindowManager *wm) bool wm_xr_events_handle(wmWindowManager *wm) { if (wm->xr.runtime && wm->xr.runtime->context) { - return GHOST_XrEventsHandle(wm->xr.runtime->context); + GHOST_XrEventsHandle(wm->xr.runtime->context); + + /* wm_window_process_events() uses the return value to determine if it can put the main thread + * to sleep for some milliseconds. We never want that to happen while the VR session runs on + * the main thread. So always return true. */ + return true; } return false; } diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index b3e83b1412f..1a71022869a 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -687,6 +687,13 @@ elseif(WIN32) ) endif() + if(WITH_FFTW3) + install( + FILES ${LIBDIR}/fftw3/lib/libfftw3-3.dll + DESTINATION "." + ) + endif() + if(WITH_WINDOWS_PDB) if(WITH_WINDOWS_STRIPPED_PDB) # Icky hack for older cmake from https://stackoverflow.com/a/21198501 diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index bd56d86784e..7acf649c3ab 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -959,7 +959,7 @@ static const char arg_handle_debug_mode_generic_set_doc_jobs[] = "Enable time profiling for background jobs."; static const char arg_handle_debug_mode_generic_set_doc_gpu[] = "\n\t" - "Enable gpu debug context and information for OpenGL 4.3+."; + "Enable GPU debug context and information for OpenGL 4.3+."; static const char arg_handle_debug_mode_generic_set_doc_depsgraph[] = "\n\t" "Enable all debug messages from dependency graph."; @@ -995,7 +995,7 @@ static int arg_handle_debug_mode_generic_set(int UNUSED(argc), static const char arg_handle_debug_mode_io_doc[] = "\n\t" - "Enable debug messages for I/O (collada, ...)."; + "Enable debug messages for I/O (Collada, ...)."; static int arg_handle_debug_mode_io(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data)) @@ -1124,7 +1124,7 @@ static int arg_handle_factory_startup_set(int UNUSED(argc), static const char arg_handle_disable_override_library_doc[] = "\n\t" - "Enable Library Override features in the UI."; + "Disable Library Override features in the UI."; static int arg_handle_disable_override_library(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data)) @@ -1497,7 +1497,7 @@ static int arg_handle_threads_set(int argc, const char **argv, void *UNUSED(data static const char arg_handle_verbosity_set_doc[] = "<verbose>\n" - "\tSet logging verbosity level for debug messages which supports it."; + "\tSet the logging verbosity level for debug messages that support it."; static int arg_handle_verbosity_set(int argc, const char **argv, void *UNUSED(data)) { const char *arg_id = "--verbose"; @@ -1592,7 +1592,6 @@ static int arg_handle_render_frame(int argc, const char **argv, void *data) } re = RE_NewSceneRender(scene); - BLI_threaded_malloc_begin(); BKE_reports_init(&reports, RPT_STORE); RE_SetReports(re, &reports); for (int i = 0; i < frames_range_len; i++) { @@ -1608,7 +1607,6 @@ static int arg_handle_render_frame(int argc, const char **argv, void *data) } RE_SetReports(re, NULL); BKE_reports_clear(&reports); - BLI_threaded_malloc_end(); MEM_freeN(frame_range_arr); return 1; } @@ -1634,13 +1632,11 @@ static int arg_handle_render_animation(int UNUSED(argc), const char **UNUSED(arg Main *bmain = CTX_data_main(C); Render *re = RE_NewSceneRender(scene); ReportList reports; - BLI_threaded_malloc_begin(); BKE_reports_init(&reports, RPT_STORE); RE_SetReports(re, &reports); RE_RenderAnim(re, bmain, scene, NULL, NULL, scene->r.sfra, scene->r.efra, scene->r.frame_step); RE_SetReports(re, NULL); BKE_reports_clear(&reports); - BLI_threaded_malloc_end(); } else { printf("\nError: no blend loaded. cannot use '-a'.\n"); |