diff options
50 files changed, 691 insertions, 312 deletions
diff --git a/extern/mantaflow/helper/util/vectorbase.h b/extern/mantaflow/helper/util/vectorbase.h index 41584663a0f..9ccf445f42c 100644 --- a/extern/mantaflow/helper/util/vectorbase.h +++ b/extern/mantaflow/helper/util/vectorbase.h @@ -248,12 +248,14 @@ template<class S> class Vector3D { protected: }; -//! helper to check whether float/double value is non-zero -inline bool notZero(Real f) +//! helper to check whether value is non-zero +template<class S> inline bool notZero(S v) { - if (std::abs(f) > VECTOR_EPSILON) - return true; - return false; + return (std::abs(v) > VECTOR_EPSILON); +} +template<class S> inline bool notZero(Vector3D<S> v) +{ + return (std::abs(norm(v)) > VECTOR_EPSILON); } //************************************************************************ diff --git a/extern/mantaflow/preprocessed/fileio/iomeshes.cpp b/extern/mantaflow/preprocessed/fileio/iomeshes.cpp index 1c50376de77..b5e51625077 100644 --- a/extern/mantaflow/preprocessed/fileio/iomeshes.cpp +++ b/extern/mantaflow/preprocessed/fileio/iomeshes.cpp @@ -315,10 +315,14 @@ int readObjFile(const std::string &name, Mesh *mesh, bool append) return 0; } + const Real dx = mesh->getParent()->getDx(); + const Vec3 gs = toVec3(mesh->getParent()->getGridSize()); + if (!append) mesh->clear(); int nodebase = mesh->numNodes(); - int cnt = nodebase; + int cntNodes = nodebase, cntNormals = nodebase; + while (ifs.good() && !ifs.eof()) { string id; ifs >> id; @@ -333,19 +337,23 @@ int readObjFile(const std::string &name, Mesh *mesh, bool append) } else if (id == "vn") { // normals - if (!mesh->numNodes()) { + if (mesh->numNodes() != cntNodes) { errMsg("invalid amount of nodes"); return 0; } - Node n = mesh->nodes(cnt); - ifs >> n.normal.x >> n.normal.y >> n.normal.z; - cnt++; + Node *n = &mesh->nodes(cntNormals); + ifs >> n->normal.x >> n->normal.y >> n->normal.z; + cntNormals++; } else if (id == "v") { // vertex Node n; ifs >> n.pos.x >> n.pos.y >> n.pos.z; + // convert to grid space + n.pos /= dx; + n.pos += gs * 0.5; mesh->addNode(n); + cntNodes++; } else if (id == "g") { // group @@ -408,7 +416,6 @@ int writeObjFile(const string &name, Mesh *mesh) // write normals for (int i = 0; i < numVerts; i++) { Vector3D<float> n = toVec3f(mesh->nodes(i).normal); - // normalize to unit cube around 0 ofs << "vn " << n.value[0] << " " << n.value[1] << " " << n.value[2] << " " << "\n"; } diff --git a/extern/mantaflow/preprocessed/gitinfo.h b/extern/mantaflow/preprocessed/gitinfo.h index 73ff70b10a0..03dcbb3d9c5 100644 --- a/extern/mantaflow/preprocessed/gitinfo.h +++ b/extern/mantaflow/preprocessed/gitinfo.h @@ -1,3 +1,3 @@ -#define MANTA_GIT_VERSION "commit d80d3c821de74315ab26b5efd153d41477b976c4" +#define MANTA_GIT_VERSION "commit 7395d36e3f504edbdabe34b30edc855b422c7baa" diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index c7737392e7b..92061f55128 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -362,8 +362,8 @@ extern GHOST_TSuccess GHOST_HasCursorShape(GHOST_WindowHandle windowhandle, * \param mask The mask data for the cursor. * \param sizex The width of the cursor * \param sizey The height of the cursor - * \param hotX The X coordinate of the cursor hotspot. - * \param hotY The Y coordinate of the cursor hotspot. + * \param hotX The X coordinate of the cursor hot-spot. + * \param hotY The Y coordinate of the cursor hot-spot. * \param canInvertColor Let macOS invert cursor color to match platform convention. * \return Indication of success. */ diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index 62290d20f1c..9c72b6f07f9 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -287,8 +287,8 @@ class GHOST_IWindow { * Set the shape of the cursor to a custom cursor. * \param bitmap The bitmap data for the cursor. * \param mask The mask data for the cursor. - * \param hotX The X coordinate of the cursor hotspot. - * \param hotY The Y coordinate of the cursor hotspot. + * \param hotX The X coordinate of the cursor hot-spot. + * \param hotY The Y coordinate of the cursor hot-spot. * \return Indication of success. */ virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap, diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index 6738aa850ce..7cfea5110c5 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -124,8 +124,8 @@ class GHOST_Window : public GHOST_IWindow { * Set the shape of the cursor to a custom cursor. * \param bitmap The bitmap data for the cursor. * \param mask The mask data for the cursor. - * \param hotX The X coordinate of the cursor hotspot. - * \param hotY The Y coordinate of the cursor hotspot. + * \param hotX The X coordinate of the cursor hot-spot. + * \param hotY The Y coordinate of the cursor hot-spot. * \return Indication of success. */ GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap, diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp index 43121f08f2d..676a2fd785e 100644 --- a/intern/mantaflow/intern/MANTA_main.cpp +++ b/intern/mantaflow/intern/MANTA_main.cpp @@ -870,9 +870,9 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd) mRNAMap["GUIDING_ALPHA"] = to_string(fds->guide_alpha); mRNAMap["GUIDING_BETA"] = to_string(fds->guide_beta); mRNAMap["GUIDING_FACTOR"] = to_string(fds->guide_vel_factor); - mRNAMap["GRAVITY_X"] = to_string(fds->gravity[0]); - mRNAMap["GRAVITY_Y"] = to_string(fds->gravity[1]); - mRNAMap["GRAVITY_Z"] = to_string(fds->gravity[2]); + mRNAMap["GRAVITY_X"] = to_string(fds->gravity_final[0]); + mRNAMap["GRAVITY_Y"] = to_string(fds->gravity_final[1]); + mRNAMap["GRAVITY_Z"] = to_string(fds->gravity_final[2]); mRNAMap["CACHE_DIR"] = cacheDirectory; mRNAMap["COMPRESSION_OPENVDB"] = vdbCompressionMethod; mRNAMap["PRECISION_OPENVDB"] = vdbPrecisionHalf; @@ -1256,6 +1256,7 @@ bool MANTA::readData(FluidModifierData *fmd, int framenr, bool resumable) << ", '" << volume_format << "', " << resumable_cache << ")"; pythonCommands.push_back(ss.str()); result &= runPythonString(pythonCommands); + return (mSmokeFromFile = result); } if (mUsingLiquid) { ss.str(""); @@ -1263,6 +1264,7 @@ bool MANTA::readData(FluidModifierData *fmd, int framenr, bool resumable) << ", '" << volume_format << "', " << resumable_cache << ")"; pythonCommands.push_back(ss.str()); result &= runPythonString(pythonCommands); + return (mFlipFromFile = result); } return result; } @@ -1296,7 +1298,7 @@ bool MANTA::readNoise(FluidModifierData *fmd, int framenr, bool resumable) << ", '" << volume_format << "', " << resumable_cache << ")"; pythonCommands.push_back(ss.str()); - return runPythonString(pythonCommands); + return (mNoiseFromFile = runPythonString(pythonCommands)); } bool MANTA::readMesh(FluidModifierData *fmd, int framenr) @@ -1331,7 +1333,7 @@ bool MANTA::readMesh(FluidModifierData *fmd, int framenr) pythonCommands.push_back(ss.str()); } - return runPythonString(pythonCommands); + return (mMeshFromFile = runPythonString(pythonCommands)); } bool MANTA::readParticles(FluidModifierData *fmd, int framenr, bool resumable) @@ -1365,7 +1367,7 @@ bool MANTA::readParticles(FluidModifierData *fmd, int framenr, bool resumable) << framenr << ", '" << volume_format << "', " << resumable_cache << ")"; pythonCommands.push_back(ss.str()); - return runPythonString(pythonCommands); + return (mParticlesFromFile = runPythonString(pythonCommands)); } bool MANTA::readGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain) diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h index 977b99e7759..4ee3ae59957 100644 --- a/intern/mantaflow/intern/strings/fluid_script.h +++ b/intern/mantaflow/intern/strings/fluid_script.h @@ -146,19 +146,19 @@ mantaMsg('1 Mantaflow cell is ' + str(ratioMetersToRes_s$ID$) + ' Blender length ratioResToBLength_s$ID$ = float(res_s$ID$) / float(domainSize_s$ID$) # [cells / blength] (blength: cm, m, or km, ... )\n\ mantaMsg('1 Blender length unit is ' + str(ratioResToBLength_s$ID$) + ' Mantaflow cells long.')\n\ \n\ -ratioBTimeToTimstep_s$ID$ = float(1) / float(frameLengthRaw_s$ID$) # the time within 1 blender time unit, see also fluid.c\n\ -mantaMsg('1 Blender time unit is ' + str(ratioBTimeToTimstep_s$ID$) + ' Mantaflow time units long.')\n\ +ratioBTimeToTimestep_s$ID$ = float(1) / float(frameLengthRaw_s$ID$) # the time within 1 blender time unit, see also fluid.c\n\ +mantaMsg('1 Blender time unit is ' + str(ratioBTimeToTimestep_s$ID$) + ' Mantaflow time units long.')\n\ \n\ ratioFrameToFramelength_s$ID$ = float(1) / float(frameLengthUnscaled_s$ID$ ) # the time within 1 frame\n\ mantaMsg('frame / frameLength is ' + str(ratioFrameToFramelength_s$ID$) + ' Mantaflow time units long.')\n\ \n\ -scaleAcceleration_s$ID$ = ratioResToBLength_s$ID$ * (ratioBTimeToTimstep_s$ID$**2)# [meters/btime^2] to [cells/timestep^2] (btime: sec, min, or h, ...)\n\ +scaleAcceleration_s$ID$ = ratioResToBLength_s$ID$ * (ratioBTimeToTimestep_s$ID$**2)# [meters/btime^2] to [cells/timestep^2] (btime: sec, min, or h, ...)\n\ mantaMsg('scaleAcceleration is ' + str(scaleAcceleration_s$ID$))\n\ \n\ scaleSpeedFrames_s$ID$ = ratioResToBLength_s$ID$ * ratioFrameToFramelength_s$ID$ # [blength/frame] to [cells/frameLength]\n\ mantaMsg('scaleSpeed is ' + str(scaleSpeedFrames_s$ID$))\n\ \n\ -scaleSpeedTime_s$ID$ = ratioResToBLength_s$ID$ * ratioBTimeToTimstep_s$ID$ # [blength/btime] to [cells/frameLength]\n\ +scaleSpeedTime_s$ID$ = ratioResToBLength_s$ID$ * ratioBTimeToTimestep_s$ID$ # [blength/btime] to [cells/frameLength]\n\ mantaMsg('scaleSpeedTime is ' + str(scaleSpeedTime_s$ID$))\n\ \n\ gravity_s$ID$ *= scaleAcceleration_s$ID$ # scale from world acceleration to cell based acceleration\n\ diff --git a/release/scripts/startup/bl_operators/view3d.py b/release/scripts/startup/bl_operators/view3d.py index a8e04eb2f24..02bfebbdc0c 100644 --- a/release/scripts/startup/bl_operators/view3d.py +++ b/release/scripts/startup/bl_operators/view3d.py @@ -159,6 +159,33 @@ class VIEW3D_OT_edit_mesh_extrude_shrink_fatten(Operator): return self.execute(context) +class VIEW3D_OT_edit_mesh_extrude_manifold_normal(Operator): + """Extrude manifold region along normals""" + bl_label = "Extrude Manifold Along Normals" + bl_idname = "view3d.edit_mesh_extrude_manifold_normal" + + @classmethod + def poll(cls, context): + obj = context.active_object + return (obj is not None and obj.mode == 'EDIT') + + def execute(self, context): + bpy.ops.mesh.extrude_manifold( + 'INVOKE_REGION_WIN', + MESH_OT_extrude_region={ + "use_dissolve_ortho_edges": True, + }, + TRANSFORM_OT_translate={ + "orient_type": 'NORMAL', + "constraint_axis": (False, False, True), + }, + ) + return {'FINISHED'} + + def invoke(self, context, _event): + return self.execute(context) + + class VIEW3D_OT_transform_gizmo_set(Operator): """Set the current transform gizmo""" bl_label = "Transform Gizmo Set" @@ -208,5 +235,6 @@ classes = ( VIEW3D_OT_edit_mesh_extrude_individual_move, VIEW3D_OT_edit_mesh_extrude_move, VIEW3D_OT_edit_mesh_extrude_shrink_fatten, + VIEW3D_OT_edit_mesh_extrude_manifold_normal, VIEW3D_OT_transform_gizmo_set, ) diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index a543ea6685c..fc11e4a0a87 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -1466,8 +1466,7 @@ class WM_OT_properties_edit(Operator): row = layout.row() row.prop(self, "use_soft_limits") - if bpy.app.use_override_library: - row.prop(self, "is_overridable_library") + row.prop(self, "is_overridable_library") row = layout.row(align=True) row.enabled = self.use_soft_limits diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 600f2b67bcc..c7556dad4fe 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -2272,8 +2272,7 @@ class VIEW3D_MT_object_relations(Menu): layout.operator("object.proxy_make", text="Make Proxy...") - if bpy.app.use_override_library: - layout.operator("object.make_override_library", text="Make Library Override...") + layout.operator("object.make_override_library", text="Make Library Override...") layout.operator("object.make_dupli_face") @@ -3893,6 +3892,8 @@ class VIEW3D_MT_edit_mesh_extrude(Menu): layout.operator("view3d.edit_mesh_extrude_move_shrink_fatten", text="Extrude Faces Along Normals"), 'FACE': lambda layout: layout.operator("mesh.extrude_faces_move", text="Extrude Individual Faces"), + 'MANIFOLD': lambda layout: + layout.operator("view3d.edit_mesh_extrude_manifold_normal", text="Extrude Manifold"), } @staticmethod @@ -3903,7 +3904,7 @@ class VIEW3D_MT_edit_mesh_extrude(Menu): menu = [] if mesh.total_face_sel: - menu += ['REGION', 'REGION_VERT_NORMAL', 'FACE'] + menu += ['REGION', 'REGION_VERT_NORMAL', 'FACE', 'MANIFOLD'] if mesh.total_edge_sel and (select_mode[0] or select_mode[1]): menu += ['EDGE'] if mesh.total_vert_sel and select_mode[0]: diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h index 22ede6dfa2d..8f6603e28ae 100644 --- a/source/blender/blenkernel/BKE_lib_override.h +++ b/source/blender/blenkernel/BKE_lib_override.h @@ -63,6 +63,10 @@ struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain, struct ID *reference_id, const bool do_tagged_remap); bool BKE_lib_override_library_create_from_tag(struct Main *bmain); +void BKE_lib_override_library_dependencies_tag(struct Main *bmain, + struct ID *id_root, + const uint tag, + const bool do_create_main_relashionships); struct IDOverrideLibraryProperty *BKE_lib_override_library_property_find( struct IDOverrideLibrary *override, const char *rna_path); diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 194d5074993..52a3521189b 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -491,6 +491,17 @@ static void manta_set_domain_from_mesh(FluidDomainSettings *fds, fds->cell_size[2] /= (float)fds->base_res[2]; } +static void update_final_gravity(FluidDomainSettings *fds, Scene *scene) +{ + if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { + copy_v3_v3(fds->gravity_final, scene->physics_settings.gravity); + } + else { + copy_v3_v3(fds->gravity_final, fds->gravity); + } + mul_v3_fl(fds->gravity_final, fds->effector_weights->global_gravity); +} + static bool BKE_fluid_modifier_init( FluidModifierData *fmd, Depsgraph *depsgraph, Object *ob, Scene *scene, Mesh *me) { @@ -502,10 +513,7 @@ static bool BKE_fluid_modifier_init( /* Set domain dimensions from mesh. */ manta_set_domain_from_mesh(fds, ob, me, true); /* Set domain gravity, use global gravity if enabled. */ - if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { - copy_v3_v3(fds->gravity, scene->physics_settings.gravity); - } - mul_v3_fl(fds->gravity, fds->effector_weights->global_gravity); + update_final_gravity(fds, scene); /* Reset domain values. */ zero_v3_int(fds->shift); zero_v3(fds->shift_f); @@ -3328,17 +3336,13 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obj mverts->co[1] = manta_liquid_get_vertex_y_at(fds->fluid, i); mverts->co[2] = manta_liquid_get_vertex_z_at(fds->fluid, i); - /* If reading raw data directly from manta, normalize now (e.g. during replay mode). - * If reading data from files from disk, omit this normalization. */ - if (!manta_liquid_mesh_from_file(fds->fluid)) { - // normalize to unit cube around 0 - mverts->co[0] -= ((float)fds->res[0] * fds->mesh_scale) * 0.5f; - mverts->co[1] -= ((float)fds->res[1] * fds->mesh_scale) * 0.5f; - mverts->co[2] -= ((float)fds->res[2] * fds->mesh_scale) * 0.5f; - mverts->co[0] *= fds->dx / fds->mesh_scale; - mverts->co[1] *= fds->dx / fds->mesh_scale; - mverts->co[2] *= fds->dx / fds->mesh_scale; - } + /* Adjust coordinates from Mantaflow to match viewport scaling. */ + float tmp[3] = {(float)fds->res[0], (float)fds->res[1], (float)fds->res[2]}; + /* Scale to unit cube around 0. */ + mul_v3_fl(tmp, fds->mesh_scale * 0.5f); + sub_v3_v3(mverts->co, tmp); + /* Apply scaling of domain object. */ + mul_v3_fl(mverts->co, fds->dx / fds->mesh_scale); mul_v3_v3(mverts->co, co_scale); add_v3_v3(mverts->co, co_offset); @@ -3808,10 +3812,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd, fds->time_per_frame = 0; /* Ensure that gravity is copied over every frame (could be keyframed). */ - if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { - copy_v3_v3(fds->gravity, scene->physics_settings.gravity); - mul_v3_fl(fds->gravity, fds->effector_weights->global_gravity); - } + update_final_gravity(fds, scene); int next_frame = scene_framenr + 1; int prev_frame = scene_framenr - 1; diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 009303b8c83..58856729f24 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -38,6 +38,7 @@ #include "BKE_key.h" #include "BKE_lib_id.h" #include "BKE_lib_override.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_main.h" @@ -354,6 +355,56 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain) return success; } +static bool lib_override_hierarchy_recursive_tag(Main *bmain, ID *id) +{ + MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->id_user_to_used, id); + + /* This way we won't process again that ID should we encounter it again through another + * relationship hierarchy. + * Note that this does not free any memory from relations, so we can still use the entries. + */ + BKE_main_relations_ID_remove(bmain, id); + + for (; entry != NULL; entry = entry->next) { + /* We only consider IDs from the same library. */ + if (entry->id_pointer != NULL && (*entry->id_pointer)->lib == id->lib) { + if (lib_override_hierarchy_recursive_tag(bmain, *entry->id_pointer)) { + id->tag |= LIB_TAG_DOIT; + } + } + } + + return (id->tag & LIB_TAG_DOIT) != 0; +} + +/** + * Tag all IDs in given \a bmain that use (depends on) given \a id_root ID. + * + * This will include all local IDs, and all IDs from the same library as the \a id_root. + * + * \param id_root The root of the hierarchy of dependencies to be tagged. + * \param do_create_main_relashionships Whether main relations needs to be created or already exist + * (in any case, they will be freed by this function). + */ +void BKE_lib_override_library_dependencies_tag(struct Main *bmain, + struct ID *id_root, + const uint tag, + const bool do_create_main_relashionships) +{ + id_root->tag |= tag; + + if (do_create_main_relashionships) { + BKE_main_relations_create(bmain, 0); + } + + /* Then we tag all intermediary data-blocks in-between two overridden ones (e.g. if a shapekey + * has a driver using an armature object's bone, we need to override the shapekey/obdata, the + * objects using them, etc.) */ + lib_override_hierarchy_recursive_tag(bmain, id_root); + + BKE_main_relations_free(bmain); +} + /* We only build override GHash on request. */ BLI_INLINE IDOverrideLibraryRuntime *override_library_rna_path_mapping_ensure( IDOverrideLibrary *override) diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index 6dd1abacf78..4ebef814337 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -28,7 +28,7 @@ * a call to a BLI function that is not prototyped here, please add a * prototype here. The library offers mathematical operations (mainly * vector and matrix calculus), an abstraction layer for file i/o, - * functions for calculating Perlin noise, scanfilling services for + * functions for calculating Perlin noise, scan-filling services for * triangles, and a system for guarded memory * allocation/deallocation. There is also a patch to make MS Windows * behave more or less Posix-compliant. diff --git a/source/blender/blenlib/BLI_memory_utils.hh b/source/blender/blenlib/BLI_memory_utils.hh index 133615f0f31..b73e0e95312 100644 --- a/source/blender/blenlib/BLI_memory_utils.hh +++ b/source/blender/blenlib/BLI_memory_utils.hh @@ -194,10 +194,6 @@ template<typename T> void initialized_move_n(T *src, uint n, T *dst) */ template<typename T> void uninitialized_move_n(T *src, uint n, T *dst) { - static_assert(std::is_nothrow_move_constructible_v<T>, - "Ideally, all types should have this property. We might have to remove this " - "limitation of a real reason comes up."); - uint current = 0; try { for (; current < n; current++) { diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index d6ae408f53e..d3191148c90 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -291,7 +291,7 @@ eFileAttributes BLI_file_attributes(const char *path) /* Return alias/shortcut file target. Apple version is defined in storage_apple.mm */ #ifndef __APPLE__ bool BLI_file_alias_target( - /* This parameter can only be const on non-windows plaforms. + /* This parameter can only be const on non-windows platforms. * NOLINTNEXTLINE: readability-non-const-parameter. */ char target[FILE_MAXDIR], const char *filepath) diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 1217b69f1b5..7f75c0100b8 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -315,7 +315,7 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene) copy_v2_fl2(scene->safe_areas.title, 0.1f, 0.05f); copy_v2_fl2(scene->safe_areas.action, 0.035f, 0.035f); - /* Change default cubemap quality. */ + /* Change default cube-map quality. */ scene->eevee.gi_filter_quality = 3.0f; /* Enable Soft Shadows by default. */ diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 8c48ae65d9b..f6e74c6822c 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -486,7 +486,7 @@ void EEVEE_downsample_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, int le } /** - * Simple down-sampling algorithm for cubemap. Reconstruct mip chain up to mip level. + * Simple down-sampling algorithm for cube-map. Reconstruct mip chain up to mip level. */ void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, int level) { diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index 78d50a02fc7..93d60d7518f 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -113,7 +113,7 @@ typedef struct EEVEE_LightBake { float samples_ct, invsamples_ct; /** Sampling bias during convolution step. */ float lod_factor; - /** Max cubemap LOD to sample when convolving. */ + /** Max cube-map LOD to sample when convolving. */ float lod_max; /** Number of probes to render + world probe. */ int cube_len, grid_len; @@ -121,7 +121,7 @@ typedef struct EEVEE_LightBake { /* Irradiance grid */ /** Current probe being rendered (UBO data). */ EEVEE_LightGrid *grid; - /** Target cubemap at MIP 0. */ + /** Target cube-map at MIP 0. */ int irr_cube_res; /** Size of the irradiance texture. */ int irr_size[3]; @@ -145,7 +145,7 @@ typedef struct EEVEE_LightBake { /* Reflection probe */ /** Current probe being rendered (UBO data). */ EEVEE_LightProbe *cube; - /** Target cubemap at MIP 0. */ + /** Target cube-map at MIP 0. */ int ref_cube_res; /** Index of the current cube. */ int cube_offset; diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c index 18365d69514..b89772441fa 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.c +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -107,9 +107,9 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, EEVEE_EffectsInfo *effects = stl->effects; EEVEE_PrivateData *g_data = stl->g_data; const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - View3DShading *shading = &v3d->shading; - Scene *scene = draw_ctx->scene; + /* The view will be NULL when rendering previews. */ + const View3D *v3d = draw_ctx->v3d; + const Scene *scene = draw_ctx->scene; const bool probe_render = pinfo != NULL; @@ -150,6 +150,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, } if (LOOK_DEV_STUDIO_LIGHT_ENABLED(v3d)) { + const View3DShading *shading = &v3d->shading; StudioLight *sl = BKE_studiolight_find(shading->lookdev_light, STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE); if (sl && (sl->flag & STUDIOLIGHT_TYPE_WORLD)) { diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c index 87ded7ef7ca..997f9a5be9d 100644 --- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -240,9 +240,9 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data view_is_valid = view_is_valid && (ED_screen_animation_no_scrub(wm) == NULL); } - effects->taa_total_sample = EEVEE_renderpasses_only_first_sample_pass_active(vedata) ? - 1 : - scene_eval->eevee.taa_samples; + const bool first_sample_only = EEVEE_renderpasses_only_first_sample_pass_active(vedata); + view_is_valid = view_is_valid && !first_sample_only; + effects->taa_total_sample = first_sample_only ? 1 : scene_eval->eevee.taa_samples; MAX2(effects->taa_total_sample, 0); DRW_view_persmat_get(NULL, persmat, false); diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h index 302f9a0d3a8..f05e8e2f9d6 100644 --- a/source/blender/draw/intern/draw_cache_extract.h +++ b/source/blender/draw/intern/draw_cache_extract.h @@ -60,6 +60,10 @@ typedef struct DRW_MeshCDMask { * modifiers could remove it. (see T68857) */ uint32_t edit_uv : 1; } DRW_MeshCDMask; +/* Keep `DRW_MeshCDMask` struct within an `uint64_t`. + * bit-wise and atomic operations are used to compare and update the struct. + * See `mesh_cd_layers_type_*` functions. */ +BLI_STATIC_ASSERT(sizeof(DRW_MeshCDMask) <= sizeof(uint64_t), "DRW_MeshCDMask exceeds 64 bits") typedef enum eMRIterType { MR_ITER_LOOPTRI = 1 << 0, diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index a22e0014bf5..40de0794b9e 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -74,22 +74,25 @@ static void mesh_batch_cache_clear(Mesh *me); /* Return true is all layers in _b_ are inside _a_. */ BLI_INLINE bool mesh_cd_layers_type_overlap(DRW_MeshCDMask a, DRW_MeshCDMask b) { - return (*((uint32_t *)&a) & *((uint32_t *)&b)) == *((uint32_t *)&b); + return (*((uint64_t *)&a) & *((uint64_t *)&b)) == *((uint64_t *)&b); } BLI_INLINE bool mesh_cd_layers_type_equal(DRW_MeshCDMask a, DRW_MeshCDMask b) { - return *((uint32_t *)&a) == *((uint32_t *)&b); + return *((uint64_t *)&a) == *((uint64_t *)&b); } BLI_INLINE void mesh_cd_layers_type_merge(DRW_MeshCDMask *a, DRW_MeshCDMask b) { - atomic_fetch_and_or_uint32((uint32_t *)a, *(uint32_t *)&b); + uint32_t *a_p = (uint32_t *)a; + uint32_t *b_p = (uint32_t *)&b; + atomic_fetch_and_or_uint32(a_p, *b_p); + atomic_fetch_and_or_uint32(a_p + 1, *(b_p + 1)); } BLI_INLINE void mesh_cd_layers_type_clear(DRW_MeshCDMask *a) { - *((uint32_t *)a) = 0; + *((uint64_t *)a) = 0; } static void mesh_cd_calc_edit_uv_layer(const Mesh *UNUSED(me), DRW_MeshCDMask *cd_used) diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c index b0af8641767..8955a666e22 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c @@ -314,7 +314,7 @@ static void gizmo_cage3d_draw_intern( } if (select) { - /* expand for hotspot */ + /* Expand for hot-spot. */ #if 0 const float size[3] = { size_real[0] + margin[0] / 2, diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 1ae8b33a03f..71b7d35908b 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_local_editable(struct bContext *C); bool ED_operator_object_active_editable_mesh(struct bContext *C); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 152c7656786..0394874e8c1 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -2123,7 +2123,7 @@ static KnifeVert *knife_find_closest_vert_of_face(KnifeTool_OpData *kcd, !ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, true)) { curv = kfv; curdis_sq = dis_sq; - copy_v3_v3(cur_kfv_sco, kfv_sco); + copy_v2_v2(cur_kfv_sco, kfv_sco); } } } @@ -2136,7 +2136,7 @@ static KnifeVert *knife_find_closest_vert_of_face(KnifeTool_OpData *kcd, /* update mouse coordinates to the snapped-to vertex's screen coordinates * this is important for angle snap, which uses the previous mouse position */ - copy_v3_v3(kcd->curr.mval, cur_kfv_sco); + copy_v2_v2(kcd->curr.mval, cur_kfv_sco); } return curv; diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 2f0969402ef..0cc4dcef442 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -778,6 +778,7 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, UvElement *newvlist = NULL, *vlist = element_map->vert[i]; UvElement *iterv, *v, *lastv, *next; float *uv, *uv2, uvdiff[2]; + bool uv_vert_sel, uv2_vert_sel; while (vlist) { v = vlist; @@ -788,6 +789,7 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, l = v->l; luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv = luv->uv; + uv_vert_sel = luv->flag & MLOOPUV_VERTSEL; lastv = NULL; iterv = vlist; @@ -798,12 +800,17 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, l = iterv->l; luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv2 = luv->uv; + uv2_vert_sel = luv->flag & MLOOPUV_VERTSEL; sub_v2_v2v2(uvdiff, uv2, uv); - if (fabsf(uvdiff[0]) < STD_UV_CONNECT_LIMIT && fabsf(uvdiff[1]) < STD_UV_CONNECT_LIMIT && - (!use_winding || - winding[BM_elem_index_get(iterv->l->f)] == winding[BM_elem_index_get(v->l->f)])) { + /* Check if the uv loops share the same selection state (if not, they are not connected as + * they have been ripped or other edit commands have seperated them). */ + bool connected = uv_vert_sel == uv2_vert_sel && fabsf(uvdiff[0]) < STD_UV_CONNECT_LIMIT && + fabsf(uvdiff[1]) < STD_UV_CONNECT_LIMIT; + + if (connected && (!use_winding || winding[BM_elem_index_get(iterv->l->f)] == + winding[BM_elem_index_get(v->l->f)])) { if (lastv) { lastv->next = next; } diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 49d80bc15ee..04113f70e52 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1463,6 +1463,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) { const bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_with_submode"); @@ -1567,7 +1574,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/object/object_relations.c b/source/blender/editors/object/object_relations.c index b81fea1848c..945c7e87eb1 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2242,28 +2242,6 @@ void OBJECT_OT_make_local(wmOperatorType *ot) /** \name Make Library Override Operator * \{ */ -static bool make_override_hierarchy_recursive_tag(Main *bmain, ID *id) -{ - MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->id_user_to_used, id); - - /* This way we won't process again that ID should we encounter it again through another - * relationship hierarchy. - * Note that this does not free any memory from relations, so we can still use the entries. - */ - BKE_main_relations_ID_remove(bmain, id); - - for (; entry != NULL; entry = entry->next) { - /* We only consider IDs from the same library. */ - if (entry->id_pointer != NULL && (*entry->id_pointer)->lib == id->lib) { - if (make_override_hierarchy_recursive_tag(bmain, *entry->id_pointer)) { - id->tag |= LIB_TAG_DOIT; - } - } - } - - return (id->tag & LIB_TAG_DOIT) != 0; -} - static int make_override_tag_ids_cb(LibraryIDLinkCallbackData *cb_data) { if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_LOOPBACK)) { @@ -2315,14 +2293,9 @@ static int make_override_library_invoke(bContext *C, wmOperator *op, const wmEve return OPERATOR_CANCELLED; } - /* Get object to work on - use a menu if we need to... */ - if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL && - ID_IS_LINKED(obact->instance_collection)) { - /* Gives menu with list of objects in group. */ - WM_enum_search_invoke(C, op, event); - return OPERATOR_CANCELLED; - } - if (ID_IS_LINKED(obact)) { + if ((!ID_IS_LINKED(obact) && obact->instance_collection != NULL && + ID_IS_OVERRIDABLE_LIBRARY(obact->instance_collection)) || + ID_IS_OVERRIDABLE_LIBRARY(obact)) { uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION); uiLayout *layout = UI_popup_menu_layout(pup); @@ -2337,6 +2310,11 @@ static int make_override_library_invoke(bContext *C, wmOperator *op, const wmEve /* This invoke just calls another instance of this operator... */ return OPERATOR_INTERFACE; } + else if (ID_IS_LINKED(obact)) { + /* Show menu with list of directly linked collections containing the active object. */ + WM_enum_search_invoke(C, op, event); + return OPERATOR_CANCELLED; + } /* Error.. cannot continue. */ BKE_report(op->reports, @@ -2366,11 +2344,28 @@ static int make_override_library_exec(bContext *C, wmOperator *op) id_root = &obact->instance_collection->id; } else if (!ID_IS_OVERRIDABLE_LIBRARY(obact)) { - BKE_reportf(op->reports, - RPT_ERROR_INVALID_INPUT, - "Active object '%s' is not overridable", - obact->id.name + 2); - return OPERATOR_CANCELLED; + const int i = RNA_property_enum_get(op->ptr, op->type->prop); + const uint collection_session_uuid = *((uint *)&i); + if (collection_session_uuid == MAIN_ID_SESSION_UUID_UNSET) { + BKE_reportf(op->reports, + RPT_ERROR_INVALID_INPUT, + "Active object '%s' is not overridable", + obact->id.name + 2); + return OPERATOR_CANCELLED; + } + + Collection *collection = BLI_listbase_bytes_find(&bmain->collections, + &collection_session_uuid, + sizeof(collection_session_uuid), + offsetof(ID, session_uuid)); + if (!ID_IS_OVERRIDABLE_LIBRARY(collection)) { + BKE_reportf(op->reports, + RPT_ERROR_INVALID_INPUT, + "Could not find an overridable collection containing object '%s'", + obact->id.name + 2); + return OPERATOR_CANCELLED; + } + id_root = &collection->id; } /* Else, poll func ensures us that ID_IS_LINKED(obact) is true. */ else { @@ -2399,12 +2394,8 @@ static int make_override_library_exec(bContext *C, wmOperator *op) } } - /* Then we tag all intermediary data-blocks in-between two overridden ones (e.g. if a shapekey - * has a driver using an armature object's bone, we need to override the shapekey/obdata, the - * objects using them, etc.) */ - make_override_hierarchy_recursive_tag(bmain, id_root); - - BKE_main_relations_free(bmain); + /* Note that this call will also free the main relations data we created above. */ + BKE_lib_override_library_dependencies_tag(bmain, id_root, LIB_TAG_DOIT, false); ID *id; FOREACH_MAIN_ID_BEGIN (bmain, id) { @@ -2524,9 +2515,39 @@ static bool make_override_library_poll(bContext *C) /* Object must be directly linked to be overridable. */ return (ED_operator_objectmode(C) && obact != NULL && - ((ID_IS_LINKED(obact) && obact->id.tag & LIB_TAG_EXTERN) || - (!ID_IS_LINKED(obact) && obact->instance_collection != NULL && - ID_IS_LINKED(obact->instance_collection)))); + (ID_IS_LINKED(obact) || (obact->instance_collection != NULL && + ID_IS_OVERRIDABLE_LIBRARY(obact->instance_collection)))); +} + +static const EnumPropertyItem *make_override_collections_of_linked_object_itemf( + bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) +{ + EnumPropertyItem item_tmp = {0}, *item = NULL; + int totitem = 0; + + Object *object = ED_object_active_context(C); + Main *bmain = CTX_data_main(C); + + if (!object || !ID_IS_LINKED(object)) { + return DummyRNA_DEFAULT_items; + } + + LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { + /* Only check for directly linked collections. */ + if (!ID_IS_LINKED(&collection->id) || (collection->id.tag & LIB_TAG_INDIRECT) != 0) { + continue; + } + if (BKE_collection_has_object_recursive(collection, object)) { + item_tmp.identifier = item_tmp.name = collection->id.name + 2; + item_tmp.value = *((int *)&collection->id.session_uuid); + RNA_enum_item_add(&item, &totitem, &item_tmp); + } + } + + RNA_enum_item_end(&item, &totitem); + *r_free = true; + + return item; } void OBJECT_OT_make_override_library(wmOperatorType *ot) @@ -2547,12 +2568,13 @@ void OBJECT_OT_make_override_library(wmOperatorType *ot) /* properties */ PropertyRNA *prop; prop = RNA_def_enum(ot->srna, - "object", + "collection", DummyRNA_DEFAULT_items, - 0, - "Override Object", - "Name of lib-linked/collection object to make an override from"); - RNA_def_enum_funcs(prop, proxy_collection_object_itemf); + MAIN_ID_SESSION_UUID_UNSET, + "Override Collection", + "Name of directly linked collection containing the selected object, to make " + "an override from"); + RNA_def_enum_funcs(prop, make_override_collections_of_linked_object_itemf); RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE); ot->prop = prop; } diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 583c68cb284..26b5f7fb2af 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -546,6 +546,7 @@ static int fluid_bake_exec(struct bContext *C, struct wmOperator *op) return OPERATOR_CANCELLED; } if (!fluid_validatepaths(job, op->reports)) { + fluid_bake_free(job); return OPERATOR_CANCELLED; } WM_report_banners_cancel(job->bmain); @@ -574,6 +575,7 @@ static int fluid_bake_invoke(struct bContext *C, } if (!fluid_validatepaths(job, op->reports)) { + fluid_bake_free(job); return OPERATOR_CANCELLED; } @@ -651,6 +653,7 @@ static int fluid_free_exec(struct bContext *C, struct wmOperator *op) job->name = op->type->name; if (!fluid_validatepaths(job, op->reports)) { + fluid_bake_free(job); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 1555dce8b79..b034fb186d2 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -349,7 +349,7 @@ bool ED_operator_object_active(bContext *C) return ((ob != NULL) && !ed_object_hidden(ob)); } -static bool operator_object_active_editable_ex(const Object *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)); } @@ -357,14 +357,14 @@ static bool operator_object_active_editable_ex(const Object *ob) bool ED_operator_object_active_editable(bContext *C) { Object *ob = ED_object_active_context(C); - return operator_object_active_editable_ex(ob); + return ED_operator_object_active_editable_ex(C, ob); } /** Object must be editable and fully local (i.e. not an override). */ bool ED_operator_object_active_local_editable(bContext *C) { Object *ob = ED_object_active_context(C); - return operator_object_active_editable_ex(ob) && !ID_IS_OVERRIDE_LIBRARY(ob); + return ED_operator_object_active_editable_ex(C, ob) && !ID_IS_OVERRIDE_LIBRARY(ob); } bool ED_operator_object_active_editable_mesh(bContext *C) diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 5d0db9eaa2e..3ce80c11160 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -2660,9 +2660,9 @@ static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist) if (filelist->dir[0] == 0) { /* make directories */ # ifdef WITH_FREESTYLE - filelist->filelist.nbr_entries = 27; + filelist->filelist.nbr_entries = 27; # else - filelist->filelist.nbr_entries = 26; + filelist->filelist.nbr_entries = 26; # endif filelist_resize(filelist, filelist->filelist.nbr_entries); @@ -2693,11 +2693,11 @@ static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist) filelist->filelist.entries[20].entry->relpath = BLI_strdup("Action"); filelist->filelist.entries[21].entry->relpath = BLI_strdup("NodeTree"); filelist->filelist.entries[22].entry->relpath = BLI_strdup("Speaker"); - filelist->filelist.entries[23].entry->relpath = BLI_strdup("Hair"); - filelist->filelist.entries[24].entry->relpath = BLI_strdup("Point Cloud"); - filelist->filelist.entries[25].entry->relpath = BLI_strdup("Volume"); + filelist->filelist.entries[23].entry->relpath = BLI_strdup("Hair"); + filelist->filelist.entries[24].entry->relpath = BLI_strdup("Point Cloud"); + filelist->filelist.entries[25].entry->relpath = BLI_strdup("Volume"); # ifdef WITH_FREESTYLE - filelist->filelist.entries[26].entry->relpath = BLI_strdup("FreestyleLineStyle"); + filelist->filelist.entries[26].entry->relpath = BLI_strdup("FreestyleLineStyle"); # endif } else { diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index ac78c711a1a..f0287984268 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -54,6 +54,7 @@ #include "BKE_context.h" #include "BKE_fcurve.h" #include "BKE_global.h" +#include "BKE_idtype.h" #include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_lib_override.h" @@ -739,22 +740,63 @@ static void id_local_cb(bContext *C, } } +typedef struct OutlinerLibOverrideData { + bool do_hierarchy; +} OutlinerLibOverrideData; + static void id_override_library_cb(bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), - TreeElement *UNUSED(te), + TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, - void *UNUSED(user_data)) + void *user_data) { - if (ID_IS_OVERRIDABLE_LIBRARY(tselem->id)) { + BLI_assert(TSE_IS_REAL_ID(tselem)); + ID *id_root = tselem->id; + + if (ID_IS_LINKED(id_root) && + (BKE_idtype_get_info_from_id(id_root)->flags & IDTYPE_FLAGS_NO_LIBLINKING) == 0) { Main *bmain = CTX_data_main(C); + OutlinerLibOverrideData *data = user_data; + const bool do_hierarchy = data->do_hierarchy; + + id_root->tag |= LIB_TAG_DOIT; + + printf("%s: Tagging root id %s\n", __func__, id_root->name); + /* For now, remapp all local usages of linked ID to local override one here. */ - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, true); - ID *override_id = BKE_lib_override_library_create_from_id(bmain, tselem->id, true); - if (override_id != NULL) { - BKE_main_id_clear_newpoins(bmain); + ID *id_iter; + FOREACH_MAIN_ID_BEGIN (bmain, id_iter) { + if (ID_IS_LINKED(id_iter)) { + id_iter->tag &= ~LIB_TAG_DOIT; + } + else { + id_iter->tag |= LIB_TAG_DOIT; + } } + FOREACH_MAIN_ID_END; + + if (do_hierarchy) { + /* Tag all linked parents in tree hierarchy to be also overridden. */ + while ((te = te->parent) != NULL) { + if (!TSE_IS_REAL_ID(te->store_elem)) { + continue; + } + if (!ID_IS_LINKED(te->store_elem->id)) { + break; + } + te->store_elem->id->tag |= LIB_TAG_DOIT; + printf("%s: Tagging parent id %s\n", __func__, te->store_elem->id->name); + } + BKE_lib_override_library_dependencies_tag(bmain, id_root, LIB_TAG_DOIT, true); + BKE_lib_override_library_create_from_tag(bmain); + } + else if (ID_IS_OVERRIDABLE_LIBRARY(id_root)) { + BKE_lib_override_library_create_from_id(bmain, id_root, true); + } + + BKE_main_id_clear_newpoins(bmain); BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); } } @@ -1326,8 +1368,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); - /* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth trick - * does not work here). */ + /* 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); @@ -1508,6 +1550,7 @@ typedef enum eOutlinerIdOpTypes { OUTLINER_IDOP_UNLINK, OUTLINER_IDOP_LOCAL, OUTLINER_IDOP_OVERRIDE_LIBRARY, + OUTLINER_IDOP_OVERRIDE_LIBRARY_HIERARCHY, OUTLINER_IDOP_SINGLE, OUTLINER_IDOP_DELETE, OUTLINER_IDOP_REMAP, @@ -1531,6 +1574,11 @@ static const EnumPropertyItem prop_id_op_types[] = { 0, "Add Library Override", "Add a local override of this linked data-block"}, + {OUTLINER_IDOP_OVERRIDE_LIBRARY_HIERARCHY, + "OVERRIDE_LIBRARY_HIERARCHY", + 0, + "Add Library Override Hierarchy", + "Add a local override of this linked data-block, and its hierarchy of dependencies"}, {OUTLINER_IDOP_SINGLE, "SINGLE", 0, "Make Single User", ""}, {OUTLINER_IDOP_DELETE, "DELETE", ICON_X, "Delete", ""}, {OUTLINER_IDOP_REMAP, @@ -1678,8 +1726,25 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op) } case OUTLINER_IDOP_OVERRIDE_LIBRARY: { /* make local */ - outliner_do_libdata_operation( - C, op->reports, scene, soops, &soops->tree, id_override_library_cb, NULL); + outliner_do_libdata_operation(C, + op->reports, + scene, + soops, + &soops->tree, + id_override_library_cb, + &(OutlinerLibOverrideData){.do_hierarchy = false}); + ED_undo_push(C, "Overridden Data"); + break; + } + case OUTLINER_IDOP_OVERRIDE_LIBRARY_HIERARCHY: { + /* make local */ + outliner_do_libdata_operation(C, + op->reports, + scene, + soops, + &soops->tree, + id_override_library_cb, + &(OutlinerLibOverrideData){.do_hierarchy = true}); ED_undo_push(C, "Overridden Data"); break; } diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index d68489759fe..be6af1e3a99 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -1270,6 +1270,9 @@ void createTransData(bContext *C, TransInfo *t) set_prop_dist(t, false); } } + else if (convert_type == TC_MESH_UV && t->flag & T_PROP_CONNECTED) { + /* Already calculated by uv_set_connectivity_distance. */ + } else if (convert_type == TC_CURVE_VERTS && t->obedit_type == OB_CURVE) { set_prop_dist(t, false); } diff --git a/source/blender/editors/transform/transform_convert_mesh_uv.c b/source/blender/editors/transform/transform_convert_mesh_uv.c index 41c09cd8ea2..56fa2d90fb2 100644 --- a/source/blender/editors/transform/transform_convert_mesh_uv.c +++ b/source/blender/editors/transform/transform_convert_mesh_uv.c @@ -26,6 +26,7 @@ #include "MEM_guardedalloc.h" #include "BLI_bitmap.h" +#include "BLI_linklist_stack.h" #include "BLI_math.h" #include "BKE_context.h" @@ -51,12 +52,13 @@ static void UVsToTransData(const float aspect[2], TransData2D *td2d, float *uv, const float *center, + float calc_dist, bool selected) { - /* uv coords are scaled by aspects. this is needed for rotations and - * proportional editing to be consistent with the stretched uv coords - * that are displayed. this also means that for display and numinput, - * and when the uv coords are flushed, these are converted each time */ + /* UV coords are scaled by aspects. this is needed for rotations and + * proportional editing to be consistent with the stretched UV coords + * that are displayed. this also means that for display and number-input, + * and when the UV coords are flushed, these are converted each time. */ td2d->loc[0] = uv[0] * aspect[0]; td2d->loc[1] = uv[1] * aspect[1]; td2d->loc[2] = 0.0f; @@ -79,12 +81,182 @@ static void UVsToTransData(const float aspect[2], td->dist = 0.0; } else { - td->dist = FLT_MAX; + td->dist = calc_dist; } unit_m3(td->mtx); unit_m3(td->smtx); } +/** + * \param dists: Store the closest connected distance to selected vertices. + */ +static void uv_set_connectivity_distance(BMesh *bm, float *dists, const float aspect[2]) +{ + /* Mostly copied from editmesh_set_connectivity_distance. */ + BLI_LINKSTACK_DECLARE(queue, BMLoop *); + + /* Any BM_ELEM_TAG'd loop is added to 'queue_next', this makes sure that we don't add things + * twice. */ + BLI_LINKSTACK_DECLARE(queue_next, BMLoop *); + + BLI_LINKSTACK_INIT(queue); + BLI_LINKSTACK_INIT(queue_next); + + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + BMIter fiter, liter; + BMVert *f; + BMLoop *l; + + BM_mesh_elem_index_ensure(bm, BM_LOOP); + + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + /* Visable faces was tagged in createTransUVs. */ + if (!BM_elem_flag_test(f, BM_ELEM_TAG)) { + continue; + } + + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + float dist; + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + bool uv_vert_sel = luv->flag & MLOOPUV_VERTSEL; + + if (uv_vert_sel) { + BLI_LINKSTACK_PUSH(queue, l); + dist = 0.0f; + } + else { + dist = FLT_MAX; + } + + /* Make sure all loops are in a clean tag state. */ + BLI_assert(BM_elem_flag_test(l, BM_ELEM_TAG) == 0); + + int loop_idx = BM_elem_index_get(l); + + dists[loop_idx] = dist; + } + } + + /* Need to be very careful of feedback loops here, store previous dist's to avoid feedback. */ + float *dists_prev = MEM_dupallocN(dists); + + do { + while ((l = BLI_LINKSTACK_POP(queue))) { + BLI_assert(dists[BM_elem_index_get(l)] != FLT_MAX); + + BMLoop *l_other, *l_connected; + BMIter l_connected_iter; + + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + float l_uv[2]; + + copy_v2_v2(l_uv, luv->uv); + mul_v2_v2(l_uv, aspect); + + BM_ITER_ELEM (l_other, &liter, l->f, BM_LOOPS_OF_FACE) { + if (l_other == l) { + continue; + } + float other_uv[2], edge_vec[2]; + MLoopUV *luv_other = BM_ELEM_CD_GET_VOID_P(l_other, cd_loop_uv_offset); + + copy_v2_v2(other_uv, luv_other->uv); + mul_v2_v2(other_uv, aspect); + + sub_v2_v2v2(edge_vec, l_uv, other_uv); + + const int i = BM_elem_index_get(l); + const int i_other = BM_elem_index_get(l_other); + float dist = len_v2(edge_vec) + dists_prev[i]; + + if (dist < dists[i_other]) { + dists[i_other] = dist; + } + else { + /* The face loop already has a shorter path to it. */ + continue; + } + + float connected_uv[2]; + float uvdiff[2]; + + bool other_vert_sel, connected_vert_sel; + + other_vert_sel = luv_other->flag & MLOOPUV_VERTSEL; + + BM_ITER_ELEM (l_connected, &l_connected_iter, l_other->v, BM_LOOPS_OF_VERT) { + if (l_connected == l_other) { + continue; + } + /* Visable faces was tagged in createTransUVs. */ + if (!BM_elem_flag_test(l_connected->f, BM_ELEM_TAG)) { + continue; + } + + MLoopUV *luv_connected = BM_ELEM_CD_GET_VOID_P(l_connected, cd_loop_uv_offset); + connected_vert_sel = luv_connected->flag & MLOOPUV_VERTSEL; + copy_v2_v2(connected_uv, luv_connected->uv); + mul_v2_v2(connected_uv, aspect); + + sub_v2_v2v2(uvdiff, connected_uv, other_uv); + /* Check if this loop is connected in UV space. + * If the uv loops share the same selection state (if not, they are not connected as + * they have been ripped or other edit commands have separated them). */ + bool connected = other_vert_sel == connected_vert_sel && + fabsf(uvdiff[0]) < STD_UV_CONNECT_LIMIT && + fabsf(uvdiff[1]) < STD_UV_CONNECT_LIMIT; + if (!connected) { + continue; + } + + /* The loop vert is occupying the same space, so it has the same distance. */ + const int i_connected = BM_elem_index_get(l_connected); + dists[i_connected] = dist; + + if (BM_elem_flag_test(l_connected, BM_ELEM_TAG) == 0) { + BM_elem_flag_enable(l_connected, BM_ELEM_TAG); + BLI_LINKSTACK_PUSH(queue_next, l_connected); + } + } + } + } + + /* Clear elem flags for the next loop. */ + for (LinkNode *lnk = queue_next; lnk; lnk = lnk->next) { + BMLoop *l_link = lnk->link; + const int i = BM_elem_index_get(l_link); + + BM_elem_flag_disable(l_link, BM_ELEM_TAG); + + /* Store all new dist values. */ + dists_prev[i] = dists[i]; + } + + BLI_LINKSTACK_SWAP(queue, queue_next); + + } while (BLI_LINKSTACK_SIZE(queue)); + +#ifndef NDEBUG + /* Check that we didn't leave any loops tagged */ + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + /* Visable faces was tagged in createTransUVs. */ + if (!BM_elem_flag_test(f, BM_ELEM_TAG)) { + continue; + } + + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + BLI_assert(BM_elem_flag_test(l, BM_ELEM_TAG) == 0); + } + } +#endif + + BLI_LINKSTACK_FREE(queue); + BLI_LINKSTACK_FREE(queue_next); + + MEM_freeN(dists_prev); +} + void createTransUVs(bContext *C, TransInfo *t) { SpaceImage *sima = CTX_wm_space_image(C); @@ -103,12 +275,11 @@ void createTransUVs(bContext *C, TransInfo *t) BMFace *efa; BMIter iter, liter; UvElementMap *elementmap = NULL; - BLI_bitmap *island_enabled = NULL; struct { float co[2]; int co_num; } *island_center = NULL; - int count = 0, countsel = 0, count_rejected = 0; + int count = 0, countsel = 0; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); if (!ED_space_image_show_uvedit(sima, tc->obedit)) { @@ -116,22 +287,15 @@ void createTransUVs(bContext *C, TransInfo *t) } /* count */ - if (is_prop_connected || is_island_center) { + if (is_island_center) { /* create element map with island information */ const bool use_facesel = (ts->uv_flag & UV_SYNC_SELECTION) == 0; - const bool use_uvsel = !is_prop_connected; - elementmap = BM_uv_element_map_create(em->bm, scene, use_facesel, use_uvsel, false, true); + elementmap = BM_uv_element_map_create(em->bm, scene, use_facesel, true, false, true); if (elementmap == NULL) { continue; } - if (is_prop_connected) { - island_enabled = BLI_BITMAP_NEW(elementmap->totalIslands, "TransIslandData(UV Editing)"); - } - - if (is_island_center) { - island_center = MEM_callocN(sizeof(*island_center) * elementmap->totalIslands, __func__); - } + island_center = MEM_callocN(sizeof(*island_center) * elementmap->totalIslands, __func__); } BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { @@ -147,20 +311,14 @@ void createTransUVs(bContext *C, TransInfo *t) if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { countsel++; - if (is_prop_connected || island_center) { + if (island_center) { UvElement *element = BM_uv_element_get(elementmap, efa, l); - if (is_prop_connected) { - BLI_BITMAP_ENABLE(island_enabled, element->island); - } - - if (is_island_center) { - if (element->flag == false) { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - add_v2_v2(island_center[element->island].co, luv->uv); - island_center[element->island].co_num++; - element->flag = true; - } + if (element->flag == false) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + add_v2_v2(island_center[element->island].co, luv->uv); + island_center[element->island].co_num++; + element->flag = true; } } } @@ -198,6 +356,14 @@ void createTransUVs(bContext *C, TransInfo *t) td = tc->data; td2d = tc->data_2d; + float *prop_dists = NULL; + + if (is_prop_connected) { + prop_dists = MEM_callocN(em->bm->totloop * sizeof(float), "TransObPropDists(UV Editing)"); + + uv_set_connectivity_distance(em->bm, prop_dists, t->aspect); + } + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BMLoop *l; @@ -209,52 +375,41 @@ void createTransUVs(bContext *C, TransInfo *t) const bool selected = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); MLoopUV *luv; const float *center = NULL; + float prop_distance = FLT_MAX; if (!is_prop_edit && !selected) { continue; } - if (is_prop_connected || is_island_center) { + if (is_prop_connected) { + const int idx = BM_elem_index_get(l); + prop_distance = prop_dists[idx]; + } + + if (is_island_center) { UvElement *element = BM_uv_element_get(elementmap, efa, l); if (element) { - if (is_prop_connected) { - if (!BLI_BITMAP_TEST(island_enabled, element->island)) { - count_rejected++; - continue; - } - } - - if (is_island_center) { - center = island_center[element->island].co; - } + center = island_center[element->island].co; } } - BM_elem_flag_enable(l, BM_ELEM_TAG); luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - UVsToTransData(t->aspect, td++, td2d++, luv->uv, center, selected); + UVsToTransData(t->aspect, td++, td2d++, luv->uv, center, prop_distance, selected); } } - if (is_prop_connected) { - tc->data_len -= count_rejected; - } - if (sima->flag & SI_LIVE_UNWRAP) { ED_uvedit_live_unwrap_begin(t->scene, tc->obedit); } finally: - if (is_prop_connected || is_island_center) { + if (is_prop_connected) { + MEM_freeN(prop_dists); + } + if (is_island_center) { BM_uv_element_map_free(elementmap); - if (is_prop_connected) { - MEM_freeN(island_enabled); - } - - if (island_center) { - MEM_freeN(island_center); - } + MEM_freeN(island_center); } } } diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index aee05197f10..cde06a9eaac 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -67,15 +67,27 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_ dist = len_v3(t->num.val); } else { + int i = 0; float dvec[3]; - - copy_v3_v3(dvec, vec); - applyAspectRatio(t, dvec); + if (!(t->flag & T_2D_EDIT) && t->con.mode & CON_APPLY) { + zero_v3(dvec); + if (t->con.mode & CON_AXIS0) { + dvec[i++] = vec[0]; + } + if (t->con.mode & CON_AXIS1) { + dvec[i++] = vec[1]; + } + if (t->con.mode & CON_AXIS2) { + dvec[i++] = vec[2]; + } + } + else { + copy_v3_v3(dvec, vec); + applyAspectRatio(t, dvec); + } dist = len_v3(vec); if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) { - int i; - for (i = 0; i < 3; i++) { bUnit_AsString2(&tvec[NUM_STR_REP_LEN * i], NUM_STR_REP_LEN, diff --git a/source/blender/editors/transform/transform_mode_vert_slide.c b/source/blender/editors/transform/transform_mode_vert_slide.c index 9e810b9c629..4bcc4cc6383 100644 --- a/source/blender/editors/transform/transform_mode_vert_slide.c +++ b/source/blender/editors/transform/transform_mode_vert_slide.c @@ -500,6 +500,10 @@ static void doVertSlide(TransInfo *t, float perc) FOREACH_TRANS_DATA_CONTAINER (t, tc) { VertSlideData *sld = tc->custom.mode.data; + if (sld == NULL) { + continue; + } + TransDataVertSlideVert *svlist = sld->sv, *sv; int i; diff --git a/source/blender/editors/uvedit/uvedit_rip.c b/source/blender/editors/uvedit/uvedit_rip.c index cd518e25971..562f0ce84c1 100644 --- a/source/blender/editors/uvedit/uvedit_rip.c +++ b/source/blender/editors/uvedit/uvedit_rip.c @@ -962,7 +962,7 @@ void UV_OT_rip(wmOperatorType *ot) ot->poll = ED_operator_uvedit; /* translation data */ - Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY); + Transform_Properties(ot, P_MIRROR_DUMMY); /* properties */ RNA_def_float_vector( diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c index 22dfc924f55..206c172d8d5 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c @@ -83,7 +83,7 @@ static void deformStroke(GpencilModifierData *md, mmd->material, mmd->pass_index, mmd->layer_pass, - mmd->mode == GP_SIMPLIFY_SAMPLE ? 3 : 4, + mmd->mode == GP_SIMPLIFY_SAMPLE ? 2 : 4, gpl, gps, mmd->flag & GP_SIMPLIFY_INVERT_LAYER, diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 0fd373d37a3..d1c7aba37df 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -348,7 +348,7 @@ void gpu_extensions_init(void) GG.mip_render_workaround = true; } - /* Intel Ivy Bridge GPU's seems to have buggy cubemap array support. (see T75943) */ + /* Intel Ivy Bridge GPU's seems to have buggy cube-map array support. (see T75943) */ if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) && (strstr(renderer, "HD Graphics 4000") || strstr(renderer, "HD Graphics 2500"))) { GG.glew_arb_texture_cube_map_array_is_supported = false; diff --git a/source/blender/io/collada/ArmatureImporter.cpp b/source/blender/io/collada/ArmatureImporter.cpp index 3755b71f300..bd5bd913a18 100644 --- a/source/blender/io/collada/ArmatureImporter.cpp +++ b/source/blender/io/collada/ArmatureImporter.cpp @@ -969,8 +969,8 @@ void ArmatureImporter::make_shape_keys(bContext *C) /* insert other shape keys */ for (int i = 0; i < morphTargetIds.getCount(); i++) { - /* better to have a separate map of morph objects, - * This'll do for now since only mesh morphing is imported */ + /* Better to have a separate map of morph objects, + * This will do for now since only mesh morphing is imported. */ Mesh *me = this->mesh_importer->get_mesh_by_geom_uid(morphTargetIds[i]); diff --git a/source/blender/makesdna/DNA_fluid_types.h b/source/blender/makesdna/DNA_fluid_types.h index b54ff7ccc17..909170523a3 100644 --- a/source/blender/makesdna/DNA_fluid_types.h +++ b/source/blender/makesdna/DNA_fluid_types.h @@ -471,9 +471,10 @@ typedef struct FluidDomainSettings { int res_max[3]; /* Cell max. */ int res[3]; /* Data resolution (res_max-res_min). */ int total_cells; - float dx; /* 1.0f / res. */ - float scale; /* Largest domain size. */ - int boundary_width; /* Usually this is just 1. */ + float dx; /* 1.0f / res. */ + float scale; /* Largest domain size. */ + int boundary_width; /* Usually this is just 1. */ + float gravity_final[3]; /* Scene or domain gravity multiplied with gravity weight. */ /* -- User-accesible fields (from here on). -- */ @@ -481,7 +482,6 @@ typedef struct FluidDomainSettings { int adapt_margin; int adapt_res; float adapt_threshold; - char _pad1[4]; /* Unused. */ /* Fluid domain options */ int maxres; /* Longest axis on the BB gets this resolution assigned. */ diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index ab0cc6def6f..3387958c2f6 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -161,7 +161,7 @@ static void rna_Fluid_flow_reset(Main *bmain, Scene *scene, PointerRNA *ptr) rna_Fluid_update(bmain, scene, ptr); } -static void rna_Fluid_domain_reset(Main *bmain, Scene *scene, PointerRNA *ptr) +static void rna_Fluid_domain_data_reset(Main *bmain, Scene *scene, PointerRNA *ptr) { # ifdef WITH_FLUID FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data; @@ -172,6 +172,39 @@ static void rna_Fluid_domain_reset(Main *bmain, Scene *scene, PointerRNA *ptr) rna_Fluid_update(bmain, scene, ptr); } +static void rna_Fluid_domain_noise_reset(Main *bmain, Scene *scene, PointerRNA *ptr) +{ +# ifdef WITH_FLUID + FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data; + BKE_fluid_modifier_reset(settings->fmd); +# endif + + rna_Fluid_noisecache_reset(bmain, scene, ptr); + rna_Fluid_update(bmain, scene, ptr); +} + +static void rna_Fluid_domain_mesh_reset(Main *bmain, Scene *scene, PointerRNA *ptr) +{ +# ifdef WITH_FLUID + FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data; + BKE_fluid_modifier_reset(settings->fmd); +# endif + + rna_Fluid_meshcache_reset(bmain, scene, ptr); + rna_Fluid_update(bmain, scene, ptr); +} + +static void rna_Fluid_domain_particles_reset(Main *bmain, Scene *scene, PointerRNA *ptr) +{ +# ifdef WITH_FLUID + FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data; + BKE_fluid_modifier_reset(settings->fmd); +# endif + + rna_Fluid_particlescache_reset(bmain, scene, ptr); + rna_Fluid_update(bmain, scene, ptr); +} + static void rna_Fluid_reset_dependency(Main *bmain, Scene *scene, PointerRNA *ptr) { # ifdef WITH_FLUID @@ -232,7 +265,7 @@ static void rna_Fluid_flip_parts_update(Main *bmain, Scene *scene, PointerRNA *p if (fmd->domain->type != FLUID_DOMAIN_TYPE_LIQUID) { rna_Fluid_parts_delete(ptr, PART_FLUID_FLIP); fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FLIP; - rna_Fluid_domain_reset(bmain, scene, ptr); + rna_Fluid_domain_data_reset(bmain, scene, ptr); return; } @@ -1350,7 +1383,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Adaptive Domain", "Adapt simulation resolution and size to fluid"); 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_domain_data_reset"); /* fluid domain options */ @@ -1364,7 +1397,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Resolution used for the fluid domain. Value corresponds to the longest domain side " "(resolution for other domain sides is calculated automatically)"); 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_domain_data_reset"); prop = RNA_def_property(srna, "use_collision_border_front", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_FRONT); @@ -1547,7 +1580,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "The noise simulation is scaled up by this factor (compared to the " "base resolution of the domain)"); 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_domain_noise_reset"); prop = RNA_def_property(srna, "noise_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "noise_type"); @@ -1555,7 +1588,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Noise Method", "Noise method which is used during the high-res simulation"); 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_domain_noise_reset"); prop = RNA_def_property(srna, "use_noise", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_NOISE); @@ -1569,7 +1602,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "simulation_method"); RNA_def_property_enum_items(prop, simulation_methods); RNA_def_property_ui_text(prop, "Simulation Method", "Change the underlying simulation method"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_data_reset"); prop = RNA_def_property(srna, "flip_ratio", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 1.0); @@ -1657,7 +1690,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Use Diffusion", "Enable fluid diffusion settings (e.g. viscosity, surface tension)"); 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_datacache_reset"); prop = RNA_def_property(srna, "surface_tension", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 100.0); @@ -1724,7 +1757,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_meshcache_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_mesh_reset"); prop = RNA_def_property(srna, "mesh_generator", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mesh_generator"); @@ -1924,7 +1957,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "The particle simulation is scaled up by this factor (compared to the " "base resolution of the domain)"); 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_domain_particles_reset"); prop = RNA_def_property(srna, "use_spray_particles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "particle_type", FLUID_DOMAIN_PARTICLE_SPRAY); @@ -2081,7 +2114,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_enum_items(prop, cache_types); RNA_def_property_enum_funcs(prop, NULL, "rna_Fluid_cachetype_set", NULL); RNA_def_property_ui_text(prop, "Type", "Change the cache type of the simulation"); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_domain_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_domain_data_reset"); prop = RNA_def_property(srna, "cache_resumable", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_RESUMABLE_CACHE); @@ -2158,7 +2191,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "only needed if you plan to analyze the cache (e.g. view grids, velocity vectors, " "particles) in Mantaflow directly (outside of Blender) after baking the simulation"); 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_domain_data_reset"); /* time options */ @@ -2655,7 +2688,7 @@ static void rna_def_fluid_effector_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "use_plane_init", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_EFFECTOR_USE_PLANE_INIT); RNA_def_property_ui_text(prop, "Is Planar", "Treat this object as a planar, unclosed mesh"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_data_reset"); prop = RNA_def_property(srna, "velocity_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "vel_multi"); diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c index cf92da1b0e6..ec5d7feba41 100644 --- a/source/blender/modifiers/intern/MOD_weld.c +++ b/source/blender/modifiers/intern/MOD_weld.c @@ -395,55 +395,51 @@ static void weld_vert_ctx_alloc_and_setup(const uint mvert_len, *v_dest_iter = OUT_OF_CONTEXT; } - uint vert_kill_len = 0; - const BVHTreeOverlap *overlap_iter = &overlap[0]; - for (uint i = 0; i < overlap_len; i++, overlap_iter++) { + const BVHTreeOverlap *overlap_iter, *overlap_end; + overlap_iter = &overlap[0]; + overlap_end = overlap + overlap_len; + for (; overlap_iter < overlap_end; overlap_iter++) { uint indexA = overlap_iter->indexA; uint indexB = overlap_iter->indexB; BLI_assert(indexA < indexB); + r_vert_dest_map[indexA] = indexB; + } - uint va_dst = r_vert_dest_map[indexA]; - uint vb_dst = r_vert_dest_map[indexB]; - if (va_dst == OUT_OF_CONTEXT) { - if (vb_dst == OUT_OF_CONTEXT) { - vb_dst = indexA; - r_vert_dest_map[indexB] = vb_dst; - } - r_vert_dest_map[indexA] = vb_dst; - vert_kill_len++; + /** + * Point all groups of merged vertices to the same vertex. + * That is, if the pairs of vertices are: + * [1, 2], [2, 3] and [3, 4], + * Adjust they to: + * [1, 4], [2, 4] and [3, 4]. + */ + v_dest_iter = &r_vert_dest_map[0]; + for (uint i = 0; i < mvert_len; i++, v_dest_iter++) { + uint v_dest = *v_dest_iter; + uint v_dest_final = v_dest; + + /* ELEM_MERGED or OUT_OF_CONTEXT. */ + if ((int)v_dest_final < 0) { + continue; } - else if (vb_dst == OUT_OF_CONTEXT) { - r_vert_dest_map[indexB] = va_dst; - vert_kill_len++; + + uint index_test; + while ((int)(index_test = r_vert_dest_map[v_dest_final]) >= 0) { + v_dest_final = index_test; } - else if (va_dst != vb_dst) { - uint v_new, v_old; - if (va_dst < vb_dst) { - v_new = va_dst; - v_old = vb_dst; - } - else { - v_new = vb_dst; - v_old = va_dst; - } - BLI_assert(r_vert_dest_map[v_old] == v_old); - BLI_assert(r_vert_dest_map[v_new] == v_new); - vert_kill_len++; - - const BVHTreeOverlap *overlap_iter_b = &overlap[0]; - for (uint j = i + 1; j--; overlap_iter_b++) { - indexA = overlap_iter_b->indexA; - indexB = overlap_iter_b->indexB; - va_dst = r_vert_dest_map[indexA]; - vb_dst = r_vert_dest_map[indexB]; - if (ELEM(v_old, vb_dst, va_dst)) { - r_vert_dest_map[indexA] = v_new; - r_vert_dest_map[indexB] = v_new; - } + + if (v_dest_final != v_dest) { + r_vert_dest_map[i] = v_dest_final; + + /* Since we have found the final destination vertex, + * it is better to update the entire path at once. */ + while ((int)(index_test = r_vert_dest_map[v_dest]) >= 0) { + r_vert_dest_map[v_dest] = v_dest_final; + v_dest = index_test; } - BLI_assert(r_vert_dest_map[v_old] == v_new); } + + r_vert_dest_map[v_dest_final] = ELEM_MERGED; } /* Vert Context. */ @@ -455,8 +451,13 @@ static void weld_vert_ctx_alloc_and_setup(const uint mvert_len, v_dest_iter = &r_vert_dest_map[0]; for (uint i = 0; i < mvert_len; i++, v_dest_iter++) { - if (*v_dest_iter != OUT_OF_CONTEXT) { - wv->vert_dest = *v_dest_iter; + uint v_dest = *v_dest_iter; + if (v_dest != OUT_OF_CONTEXT) { + if (v_dest == ELEM_MERGED) { + /* Point to itself. Useful for finding groups. */ + *v_dest_iter = v_dest = i; + } + wv->vert_dest = v_dest; wv->vert_orig = i; wv++; wvert_len++; @@ -469,7 +470,7 @@ static void weld_vert_ctx_alloc_and_setup(const uint mvert_len, *r_wvert = MEM_reallocN(wvert, sizeof(*wvert) * wvert_len); *r_wvert_len = wvert_len; - *r_vert_kill_len = vert_kill_len; + *r_vert_kill_len = overlap_len; } static void weld_vert_groups_setup(const uint mvert_len, diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 63137e094b7..3e30c81c8c6 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -2526,7 +2526,6 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2) } if (mat1 && mat2) { -#ifdef USE_MATHUTILS_ELEM_MUL /* MATRIX * MATRIX */ float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; @@ -2540,7 +2539,6 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2) mul_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1)); -#endif } else if (mat2) { /*FLOAT/INT * MATRIX */ @@ -2584,7 +2582,6 @@ static PyObject *Matrix_imul(PyObject *m1, PyObject *m2) } if (mat1 && mat2) { -#ifdef USE_MATHUTILS_ELEM_MUL /* MATRIX *= MATRIX */ if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) { PyErr_SetString(PyExc_ValueError, @@ -2594,14 +2591,6 @@ static PyObject *Matrix_imul(PyObject *m1, PyObject *m2) } mul_vn_vn(mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); -#else - PyErr_Format(PyExc_TypeError, - "In place element-wise multiplication: " - "not supported between '%.200s' and '%.200s' types", - Py_TYPE(m1)->tp_name, - Py_TYPE(m2)->tp_name); - return NULL; -#endif } else if (mat1 && (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0)) { /* MATRIX *= FLOAT/INT */ diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index 7ce0ea5f249..2b7761b7678 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -962,11 +962,9 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2) } if (quat1 && quat2) { /* QUAT * QUAT (element-wise product) */ -#ifdef USE_MATHUTILS_ELEM_MUL float quat[QUAT_SIZE]; mul_vn_vnvn(quat, quat1->quat, quat2->quat, QUAT_SIZE); return Quaternion_CreatePyObject(quat, Py_TYPE(q1)); -#endif } /* the only case this can happen (for a supported type is "FLOAT * QUAT") */ else if (quat2) { /* FLOAT * QUAT */ @@ -1007,17 +1005,8 @@ static PyObject *Quaternion_imul(PyObject *q1, PyObject *q2) } } - if (quat1 && quat2) { /* QUAT *= QUAT (inplace element-wise product) */ -#ifdef USE_MATHUTILS_ELEM_MUL + if (quat1 && quat2) { /* QUAT *= QUAT (in-place element-wise product). */ mul_vn_vn(quat1->quat, quat2->quat, QUAT_SIZE); -#else - PyErr_Format(PyExc_TypeError, - "In place element-wise multiplication: " - "not supported between '%.200s' and '%.200s' types", - Py_TYPE(q1)->tp_name, - Py_TYPE(q2)->tp_name); - return NULL; -#endif } else if (quat1 && (((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) { /* QUAT *= FLOAT */ diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 15ae811fd91..4b47440a530 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -1738,7 +1738,7 @@ static PyObject *vector_mul_float(VectorObject *vec, const float scalar) mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar); return Vector_CreatePyObject_alloc(tvec, vec->size, Py_TYPE(vec)); } -#ifdef USE_MATHUTILS_ELEM_MUL + static PyObject *vector_mul_vec(VectorObject *vec1, VectorObject *vec2) { float *tvec = PyMem_Malloc(vec1->size * sizeof(float)); @@ -1752,7 +1752,7 @@ static PyObject *vector_mul_vec(VectorObject *vec1, VectorObject *vec2) mul_vn_vnvn(tvec, vec1->vec, vec2->vec, vec1->size); return Vector_CreatePyObject_alloc(tvec, vec1->size, Py_TYPE(vec1)); } -#endif + static PyObject *Vector_mul(PyObject *v1, PyObject *v2) { VectorObject *vec1 = NULL, *vec2 = NULL; @@ -1775,7 +1775,6 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2) /* make sure v1 is always the vector */ if (vec1 && vec2) { -#ifdef USE_MATHUTILS_ELEM_MUL if (vec1->size != vec2->size) { PyErr_SetString(PyExc_ValueError, "Vector multiplication: " @@ -1785,7 +1784,6 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2) /* element-wise product */ return vector_mul_vec(vec1, vec2); -#endif } else if (vec1) { if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */ @@ -1832,7 +1830,6 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2) /* Intentionally don't support (Quaternion, Matrix) here, uses reverse order instead. */ if (vec1 && vec2) { -#ifdef USE_MATHUTILS_ELEM_MUL if (vec1->size != vec2->size) { PyErr_SetString(PyExc_ValueError, "Vector multiplication: " @@ -1840,16 +1837,8 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2) return NULL; } - /* element-wise product inplace */ + /* Element-wise product in-place. */ mul_vn_vn(vec1->vec, vec2->vec, vec1->size); -#else - PyErr_Format(PyExc_TypeError, - "In place element-wise multiplication: " - "not supported between '%.200s' and '%.200s' types", - Py_TYPE(v1)->tp_name, - Py_TYPE(v2)->tp_name); - return NULL; -#endif } else if (vec1 && (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0)) { /* VEC *= FLOAT */ diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index 9926e08c968..b37eeed3681 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -902,7 +902,7 @@ static void do_2d_mapping( float fx, fy, fac1, area[8]; int ok, proj, areaflag = 0, wrap; - /* mtex variables localized, only cubemap doesn't cooperate yet... */ + /* #MTex variables localized, only cube-map doesn't cooperate yet. */ wrap = mtex->mapping; tex = mtex->tex; diff --git a/tests/gtests/blenlib/BLI_vector_test.cc b/tests/gtests/blenlib/BLI_vector_test.cc index a020611aed6..25435739a43 100644 --- a/tests/gtests/blenlib/BLI_vector_test.cc +++ b/tests/gtests/blenlib/BLI_vector_test.cc @@ -657,7 +657,7 @@ TEST(vector, ConstructVoidPointerVector) float b; double c; Vector<void *> vec = {&a, &b, &c}; - EXPECT_EQ(vec.size(), 3); + EXPECT_EQ(vec.size(), 3u); } } // namespace blender |