Brush Assets: Add catalog option to asset pushing operator #118382

Merged
Hans Goudey merged 26 commits from HooglyBoogly/blender:brush-assets-save-catalog-option into brush-assets-project 2024-02-21 14:03:41 +01:00
177 changed files with 2882 additions and 788 deletions
Showing only changes of commit 5f9e9e7c52 - Show all commits

View File

@ -703,12 +703,7 @@ mark_as_advanced(WITH_DRAW_DEBUG)
# LLVM
option(WITH_LLVM "Use LLVM" OFF)
if(APPLE)
# We prefer static llvm build on Apple, dyn build possible though.
option(LLVM_STATIC "Link with LLVM static libraries" ON)
else()
option(LLVM_STATIC "Link with LLVM static libraries" OFF)
endif()
option(LLVM_STATIC "Link with LLVM static libraries" OFF)
mark_as_advanced(LLVM_STATIC)
option(WITH_CLANG "Use Clang" OFF)
@ -1156,14 +1151,7 @@ set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_CYCLES_OSL OFF)
# Hydra requires USD.
set_and_warn_dependency(WITH_USD WITH_HYDRA OFF)
# auto enable openimageio for cycles
if(WITH_CYCLES)
# auto enable llvm for cycles_osl
if(WITH_CYCLES_OSL)
set(WITH_LLVM ON CACHE BOOL "" FORCE)
set(WITH_CLANG ON CACHE BOOL "" FORCE)
endif()
else()
if(NOT WITH_CYCLES)
set(WITH_CYCLES_OSL OFF)
endif()
@ -1382,18 +1370,6 @@ if(NOT WITH_FFTW3 AND WITH_MOD_OCEANSIM)
message(FATAL_ERROR "WITH_MOD_OCEANSIM requires WITH_FFTW3 to be ON")
endif()
if(WITH_CYCLES)
if(WITH_CYCLES_OSL)
if(NOT WITH_LLVM)
message(
FATAL_ERROR
"Cycles OSL requires WITH_LLVM, the library may not have been found. "
"Configure LLVM or disable WITH_CYCLES_OSL"
)
endif()
endif()
endif()
if(WITH_INTERNATIONAL)
if(NOT WITH_BOOST)
message(

View File

@ -176,19 +176,6 @@ int CLG_color_support_get(CLG_LogRef *clg_ref);
} \
((void)0)
#define CLOG_STR_AT_SEVERITY_N(clg_ref, severity, verbose_level, str) \
{ \
CLG_LogType *_lg_ty = CLOG_ENSURE(clg_ref); \
if (((_lg_ty->flag & CLG_FLAG_USE) && (_lg_ty->level >= verbose_level)) || \
(severity >= CLG_SEVERITY_WARN)) \
{ \
const char *_str = str; \
CLG_log_str(_lg_ty, severity, __FILE__ ":" STRINGIFY(__LINE__), __func__, _str); \
MEM_freeN((void *)_str); \
} \
} \
((void)0)
#define CLOG_INFO(clg_ref, level, ...) \
CLOG_AT_SEVERITY(clg_ref, CLG_SEVERITY_INFO, level, __VA_ARGS__)
#define CLOG_WARN(clg_ref, ...) CLOG_AT_SEVERITY(clg_ref, CLG_SEVERITY_WARN, 0, __VA_ARGS__)
@ -201,13 +188,6 @@ int CLG_color_support_get(CLG_LogRef *clg_ref);
#define CLOG_STR_ERROR(clg_ref, str) CLOG_STR_AT_SEVERITY(clg_ref, CLG_SEVERITY_ERROR, 0, str)
#define CLOG_STR_FATAL(clg_ref, str) CLOG_STR_AT_SEVERITY(clg_ref, CLG_SEVERITY_FATAL, 0, str)
/* Allocated string which is immediately freed. */
#define CLOG_STR_INFO_N(clg_ref, level, str) \
CLOG_STR_AT_SEVERITY_N(clg_ref, CLG_SEVERITY_INFO, level, str)
#define CLOG_STR_WARN_N(clg_ref, str) CLOG_STR_AT_SEVERITY_N(clg_ref, CLG_SEVERITY_WARN, 0, str)
#define CLOG_STR_ERROR_N(clg_ref, str) CLOG_STR_AT_SEVERITY_N(clg_ref, CLG_SEVERITY_ERROR, 0, str)
#define CLOG_STR_FATAL_N(clg_ref, str) CLOG_STR_AT_SEVERITY_N(clg_ref, CLG_SEVERITY_FATAL, 0, str)
#ifdef __cplusplus
}
#endif

View File

@ -93,7 +93,7 @@ macro(cycles_external_libraries_append libraries)
list(APPEND ${libraries} ${GLOG_LIBRARIES} ${GFLAGS_LIBRARIES})
endif()
if(WITH_CYCLES_OSL)
list(APPEND ${libraries} ${OSL_LIBRARIES} ${CLANG_LIBRARIES} ${LLVM_LIBRARY})
list(APPEND ${libraries} ${OSL_LIBRARIES})
endif()
if(WITH_CYCLES_EMBREE)
list(APPEND ${libraries} ${EMBREE_LIBRARIES})

View File

@ -32,8 +32,6 @@ set(LIB
${OSL_LIBRARIES}
${OPENIMAGEIO_LIBRARIES}
${PUGIXML_LIBRARIES}
${CLANG_LIBRARIES}
${LLVM_LIBRARY}
)
if(APPLE)

View File

@ -3286,10 +3286,10 @@ static void data_device_handle_drop(void *data, wl_data_device * /*wl_data_devic
GHOST_SystemWayland *const system = seat->system;
if (mime_receive == ghost_wl_mime_text_uri) {
static constexpr const char *file_proto = "file://";
const char file_proto[] = "file://";
/* NOTE: some applications CRLF (`\r\n`) GTK3 for e.g. & others don't `pcmanfm-qt`.
* So support both, once `\n` is found, strip the preceding `\r` if found. */
static constexpr const char *lf = "\n";
const char lf = '\n';
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_window);
std::vector<std::string> uris;

View File

@ -55,6 +55,10 @@ class GREASE_PENCIL_MT_grease_pencil_add_layer_extra(Menu):
layout.operator("grease_pencil.layer_reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
layout.operator("grease_pencil.layer_hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
layout.separator()
layout.operator("grease_pencil.layer_lock_all", icon='LOCKED', text="Lock All")
layout.operator("grease_pencil.layer_lock_all", icon='UNLOCKED', text="Unlock All").lock = False
class DATA_PT_grease_pencil_layers(DataButtonsPanel, Panel):
bl_label = "Layers"

View File

@ -151,7 +151,9 @@ class OBJECT_MT_modifier_add_generate(ModifierAddMenu, Menu):
self.operator_modifier_add(layout, 'WIREFRAME')
if ob_type == 'GREASEPENCIL':
self.operator_modifier_add(layout, 'GREASE_PENCIL_DASH')
self.operator_modifier_add(layout, 'GREASE_PENCIL_LENGTH')
self.operator_modifier_add(layout, 'GREASE_PENCIL_MIRROR')
self.operator_modifier_add(layout, 'GREASE_PENCIL_MULTIPLY')
self.operator_modifier_add(layout, 'GREASE_PENCIL_SUBDIV')
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)

View File

@ -94,7 +94,6 @@ std::string AS_asset_library_find_suitable_root_path_from_main(const Main *bmain
return AS_asset_library_find_suitable_root_path_from_path(bmain->filepath);
}
void AS_asset_library_remap_ids(const bke::id::IDRemapper &mappings)
{
AssetLibraryService *service = AssetLibraryService::get();

View File

@ -212,12 +212,13 @@ enum {
G_DEBUG_GPU = (1 << 16), /* gpu debug */
G_DEBUG_IO = (1 << 17), /* IO Debugging (for Collada, ...). */
G_DEBUG_GPU_FORCE_WORKAROUNDS = (1 << 18), /* force gpu workarounds bypassing detections. */
G_DEBUG_GPU_RENDERDOC = (1 << 19), /* Enable RenderDoc integration. */
G_DEBUG_XR = (1 << 20), /* XR/OpenXR messages */
G_DEBUG_XR_TIME = (1 << 21), /* XR/OpenXR timing messages */
G_DEBUG_GPU_COMPILE_SHADERS = (1 << 19), /* Compile all statically defined shaders. . */
G_DEBUG_GPU_RENDERDOC = (1 << 20), /* Enable RenderDoc integration. */
G_DEBUG_XR = (1 << 21), /* XR/OpenXR messages */
G_DEBUG_XR_TIME = (1 << 22), /* XR/OpenXR timing messages */
G_DEBUG_GHOST = (1 << 22), /* Debug GHOST module. */
G_DEBUG_WINTAB = (1 << 23), /* Debug Wintab. */
G_DEBUG_GHOST = (1 << 23), /* Debug GHOST module. */
G_DEBUG_WINTAB = (1 << 24), /* Debug Wintab. */
};
#define G_DEBUG_ALL \

View File

@ -513,6 +513,8 @@ class LayerGroup : public ::GreasePencilLayerTreeGroup {
LayerGroup(const LayerGroup &other);
~LayerGroup();
LayerGroup &operator=(const LayerGroup &other);
public:
/* Define the common functions for #TreeNode. */
TREENODE_COMMON_METHODS;

View File

@ -33,6 +33,8 @@
#include "BLI_compiler_attrs.h"
#include "BLI_utildefines.h"
#include "BLI_set.hh"
#include "DNA_userdef_enums.h"
struct BlendWriter;
@ -319,11 +321,23 @@ void BKE_id_delete_ex(Main *bmain, void *idv, const int extra_remapping_flags) A
* This is more efficient than calling #BKE_id_delete repetitively on a large set of IDs
* (several times faster when deleting most of the IDs at once).
*
* \warning Considered experimental for now, seems to be working OK but this is
* risky code in a complicated area.
* \return Number of deleted data-blocks.
*/
size_t BKE_id_multi_tagged_delete(Main *bmain) ATTR_NONNULL();
/**
* Properly delete all IDs from \a ids_to_delete, from given \a bmain database.
*
* This is more efficient than calling #BKE_id_delete repetitively on a large set of IDs
* (several times faster when deleting most of the IDs at once).
*
* \note The ID pointers are not removed from the Set (which may contain more pointers than
* originally given, when extra users or dependencies also had to be deleted with the original set
* of IDs). They are all freed though, so these pointers are all invalid after calling this
* function.
*
* \return Number of deleted data-blocks.
*/
size_t BKE_id_multi_delete(Main *bmain, blender::Set<ID *> &ids_to_delete);
/**
* Add a 'NO_MAIN' data-block to given main (also sets user-counts of its IDs if needed).

View File

@ -22,6 +22,7 @@
#include "BLI_compiler_attrs.h"
#include "BLI_map.hh"
#include "BLI_set.hh"
#include "BLI_span.hh"
#include "BLI_utildefines.h"
@ -48,10 +49,11 @@ enum {
*/
ID_REMAP_SKIP_NEVER_NULL_USAGE = 1 << 1,
/**
* This tells the callback func to flag with #LIB_DOIT all IDs
* using target one with a 'never NULL' pointer (like e.g. #Object.data).
* Store in the #IDRemapper all IDs using target one with a 'never NULL' pointer (like e.g.
* #Object.data), when such ID usage has (or should have) been remapped to `nullptr`. See also
* #ID_REMAP_FORCE_NEVER_NULL_USAGE and #ID_REMAP_SKIP_NEVER_NULL_USAGE.
*/
ID_REMAP_FLAG_NEVER_NULL_USAGE = 1 << 2,
ID_REMAP_STORE_NEVER_NULL_USAGE = 1 << 2,
/**
* This tells the callback func to force setting IDs
* using target one with a 'never NULL' pointer to NULL.
@ -163,12 +165,8 @@ void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, int remap_fla
/**
* Unlink given \a id from given \a bmain
* (does not touch to indirect, i.e. library, usages of the ID).
*
* \param do_flag_never_null: If true, all IDs using \a idv in a 'non-NULL' way are flagged by
* #LIB_TAG_DOIT flag (quite obviously, 'non-NULL' usages can never be unlinked by this function).
*/
void BKE_libblock_unlink(Main *bmain, void *idv, bool do_flag_never_null, bool do_skip_indirect)
ATTR_NONNULL();
void BKE_libblock_unlink(Main *bmain, void *idv, bool do_skip_indirect) ATTR_NONNULL();
/**
* Similar to libblock_remap, but only affects IDs used by given \a idv ID.
@ -263,10 +261,17 @@ class IDRemapper {
blender::Map<ID *, ID *> mappings_;
IDTypeFilter source_types_ = 0;
/**
* Store all IDs using another ID with the 'NEVER_NULL' flag, which have (or
* should have been) remapped to `nullptr`.
*/
blender::Set<ID *> never_null_users_;
public:
void clear(void)
{
mappings_.clear();
never_null_users_.clear();
source_types_ = 0;
}
@ -302,6 +307,16 @@ class IDRemapper {
IDRemapperApplyOptions options,
ID *id_self = nullptr) const;
void never_null_users_add(ID *id)
{
never_null_users_.add(id);
}
const blender::Set<ID *> &never_null_users(void) const
{
return never_null_users_;
}
/** Iterate over all remapping pairs in the remapper, and call the callback function on them. */
void iter(IDRemapperIterFunction func, void *user_data) const
{

View File

@ -17,6 +17,7 @@ struct UndoType;
struct bContext;
/* IDs */
struct GreasePencil;
struct Main;
struct Mesh;
struct Object;
@ -33,6 +34,7 @@ struct UndoRefID {
struct ptr_ty *ptr; \
char name[MAX_ID_NAME]; \
}
UNDO_REF_ID_TYPE(GreasePencil);
UNDO_REF_ID_TYPE(Mesh);
UNDO_REF_ID_TYPE(Object);
UNDO_REF_ID_TYPE(Scene);

View File

@ -4,12 +4,20 @@
#pragma once
#include "DNA_windowmanager_types.h"
namespace blender::bke {
class WindowManagerRuntime {
public:
/** Indicates whether interface is locked for user interaction. */
bool is_interface_locked = false;
/** Information and error reports. */
ReportList reports;
WindowManagerRuntime();
~WindowManagerRuntime();
};
} // namespace blender::bke

View File

@ -71,8 +71,18 @@ bool BKE_ffmpeg_alpha_channel_is_supported(const RenderData *rd);
void *BKE_ffmpeg_context_create(void);
void BKE_ffmpeg_context_free(void *context_v);
void BKE_ffmpeg_exit();
/**
* Gets a libswscale context for given size and format parameters.
* After you're done using the context, call #BKE_ffmpeg_sws_release_context
* to release it. Internally the contexts are coming from the context
* pool/cache.
*/
SwsContext *BKE_ffmpeg_sws_get_context(
int width, int height, int av_src_format, int av_dst_format, int sws_flags);
void BKE_ffmpeg_sws_release_context(SwsContext *ctx);
void BKE_ffmpeg_sws_scale_frame(SwsContext *ctx, AVFrame *dst, const AVFrame *src);
#endif

View File

@ -315,6 +315,7 @@ set(SRC
intern/volume_grid_file_cache.cc
intern/volume_render.cc
intern/volume_to_mesh.cc
intern/wm_runtime.cc
intern/workspace.cc
intern/world.cc
intern/writeavi.cc

View File

@ -36,6 +36,7 @@
#include "BKE_report.hh"
#include "BKE_screen.hh"
#include "BKE_studiolight.h"
#include "BKE_writeffmpeg.hh"
#include "DEG_depsgraph.hh"
@ -75,6 +76,9 @@ void BKE_blender_free()
BKE_callback_global_finalize();
IMB_moviecache_destruct();
#ifdef WITH_FFMPEG
BKE_ffmpeg_exit();
#endif
BKE_node_system_exit();
}

View File

@ -1131,7 +1131,7 @@ static void setup_app_data(bContext *C,
BLI_assert(BKE_main_namemap_validate(bmain));
if (mode != LOAD_UNDO && !USER_EXPERIMENTAL_TEST(&U, no_override_auto_resync)) {
reports->duration.lib_overrides_resync = BLI_check_seconds_timer();
reports->duration.lib_overrides_resync = BLI_time_now_seconds();
BKE_lib_override_library_main_resync(
bmain,
@ -1139,7 +1139,7 @@ static void setup_app_data(bContext *C,
bfd->cur_view_layer ? bfd->cur_view_layer : BKE_view_layer_default_view(curscene),
reports);
reports->duration.lib_overrides_resync = BLI_check_seconds_timer() -
reports->duration.lib_overrides_resync = BLI_time_now_seconds() -
reports->duration.lib_overrides_resync;
/* We need to rebuild some of the deleted override rules (for UI feedback purpose). */

View File

@ -767,7 +767,7 @@ wmMsgBus *CTX_wm_message_bus(const bContext *C)
ReportList *CTX_wm_reports(const bContext *C)
{
if (C->wm.manager) {
return &(C->wm.manager->reports);
return &(C->wm.manager->runtime->reports);
}
return nullptr;

View File

@ -79,7 +79,7 @@ PartDeflect *BKE_partdeflect_new(int type)
pd->pdef_sbift = 0.2f;
pd->pdef_sboft = 0.02f;
pd->pdef_cfrict = 5.0f;
pd->seed = (uint(ceil(BLI_check_seconds_timer())) + 1) % 128;
pd->seed = (uint(ceil(BLI_time_now_seconds())) + 1) % 128;
pd->f_strength = 1.0f;
pd->f_damp = 1.0f;

View File

@ -1065,6 +1065,18 @@ LayerGroup::~LayerGroup()
this->runtime = nullptr;
}
LayerGroup &LayerGroup::operator=(const LayerGroup &other)
{
if (this == &other) {
return *this;
}
this->~LayerGroup();
new (this) LayerGroup(other);
return *this;
}
Layer &LayerGroup::add_layer(StringRefNull name)
{
Layer *new_layer = MEM_new<Layer>(__func__, name);
@ -1715,6 +1727,32 @@ blender::MutableSpan<GreasePencilDrawingBase *> GreasePencil::drawings()
this->drawing_array_num};
}
void GreasePencil::resize_drawings(const int new_num)
{
using namespace blender;
BLI_assert(new_num > 0);
const int prev_num = int(this->drawings().size());
if (new_num == prev_num) {
return;
}
if (new_num > prev_num) {
const int add_num = new_num - prev_num;
grow_array<GreasePencilDrawingBase *>(&this->drawing_array, &this->drawing_array_num, add_num);
}
else { /* if (new_num < prev_num) */
const int shrink_num = prev_num - new_num;
MutableSpan<GreasePencilDrawingBase *> old_drawings = this->drawings().drop_front(new_num);
for (const int64_t i : old_drawings.index_range()) {
if (old_drawings[i]) {
MEM_delete(old_drawings[i]);
}
}
shrink_array<GreasePencilDrawingBase *>(
&this->drawing_array, &this->drawing_array_num, shrink_num);
}
}
void GreasePencil::add_empty_drawings(const int add_num)
{
using namespace blender;

View File

@ -1494,7 +1494,7 @@ void BKE_image_packfiles_from_mem(ReportList *reports,
void BKE_image_tag_time(Image *ima)
{
ima->lastused = BLI_check_seconds_timer_i();
ima->lastused = BLI_time_now_seconds_i();
}
static uintptr_t image_mem_size(Image *image)

View File

@ -585,7 +585,7 @@ void BKE_image_free_anim_gputextures(Main *bmain)
void BKE_image_free_old_gputextures(Main *bmain)
{
static int lasttime = 0;
int ctime = int(BLI_check_seconds_timer());
int ctime = int(BLI_time_now_seconds());
/*
* Run garbage collector once for every collecting period of time

View File

@ -8,8 +8,6 @@
* Contains management of ID's for freeing & deletion.
*/
#include "CLG_log.h"
#include "MEM_guardedalloc.h"
/* all types are needed here, in order to do memory operations */
@ -18,8 +16,8 @@
#include "BLI_utildefines.h"
#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BLI_set.hh"
#include "BLI_vector.hh"
#include "BKE_anim_data.h"
@ -44,8 +42,6 @@
using namespace blender::bke::id;
static CLG_LogRef LOG = {"bke.lib_id_delete"};
void BKE_libblock_free_data(ID *id, const bool do_id_user)
{
if (id->properties) {
@ -214,213 +210,132 @@ void BKE_id_free_us(Main *bmain, void *idv) /* test users */
}
if (id->us == 0) {
BKE_libblock_unlink(bmain, id, false, false);
BKE_libblock_unlink(bmain, id, false);
BKE_id_free(bmain, id);
}
}
static size_t id_delete(Main *bmain,
const bool do_tagged_deletion,
blender::Set<ID *> &ids_to_delete,
const int extra_remapping_flags)
{
const int tag = LIB_TAG_DOIT;
ListBase *lbarray[INDEX_ID_MAX];
int base_count, i;
/* Used by batch tagged deletion, when we call BKE_id_free then, id is no more in Main database,
* and has already properly unlinked its other IDs usages.
* UI users are always cleared in BKE_libblock_remap_locked() call, so we can always skip it. */
const int free_flag = LIB_ID_FREE_NO_UI_USER |
(do_tagged_deletion ? LIB_ID_FREE_NO_MAIN | LIB_ID_FREE_NO_USER_REFCOUNT :
0);
const int remapping_flags = (ID_REMAP_FLAG_NEVER_NULL_USAGE | ID_REMAP_FORCE_NEVER_NULL_USAGE |
const int free_flag = LIB_ID_FREE_NO_UI_USER | LIB_ID_FREE_NO_MAIN |
LIB_ID_FREE_NO_USER_REFCOUNT;
const int remapping_flags = (ID_REMAP_STORE_NEVER_NULL_USAGE | ID_REMAP_FORCE_NEVER_NULL_USAGE |
ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS | extra_remapping_flags);
ListBase tagged_deleted_ids = {nullptr};
base_count = set_listbasepointers(bmain, lbarray);
ListBase *lbarray[INDEX_ID_MAX];
const int base_count = set_listbasepointers(bmain, lbarray);
BKE_main_lock(bmain);
if (do_tagged_deletion) {
IDRemapper id_remapper;
BKE_layer_collection_resync_forbid();
BKE_layer_collection_resync_forbid();
IDRemapper id_remapper;
/* Main idea of batch deletion is to remove all IDs to be deleted from Main database.
* This means that we won't have to loop over all deleted IDs to remove usages
* of other deleted IDs.
* This gives tremendous speed-up when deleting a large amount of IDs from a Main
* containing thousands of those.
* This also means that we have to be very careful here, as we by-pass many 'common'
* processing, hence risking to 'corrupt' at least user counts, if not IDs themselves. */
bool keep_looping = true;
while (keep_looping) {
ID *id, *id_next;
keep_looping = false;
/* Main idea of batch deletion is to remove all IDs to be deleted from Main database.
* This means that we won't have to loop over all deleted IDs to remove usages
* of other deleted IDs.
* This gives tremendous speed-up when deleting a large amount of IDs from a Main
* containing thousands of these.
* This also means that we have to be very careful here, as we by-pass many 'common'
* processing, hence risking to 'corrupt' at least user counts, if not IDs themselves. */
bool keep_looping = true;
while (keep_looping) {
keep_looping = false;
/* First tag and remove from Main all datablocks directly from target lib.
* Note that we go forward here, since we want to check dependencies before users
* (e.g. meshes before objects). Avoids to have to loop twice. */
for (i = 0; i < base_count; i++) {
ListBase *lb = lbarray[i];
for (id = static_cast<ID *>(lb->first); id; id = id_next) {
id_next = static_cast<ID *>(id->next);
/* NOTE: in case we delete a library, we also delete all its datablocks! */
if ((id->tag & tag) || (ID_IS_LINKED(id) && (id->lib->id.tag & tag))) {
BLI_remlink(lb, id);
BKE_main_namemap_remove_name(bmain, id, id->name + 2);
BLI_addtail(&tagged_deleted_ids, id);
id_remapper.add(id, nullptr);
/* Do not tag as no_main now, we want to unlink it first (lower-level ID management
* code has some specific handling of 'no main' IDs that would be a problem in that
* case). */
id->tag |= tag;
/* Forcefully also delete shapekeys of the deleted ID if any, 'orphaned' shapekeys are
* not allowed in Blender and will cause lots of problem in modern code (liboverrides,
* warning on write & read, etc.). */
Key *shape_key = BKE_key_from_id(id);
if (shape_key && (shape_key->id.tag & tag) == 0) {
BLI_remlink(&bmain->shapekeys, &shape_key->id);
BKE_main_namemap_remove_name(bmain, &shape_key->id, shape_key->id.name + 2);
BLI_addtail(&tagged_deleted_ids, &shape_key->id);
id_remapper.add(&shape_key->id, nullptr);
shape_key->id.tag |= tag;
}
keep_looping = true;
}
}
}
/* Will tag 'never nullptr' users of this ID too.
*
* NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
* links, this can lead to nasty crashing here in second, actual deleting loop.
* Also, this will also flag users of deleted data that cannot be unlinked
* (object using deleted obdata, etc.), so that they also get deleted. */
BKE_libblock_remap_multiple_locked(bmain, id_remapper, remapping_flags);
id_remapper.clear();
}
/* Since we removed IDs from Main, their own other IDs usages need to be removed 'manually'. */
blender::Vector<ID *> cleanup_ids;
for (ID *id = static_cast<ID *>(tagged_deleted_ids.first); id;
id = static_cast<ID *>(id->next))
{
cleanup_ids.append(id);
}
BKE_libblock_relink_multiple(bmain,
cleanup_ids,
ID_REMAP_TYPE_CLEANUP,
id_remapper,
ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS |
ID_REMAP_SKIP_USER_CLEAR);
cleanup_ids.clear();
BKE_layer_collection_resync_allow();
BKE_main_collection_sync_remap(bmain);
/* Now we can safely mark that ID as not being in Main database anymore. */
/* NOTE: This needs to be done in a separate loop than above, otherwise some user-counts of
* deleted IDs may not be properly decreased by the remappings (since `NO_MAIN` ID user-counts
* is never affected). */
for (ID *id = static_cast<ID *>(tagged_deleted_ids.first); id;
id = static_cast<ID *>(id->next))
{
id->tag |= LIB_TAG_NO_MAIN;
/* User-count needs to be reset artificially, since some usages may not be cleared in batch
* deletion (typically, if one deleted ID uses another deleted ID, this may not be cleared by
* remapping code, depending on order in which these are handled). */
id->us = ID_FAKE_USERS(id);
}
}
else {
/* First tag all data-blocks directly from target lib.
/* First tag and remove from Main all datablocks directly from target lib.
* Note that we go forward here, since we want to check dependencies before users
* (e.g. meshes before objects).
* Avoids to have to loop twice. */
IDRemapper remapper;
for (i = 0; i < base_count; i++) {
* (e.g. meshes before objects). Reduces the chances to have to loop many times in the
* `while (keep_looking)` outer loop. */
for (int i = 0; i < base_count; i++) {
ListBase *lb = lbarray[i];
ID *id, *id_next;
remapper.clear();
ID *id_iter;
for (id = static_cast<ID *>(lb->first); id; id = id_next) {
id_next = static_cast<ID *>(id->next);
FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id_iter) {
/* NOTE: in case we delete a library, we also delete all its datablocks! */
if ((id->tag & tag) || (ID_IS_LINKED(id) && (id->lib->id.tag & tag))) {
id->tag |= tag;
remapper.add(id, nullptr);
if (ids_to_delete.contains(id_iter) ||
(ID_IS_LINKED(id_iter) && ids_to_delete.contains(&id_iter->lib->id)))
{
BLI_remlink(lb, id_iter);
BKE_main_namemap_remove_name(bmain, id_iter, id_iter->name + 2);
ids_to_delete.add(id_iter);
id_remapper.add(id_iter, nullptr);
/* Do not tag as no_main now, we want to unlink it first (lower-level ID management
* code has some specific handling of 'no main' IDs that would be a problem in that
* case). */
/* Forcefully also delete shapekeys of the deleted ID if any, 'orphaned' shapekeys are
* not allowed in Blender and will cause lots of problem in modern code (liboverrides,
* warning on write & read, etc.). */
Key *shape_key = BKE_key_from_id(id_iter);
if (shape_key && !ids_to_delete.contains(&shape_key->id)) {
BLI_remlink(&bmain->shapekeys, &shape_key->id);
BKE_main_namemap_remove_name(bmain, &shape_key->id, shape_key->id.name + 2);
ids_to_delete.add(&shape_key->id);
id_remapper.add(&shape_key->id, nullptr);
}
keep_looping = true;
}
}
if (remapper.is_empty()) {
continue;
}
/* Will tag 'never nullptr' users of this ID too.
*
* NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
* links, this can lead to nasty crashing here in second, actual deleting loop.
* Also, this will also flag users of deleted data that cannot be unlinked
* (object using deleted obdata, etc.), so that they also get deleted. */
BKE_libblock_remap_multiple_locked(bmain, remapper, remapping_flags);
FOREACH_MAIN_LISTBASE_ID_END;
}
/* Will tag 'never nullptr' users of this ID too.
*
* NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
* links, this can lead to nasty crashing here in second, actual deleting loop.
* Also, this will also flag users of deleted data that cannot be unlinked
* (object using deleted obdata, etc.), so that they also get deleted. */
BKE_libblock_remap_multiple_locked(bmain, id_remapper, remapping_flags);
for (ID *id_never_null_iter : id_remapper.never_null_users()) {
ids_to_delete.add(id_never_null_iter);
}
id_remapper.clear();
}
/* Since we removed IDs from Main, their own other IDs usages need to be removed 'manually'. */
blender::Vector<ID *> cleanup_ids{ids_to_delete.begin(), ids_to_delete.end()};
BKE_libblock_relink_multiple(
bmain,
cleanup_ids,
ID_REMAP_TYPE_CLEANUP,
id_remapper,
(ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS | ID_REMAP_SKIP_USER_CLEAR));
cleanup_ids.clear();
/* Now we can safely mark that ID as not being in Main database anymore. */
/* NOTE: This needs to be done in a separate loop than above, otherwise some user-counts of
* deleted IDs may not be properly decreased by the remappings (since `NO_MAIN` ID user-counts
* is never affected). */
for (ID *id : ids_to_delete) {
id->tag |= LIB_TAG_NO_MAIN;
/* User-count needs to be reset artificially, since some usages may not be cleared in batch
* deletion (typically, if one deleted ID uses another deleted ID, this may not be cleared by
* remapping code, depending on order in which these are handled). */
id->us = ID_FAKE_USERS(id);
id_free(bmain, id, free_flag, false);
}
BKE_main_unlock(bmain);
/* ViewLayer resync needs to be delayed during Scene freeing, since internal relationships
* between the Scene's master collection and its view_layers become invalid
* (due to remapping). */
BKE_layer_collection_resync_forbid();
/* In usual reversed order, such that all usage of a given ID, even 'never nullptr' ones,
* have been already cleared when we reach it
* (e.g. Objects being processed before meshes, they'll have already released their 'reference'
* over meshes when we come to freeing obdata). */
size_t num_datablocks_deleted = 0;
for (i = do_tagged_deletion ? 1 : base_count; i--;) {
ListBase *lb = lbarray[i];
ID *id, *id_next;
for (id = static_cast<ID *>(do_tagged_deletion ? tagged_deleted_ids.first : lb->first); id;
id = id_next)
{
id_next = static_cast<ID *>(id->next);
if (id->tag & tag) {
if (((id->tag & LIB_TAG_EXTRAUSER_SET) == 0 && ID_REAL_USERS(id) != 0) ||
((id->tag & LIB_TAG_EXTRAUSER_SET) != 0 && ID_REAL_USERS(id) != 1))
{
CLOG_ERROR(&LOG,
"Deleting %s which still has %d users (including %d 'extra' shallow users)\n",
id->name,
ID_REAL_USERS(id),
(id->tag & LIB_TAG_EXTRAUSER_SET) != 0 ? 1 : 0);
}
id_free(bmain, id, free_flag, !do_tagged_deletion);
++num_datablocks_deleted;
}
}
}
BKE_layer_collection_resync_allow();
BKE_main_collection_sync_remap(bmain);
bmain->is_memfile_undo_written = false;
return num_datablocks_deleted;
return size_t(ids_to_delete.size());
}
void BKE_id_delete_ex(Main *bmain, void *idv, const int extra_remapping_flags)
{
BLI_assert_msg((((ID *)idv)->tag & LIB_TAG_NO_MAIN) == 0,
"Cannot be used with IDs outside of Main");
ID *id = static_cast<ID *>(idv);
BLI_assert_msg((id->tag & LIB_TAG_NO_MAIN) == 0, "Cannot be used with IDs outside of Main");
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
((ID *)idv)->tag |= LIB_TAG_DOIT;
id_delete(bmain, false, extra_remapping_flags);
blender::Set<ID *> ids_to_delete = {id};
id_delete(bmain, ids_to_delete, extra_remapping_flags);
}
void BKE_id_delete(Main *bmain, void *idv)
@ -430,7 +345,20 @@ void BKE_id_delete(Main *bmain, void *idv)
size_t BKE_id_multi_tagged_delete(Main *bmain)
{
return id_delete(bmain, true, 0);
blender::Set<ID *> ids_to_delete;
ID *id_iter;
FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
if (id_iter->tag & LIB_TAG_DOIT) {
ids_to_delete.add(id_iter);
}
}
FOREACH_MAIN_ID_END;
return id_delete(bmain, ids_to_delete, 0);
}
size_t BKE_id_multi_delete(Main *bmain, blender::Set<ID *> &ids_to_delete)
{
return id_delete(bmain, ids_to_delete, 0);
}
/* -------------------------------------------------------------------- */

View File

@ -3212,7 +3212,7 @@ static bool lib_override_library_main_resync_on_library_indirect_level(
BlendFileReadReport *reports)
{
const bool do_reports_recursive_resync_timing = (library_indirect_level != 0);
const double init_time = do_reports_recursive_resync_timing ? BLI_check_seconds_timer() : 0.0;
const double init_time = do_reports_recursive_resync_timing ? BLI_time_now_seconds() : 0.0;
BKE_main_relations_create(bmain, 0);
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
@ -3518,7 +3518,7 @@ static bool lib_override_library_main_resync_on_library_indirect_level(
BKE_lib_override_library_main_hierarchy_root_ensure(bmain);
if (do_reports_recursive_resync_timing) {
reports->duration.lib_overrides_recursive_resync += BLI_check_seconds_timer() - init_time;
reports->duration.lib_overrides_recursive_resync += BLI_time_now_seconds() - init_time;
}
return process_lib_level_again;

View File

@ -256,8 +256,11 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
skip_reference);
#endif
if ((id_remap_data->flag & ID_REMAP_FLAG_NEVER_NULL_USAGE) && (cb_flag & IDWALK_CB_NEVER_NULL)) {
id_owner->tag |= LIB_TAG_DOIT;
if ((id_remap_data->flag & ID_REMAP_STORE_NEVER_NULL_USAGE) &&
(cb_flag & IDWALK_CB_NEVER_NULL) &&
(expected_mapping_result == ID_REMAP_RESULT_SOURCE_UNASSIGNED))
{
id_remapper.never_null_users_add(id_owner);
}
/* Special hack in case it's Object->data and we are in edit mode, and new_id is not nullptr
@ -715,13 +718,9 @@ void BKE_libblock_remap_multiple(Main *bmain, IDRemapper &mappings, const int re
BKE_main_unlock(bmain);
}
void BKE_libblock_unlink(Main *bmain,
void *idv,
const bool do_flag_never_null,
const bool do_skip_indirect)
void BKE_libblock_unlink(Main *bmain, void *idv, const bool do_skip_indirect)
{
const int remap_flags = (do_skip_indirect ? ID_REMAP_SKIP_INDIRECT_USAGE : 0) |
(do_flag_never_null ? ID_REMAP_FLAG_NEVER_NULL_USAGE : 0);
const int remap_flags = (do_skip_indirect ? ID_REMAP_SKIP_INDIRECT_USAGE : 0);
BKE_main_lock(bmain);

View File

@ -32,6 +32,8 @@
#include "MEM_guardedalloc.h"
using namespace blender::bke::id;
namespace blender::bke::tests {
class TestData {
@ -298,7 +300,7 @@ TEST(lib_remap, never_null_usage_flag_not_requested_on_delete)
EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
}
TEST(lib_remap, never_null_usage_flag_requested_on_delete)
TEST(lib_remap, never_null_usage_storage_requested_on_delete)
{
Context<MeshObjectTestData> context;
@ -306,14 +308,19 @@ TEST(lib_remap, never_null_usage_flag_requested_on_delete)
EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
/* Never null usage is requested so the flag should be set. */
BKE_libblock_remap(context.test_data.bmain,
context.test_data.mesh,
nullptr,
ID_REMAP_SKIP_NEVER_NULL_USAGE | ID_REMAP_FLAG_NEVER_NULL_USAGE);
/* Never null usage is requested so the owner ID (the Object) should be added to the set. */
IDRemapper remapper;
remapper.add(&context.test_data.mesh->id, nullptr);
BKE_libblock_remap_multiple_locked(
context.test_data.bmain,
remapper,
(ID_REMAP_SKIP_NEVER_NULL_USAGE | ID_REMAP_STORE_NEVER_NULL_USAGE));
/* Never null usages unassignement is not enforced (no #ID_REMAP_FORCE_NEVER_NULL_USAGE), so the
* obdta should still use the original mesh. */
EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
EXPECT_NE(context.test_data.object->data, nullptr);
EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, LIB_TAG_DOIT);
EXPECT_TRUE(remapper.never_null_users().contains(&context.test_data.object->id));
}
TEST(lib_remap, never_null_usage_flag_not_requested_on_remap)
@ -332,7 +339,7 @@ TEST(lib_remap, never_null_usage_flag_not_requested_on_remap)
EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
}
TEST(lib_remap, never_null_usage_flag_requested_on_remap)
TEST(lib_remap, never_null_usage_storage_requested_on_remap)
{
Context<MeshObjectTestData> context;
Mesh *other_mesh = BKE_mesh_add(context.test_data.bmain, nullptr);
@ -341,13 +348,16 @@ TEST(lib_remap, never_null_usage_flag_requested_on_remap)
EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
/* Never null usage is requested so the flag should be set. */
BKE_libblock_remap(context.test_data.bmain,
context.test_data.mesh,
other_mesh,
ID_REMAP_SKIP_NEVER_NULL_USAGE | ID_REMAP_FLAG_NEVER_NULL_USAGE);
/* Never null usage is requested, but the obdata is remapped to another Mesh, not to `nullptr`,
* so the `never_null_users` set should remain empty. */
IDRemapper remapper;
remapper.add(&context.test_data.mesh->id, &other_mesh->id);
BKE_libblock_remap_multiple_locked(
context.test_data.bmain,
remapper,
(ID_REMAP_SKIP_NEVER_NULL_USAGE | ID_REMAP_STORE_NEVER_NULL_USAGE));
EXPECT_EQ(context.test_data.object->data, other_mesh);
EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, LIB_TAG_DOIT);
EXPECT_TRUE(remapper.never_null_users().is_empty());
}
/** \} */

View File

@ -96,7 +96,7 @@ static void mesh_init_data(ID *id)
mesh->runtime = new blender::bke::MeshRuntime();
mesh->face_sets_color_seed = BLI_hash_int(BLI_check_seconds_timer_i() & UINT_MAX);
mesh->face_sets_color_seed = BLI_hash_int(BLI_time_now_seconds_i() & UINT_MAX);
}
static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)

View File

@ -2539,7 +2539,7 @@ void nodeUniqueName(bNodeTree *ntree, bNode *node)
void nodeUniqueID(bNodeTree *ntree, bNode *node)
{
/* Use a pointer cast to avoid overflow warnings. */
const double time = BLI_check_seconds_timer() * 1000000.0;
const double time = BLI_time_now_seconds() * 1000000.0;
blender::RandomNumberGenerator id_rng{*reinterpret_cast<const uint32_t *>(&time)};
/* In the unlikely case that the random ID doesn't match, choose a new one until it does. */

View File

@ -1224,7 +1224,7 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *pbvh, BMEdge *
static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *pbvh)
{
const double start_time = BLI_check_seconds_timer();
const double start_time = BLI_time_now_seconds();
bool any_subdivided = false;
@ -1267,7 +1267,7 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *pbvh
#endif
CLOG_INFO(
&LOG, 2, "Long edge subdivision took %f seconds.", BLI_check_seconds_timer() - start_time);
&LOG, 2, "Long edge subdivision took %f seconds.", BLI_time_now_seconds() - start_time);
return any_subdivided;
}
@ -1701,7 +1701,7 @@ static void pbvh_bmesh_collapse_edge(
static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx, PBVH *pbvh)
{
const double start_time = BLI_check_seconds_timer();
const double start_time = BLI_time_now_seconds();
const float min_len_squared = pbvh->bm_min_edge_len * pbvh->bm_min_edge_len;
bool any_collapsed = false;
@ -1751,8 +1751,7 @@ static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx, PBVH *pbvh
BLI_ghash_free(deleted_verts, nullptr, nullptr);
CLOG_INFO(
&LOG, 2, "Short edge collapse took %f seconds.", BLI_check_seconds_timer() - start_time);
CLOG_INFO(&LOG, 2, "Short edge collapse took %f seconds.", BLI_time_now_seconds() - start_time);
return any_collapsed;
}

View File

@ -3297,7 +3297,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
char run[32], cur[32], etd[32];
int cancel = 0;
stime = ptime = BLI_check_seconds_timer();
stime = ptime = BLI_time_now_seconds();
for (int fr = scene->r.cfra; fr <= endframe; fr += baker->quick_step, scene->r.cfra = fr) {
BKE_scene_graph_update_for_newframe(depsgraph);
@ -3311,7 +3311,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
printf("bake: frame %d :: %d\n", scene->r.cfra, endframe);
}
else {
ctime = BLI_check_seconds_timer();
ctime = BLI_time_now_seconds();
fetd = (ctime - ptime) * (endframe - scene->r.cfra) / baker->quick_step;
@ -3343,7 +3343,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
if (use_timer) {
/* start with newline because of \r above */
ptcache_dt_to_str(run, sizeof(run), BLI_check_seconds_timer() - stime);
ptcache_dt_to_str(run, sizeof(run), BLI_time_now_seconds() - stime);
printf("\nBake %s %s (%i frames simulated).\n",
(cancel ? "canceled after" : "finished in"),
run,

View File

@ -3357,7 +3357,7 @@ static void softbody_step(
float forcetime;
double sct, sst;
sst = BLI_check_seconds_timer();
sst = BLI_time_now_seconds();
/* Integration back in time is possible in theory, but pretty useless here.
* So we refuse to do so. Since we do not know anything about 'outside' changes
* especially colliders we refuse to go more than 10 frames.
@ -3453,7 +3453,7 @@ static void softbody_step(
}
loops++;
if (sb->solverflags & SBSO_MONITOR) {
sct = BLI_check_seconds_timer();
sct = BLI_time_now_seconds();
if (sct - sst > 0.5) {
printf("%3.0f%% \r", 100.0f * timedone / dtime);
}
@ -3494,7 +3494,7 @@ static void softbody_step(
}
if (sb->solverflags & SBSO_MONITOR) {
sct = BLI_check_seconds_timer();
sct = BLI_time_now_seconds();
if ((sct - sst > 0.5) || (G.debug & G_DEBUG)) {
printf(" solver time %f sec %s\n", sct - sst, ob->id.name);
}

View File

@ -26,12 +26,12 @@ void BKE_subdiv_stats_init(SubdivStats *stats)
void BKE_subdiv_stats_begin(SubdivStats *stats, eSubdivStatsValue value)
{
stats->begin_timestamp_[value] = BLI_check_seconds_timer();
stats->begin_timestamp_[value] = BLI_time_now_seconds();
}
void BKE_subdiv_stats_end(SubdivStats *stats, eSubdivStatsValue value)
{
stats->values_[value] = BLI_check_seconds_timer() - stats->begin_timestamp_[value];
stats->values_[value] = BLI_time_now_seconds() - stats->begin_timestamp_[value];
}
void BKE_subdiv_stats_reset(SubdivStats *stats, eSubdivStatsValue value)

View File

@ -0,0 +1,24 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bke
*/
#include "BKE_report.hh"
#include "BKE_wm_runtime.hh"
namespace blender::bke {
WindowManagerRuntime::WindowManagerRuntime()
{
BKE_reports_init(&this->reports, RPT_STORE);
}
WindowManagerRuntime::~WindowManagerRuntime()
{
BKE_reports_free(&this->reports);
}
} // namespace blender::bke

View File

@ -28,6 +28,7 @@
# include "BLI_math_base.h"
# include "BLI_threads.h"
# include "BLI_utildefines.h"
# include "BLI_vector.hh"
# include "BKE_global.hh"
# include "BKE_image.h"
@ -56,6 +57,25 @@ extern "C" {
struct StampData;
/* libswscale context creation and destruction is expensive.
* Maintain a cache of already created contexts. */
constexpr int64_t swscale_cache_max_entries = 32;
struct SwscaleContext {
int width = 0, height = 0;
AVPixelFormat src_format = AV_PIX_FMT_NONE, dst_format = AV_PIX_FMT_NONE;
int flags = 0;
SwsContext *context = nullptr;
int64_t last_use_timestamp = 0;
bool is_used = false;
};
static ThreadMutex swscale_cache_lock = PTHREAD_MUTEX_INITIALIZER;
static int64_t swscale_cache_timestamp = 0;
static blender::Vector<SwscaleContext> *swscale_cache = nullptr;
struct FFMpegContext {
int ffmpeg_type;
AVCodecID ffmpeg_codec;
@ -665,7 +685,7 @@ static const AVCodec *get_av1_encoder(
return codec;
}
SwsContext *BKE_ffmpeg_sws_get_context(
static SwsContext *sws_create_context(
int width, int height, int av_src_format, int av_dst_format, int sws_flags)
{
# if defined(FFMPEG_SWSCALE_THREADING)
@ -703,6 +723,128 @@ SwsContext *BKE_ffmpeg_sws_get_context(
return c;
}
static void init_swscale_cache_if_needed()
{
if (swscale_cache == nullptr) {
swscale_cache = new blender::Vector<SwscaleContext>();
swscale_cache_timestamp = 0;
}
}
static bool remove_oldest_swscale_context()
{
int64_t oldest_index = -1;
int64_t oldest_time = 0;
for (int64_t index = 0; index < swscale_cache->size(); index++) {
SwscaleContext &ctx = (*swscale_cache)[index];
if (ctx.is_used) {
continue;
}
int64_t time = swscale_cache_timestamp - ctx.last_use_timestamp;
if (time > oldest_time) {
oldest_time = time;
oldest_index = index;
}
}
if (oldest_index >= 0) {
SwscaleContext &ctx = (*swscale_cache)[oldest_index];
sws_freeContext(ctx.context);
swscale_cache->remove_and_reorder(oldest_index);
return true;
}
return false;
}
static void maintain_swscale_cache_size()
{
while (swscale_cache->size() > swscale_cache_max_entries) {
if (!remove_oldest_swscale_context()) {
/* Could not remove anything (all contexts are actively used),
* stop trying. */
break;
}
}
}
SwsContext *BKE_ffmpeg_sws_get_context(
int width, int height, int av_src_format, int av_dst_format, int sws_flags)
{
BLI_mutex_lock(&swscale_cache_lock);
init_swscale_cache_if_needed();
swscale_cache_timestamp++;
/* Search for unused context that has suitable parameters. */
SwsContext *ctx = nullptr;
for (SwscaleContext &c : *swscale_cache) {
if (!c.is_used && c.width == width && c.height == height && c.src_format == av_src_format &&
c.dst_format == av_dst_format && c.flags == sws_flags)
{
ctx = c.context;
/* Mark as used. */
c.is_used = true;
c.last_use_timestamp = swscale_cache_timestamp;
break;
}
}
if (ctx == nullptr) {
/* No free matching context in cache: create a new one. */
ctx = sws_create_context(width, height, av_src_format, av_dst_format, sws_flags);
SwscaleContext c;
c.width = width;
c.height = height;
c.src_format = AVPixelFormat(av_src_format);
c.dst_format = AVPixelFormat(av_dst_format);
c.flags = sws_flags;
c.context = ctx;
c.is_used = true;
c.last_use_timestamp = swscale_cache_timestamp;
swscale_cache->append(c);
maintain_swscale_cache_size();
}
BLI_mutex_unlock(&swscale_cache_lock);
return ctx;
}
void BKE_ffmpeg_sws_release_context(SwsContext *ctx)
{
BLI_mutex_lock(&swscale_cache_lock);
init_swscale_cache_if_needed();
bool found = false;
for (SwscaleContext &c : *swscale_cache) {
if (c.context == ctx) {
BLI_assert_msg(c.is_used, "Releasing ffmpeg swscale context that is not in use");
c.is_used = false;
found = true;
break;
}
}
BLI_assert_msg(found, "Releasing ffmpeg swscale context that is not in cache");
UNUSED_VARS_NDEBUG(found);
maintain_swscale_cache_size();
BLI_mutex_unlock(&swscale_cache_lock);
}
void BKE_ffmpeg_exit()
{
BLI_mutex_lock(&swscale_cache_lock);
if (swscale_cache != nullptr) {
for (SwscaleContext &c : *swscale_cache) {
sws_freeContext(c.context);
}
delete swscale_cache;
swscale_cache = nullptr;
}
BLI_mutex_unlock(&swscale_cache_lock);
}
void BKE_ffmpeg_sws_scale_frame(SwsContext *ctx, AVFrame *dst, const AVFrame *src)
{
# if defined(FFMPEG_SWSCALE_THREADING)
@ -1677,7 +1819,7 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
}
if (context->img_convert_ctx != nullptr) {
sws_freeContext(context->img_convert_ctx);
BKE_ffmpeg_sws_release_context(context->img_convert_ctx);
context->img_convert_ctx = nullptr;
}
}

View File

@ -13,24 +13,20 @@
extern "C" {
#endif
extern
/** Return an indication of time, expressed as
* seconds since some fixed point. Successive calls
* are guaranteed to generate values greater than or
* equal to the last call. */
double
BLI_check_seconds_timer(void);
/**
* Return an indication of time, expressed as seconds since some fixed point.
* Successive calls are guaranteed to generate values greater than or equal to the last call.
*/
extern double BLI_time_now_seconds(void);
extern
/** `int` version of #BLI_check_seconds_timer. */
long int
BLI_check_seconds_timer_i(void);
/** `int` version of #BLI_time_now_seconds. */
extern long int BLI_time_now_seconds_i(void);
/**
* Platform-independent sleep function.
* \param ms: Number of milliseconds to sleep
*/
void BLI_sleep_ms(int ms);
void BLI_time_sleep_ms(int ms);
#ifdef __cplusplus
}

View File

@ -9,12 +9,12 @@
#pragma once
#include "BLI_time.h" /* for BLI_check_seconds_timer */
#include "BLI_time.h" /* for BLI_time_now_seconds */
#include "BLI_utildefines.h" /* for AT */
#define TIMEIT_START(var) \
{ \
double _timeit_##var = BLI_check_seconds_timer(); \
double _timeit_##var = BLI_time_now_seconds(); \
printf("time start (" #var "): " AT "\n"); \
fflush(stdout); \
{ \
@ -23,7 +23,7 @@
/**
* \return the time since TIMEIT_START was called.
*/
#define TIMEIT_VALUE(var) (float)(BLI_check_seconds_timer() - _timeit_##var)
#define TIMEIT_VALUE(var) (float)(BLI_time_now_seconds() - _timeit_##var)
#define TIMEIT_VALUE_PRINT(var) \
{ \
@ -54,7 +54,7 @@
{ \
static float _sum_##var = 0.0f; \
static float _num_##var = 0.0f; \
double _timeit_##var = BLI_check_seconds_timer(); \
double _timeit_##var = BLI_time_now_seconds(); \
printf("time start (" #var "): " AT "\n"); \
fflush(stdout); \
{ \
@ -95,13 +95,13 @@
#define TIMEIT_BLOCK_START(id) \
{ \
double _timeit_block_start_##id = BLI_check_seconds_timer(); \
double _timeit_block_start_##id = BLI_time_now_seconds(); \
{ \
(void)0
#define TIMEIT_BLOCK_END(id) \
} \
_timeit_var_##id += (BLI_check_seconds_timer() - _timeit_block_start_##id); \
_timeit_var_##id += (BLI_time_now_seconds() - _timeit_block_start_##id); \
} \
(void)0

View File

@ -12,7 +12,7 @@
#include "MEM_guardedalloc.h"
#define GET_TIME() BLI_check_seconds_timer()
#define GET_TIME() BLI_time_now_seconds()
typedef struct TimedFunction {
struct TimedFunction *next, *prev;

View File

@ -3557,7 +3557,7 @@ IMesh boolean_trimesh(IMesh &tm_in,
return IMesh(tm_in);
}
# ifdef PERFDEBUG
double start_time = BLI_check_seconds_timer();
double start_time = BLI_time_now_seconds();
std::cout << " boolean_trimesh, timing begins\n";
# endif
@ -3567,7 +3567,7 @@ IMesh boolean_trimesh(IMesh &tm_in,
std::cout << "\nboolean_tm_input after intersection:\n" << tm_si;
}
# ifdef PERFDEBUG
double intersect_time = BLI_check_seconds_timer();
double intersect_time = BLI_time_now_seconds();
std::cout << " intersected, time = " << intersect_time - start_time << "\n";
# endif
@ -3578,12 +3578,12 @@ IMesh boolean_trimesh(IMesh &tm_in,
auto si_shape_fn = [shape_fn, tm_si](int t) { return shape_fn(tm_si.face(t)->orig); };
TriMeshTopology tm_si_topo(tm_si);
# ifdef PERFDEBUG
double topo_time = BLI_check_seconds_timer();
double topo_time = BLI_time_now_seconds();
std::cout << " topology built, time = " << topo_time - intersect_time << "\n";
# endif
bool pwn = is_pwn(tm_si, tm_si_topo);
# ifdef PERFDEBUG
double pwn_time = BLI_check_seconds_timer();
double pwn_time = BLI_time_now_seconds();
std::cout << " pwn checked, time = " << pwn_time - topo_time << "\n";
# endif
IMesh tm_out;
@ -3599,14 +3599,14 @@ IMesh boolean_trimesh(IMesh &tm_in,
tm_out = raycast_patches_boolean(tm_si, op, nshapes, shape_fn, pinfo, arena);
}
# ifdef PERFDEBUG
double raycast_time = BLI_check_seconds_timer();
double raycast_time = BLI_time_now_seconds();
std::cout << " raycast_boolean done, time = " << raycast_time - pwn_time << "\n";
# endif
}
else {
PatchesInfo pinfo = find_patches(tm_si, tm_si_topo);
# ifdef PERFDEBUG
double patch_time = BLI_check_seconds_timer();
double patch_time = BLI_time_now_seconds();
std::cout << " patches found, time = " << patch_time - pwn_time << "\n";
# endif
CellsInfo cinfo = find_cells(tm_si, tm_si_topo, pinfo);
@ -3614,12 +3614,12 @@ IMesh boolean_trimesh(IMesh &tm_in,
std::cout << "Input is PWN\n";
}
# ifdef PERFDEBUG
double cell_time = BLI_check_seconds_timer();
double cell_time = BLI_time_now_seconds();
std::cout << " cells found, time = " << cell_time - pwn_time << "\n";
# endif
finish_patch_cell_graph(tm_si, cinfo, pinfo, tm_si_topo, arena);
# ifdef PERFDEBUG
double finish_pc_time = BLI_check_seconds_timer();
double finish_pc_time = BLI_time_now_seconds();
std::cout << " finished patch-cell graph, time = " << finish_pc_time - cell_time << "\n";
# endif
bool pc_ok = patch_cell_graph_ok(cinfo, pinfo);
@ -3631,7 +3631,7 @@ IMesh boolean_trimesh(IMesh &tm_in,
cinfo.init_windings(nshapes);
int c_ambient = find_ambient_cell(tm_si, nullptr, tm_si_topo, pinfo, arena);
# ifdef PERFDEBUG
double amb_time = BLI_check_seconds_timer();
double amb_time = BLI_time_now_seconds();
std::cout << " ambient cell found, time = " << amb_time - finish_pc_time << "\n";
# endif
if (c_ambient == NO_INDEX) {
@ -3641,12 +3641,12 @@ IMesh boolean_trimesh(IMesh &tm_in,
}
propagate_windings_and_in_output_volume(pinfo, cinfo, c_ambient, op, nshapes, si_shape_fn);
# ifdef PERFDEBUG
double propagate_time = BLI_check_seconds_timer();
double propagate_time = BLI_time_now_seconds();
std::cout << " windings propagated, time = " << propagate_time - amb_time << "\n";
# endif
tm_out = extract_from_in_output_volume_diffs(tm_si, pinfo, cinfo, arena);
# ifdef PERFDEBUG
double extract_time = BLI_check_seconds_timer();
double extract_time = BLI_time_now_seconds();
std::cout << " extracted, time = " << extract_time - propagate_time << "\n";
# endif
if (dbg_level > 0) {
@ -3662,7 +3662,7 @@ IMesh boolean_trimesh(IMesh &tm_in,
std::cout << "boolean tm output:\n" << tm_out;
}
# ifdef PERFDEBUG
double end_time = BLI_check_seconds_timer();
double end_time = BLI_time_now_seconds();
std::cout << " boolean_trimesh done, total time = " << end_time - start_time << "\n";
# endif
return tm_out;
@ -3708,7 +3708,7 @@ IMesh boolean_mesh(IMesh &imesh,
IMesh *tm_in = imesh_triangulated;
IMesh our_triangulation;
# ifdef PERFDEBUG
double start_time = BLI_check_seconds_timer();
double start_time = BLI_time_now_seconds();
std::cout << "boolean_mesh, timing begins\n";
# endif
if (tm_in == nullptr) {
@ -3716,7 +3716,7 @@ IMesh boolean_mesh(IMesh &imesh,
tm_in = &our_triangulation;
}
# ifdef PERFDEBUG
double tri_time = BLI_check_seconds_timer();
double tri_time = BLI_time_now_seconds();
std::cout << "triangulated, time = " << tri_time - start_time << "\n";
# endif
if (dbg_level > 1) {
@ -3724,7 +3724,7 @@ IMesh boolean_mesh(IMesh &imesh,
}
IMesh tm_out = boolean_trimesh(*tm_in, op, nshapes, shape_fn, use_self, hole_tolerant, arena);
# ifdef PERFDEBUG
double bool_tri_time = BLI_check_seconds_timer();
double bool_tri_time = BLI_time_now_seconds();
std::cout << "boolean_trimesh done, time = " << bool_tri_time - tri_time << "\n";
# endif
if (dbg_level > 1) {
@ -3733,7 +3733,7 @@ IMesh boolean_mesh(IMesh &imesh,
}
IMesh ans = polymesh_from_trimesh_with_dissolve(tm_out, imesh, arena);
# ifdef PERFDEBUG
double dissolve_time = BLI_check_seconds_timer();
double dissolve_time = BLI_time_now_seconds();
std::cout << "polymesh from dissolving, time = " << dissolve_time - bool_tri_time << "\n";
# endif
if (dbg_level > 0) {
@ -3744,7 +3744,7 @@ IMesh boolean_mesh(IMesh &imesh,
}
}
# ifdef PERFDEBUG
double end_time = BLI_check_seconds_timer();
double end_time = BLI_time_now_seconds();
std::cout << "boolean_mesh done, total time = " << end_time - start_time << "\n";
# endif
return ans;

View File

@ -2954,7 +2954,7 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
}
# ifdef PERFDEBUG
perfdata_init();
double start_time = BLI_check_seconds_timer();
double start_time = BLI_time_now_seconds();
std::cout << "trimesh_nary_intersect start\n";
# endif
/* Usually can use tm_in but if it has degenerate or illegal triangles,
@ -2972,17 +2972,17 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
}
}
# ifdef PERFDEBUG
double clean_time = BLI_check_seconds_timer();
double clean_time = BLI_time_now_seconds();
std::cout << "cleaned, time = " << clean_time - start_time << "\n";
# endif
Array<BoundingBox> tri_bb = calc_face_bounding_boxes(*tm_clean);
# ifdef PERFDEBUG
double bb_calc_time = BLI_check_seconds_timer();
double bb_calc_time = BLI_time_now_seconds();
std::cout << "bbs calculated, time = " << bb_calc_time - clean_time << "\n";
# endif
TriOverlaps tri_ov(*tm_clean, tri_bb, nshapes, shape_fn, use_self);
# ifdef PERFDEBUG
double overlap_time = BLI_check_seconds_timer();
double overlap_time = BLI_time_now_seconds();
std::cout << "intersect overlaps calculated, time = " << overlap_time - bb_calc_time << "\n";
# endif
Array<IMesh> tri_subdivided(tm_clean->face_size(), NoInitialization());
@ -2995,7 +2995,7 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
}
});
# ifdef PERFDEBUG
double plane_populate = BLI_check_seconds_timer();
double plane_populate = BLI_time_now_seconds();
std::cout << "planes populated, time = " << plane_populate - overlap_time << "\n";
# endif
/* itt_map((a,b)) will hold the intersection value resulting from intersecting
@ -3004,7 +3004,7 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
itt_map.reserve(tri_ov.overlap().size());
calc_overlap_itts(itt_map, *tm_clean, tri_ov, arena);
# ifdef PERFDEBUG
double itt_time = BLI_check_seconds_timer();
double itt_time = BLI_time_now_seconds();
std::cout << "itts found, time = " << itt_time - plane_populate << "\n";
# endif
CoplanarClusterInfo clinfo = find_clusters(*tm_clean, tri_bb, itt_map);
@ -3012,7 +3012,7 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
std::cout << clinfo;
}
# ifdef PERFDEBUG
double find_cluster_time = BLI_check_seconds_timer();
double find_cluster_time = BLI_time_now_seconds();
std::cout << "clusters found, time = " << find_cluster_time - itt_time << "\n";
doperfmax(0, tm_in.face_size());
doperfmax(1, clinfo.tot_cluster());
@ -3020,7 +3020,7 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
# endif
calc_subdivided_non_cluster_tris(tri_subdivided, *tm_clean, itt_map, clinfo, tri_ov, arena);
# ifdef PERFDEBUG
double subdivided_tris_time = BLI_check_seconds_timer();
double subdivided_tris_time = BLI_time_now_seconds();
std::cout << "subdivided non-cluster tris found, time = " << subdivided_tris_time - itt_time
<< "\n";
# endif
@ -3029,13 +3029,13 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
cluster_subdivided[c] = calc_cluster_subdivided(clinfo, c, *tm_clean, tri_ov, itt_map, arena);
}
# ifdef PERFDEBUG
double cluster_subdivide_time = BLI_check_seconds_timer();
double cluster_subdivide_time = BLI_time_now_seconds();
std::cout << "subdivided clusters found, time = "
<< cluster_subdivide_time - subdivided_tris_time << "\n";
# endif
calc_cluster_tris(tri_subdivided, *tm_clean, clinfo, cluster_subdivided, arena);
# ifdef PERFDEBUG
double extract_time = BLI_check_seconds_timer();
double extract_time = BLI_time_now_seconds();
std::cout << "subdivided cluster tris found, time = " << extract_time - cluster_subdivide_time
<< "\n";
# endif
@ -3045,7 +3045,7 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
std::cout << combined;
}
# ifdef PERFDEBUG
double end_time = BLI_check_seconds_timer();
double end_time = BLI_time_now_seconds();
std::cout << "triangles combined, time = " << end_time - extract_time << "\n";
std::cout << "trimesh_nary_intersect done, total time = " << end_time - start_time << "\n";
dump_perfdata();

View File

@ -63,7 +63,7 @@
* // tag job 'processed
* BLI_threadpool_insert(&lb, job);
* }
* else BLI_sleep_ms(50);
* else BLI_time_sleep_ms(50);
*
* // Find if a job is ready, this the do_something_func() should write in job somewhere.
* cont = 0;
@ -687,7 +687,7 @@ void *BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms)
void *work = nullptr;
timespec timeout;
t = BLI_check_seconds_timer();
t = BLI_time_now_seconds();
wait_timeout(&timeout, ms);
/* wait until there is work */
@ -696,7 +696,7 @@ void *BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms)
if (pthread_cond_timedwait(&queue->push_cond, &queue->mutex, &timeout) == ETIMEDOUT) {
break;
}
if (BLI_check_seconds_timer() - t >= ms * 0.001) {
if (BLI_time_now_seconds() - t >= ms * 0.001) {
break;
}
}

View File

@ -12,7 +12,7 @@
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
double BLI_check_seconds_timer(void)
double BLI_time_now_seconds(void)
{
static int hasperfcounter = -1; /* (-1 == unknown) */
static double perffreq;
@ -47,12 +47,12 @@ double BLI_check_seconds_timer(void)
}
}
long int BLI_check_seconds_timer_i(void)
long int BLI_time_now_seconds_i(void)
{
return (long int)BLI_check_seconds_timer();
return (long int)BLI_time_now_seconds();
}
void BLI_sleep_ms(int ms)
void BLI_time_sleep_ms(int ms)
{
Sleep(ms);
}
@ -62,7 +62,7 @@ void BLI_sleep_ms(int ms)
# include <sys/time.h>
# include <unistd.h>
double BLI_check_seconds_timer(void)
double BLI_time_now_seconds(void)
{
struct timeval tv;
struct timezone tz;
@ -72,7 +72,7 @@ double BLI_check_seconds_timer(void)
return ((double)tv.tv_sec + tv.tv_usec / 1000000.0);
}
long int BLI_check_seconds_timer_i(void)
long int BLI_time_now_seconds_i(void)
{
struct timeval tv;
struct timezone tz;
@ -82,7 +82,7 @@ long int BLI_check_seconds_timer_i(void)
return tv.tv_sec;
}
void BLI_sleep_ms(int ms)
void BLI_time_sleep_ms(int ms)
{
if (ms >= 1000) {
sleep(ms / 1000);

View File

@ -1877,9 +1877,9 @@ void text_test(
}
in.epsilon = b_before_arcs_in.epsilon;
in.need_ids = need_ids;
double tstart = BLI_check_seconds_timer();
double tstart = BLI_time_now_seconds();
CDT_result<T> out = delaunay_2d_calc(in, otype);
double tend = BLI_check_seconds_timer();
double tend = BLI_time_now_seconds();
if (print_timing) {
std::cout << "time = " << tend - tstart << "\n";
}
@ -2190,10 +2190,10 @@ void rand_delaunay_test(int test_kind,
}
/* Run the test. */
double tstart = BLI_check_seconds_timer();
double tstart = BLI_time_now_seconds();
CDT_result<T> out = delaunay_2d_calc(in, otype);
EXPECT_NE(out.vert.size(), 0);
times[lg_size] += BLI_check_seconds_timer() - tstart;
times[lg_size] += BLI_time_now_seconds() - tstart;
if (DO_DRAW) {
graph_draw<T>(test_label, out.vert, out.edge, out.face);
}

View File

@ -980,7 +980,7 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self)
return;
}
BLI_task_scheduler_init(); /* Without this, no parallelism. */
double time_start = BLI_check_seconds_timer();
double time_start = BLI_time_now_seconds();
IMeshArena arena;
int nsegs = 2 * nrings;
int sphere_verts_num;
@ -1009,7 +1009,7 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self)
sphere_verts_num,
&arena);
IMesh mesh(tris);
double time_create = BLI_check_seconds_timer();
double time_create = BLI_time_now_seconds();
// write_obj_mesh(mesh, "spheresphere_in");
IMesh out;
if (use_self) {
@ -1020,7 +1020,7 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self)
out = trimesh_nary_intersect(
mesh, 2, [nf](int t) { return t < nf ? 0 : 1; }, false, &arena);
}
double time_intersect = BLI_check_seconds_timer();
double time_intersect = BLI_time_now_seconds();
std::cout << "Create time: " << time_create - time_start << "\n";
std::cout << "Intersect time: " << time_intersect - time_create << "\n";
std::cout << "Total time: " << time_intersect - time_start << "\n";
@ -1120,7 +1120,7 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us
return;
}
BLI_task_scheduler_init(); /* Without this, no parallelism. */
double time_start = BLI_check_seconds_timer();
double time_start = BLI_time_now_seconds();
IMeshArena arena;
int sphere_verts_num;
int sphere_tris_num;
@ -1154,7 +1154,7 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us
sphere_tris_num,
&arena);
IMesh mesh(tris);
double time_create = BLI_check_seconds_timer();
double time_create = BLI_time_now_seconds();
// write_obj_mesh(mesh, "spheregrid_in");
IMesh out;
if (use_self) {
@ -1165,7 +1165,7 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us
out = trimesh_nary_intersect(
mesh, 2, [nf](int t) { return t < nf ? 0 : 1; }, false, &arena);
}
double time_intersect = BLI_check_seconds_timer();
double time_intersect = BLI_time_now_seconds();
std::cout << "Create time: " << time_create - time_start << "\n";
std::cout << "Intersect time: " << time_intersect - time_create << "\n";
std::cout << "Total time: " << time_intersect - time_start << "\n";
@ -1187,7 +1187,7 @@ static void gridgrid_test(int x_level_1,
/* Make two grids, each 4x4, with given subdivision levels in x and y,
* and the second offset from the first by x_off, y_off, and rotated by rot_deg degrees. */
BLI_task_scheduler_init(); /* Without this, no parallelism. */
double time_start = BLI_check_seconds_timer();
double time_start = BLI_time_now_seconds();
IMeshArena arena;
int x_subdivs_1 = 1 << x_level_1;
int y_subdivs_1 = 1 << y_level_1;
@ -1223,7 +1223,7 @@ static void gridgrid_test(int x_level_1,
grid_tris_1_num,
&arena);
IMesh mesh(tris);
double time_create = BLI_check_seconds_timer();
double time_create = BLI_time_now_seconds();
// write_obj_mesh(mesh, "gridgrid_in");
IMesh out;
if (use_self) {
@ -1234,7 +1234,7 @@ static void gridgrid_test(int x_level_1,
out = trimesh_nary_intersect(
mesh, 2, [nf](int t) { return t < nf ? 0 : 1; }, false, &arena);
}
double time_intersect = BLI_check_seconds_timer();
double time_intersect = BLI_time_now_seconds();
std::cout << "Create time: " << time_create - time_start << "\n";
std::cout << "Intersect time: " << time_intersect - time_create << "\n";
std::cout << "Total time: " << time_intersect - time_start << "\n";

View File

@ -3666,7 +3666,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
}
if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
fd->reports->duration.libraries = BLI_check_seconds_timer();
fd->reports->duration.libraries = BLI_time_now_seconds();
read_libraries(fd, &mainlist);
blo_join_main(&mainlist);
@ -3681,7 +3681,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
read_undo_remap_noundo_data(fd);
}
fd->reports->duration.libraries = BLI_check_seconds_timer() - fd->reports->duration.libraries;
fd->reports->duration.libraries = BLI_time_now_seconds() - fd->reports->duration.libraries;
/* Skip in undo case. */
if ((fd->flags & FD_FLAGS_IS_MEMFILE) == 0) {
@ -3739,7 +3739,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
* we can re-generate overrides from their references. */
if ((fd->flags & FD_FLAGS_IS_MEMFILE) == 0) {
/* Do not apply in undo case! */
fd->reports->duration.lib_overrides = BLI_check_seconds_timer();
fd->reports->duration.lib_overrides = BLI_time_now_seconds();
std::string cur_view_layer_name = bfd->cur_view_layer != nullptr ?
bfd->cur_view_layer->name :
@ -3760,7 +3760,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
* Proper fix involves first addressing #90610. */
BKE_main_collections_parent_relations_rebuild(bfd->main);
fd->reports->duration.lib_overrides = BLI_check_seconds_timer() -
fd->reports->duration.lib_overrides = BLI_time_now_seconds() -
fd->reports->duration.lib_overrides;
}

View File

@ -2592,7 +2592,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
ob = static_cast<Object *>(ob->id.next))
{
if (ob->pd) {
ob->pd->seed = (uint(ceil(BLI_check_seconds_timer())) + 1) % 128;
ob->pd->seed = (uint(ceil(BLI_time_now_seconds())) + 1) % 128;
}
}
}

View File

@ -7763,7 +7763,7 @@ void BM_mesh_bevel(BMesh *bm,
}
#ifdef BEVEL_DEBUG_TIME
double start_time = BLI_check_seconds_timer();
double start_time = BLI_time_now_seconds();
#endif
/* Disable the miters with the cutoff vertex mesh method, the combination isn't useful anyway. */
@ -7931,7 +7931,7 @@ void BM_mesh_bevel(BMesh *bm,
BLI_memarena_free(bp.mem_arena);
#ifdef BEVEL_DEBUG_TIME
double end_time = BLI_check_seconds_timer();
double end_time = BLI_time_now_seconds();
printf("BMESH BEVEL TIME = %.3f\n", end_time - start_time);
#endif
}

View File

@ -350,11 +350,11 @@ static bool bmesh_boolean(BMesh *bm,
IMeshArena arena;
IMesh m_triangulated;
# ifdef PERF_DEBUG
double start_time = BLI_check_seconds_timer();
double start_time = BLI_time_now_seconds();
# endif
IMesh m_in = mesh_from_bm(bm, looptris, looptris_tot, &m_triangulated, &arena);
# ifdef PERF_DEBUG
double mesh_time = BLI_check_seconds_timer();
double mesh_time = BLI_time_now_seconds();
std::cout << "bmesh_boolean, imesh_from_bm done, time = " << mesh_time - start_time << "\n";
# endif
std::function<int(int)> shape_fn;
@ -382,12 +382,12 @@ static bool bmesh_boolean(BMesh *bm,
IMesh m_out = boolean_mesh(
m_in, boolean_mode, nshapes, shape_fn, use_self, hole_tolerant, &m_triangulated, &arena);
# ifdef PERF_DEBUG
double boolean_time = BLI_check_seconds_timer();
double boolean_time = BLI_time_now_seconds();
std::cout << "boolean done, time = " << boolean_time - mesh_time << "\n";
# endif
bool any_change = apply_mesh_output_to_bmesh(bm, m_out, keep_hidden);
# ifdef PERF_DEBUG
double apply_mesh_time = BLI_check_seconds_timer();
double apply_mesh_time = BLI_time_now_seconds();
std::cout << "applied boolean output to bmesh, time = " << apply_mesh_time - boolean_time
<< "\n";
# endif

View File

@ -304,7 +304,7 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
} /** \note Early break out. */
uint chunk_index;
execution_start_time_ = BLI_check_seconds_timer();
execution_start_time_ = BLI_time_now_seconds();
chunks_finished_ = 0;
bTree_ = bTree;

View File

@ -73,7 +73,7 @@ void ScreenLensDistortionOperation::init_execution()
input_program_ = this->get_input_socket_reader(0);
this->init_mutex();
uint rng_seed = uint(BLI_check_seconds_timer_i() & UINT_MAX);
uint rng_seed = uint(BLI_time_now_seconds_i() & UINT_MAX);
rng_seed ^= uint(POINTER_AS_INT(input_program_));
rng_ = BLI_rng_new(rng_seed);
}

View File

@ -7,6 +7,11 @@
void main()
{
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
ivec2 output_texel = texel + lower_bound;
if (any(greaterThan(output_texel, upper_bound))) {
return;
}
vec4 input_color = texture_load(input_tx, texel);
#if defined(DIRECT_OUTPUT)

View File

@ -7,6 +7,7 @@
GPU_SHADER_CREATE_INFO(compositor_write_output_shared)
.local_group_size(16, 16)
.push_constant(Type::IVEC2, "lower_bound")
.push_constant(Type::IVEC2, "upper_bound")
.sampler(0, ImageType::FLOAT_2D, "input_tx")
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
.compute_source("compositor_write_output.glsl");

View File

@ -29,7 +29,7 @@ void AbstractBuilderPipeline::build()
{
double start_time = 0.0;
if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
start_time = BLI_check_seconds_timer();
start_time = BLI_time_now_seconds();
}
build_step_sanity_check();
@ -38,7 +38,7 @@ void AbstractBuilderPipeline::build()
build_step_finalize();
if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
printf("Depsgraph built in %f seconds.\n", BLI_check_seconds_timer() - start_time);
printf("Depsgraph built in %f seconds.\n", BLI_time_now_seconds() - start_time);
}
}

View File

@ -33,7 +33,7 @@ void DepsgraphDebug::begin_graph_evaluation()
return;
}
const double current_time = BLI_check_seconds_timer();
const double current_time = BLI_time_now_seconds();
graph_evaluation_start_time_ = current_time;
}
@ -44,7 +44,7 @@ void DepsgraphDebug::end_graph_evaluation()
return;
}
const double graph_eval_end_time = BLI_check_seconds_timer();
const double graph_eval_end_time = BLI_time_now_seconds();
const double graph_eval_time = graph_eval_end_time - graph_evaluation_start_time_;
if (name.empty()) {

View File

@ -93,9 +93,9 @@ void evaluate_node(const DepsgraphEvalState *state, OperationNode *operation_nod
BLI_assert_msg(!operation_node->is_noop(), "NOOP nodes should not actually be scheduled");
/* Perform operation. */
if (state->do_stats) {
const double start_time = BLI_check_seconds_timer();
const double start_time = BLI_time_now_seconds();
operation_node->evaluate(depsgraph);
operation_node->stats.current_time += BLI_check_seconds_timer() - start_time;
operation_node->stats.current_time += BLI_time_now_seconds() - start_time;
}
else {
operation_node->evaluate(depsgraph);

View File

@ -91,42 +91,14 @@ class Context : public realtime_compositor::Context {
return int2(float2(DRW_viewport_size_get()));
}
/* Returns true if the viewport is in camera view and has an opaque passepartout, that is, the
* area outside of the camera border is not visible. */
bool is_opaque_camera_view() const
{
/* Check if the viewport is in camera view. */
if (DRW_context_state_get()->rv3d->persp != RV3D_CAMOB) {
return false;
}
/* Check if the camera object that is currently in view is an actual camera. It is possible for
* a non camera object to be used as a camera, in which case, there will be no passepartout or
* any other camera setting, so those pseudo cameras can be ignored. */
Object *camera_object = DRW_context_state_get()->v3d->camera;
if (camera_object->type != OB_CAMERA) {
return false;
}
/* Check if the camera has passepartout active and is totally opaque. */
Camera *cam = static_cast<Camera *>(camera_object->data);
if (!(cam->flag & CAM_SHOWPASSEPARTOUT) || cam->passepartalpha != 1.0f) {
return false;
}
return true;
}
/* We limit the compositing region to the camera region if in camera view, while we use the
* entire viewport otherwise. */
rcti get_compositing_region() const override
{
const int2 viewport_size = int2(float2(DRW_viewport_size_get()));
const rcti render_region = rcti{0, viewport_size.x, 0, viewport_size.y};
/* If the camera view is not opaque, that means the content outside of the camera region is
* visible to some extent, so it would make sense to include them in the compositing region.
* Otherwise, we limit the compositing region to the visible camera region because anything
* outside of the camera region will not be visible anyways. */
if (!is_opaque_camera_view()) {
if (DRW_context_state_get()->rv3d->persp != RV3D_CAMOB) {
return render_region;
}

View File

@ -1453,7 +1453,7 @@ void EEVEE_lightbake_job(void *custom_data, wmJobWorkerStatus *worker_status)
* because this step is locking at this moment. */
/* TODO: remove this. */
if (lbake->delay) {
BLI_sleep_ms(lbake->delay);
BLI_time_sleep_ms(lbake->delay);
}
/* Render world irradiance and reflection first */

View File

@ -142,7 +142,7 @@ class LightBake {
DEG_evaluate_on_framechange(depsgraph_, frame_);
if (delay_ms_ > 0) {
BLI_sleep_ms(delay_ms_);
BLI_time_sleep_ms(delay_ms_);
}
context_enable();

View File

@ -25,7 +25,7 @@ void OVERLAY_mode_transfer_cache_init(OVERLAY_Data *vedata)
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
pd->mode_transfer.time = BLI_check_seconds_timer();
pd->mode_transfer.time = BLI_time_now_seconds();
for (int i = 0; i < 2; i++) {
/* Non Meshes Pass (Camera, empties, lights ...) */

View File

@ -692,7 +692,7 @@ void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
}
#ifdef DEBUG_TIME
double rdata_start = BLI_check_seconds_timer();
double rdata_start = BLI_time_now_seconds();
#endif
MeshRenderData *mr = mesh_render_data_create(
@ -703,7 +703,7 @@ void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
mr->use_simplify_normals = (scene->r.mode & R_SIMPLIFY) && (scene->r.mode & R_SIMPLIFY_NORMALS);
#ifdef DEBUG_TIME
double rdata_end = BLI_check_seconds_timer();
double rdata_end = BLI_time_now_seconds();
#endif
eMRIterType iter_type = extractors.iter_types();
@ -757,7 +757,7 @@ void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
#ifdef DEBUG_TIME
BLI_task_graph_work_and_wait(task_graph);
double end = BLI_check_seconds_timer();
double end = BLI_time_now_seconds();
static double avg = 0;
static double avg_fps = 0;

View File

@ -2323,7 +2323,7 @@ void DRW_create_subdivision(Object *ob,
#undef TIME_SUBDIV
#ifdef TIME_SUBDIV
const double begin_time = BLI_check_seconds_timer();
const double begin_time = BLI_time_now_seconds();
#endif
if (!draw_subdiv_create_requested_buffers(ob,
@ -2345,7 +2345,7 @@ void DRW_create_subdivision(Object *ob,
}
#ifdef TIME_SUBDIV
const double end_time = BLI_check_seconds_timer();
const double end_time = BLI_time_now_seconds();
fprintf(stderr, "Time to update subdivision: %f\n", end_time - begin_time);
fprintf(stderr, "Maximum FPS: %f\n", 1.0 / (end_time - begin_time));
#endif

View File

@ -58,19 +58,19 @@ struct CurvesUniformBufPool;
# define PROFILE_TIMER_FALLOFF 0.04
# define PROFILE_START(time_start) \
double time_start = BLI_check_seconds_timer(); \
double time_start = BLI_time_now_seconds(); \
((void)0)
# define PROFILE_END_ACCUM(time_accum, time_start) \
{ \
time_accum += (BLI_check_seconds_timer() - time_start) * 1e3; \
time_accum += (BLI_time_now_seconds() - time_start) * 1e3; \
} \
((void)0)
/* exp average */
# define PROFILE_END_UPDATE(time_update, time_start) \
{ \
double _time_delta = (BLI_check_seconds_timer() - time_start) * 1e3; \
double _time_delta = (BLI_time_now_seconds() - time_start) * 1e3; \
time_update = (time_update * (1.0 - PROFILE_TIMER_FALLOFF)) + \
(_time_delta * PROFILE_TIMER_FALLOFF); \
} \

View File

@ -976,7 +976,7 @@ void DRW_cache_free_old_batches(Main *bmain)
using namespace blender::draw;
Scene *scene;
static int lasttime = 0;
int ctime = int(BLI_check_seconds_timer());
int ctime = int(BLI_time_now_seconds());
if (U.vbotimeout == 0 || (ctime - lasttime) < U.vbocollectrate || ctime == lasttime) {
return;

View File

@ -270,7 +270,7 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
DRW_deferred_shader_remove(mat);
/* Shaders could already be compiling. Have to wait for compilation to finish. */
while (GPU_material_status(mat) == GPU_MAT_QUEUED) {
BLI_sleep_ms(20);
BLI_time_sleep_ms(20);
}
if (GPU_material_status(mat) == GPU_MAT_CREATED) {
GPU_material_compile(mat);
@ -568,7 +568,7 @@ void DRW_shader_queue_optimize_material(GPUMaterial *mat)
DRW_deferred_shader_optimize_remove(mat);
/* If optimization job had already started, wait for it to complete. */
while (GPU_material_optimization_status(mat) == GPU_MAT_OPTIMIZATION_QUEUED) {
BLI_sleep_ms(20);
BLI_time_sleep_ms(20);
}
}
return;

View File

@ -4477,36 +4477,33 @@ static void ANIM_OT_channels_bake(wmOperatorType *ot)
"Bake Modifiers into keyframes and delete them after");
}
/* Find a Graph Editor area and modify the given context to be the window region of it. */
static bool move_context_to_graph_editor(bContext *C)
/**
* Find a Graph Editor area and set the context arguments accordingly.
*/
static bool context_find_graph_editor(bContext *C,
wmWindow **r_win,
ScrArea **r_area,
ARegion **r_region)
{
bool found_graph_editor = false;
LISTBASE_FOREACH (wmWindow *, win, &CTX_wm_manager(C)->windows) {
bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
bScreen *screen = WM_window_get_active_screen(win);
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
if (area->spacetype != SPACE_GRAPH) {
continue;
}
ARegion *window_region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
if (!window_region) {
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
if (!region) {
continue;
}
CTX_wm_window_set(C, win);
CTX_wm_screen_set(C, screen);
CTX_wm_area_set(C, area);
CTX_wm_region_set(C, window_region);
found_graph_editor = true;
break;
}
if (found_graph_editor) {
break;
*r_win = win;
*r_area = area;
*r_region = region;
return true;
}
}
return found_graph_editor;
return false;
}
static void deselect_all_fcurves(bAnimContext *ac, const bool hide)
@ -4628,8 +4625,16 @@ static int view_curve_in_graph_editor_exec(bContext *C, wmOperator *op)
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
int retval = OPERATOR_FINISHED;
ListBase selection = {nullptr, nullptr};
struct {
wmWindow *win;
ScrArea *area;
ARegion *region;
} wm_context_prev = {nullptr}, wm_context_temp = {nullptr};
bool path_from_id;
std::optional<std::string> id_to_prop_path;
const bool selected_list_success = UI_context_copy_to_selected_list(
@ -4637,49 +4642,63 @@ static int view_curve_in_graph_editor_exec(bContext *C, wmOperator *op)
if (BLI_listbase_is_empty(&selection) || !selected_list_success) {
WM_report(RPT_ERROR, "Nothing selected");
BLI_freelistN(&selection);
return OPERATOR_CANCELLED;
retval = OPERATOR_CANCELLED;
}
const bool found_graph_editor = move_context_to_graph_editor(C);
if (!found_graph_editor) {
else if (!context_find_graph_editor(
C, &wm_context_temp.win, &wm_context_temp.area, &wm_context_temp.region))
{
WM_report(RPT_WARNING, "No open Graph Editor window found");
return OPERATOR_CANCELLED;
retval = OPERATOR_CANCELLED;
}
else {
wm_context_prev.win = CTX_wm_window(C);
wm_context_prev.area = CTX_wm_area(C);
wm_context_prev.region = CTX_wm_region(C);
bAnimContext ac;
if (!ANIM_animdata_get_context(C, &ac)) {
/* This might never be called since we are manually setting the Graph Editor just before. */
WM_report(RPT_ERROR, "Cannot create the Animation Context");
return OPERATOR_CANCELLED;
CTX_wm_window_set(C, wm_context_temp.win);
CTX_wm_area_set(C, wm_context_temp.area);
CTX_wm_region_set(C, wm_context_temp.region);
bAnimContext ac;
if (!ANIM_animdata_get_context(C, &ac)) {
/* This might never be called since we are manually setting the Graph Editor just before. */
WM_report(RPT_ERROR, "Cannot create the Animation Context");
retval = OPERATOR_CANCELLED;
}
else {
const bool isolate = RNA_boolean_get(op->ptr, "isolate");
deselect_all_fcurves(&ac, isolate);
const bool whole_array = RNA_boolean_get(op->ptr, "all");
rctf bounds = calculate_selection_fcurve_bounds_and_unhide(
C, &selection, prop, id_to_prop_path.value_or(""), index, whole_array);
if (!BLI_rctf_is_valid(&bounds)) {
WM_report(RPT_ERROR, "F-Curves have no valid size");
retval = OPERATOR_CANCELLED;
}
else {
ARegion *region = wm_context_temp.region;
ScrArea *area = wm_context_temp.area;
add_region_padding(C, region, &bounds);
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
UI_view2d_smooth_view(C, region, &bounds, smooth_viewtx);
/* This ensures the channel list updates. */
ED_area_tag_redraw(area);
}
}
CTX_wm_window_set(C, wm_context_prev.win);
CTX_wm_area_set(C, wm_context_prev.area);
CTX_wm_region_set(C, wm_context_prev.region);
}
const bool isolate = RNA_boolean_get(op->ptr, "isolate");
deselect_all_fcurves(&ac, isolate);
const bool whole_array = RNA_boolean_get(op->ptr, "all");
rctf bounds = calculate_selection_fcurve_bounds_and_unhide(
C, &selection, prop, id_to_prop_path.value_or(""), index, whole_array);
BLI_freelistN(&selection);
if (!BLI_rctf_is_valid(&bounds)) {
WM_report(RPT_ERROR, "F-Curves have no valid size");
return OPERATOR_CANCELLED;
}
ARegion *region = CTX_wm_region(C);
add_region_padding(C, region, &bounds);
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
UI_view2d_smooth_view(C, region, &bounds, smooth_viewtx);
/* This ensures the channel list updates. */
ED_area_tag_redraw(CTX_wm_area(C));
return OPERATOR_FINISHED;
return retval;
}
static void ANIM_OT_view_curve_in_graph_editor(wmOperatorType *ot)

View File

@ -2146,7 +2146,7 @@ static void annotation_draw_apply_event(
}
}
p->curtime = BLI_check_seconds_timer();
p->curtime = BLI_time_now_seconds();
/* handle pressure sensitivity (which is supplied by tablets or otherwise 1.0) */
p->pressure = event->tablet.pressure;

View File

@ -2159,7 +2159,7 @@ static tGPsdata *gpencil_session_initpaint(bContext *C, wmOperator *op)
}
/* Random generator, only init once. */
uint rng_seed = uint(BLI_check_seconds_timer_i() & UINT_MAX);
uint rng_seed = uint(BLI_time_now_seconds_i() & UINT_MAX);
rng_seed ^= POINTER_AS_UINT(p);
p->rng = BLI_rng_new(rng_seed);
@ -2961,7 +2961,7 @@ static void gpencil_draw_apply_event(bContext *C,
}
}
p->curtime = BLI_check_seconds_timer();
p->curtime = BLI_time_now_seconds();
/* handle pressure sensitivity (which is supplied by tablets or otherwise 1.0) */
p->pressure = event->tablet.pressure;

View File

@ -363,7 +363,7 @@ static void gpencil_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
gpencil_primitive_allocate_memory(tgpi);
/* Random generator, only init once. */
uint rng_seed = uint(BLI_check_seconds_timer_i() & UINT_MAX);
uint rng_seed = uint(BLI_time_now_seconds_i() & UINT_MAX);
tgpi->rng = BLI_rng_new(rng_seed);
DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_COPY_ON_WRITE);

View File

@ -1165,7 +1165,7 @@ static bool gpencil_sculpt_brush_init(bContext *C, wmOperator *op)
gso->settings = gpencil_sculpt_get_settings(scene);
/* Random generator, only init once. */
uint rng_seed = uint(BLI_check_seconds_timer_i() & UINT_MAX);
uint rng_seed = uint(BLI_time_now_seconds_i() & UINT_MAX);
rng_seed ^= POINTER_AS_UINT(gso);
gso->rng = BLI_rng_new(rng_seed);

View File

@ -2838,7 +2838,7 @@ void ED_gpencil_init_random_settings(Brush *brush,
const int mval[2],
GpRandomSettings *random_settings)
{
int seed = (uint(ceil(BLI_check_seconds_timer())) + 1) % 128;
int seed = (uint(ceil(BLI_time_now_seconds())) + 1) % 128;
/* Use mouse position to get randomness. */
int ix = mval[0] * seed;
int iy = mval[1] * seed;
@ -2884,7 +2884,7 @@ static void gpencil_sbuffer_vertex_color_random(
{
BrushGpencilSettings *brush_settings = brush->gpencil_settings;
if (brush_settings->flag & GP_BRUSH_GROUP_RANDOM) {
int seed = (uint(ceil(BLI_check_seconds_timer())) + 1) % 128;
int seed = (uint(ceil(BLI_time_now_seconds())) + 1) % 128;
int ix = int(tpt->m_xy[0] * seed);
int iy = int(tpt->m_xy[1] * seed);

View File

@ -29,6 +29,7 @@ set(SRC
intern/grease_pencil_material.cc
intern/grease_pencil_ops.cc
intern/grease_pencil_select.cc
intern/grease_pencil_undo.cc
intern/grease_pencil_utils.cc
)
@ -38,6 +39,7 @@ set(LIB
PRIVATE bf::depsgraph
PRIVATE bf::dna
PRIVATE bf::intern::guardedalloc
PRIVATE bf::intern::clog
extern_curve_fit_nd
)

View File

@ -428,6 +428,47 @@ static void GREASE_PENCIL_OT_layer_isolate(wmOperatorType *ot)
RNA_def_boolean(
ot->srna, "affect_visibility", false, "Affect Visibility", "Also affect the visibility");
}
static int grease_pencil_layer_lock_all_exec(bContext *C, wmOperator *op)
{
using namespace blender::bke::greasepencil;
Object *object = CTX_data_active_object(C);
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
const bool lock_value = RNA_boolean_get(op->ptr, "lock");
if (grease_pencil.layers().is_empty()) {
return OPERATOR_CANCELLED;
}
for (Layer *layer : grease_pencil.layers_for_write()) {
layer->set_locked(lock_value);
}
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, nullptr);
return OPERATOR_FINISHED;
}
static void GREASE_PENCIL_OT_layer_lock_all(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Lock All Layers";
ot->idname = "GREASE_PENCIL_OT_layer_lock_all";
ot->description =
"Lock all Grease Pencil layers to prevent them from being accidentally modified";
/* callbacks */
ot->exec = grease_pencil_layer_lock_all_exec;
ot->poll = active_grease_pencil_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
RNA_def_boolean(ot->srna, "lock", true, "Lock Value", "Lock/Unlock all layers");
}
} // namespace blender::ed::greasepencil
void ED_operatortypes_grease_pencil_layers()
@ -440,6 +481,7 @@ void ED_operatortypes_grease_pencil_layers()
WM_operatortype_append(GREASE_PENCIL_OT_layer_hide);
WM_operatortype_append(GREASE_PENCIL_OT_layer_reveal);
WM_operatortype_append(GREASE_PENCIL_OT_layer_isolate);
WM_operatortype_append(GREASE_PENCIL_OT_layer_lock_all);
WM_operatortype_append(GREASE_PENCIL_OT_layer_group_add);
}

View File

@ -0,0 +1,424 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edgrease_pencil
*/
#include "BLI_string.h"
#include "BLI_task.hh"
#include "BKE_context.hh"
#include "BKE_curves.hh"
#include "BKE_customdata.hh"
#include "BKE_grease_pencil.hh"
#include "BKE_lib_id.hh"
#include "BKE_main.hh"
#include "BKE_object.hh"
#include "BKE_undo_system.hh"
#include "CLG_log.h"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_build.hh"
#include "ED_grease_pencil.hh"
#include "ED_undo.hh"
#include "MEM_guardedalloc.h"
#include "WM_api.hh"
#include "WM_types.hh"
#include <iostream>
#include <ostream>
static CLG_LogRef LOG = {"ed.undo.greasepencil"};
namespace blender::ed::greasepencil::undo {
/* -------------------------------------------------------------------- */
/** \name Implements ED Undo System
*
* \note This is similar for all edit-mode types.
* \{ */
/**
* Store all drawings, layers and layers data, in each undo step.
*
* Each drawing type has its own array in the undo #StepObject data.
*
* NOTE: Storing Reference drawings is also needed, since drawings can be added or removed, data
* from Reference ones also needs to be stored.
*/
/* Store contextual data and status info during undo step encoding or decoding. */
struct StepEncodeStatus {};
struct StepDecodeStatus {
/**
* In case some reference drawing needs to be re-created, the GreasePencil ID gets a new
* relation to another GreasePencil ID.
*/
bool needs_relationships_update = false;
};
class StepDrawingGeometryBase {
protected:
/* Index of this drawing in the original combined array of all drawings in GreasePencil ID. */
int index_;
/* Data from #GreasePencilDrawingBase that needs to be saved in udo steps. */
uint32_t flag_;
protected:
/* Ensures that the drawing from the given array at the current index exists, and has the propoer
* type.
*
* Non-existing drawings can happen after extenting the drawings array.
*
* Mismatch in drawing types can happen when some drawings have been deleted between the undo
* step storage, and the current state of the GreasePencil data. */
void decode_valid_drawingtype_at_index_ensure(MutableSpan<GreasePencilDrawingBase *> &drawings,
const GreasePencilDrawingType drawing_type) const
{
/* TODO: Maybe that code should rather be part of GreasePencil:: API, together with
* `add_empty_drawings` and such? */
GreasePencilDrawingBase *drawing = drawings[index_];
if (drawing != nullptr) {
if (drawing->type == drawing_type) {
return;
}
switch (drawing->type) {
case GP_DRAWING:
MEM_delete(&reinterpret_cast<GreasePencilDrawing *>(drawing)->wrap());
break;
case GP_DRAWING_REFERENCE:
MEM_delete(&reinterpret_cast<GreasePencilDrawingReference *>(drawing)->wrap());
break;
}
drawing = nullptr;
}
if (drawing == nullptr) {
switch (drawing_type) {
case GP_DRAWING:
drawings[index_] = reinterpret_cast<GreasePencilDrawingBase *>(
MEM_new<bke::greasepencil::Drawing>(__func__));
break;
case GP_DRAWING_REFERENCE:
drawings[index_] = reinterpret_cast<GreasePencilDrawingBase *>(
MEM_new<bke::greasepencil::DrawingReference>(__func__));
break;
}
}
}
};
class StepDrawingGeometry : public StepDrawingGeometryBase {
bke::CurvesGeometry geometry_;
public:
void encode(const GreasePencilDrawing &drawing_geometry,
const int64_t drawing_index,
StepEncodeStatus & /* encode_status */)
{
BLI_assert(drawing_index >= 0 && drawing_index < INT32_MAX);
index_ = int(drawing_index);
flag_ = drawing_geometry.base.flag;
geometry_ = drawing_geometry.geometry.wrap();
}
void decode(GreasePencil &grease_pencil, StepDecodeStatus & /*decode_status*/) const
{
MutableSpan<GreasePencilDrawingBase *> drawings = grease_pencil.drawings();
this->decode_valid_drawingtype_at_index_ensure(drawings, GP_DRAWING);
BLI_assert(drawings[index_]->type == GP_DRAWING);
GreasePencilDrawing &drawing_geometry = *reinterpret_cast<GreasePencilDrawing *>(
drawings[index_]);
drawing_geometry.base.flag = flag_;
drawing_geometry.geometry.wrap() = geometry_;
/* TODO: Check if there is a way to tell if both stored and current geometry are still the
* same, to avoid recomputing the cache all the time for all drawings? */
drawing_geometry.runtime->triangles_cache.tag_dirty();
}
};
class StepDrawingReference : public StepDrawingGeometryBase {
UndoRefID_GreasePencil grease_pencil_ref_ = {};
public:
void encode(const GreasePencilDrawingReference &drawing_reference,
const int64_t drawing_index,
StepEncodeStatus & /* encode_status */)
{
BLI_assert(drawing_index >= 0 && drawing_index < INT32_MAX);
index_ = int(drawing_index);
flag_ = drawing_reference.base.flag;
grease_pencil_ref_.ptr = drawing_reference.id_reference;
}
void decode(GreasePencil &grease_pencil, StepDecodeStatus &decode_status) const
{
MutableSpan<GreasePencilDrawingBase *> drawings = grease_pencil.drawings();
this->decode_valid_drawingtype_at_index_ensure(drawings, GP_DRAWING_REFERENCE);
BLI_assert(drawings[index_]->type == GP_DRAWING_REFERENCE);
GreasePencilDrawingReference &drawing_reference =
*reinterpret_cast<GreasePencilDrawingReference *>(drawings[index_]);
drawing_reference.base.flag = flag_;
if (drawing_reference.id_reference != grease_pencil_ref_.ptr) {
id_us_min(reinterpret_cast<ID *>(drawing_reference.id_reference));
drawing_reference.id_reference = grease_pencil_ref_.ptr;
id_us_plus(reinterpret_cast<ID *>(drawing_reference.id_reference));
decode_status.needs_relationships_update = true;
}
}
void foreach_id_ref(UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
{
foreach_ID_ref_fn(user_data, reinterpret_cast<UndoRefID *>(&grease_pencil_ref_));
}
};
class StepObject {
public:
UndoRefID_Object obedit_ref = {};
private:
Array<StepDrawingGeometry> drawings_geometry_;
Array<StepDrawingReference> drawings_reference_;
int layers_num_ = 0;
bke::greasepencil::LayerGroup root_group_;
std::string active_layer_name_;
CustomData layers_data_ = {};
private:
void encode_drawings(const GreasePencil &grease_pencil, StepEncodeStatus &encode_status)
{
const Span<const GreasePencilDrawingBase *> drawings = grease_pencil.drawings();
int64_t drawings_geometry_num = 0;
int64_t drawings_reference_num = 0;
for (const int64_t idx : drawings.index_range()) {
const GreasePencilDrawingBase &drawing = *drawings[idx];
switch (drawing.type) {
case GP_DRAWING:
drawings_geometry_num++;
break;
case GP_DRAWING_REFERENCE:
drawings_reference_num++;
break;
}
}
drawings_geometry_.reinitialize(drawings_geometry_num);
drawings_reference_.reinitialize(drawings_reference_num);
int drawings_geometry_idx = 0;
int drawings_reference_idx = 0;
for (const int64_t idx : drawings.index_range()) {
const GreasePencilDrawingBase &drawing = *drawings[idx];
switch (drawing.type) {
case GP_DRAWING:
drawings_geometry_[drawings_geometry_idx++].encode(
reinterpret_cast<const GreasePencilDrawing &>(drawing), idx, encode_status);
break;
case GP_DRAWING_REFERENCE:
drawings_reference_[drawings_reference_idx++].encode(
reinterpret_cast<const GreasePencilDrawingReference &>(drawing), idx, encode_status);
break;
}
}
}
void decode_drawings(GreasePencil &grease_pencil, StepDecodeStatus &decode_status) const
{
const int drawing_array_num = int(drawings_geometry_.size() + drawings_reference_.size());
grease_pencil.resize_drawings(drawing_array_num);
for (const StepDrawingGeometry &drawing : drawings_geometry_) {
drawing.decode(grease_pencil, decode_status);
}
for (const StepDrawingReference &drawing : drawings_reference_) {
drawing.decode(grease_pencil, decode_status);
}
}
void encode_layers(const GreasePencil &grease_pencil, StepEncodeStatus & /*encode_status*/)
{
layers_num_ = int(grease_pencil.layers().size());
CustomData_copy(
&grease_pencil.layers_data, &layers_data_, eCustomDataMask(CD_MASK_ALL), layers_num_);
if (grease_pencil.has_active_layer()) {
active_layer_name_ = grease_pencil.get_active_layer()->name();
}
root_group_ = grease_pencil.root_group();
}
void decode_layers(GreasePencil &grease_pencil, StepDecodeStatus & /*decode_status*/) const
{
if (grease_pencil.root_group_ptr) {
MEM_delete(&grease_pencil.root_group());
}
grease_pencil.root_group_ptr = MEM_new<bke::greasepencil::LayerGroup>(__func__, root_group_);
BLI_assert(layers_num_ == grease_pencil.layers().size());
if (!active_layer_name_.empty()) {
const bke::greasepencil::TreeNode *active_node =
grease_pencil.root_group().find_node_by_name(active_layer_name_);
if (active_node && active_node->is_layer()) {
grease_pencil.set_active_layer(&active_node->as_layer());
}
}
CustomData_copy(
&layers_data_, &grease_pencil.layers_data, eCustomDataMask(CD_MASK_ALL), layers_num_);
}
public:
void encode(Object *ob, StepEncodeStatus &encode_status)
{
const GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
this->obedit_ref.ptr = ob;
this->encode_drawings(grease_pencil, encode_status);
this->encode_layers(grease_pencil, encode_status);
}
void decode(StepDecodeStatus &decode_status) const
{
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(this->obedit_ref.ptr->data);
this->decode_drawings(grease_pencil, decode_status);
this->decode_layers(grease_pencil, decode_status);
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
}
void foreach_id_ref(UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
{
foreach_ID_ref_fn(user_data, reinterpret_cast<UndoRefID *>(&this->obedit_ref));
for (StepDrawingReference &drawing_ref : drawings_reference_) {
drawing_ref.foreach_id_ref(foreach_ID_ref_fn, user_data);
}
}
};
struct GreasePencilUndoStep {
UndoStep step;
/** See #ED_undo_object_editmode_validate_scene_from_windows code comment for details. */
UndoRefID_Scene scene_ref = {};
Array<StepObject> objects;
};
static bool step_encode(bContext *C, Main *bmain, UndoStep *us_p)
{
GreasePencilUndoStep *us = reinterpret_cast<GreasePencilUndoStep *>(us_p);
StepEncodeStatus encode_status;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_num = 0;
Object **objects = ED_undo_editmode_objects_from_view_layer(scene, view_layer, &objects_num);
BLI_SCOPED_DEFER([&]() { MEM_SAFE_FREE(objects); })
us->scene_ref.ptr = scene;
new (&us->objects) Array<StepObject>(objects_num);
threading::parallel_for(us->objects.index_range(), 8, [&](const IndexRange range) {
for (const int64_t i : range) {
Object *ob = objects[i];
us->objects[i].encode(ob, encode_status);
}
});
bmain->is_memfile_undo_flush_needed = true;
return true;
}
static void step_decode(
bContext *C, Main *bmain, UndoStep *us_p, const eUndoStepDir /*dir*/, bool /*is_final*/)
{
GreasePencilUndoStep *us = reinterpret_cast<GreasePencilUndoStep *>(us_p);
StepDecodeStatus decode_status;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
ED_undo_object_editmode_validate_scene_from_windows(
CTX_wm_manager(C), us->scene_ref.ptr, &scene, &view_layer);
ED_undo_object_editmode_restore_helper(scene,
view_layer,
&us->objects.first().obedit_ref.ptr,
uint(us->objects.size()),
sizeof(decltype(us->objects)::value_type));
BLI_assert(BKE_object_is_in_editmode(us->objects.first().obedit_ref.ptr));
for (const StepObject &step_object : us->objects) {
step_object.decode(decode_status);
}
if (decode_status.needs_relationships_update) {
DEG_relations_tag_update(bmain);
}
ED_undo_object_set_active_or_warn(
scene, view_layer, us->objects.first().obedit_ref.ptr, us_p->name, &LOG);
bmain->is_memfile_undo_flush_needed = true;
WM_event_add_notifier(C, NC_GEOM | ND_DATA, nullptr);
}
static void step_free(UndoStep *us_p)
{
GreasePencilUndoStep *us = reinterpret_cast<GreasePencilUndoStep *>(us_p);
us->objects.~Array();
}
static void foreach_ID_ref(UndoStep *us_p,
UndoTypeForEachIDRefFn foreach_ID_ref_fn,
void *user_data)
{
GreasePencilUndoStep *us = reinterpret_cast<GreasePencilUndoStep *>(us_p);
foreach_ID_ref_fn(user_data, reinterpret_cast<UndoRefID *>(&us->scene_ref));
for (StepObject &object : us->objects) {
object.foreach_id_ref(foreach_ID_ref_fn, user_data);
}
}
/** \} */
} // namespace blender::ed::greasepencil::undo
void ED_undosys_type_grease_pencil(UndoType *ut)
{
using namespace blender::ed;
ut->name = "Edit GreasePencil";
ut->poll = greasepencil::editable_grease_pencil_poll;
ut->step_encode = greasepencil::undo::step_encode;
ut->step_decode = greasepencil::undo::step_decode;
ut->step_free = greasepencil::undo::step_free;
ut->step_foreach_ID_ref = greasepencil::undo::foreach_ID_ref;
ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE;
ut->step_size = sizeof(greasepencil::undo::GreasePencilUndoStep);
}

View File

@ -25,6 +25,7 @@ struct KeyframeEditData;
struct wmKeyConfig;
struct ToolSettings;
struct Scene;
struct UndoType;
struct ViewDepths;
struct View3D;
namespace blender {
@ -51,6 +52,8 @@ void ED_operatortypes_grease_pencil_edit();
void ED_operatortypes_grease_pencil_material();
void ED_operatormacros_grease_pencil();
void ED_keymap_grease_pencil(wmKeyConfig *keyconf);
void ED_undosys_type_grease_pencil(UndoType *undo_type);
/**
* Get the selection mode for Grease Pencil selection operators: point, stroke, segment.
*/

View File

@ -54,7 +54,7 @@ struct SceneFPS_State {
/**
* Update frame rate info for viewport drawing.
* \param ltime: Time since the last update,
* compatible with the result of #BLI_check_seconds_timer.
* compatible with the result of #BLI_time_now_seconds.
*/
void ED_scene_fps_average_accumulate(Scene *scene, short fps_samples, double ltime)
ATTR_NONNULL(1);

View File

@ -4398,7 +4398,7 @@ static void ui_block_open_end(bContext *C, uiBut *but, uiHandleButtonData *data)
but->editval = nullptr;
but->editvec = nullptr;
but->block->auto_open_last = BLI_check_seconds_timer();
but->block->auto_open_last = BLI_time_now_seconds();
}
if (data->menu) {
@ -8650,7 +8650,7 @@ static void button_activate_init(bContext *C,
* want to allow auto opening adjacent menus even if no button is activated
* in between going over to the other button, but only for a short while */
if (type == BUTTON_ACTIVATE_OVER && but->block->auto_open == true) {
if (but->block->auto_open_last + BUTTON_AUTO_OPEN_THRESH < BLI_check_seconds_timer()) {
if (but->block->auto_open_last + BUTTON_AUTO_OPEN_THRESH < BLI_time_now_seconds()) {
but->block->auto_open = false;
}
}
@ -8696,7 +8696,7 @@ static void button_activate_init(bContext *C,
if (UI_but_has_tooltip_label(but)) {
/* Show a label for this button. */
bScreen *screen = WM_window_get_active_screen(data->window);
if ((BLI_check_seconds_timer() - WM_tooltip_time_closed()) < 0.1) {
if ((BLI_time_now_seconds() - WM_tooltip_time_closed()) < 0.1) {
WM_tooltip_immediate_init(C, CTX_wm_window(C), data->area, region, ui_but_tooltip_init);
if (screen->tool_tip) {
screen->tool_tip->pass = 1;
@ -9977,7 +9977,7 @@ static void ui_mouse_motion_towards_init_ex(uiPopupBlockHandle *menu,
menu->towardstime = DBL_MAX; /* unlimited time */
}
else {
menu->towardstime = BLI_check_seconds_timer();
menu->towardstime = BLI_time_now_seconds();
}
}
}
@ -10057,7 +10057,7 @@ static bool ui_mouse_motion_towards_check(uiBlock *block,
}
/* 1 second timer */
if (BLI_check_seconds_timer() - menu->towardstime > BUTTON_MOUSE_TOWARDS_THRESH) {
if (BLI_time_now_seconds() - menu->towardstime > BUTTON_MOUSE_TOWARDS_THRESH) {
menu->dotowards = false;
}

View File

@ -1791,7 +1791,7 @@ static void ui_do_animate(bContext *C, Panel *panel)
uiHandlePanelData *data = static_cast<uiHandlePanelData *>(panel->activedata);
ARegion *region = CTX_wm_region(C);
float fac = (BLI_check_seconds_timer() - data->starttime) / ANIMATION_TIME;
float fac = (BLI_time_now_seconds() - data->starttime) / ANIMATION_TIME;
fac = min_ff(sqrtf(fac), 1.0f);
if (uiAlignPanelStep(region, fac, false)) {
@ -2649,7 +2649,7 @@ static void panel_handle_data_ensure(const bContext *C,
data->startofsy = panel->ofsy;
data->start_cur_xmin = region->v2d.cur.xmin;
data->start_cur_ymin = region->v2d.cur.ymin;
data->starttime = BLI_check_seconds_timer();
data->starttime = BLI_time_now_seconds();
}
/**

View File

@ -191,7 +191,7 @@ void UI_pie_menu_end(bContext *C, uiPieMenu *pie)
menu = ui_popup_block_create(C, nullptr, nullptr, nullptr, ui_block_func_PIE, pie, nullptr);
menu->popup = true;
menu->towardstime = BLI_check_seconds_timer();
menu->towardstime = BLI_time_now_seconds();
UI_popup_handlers_add(C, &window->modalhandlers, menu, WM_HANDLER_ACCEPT_DBL_CLICK);
WM_event_add_mousemove(window);

View File

@ -6091,7 +6091,7 @@ static std::string progress_tooltip_func(bContext * /*C*/, void *argN, const cha
/* create tooltip text and associate it with the job */
char elapsed_str[32];
char remaining_str[32] = "Unknown";
const double elapsed = BLI_check_seconds_timer() - WM_jobs_starttime(wm, owner);
const double elapsed = BLI_time_now_seconds() - WM_jobs_starttime(wm, owner);
BLI_timecode_string_from_time_simple(elapsed_str, sizeof(elapsed_str), elapsed);
if (progress) {

View File

@ -98,7 +98,7 @@ void UI_view2d_edge_pan_reset(View2DEdgePanData *vpd)
{
vpd->edge_pan_start_time_x = 0.0;
vpd->edge_pan_start_time_y = 0.0;
vpd->edge_pan_last_time = BLI_check_seconds_timer();
vpd->edge_pan_last_time = BLI_time_now_seconds();
vpd->initial_rect = vpd->region->v2d.cur;
}
@ -250,7 +250,7 @@ void UI_view2d_edge_pan_apply(bContext *C, View2DEdgePanData *vpd, const int xy[
}
}
const double current_time = BLI_check_seconds_timer();
const double current_time = BLI_time_now_seconds();
edge_pan_manage_delay_timers(vpd, pan_dir_x, pan_dir_y, current_time);
/* Calculate the delta since the last time the operator was called. */

View File

@ -1031,7 +1031,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
/* Check if the 'timer' is initialized, as zooming with the trackpad
* never uses the "Continuous" zoom method, and the 'timer' is not initialized. */
if ((U.viewzoom == USER_ZOOM_CONTINUE) && vzd->timer) { /* XXX store this setting as RNA prop? */
const double time = BLI_check_seconds_timer();
const double time = BLI_time_now_seconds();
const float time_step = float(time - vzd->timer_lastdraw);
dx *= time_step * 5.0f;
@ -1231,7 +1231,7 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even
if (U.viewzoom == USER_ZOOM_CONTINUE) {
/* needs a timer to continue redrawing */
vzd->timer = WM_event_timer_add(CTX_wm_manager(C), window, TIMER, 0.01f);
vzd->timer_lastdraw = BLI_check_seconds_timer();
vzd->timer_lastdraw = BLI_time_now_seconds();
}
return OPERATOR_RUNNING_MODAL;

View File

@ -92,13 +92,13 @@ void EDBM_automerge_and_split(Object *obedit,
#ifdef DEBUG_TIME
em->bm = BM_mesh_copy(bm);
double t1 = BLI_check_seconds_timer();
double t1 = BLI_time_now_seconds();
EDBM_automerge(obedit, false, hflag, dist);
t1 = BLI_check_seconds_timer() - t1;
t1 = BLI_time_now_seconds() - t1;
BM_mesh_free(em->bm);
em->bm = bm;
double t2 = BLI_check_seconds_timer();
double t2 = BLI_time_now_seconds();
#endif
BMOperator weldop;
@ -118,7 +118,7 @@ void EDBM_automerge_and_split(Object *obedit,
BMO_op_finish(bm, &weldop);
#ifdef DEBUG_TIME
t2 = BLI_check_seconds_timer() - t2;
t2 = BLI_time_now_seconds() - t2;
printf("t1: %lf; t2: %lf; fac: %lf\n", t1, t2, t1 / t2);
#endif

View File

@ -3982,6 +3982,9 @@ static int edbm_solidify_exec(bContext *C, wmOperator *op)
/* select the newly generated faces */
BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
/* No need to flush the selection, any selection history is no longer valid. */
BM_select_history_clear(bm);
if (!EDBM_op_finish(em, &bmop, op, true)) {
continue;
}

View File

@ -433,7 +433,7 @@ static void object_overlay_mode_transfer_animation_start(bContext *C, Object *ob
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Object *ob_dst_eval = DEG_get_evaluated_object(depsgraph, ob_dst);
ob_dst_eval->runtime->overlay_mode_transfer_start_time = BLI_check_seconds_timer();
ob_dst_eval->runtime->overlay_mode_transfer_start_time = BLI_time_now_seconds();
}
static bool object_transfer_mode_to_base(bContext *C, wmOperator *op, Base *base_dst)

View File

@ -327,7 +327,7 @@ static void dpaint_bake_endjob(void *customdata)
if (job->success) {
/* Show bake info */
WM_reportf(
RPT_INFO, "DynamicPaint: Bake complete! (%.2f)", BLI_check_seconds_timer() - job->start);
RPT_INFO, "DynamicPaint: Bake complete! (%.2f)", BLI_time_now_seconds() - job->start);
}
else {
if (strlen(canvas->error)) { /* If an error occurred */
@ -438,7 +438,7 @@ static void dpaint_bake_startjob(void *customdata, wmJobWorkerStatus *worker_sta
job->stop = &worker_status->stop;
job->do_update = &worker_status->do_update;
job->progress = &worker_status->progress;
job->start = BLI_check_seconds_timer();
job->start = BLI_time_now_seconds();
job->success = 1;
G.is_break = false;

View File

@ -550,7 +550,7 @@ static void PE_free_shape_tree(PEData *data)
static void PE_create_random_generator(PEData *data)
{
uint rng_seed = uint(BLI_check_seconds_timer_i() & UINT_MAX);
uint rng_seed = uint(BLI_time_now_seconds_i() & UINT_MAX);
rng_seed ^= POINTER_AS_UINT(data->ob);
rng_seed ^= POINTER_AS_UINT(data->edit);
data->rng = BLI_rng_new(rng_seed);

View File

@ -338,7 +338,7 @@ static void fluid_bake_endjob(void *customdata)
if (job->success) {
/* Show bake info. */
WM_reportf(
RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, BLI_check_seconds_timer() - job->start);
RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, BLI_time_now_seconds() - job->start);
}
else {
if (fds->error[0] != '\0') {
@ -361,7 +361,7 @@ static void fluid_bake_startjob(void *customdata, wmJobWorkerStatus *worker_stat
job->stop = &worker_status->stop;
job->do_update = &worker_status->do_update;
job->progress = &worker_status->progress;
job->start = BLI_check_seconds_timer();
job->start = BLI_time_now_seconds();
job->success = 1;
G.is_break = false;
@ -446,7 +446,7 @@ static void fluid_free_endjob(void *customdata)
if (job->success) {
/* Show free job info */
WM_reportf(
RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, BLI_check_seconds_timer() - job->start);
RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, BLI_time_now_seconds() - job->start);
}
else {
if (fds->error[0] != '\0') {
@ -466,7 +466,7 @@ static void fluid_free_startjob(void *customdata, wmJobWorkerStatus *worker_stat
job->stop = &worker_status->stop;
job->do_update = &worker_status->do_update;
job->progress = &worker_status->progress;
job->start = BLI_check_seconds_timer();
job->start = BLI_time_now_seconds();
job->success = 1;
G.is_break = false;

View File

@ -459,7 +459,7 @@ static void make_renderinfo_string(const RenderStats *rs,
info_time = info_buffers.time_elapsed;
BLI_timecode_string_from_time_simple(info_buffers.time_elapsed,
sizeof(info_buffers.time_elapsed),
BLI_check_seconds_timer() - rs->starttime);
BLI_time_now_seconds() - rs->starttime);
}
ret_array[i++] = RPT_("Time:");

View File

@ -858,7 +858,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
BLI_condition_init(&oglrender->task_condition);
#ifdef DEBUG_TIME
oglrender->time_start = BLI_check_seconds_timer();
oglrender->time_start = BLI_time_now_seconds();
#endif
return true;
@ -894,7 +894,7 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
BLI_condition_end(&oglrender->task_condition);
#ifdef DEBUG_TIME
printf("Total render time: %f\n", BLI_check_seconds_timer() - oglrender->time_start);
printf("Total render time: %f\n", BLI_time_now_seconds() - oglrender->time_start);
#endif
MEM_SAFE_FREE(oglrender->render_frames);

View File

@ -69,6 +69,7 @@
#include "WM_api.hh"
#include "WM_types.hh"
#include "ED_gpencil_legacy.hh"
#include "ED_paint.hh"
#include "ED_screen.hh"
#include "ED_sculpt.hh"
@ -3958,7 +3959,7 @@ bool SCULPT_mode_poll(bContext *C)
bool SCULPT_mode_poll_view3d(bContext *C)
{
return (SCULPT_mode_poll(C) && CTX_wm_region_view3d(C));
return (SCULPT_mode_poll(C) && CTX_wm_region_view3d(C) && !ED_gpencil_session_active());
}
bool SCULPT_poll(bContext *C)

View File

@ -116,7 +116,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *op)
undo::push_begin(ob, op);
undo::push_node(ob, nullptr, undo::Type::Position);
const double start_time = BLI_check_seconds_timer();
const double start_time = BLI_time_now_seconds();
while (bke::pbvh::bmesh_update_topology(
ss->pbvh, PBVH_Collapse | PBVH_Subdivide, center, nullptr, size, false, false))
@ -126,7 +126,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *op)
}
}
CLOG_INFO(&LOG, 2, "Detail flood fill took %f seconds.", BLI_check_seconds_timer() - start_time);
CLOG_INFO(&LOG, 2, "Detail flood fill took %f seconds.", BLI_time_now_seconds() - start_time);
undo::push_end(ob);

View File

@ -100,7 +100,7 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
SCULPT_topology_islands_ensure(ob);
}
const int mask_init_seed = BLI_check_seconds_timer();
const int mask_init_seed = BLI_time_now_seconds();
const SculptMaskWriteInfo mask_write = SCULPT_mask_get_for_write(ss);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {

View File

@ -556,7 +556,7 @@ static void view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event)
if (U.viewzoom == USER_ZOOM_CONTINUE) {
/* needs a timer to continue redrawing */
vpd->timer = WM_event_timer_add(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
vpd->timer_lastdraw = BLI_check_seconds_timer();
vpd->timer_lastdraw = BLI_time_now_seconds();
}
vpd->x = event->xy[0];
@ -648,7 +648,7 @@ static void view_zoom_apply(
if (U.viewzoom == USER_ZOOM_CONTINUE) {
SpaceClip *sclip = CTX_wm_space_clip(C);
double time = BLI_check_seconds_timer();
double time = BLI_time_now_seconds();
float time_step = float(time - vpd->timer_lastdraw);
float zfac;

View File

@ -216,15 +216,15 @@ static void track_markers_startjob(void *tmv, wmJobWorkerStatus *worker_status)
* exec_time for "Fastest" tracking
*/
double start_time = BLI_check_seconds_timer(), exec_time;
double start_time = BLI_time_now_seconds(), exec_time;
if (!BKE_autotrack_context_step(tmj->context)) {
break;
}
exec_time = BLI_check_seconds_timer() - start_time;
exec_time = BLI_time_now_seconds() - start_time;
if (tmj->delay > float(exec_time)) {
BLI_sleep_ms(tmj->delay - float(exec_time));
BLI_time_sleep_ms(tmj->delay - float(exec_time));
}
}
else if (!BKE_autotrack_context_step(tmj->context)) {

View File

@ -181,11 +181,14 @@ class AssetCatalogTreeViewUnassignedItem : public ui::BasicTreeViewItem {
AssetCatalogTreeView::AssetCatalogTreeView(asset_system::AssetLibrary *library,
FileAssetSelectParams *params,
SpaceFile &space_file)
: asset_library_(library),
catalog_tree_(library->catalog_service->get_catalog_tree()),
params_(params),
space_file_(space_file)
: asset_library_(library), params_(params), space_file_(space_file)
{
if (library && library->catalog_service) {
catalog_tree_ = library->catalog_service->get_catalog_tree();
}
else {
catalog_tree_ = nullptr;
}
}
void AssetCatalogTreeView::build_tree()

View File

@ -536,7 +536,7 @@ static void image_view_zoom_init(bContext *C, wmOperator *op, const wmEvent *eve
if (U.viewzoom == USER_ZOOM_CONTINUE) {
/* needs a timer to continue redrawing */
vpd->timer = WM_event_timer_add(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
vpd->timer_lastdraw = BLI_check_seconds_timer();
vpd->timer_lastdraw = BLI_time_now_seconds();
}
vpd->sima = sima;
@ -646,7 +646,7 @@ static void image_zoom_apply(ViewZoomData *vpd,
}
if (viewzoom == USER_ZOOM_CONTINUE) {
double time = BLI_check_seconds_timer();
double time = BLI_time_now_seconds();
float time_step = float(time - vpd->timer_lastdraw);
float zfac;
zfac = 1.0f + ((delta / 20.0f) * time_step);

View File

@ -188,7 +188,11 @@ static bool sequencer_write_copy_paste_file(Main *bmain_src,
BKE_library_foreach_ID_link(
bmain_src, &scene_dst->id, gather_strip_data_ids_to_null, &id_remapper, IDWALK_RECURSE);
BKE_libblock_remap_multiple(bmain_src, id_remapper, 0);
BKE_libblock_relink_multiple(bmain_src,
{&scene_dst->id},
ID_REMAP_TYPE_REMAP,
id_remapper,
(ID_REMAP_SKIP_USER_CLEAR | ID_REMAP_SKIP_USER_REFCOUNT));
/* Ensure that there are no old copy tags around */
BKE_blendfile_write_partial_begin(bmain_src);

View File

@ -113,7 +113,7 @@ ImBuf *make_waveform_view_from_ibuf(const ImBuf *ibuf)
#endif
const int w = ibuf->x;
const int h = 256;
ImBuf *rval = IMB_allocImBuf(w, h, 32, IB_rect);
ImBuf *rval = IMB_allocImBuf(w, h, 32, IB_rect | IB_uninitialized_pixels);
uchar *tgt = rval->byte_buffer.data;
uchar wtable[256];
@ -172,7 +172,7 @@ ImBuf *make_sep_waveform_view_from_ibuf(const ImBuf *ibuf)
#endif
int w = ibuf->x;
int h = 256;
ImBuf *rval = IMB_allocImBuf(w, h, 32, IB_rect);
ImBuf *rval = IMB_allocImBuf(w, h, 32, IB_rect | IB_uninitialized_pixels);
uchar *tgt = rval->byte_buffer.data;
int sw = ibuf->x / 3;
@ -222,7 +222,7 @@ ImBuf *make_zebra_view_from_ibuf(const ImBuf *ibuf, float perc)
#ifdef DEBUG_TIME
SCOPED_TIMER(__func__);
#endif
ImBuf *res = IMB_allocImBuf(ibuf->x, ibuf->y, 32, IB_rect);
ImBuf *res = IMB_allocImBuf(ibuf->x, ibuf->y, 32, IB_rect | IB_uninitialized_pixels);
threading::parallel_for(IndexRange(ibuf->y), 16, [&](IndexRange y_range) {
if (ibuf->float_buffer.data) {
@ -346,7 +346,7 @@ ImBuf *make_vectorscope_view_from_ibuf(const ImBuf *ibuf)
#endif
const int size = 512;
const float size_mul = size - 1.0f;
ImBuf *rval = IMB_allocImBuf(size, size, 32, IB_rect);
ImBuf *rval = IMB_allocImBuf(size, size, 32, IB_rect | IB_uninitialized_pixels);
uchar *dst = rval->byte_buffer.data;
float rgb[3];

View File

@ -3520,7 +3520,7 @@ static int text_line_number_invoke(bContext *C, wmOperator * /*op*/, const wmEve
return OPERATOR_PASS_THROUGH;
}
time = BLI_check_seconds_timer();
time = BLI_time_now_seconds();
if (last_jump < time - 1) {
jump_to = 0;
}

View File

@ -366,7 +366,7 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent
fly->ndof = nullptr;
#endif
fly->time_lastdraw = fly->time_lastwheel = BLI_check_seconds_timer();
fly->time_lastdraw = fly->time_lastwheel = BLI_time_now_seconds();
fly->draw_handle_pixel = ED_region_draw_cb_activate(
fly->region->type, drawFlyPixel, fly, REGION_DRAW_POST_PIXEL);
@ -513,7 +513,7 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event)
fly->ndof = nullptr;
}
/* Update the time else the view will jump when 2D mouse/timer resume. */
fly->time_lastdraw = BLI_check_seconds_timer();
fly->time_lastdraw = BLI_time_now_seconds();
break;
}
default: {
@ -561,7 +561,7 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event)
fly->speed = fabsf(fly->speed);
}
time_currwheel = BLI_check_seconds_timer();
time_currwheel = BLI_time_now_seconds();
time_wheel = float(time_currwheel - fly->time_lastwheel);
fly->time_lastwheel = time_currwheel;
/* Mouse wheel delays range from (0.5 == slow) to (0.01 == fast). */
@ -586,7 +586,7 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event)
fly->speed = -fabsf(fly->speed);
}
time_currwheel = BLI_check_seconds_timer();
time_currwheel = BLI_time_now_seconds();
time_wheel = float(time_currwheel - fly->time_lastwheel);
fly->time_lastwheel = time_currwheel;
/* 0-0.5 -> 0-5.0 */
@ -843,7 +843,7 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm)
#ifdef NDOF_FLY_DRAW_TOOMUCH
fly->redraw = 1;
#endif
time_current = BLI_check_seconds_timer();
time_current = BLI_time_now_seconds();
time_redraw = float(time_current - fly->time_lastdraw);
/* Clamp redraw time to avoid jitter in roll correction. */
@ -1017,7 +1017,7 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm)
}
else {
/* We're not redrawing but we need to update the time else the view will jump. */
fly->time_lastdraw = BLI_check_seconds_timer();
fly->time_lastdraw = BLI_time_now_seconds();
}
/* End drawing. */
copy_v3_v3(fly->dvec_prev, dvec);

Some files were not shown because too many files have changed in this diff Show More