Anim: Change how Only Insert Needed works #115360

Merged
Christoph Lendenfeld merged 11 commits from ChrisLend/blender:refactor_insert_needed_logic into main 2023-11-30 14:45:59 +01:00
337 changed files with 3641 additions and 6255 deletions
Showing only changes of commit bf24b93eca - Show all commits

View File

@ -599,7 +599,7 @@ doc_dna: .FORCE
@echo "docs written into: '$(BLENDER_DIR)/doc/blender_file_format/dna.html'"
doc_man: .FORCE
@$(BLENDER_BIN) --background --python doc/manpage/blender.1.py -- --output=blender.1 --verbose
@$(PYTHON) doc/manpage/blender.1.py --blender="$(BLENDER_BIN)" --output=blender.1 --verbose
help_features: .FORCE
@$(PYTHON) "$(BLENDER_DIR)/build_files/cmake/cmake_print_build_options.py" $(BLENDER_DIR)"/CMakeLists.txt"

View File

@ -2,13 +2,6 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
if(CMAKE_COMPILER_IS_GNUCC)
# NOTE: Resolved up-stream, quiet noisy compiler warnings for now.
add_cxx_flag("-Wno-uninitialized")
# Needed as build-type options may be added after the CXX flag added above.
remove_cxx_flag("-Wuninitialized")
endif()
set(INC
include
)

View File

@ -94,7 +94,7 @@ class BVHParams {
/* Split time range to this number of steps and create leaf node for each
* of this time steps.
*
* Speeds up rendering of motion primitives in the cost of higher memory usage.
* Speeds up rendering of motion primitives at the cost of higher memory usage.
*/
/* Same as above, but for triangle primitives. */

View File

@ -717,11 +717,11 @@ extern GHOST_TSuccess GHOST_SetSwapInterval(GHOST_WindowHandle windowhandle, int
/**
* Gets the current swap interval for #swapBuffers.
* \param windowhandle: The handle to the window
* \param intervalOut: pointer to location to return swap interval
* \param r_interval: pointer to location to return swap interval
* (left untouched if there is an error)
* \return A boolean success indicator of if swap interval was successfully read.
*/
extern GHOST_TSuccess GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle, int *intervalOut);
extern GHOST_TSuccess GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle, int *r_interval);
/**
* Activates the drawing context of this window.

View File

@ -715,11 +715,11 @@ GHOST_TSuccess GHOST_SetSwapInterval(GHOST_WindowHandle windowhandle, int interv
return window->setSwapInterval(interval);
}
GHOST_TSuccess GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle, int *intervalOut)
GHOST_TSuccess GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle, int *r_interval)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
return window->getSwapInterval(*intervalOut);
return window->getSwapInterval(*r_interval);
}
GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle)

View File

@ -420,7 +420,7 @@ void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button,
GHOST_ASSERT(button > NDOF_BUTTON_NONE && button < NDOF_BUTTON_NUM,
"rogue button trying to escape NDOF manager");
GHOST_EventNDOFButton *event = new GHOST_EventNDOFButton(time, window);
const GHOST_EventNDOFButton *event = new GHOST_EventNDOFButton(time, window);
GHOST_TEventNDOFButtonData *data = (GHOST_TEventNDOFButtonData *)event->getData();
data->action = press ? GHOST_kPress : GHOST_kRelease;
@ -435,7 +435,7 @@ void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key,
GHOST_IWindow *window)
{
GHOST_TEventType type = press ? GHOST_kEventKeyDown : GHOST_kEventKeyUp;
GHOST_EventKey *event = new GHOST_EventKey(time, type, window, key, false);
const GHOST_EventKey *event = new GHOST_EventKey(time, type, window, key, false);
system_.pushEvent(event);
}
@ -561,7 +561,7 @@ bool GHOST_NDOFManager::sendMotionEvent()
return false;
}
GHOST_EventNDOFMotion *event = new GHOST_EventNDOFMotion(motion_time_, window);
const GHOST_EventNDOFMotion *event = new GHOST_EventNDOFMotion(motion_time_, window);
GHOST_TEventNDOFMotionData *data = (GHOST_TEventNDOFMotionData *)event->getData();
/* Scale axis values here to normalize them to around +/- 1

View File

@ -837,6 +837,10 @@ struct GWL_Seat {
*/
xkb_state *state_empty_with_numlock = nullptr;
/**
* The active layout, where a single #xkb_keymap may have multiple layouts.
*/
xkb_layout_index_t layout_active = 0;
} xkb;
#ifdef WITH_INPUT_IME
@ -879,7 +883,15 @@ struct GWL_Seat {
* so every time a modifier is accessed a string lookup isn't required.
* Be sure to check for #XKB_MOD_INVALID before using.
*/
xkb_mod_index_t xkb_keymap_mod_index[MOD_INDEX_NUM];
xkb_mod_index_t xkb_keymap_mod_index[MOD_INDEX_NUM] = {XKB_MOD_INVALID};
/* Cache result for other modifiers which aren't stored in `xkb_keymap_mod_index`
* since their depressed state isn't tracked. */
/** Cache result of `xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM)`. */
xkb_mod_index_t xkb_keymap_mod_index_mod2 = XKB_MOD_INVALID;
/** Cache result of `xkb_keymap_mod_get_index(keymap, "NumLock")`. */
xkb_mod_index_t xkb_keymap_mod_index_numlock = XKB_MOD_INVALID;
struct {
/** Key repetition in character per second. */
@ -941,6 +953,39 @@ static GWL_SeatStatePointer *gwl_seat_state_pointer_from_cursor_surface(
return nullptr;
}
/**
* Account for changes to #GWL_Seat::xkb::layout_active by running #xkb_state_update_mask
* on static states which are used for lookups.
*
* This is also used when initializing the states.
*/
static void gwl_seat_key_layout_active_state_update_mask(GWL_Seat *seat)
{
const xkb_layout_index_t group = seat->xkb.layout_active;
const xkb_mod_index_t mod_shift = seat->xkb_keymap_mod_index[MOD_INDEX_SHIFT];
const xkb_mod_index_t mod_mod2 = seat->xkb_keymap_mod_index_mod2;
const xkb_mod_index_t mod_numlock = seat->xkb_keymap_mod_index_numlock;
/* Handle `state_empty`. */
xkb_state_update_mask(seat->xkb.state_empty, 0, 0, 0, 0, 0, group);
/* Handle `state_empty_with_shift`. */
GHOST_ASSERT((mod_shift == XKB_MOD_INVALID) == (seat->xkb.state_empty_with_shift == nullptr),
"Invalid state for SHIFT");
if (seat->xkb.state_empty_with_shift) {
xkb_state_update_mask(seat->xkb.state_empty_with_shift, 1 << mod_shift, 0, 0, 0, 0, group);
}
/* Handle `state_empty_with_shift`. */
GHOST_ASSERT((mod_mod2 == XKB_MOD_INVALID || mod_numlock == XKB_MOD_INVALID) ==
(seat->xkb.state_empty_with_numlock == nullptr),
"Invalid state for NUMLOCK");
if (seat->xkb.state_empty_with_numlock) {
xkb_state_update_mask(
seat->xkb.state_empty_with_numlock, 1 << mod_mod2, 0, 1 << mod_numlock, 0, 0, group);
}
}
/**
* \note Caller must lock `timer_mutex`.
*/
@ -1088,6 +1133,9 @@ struct GWL_Display {
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
GWL_LibDecor_System *libdecor = nullptr;
bool libdecor_required = false;
#endif
#ifdef USE_XDG_INIT_WINDOW_SIZE_HACK
bool xdg_decor_ignore_initial_window_size = false;
#endif
GWL_XDG_Decor_System *xdg_decor = nullptr;
@ -3595,7 +3643,7 @@ static void tablet_tool_handle_proximity_in(void *data,
/* In case pressure isn't supported. */
td.Pressure = 1.0f;
GHOST_WindowWayland *win = ghost_wl_surface_user_data(seat->tablet.wl.surface_window);
const GHOST_WindowWayland *win = ghost_wl_surface_user_data(seat->tablet.wl.surface_window);
seat->system->cursor_shape_set(win->getCursorShape());
}
@ -3922,6 +3970,13 @@ static void keyboard_handle_keymap(void *data,
CLOG_INFO(LOG, 2, "keymap");
/* Reset in case there was a previous non-zero active layout for the the last key-map.
* Note that this is set later by `wl_keyboard_listener::modifiers`, it's possible that handling
* the first modifier will run #xkb_state_update_mask again (if the active layout is non-zero)
* however as this is only done when the layout changed, it's harmless.
* With a single layout - in practice the active layout will be zero. */
seat->xkb.layout_active = 0;
if (seat->xkb.compose_state) {
xkb_compose_state_reset(seat->xkb.compose_state);
}
@ -3941,29 +3996,25 @@ static void keyboard_handle_keymap(void *data,
const GWL_ModifierInfo &mod_info = g_modifier_info_table[i];
seat->xkb_keymap_mod_index[i] = xkb_keymap_mod_get_index(keymap, mod_info.xkb_id);
}
seat->xkb_keymap_mod_index_mod2 = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM);
seat->xkb_keymap_mod_index_numlock = xkb_keymap_mod_get_index(keymap, "NumLock");
xkb_state_unref(seat->xkb.state_empty_with_shift);
seat->xkb.state_empty_with_shift = nullptr;
{
const xkb_mod_index_t mod_shift = seat->xkb_keymap_mod_index[MOD_INDEX_SHIFT];
if (mod_shift != XKB_MOD_INVALID) {
seat->xkb.state_empty_with_shift = xkb_state_new(keymap);
xkb_state_update_mask(seat->xkb.state_empty_with_shift, (1 << mod_shift), 0, 0, 0, 0, 0);
}
if (seat->xkb_keymap_mod_index[MOD_INDEX_SHIFT] != XKB_MOD_INVALID) {
seat->xkb.state_empty_with_shift = xkb_state_new(keymap);
}
xkb_state_unref(seat->xkb.state_empty_with_numlock);
seat->xkb.state_empty_with_numlock = nullptr;
if ((seat->xkb_keymap_mod_index_mod2 != XKB_MOD_INVALID) &&
(seat->xkb_keymap_mod_index_numlock != XKB_MOD_INVALID))
{
const xkb_mod_index_t mod2 = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM);
const xkb_mod_index_t num = xkb_keymap_mod_get_index(keymap, "NumLock");
if (num != XKB_MOD_INVALID && mod2 != XKB_MOD_INVALID) {
seat->xkb.state_empty_with_numlock = xkb_state_new(keymap);
xkb_state_update_mask(
seat->xkb.state_empty_with_numlock, (1 << mod2), 0, (1 << num), 0, 0, 0);
}
seat->xkb.state_empty_with_numlock = xkb_state_new(keymap);
}
gwl_seat_key_layout_active_state_update_mask(seat);
#ifdef USE_NON_LATIN_KB_WORKAROUND
seat->xkb_use_non_latin_workaround = false;
if (seat->xkb.state_empty_with_shift) {
@ -4126,6 +4177,8 @@ static bool xkb_compose_state_feed_and_get_utf8(
break;
}
case XKB_COMPOSE_COMPOSING: {
r_utf8_buf[0] = '\0';
handled = true;
break;
}
case XKB_COMPOSE_COMPOSED: {
@ -4139,6 +4192,13 @@ static bool xkb_compose_state_feed_and_get_utf8(
break;
}
case XKB_COMPOSE_CANCELLED: {
/* NOTE(@ideasman42): QT & GTK ignore these events as well as not inputting any text
* so `<Compose><Backspace>` for e.g. causes a cancel and *not* back-space.
* This isn't supported under GHOST at the moment.
* The key-event could also be ignored but this means tracking held state of
* keys wont work properly, so don't do any input and pass in the key-symbol. */
r_utf8_buf[0] = '\0';
handled = true;
break;
}
}
@ -4358,6 +4418,13 @@ static void keyboard_handle_modifiers(void *data,
GWL_Seat *seat = static_cast<GWL_Seat *>(data);
xkb_state_update_mask(seat->xkb.state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
/* Account for the active layout changing within the same key-map,
* needed so modifiers are detected from the expected layout, see: #115160. */
if (group != seat->xkb.layout_active) {
seat->xkb.layout_active = group;
gwl_seat_key_layout_active_state_update_mask(seat);
}
/* A modifier changed so reset the timer,
* see comment in #keyboard_handle_key regarding this behavior. */
{
@ -4845,7 +4912,7 @@ static void gwl_seat_capability_pointer_disable(GWL_Seat *seat)
return;
}
zwp_pointer_gestures_v1 *pointer_gestures = seat->system->wp_pointer_gestures_get();
const zwp_pointer_gestures_v1 *pointer_gestures = seat->system->wp_pointer_gestures_get();
if (pointer_gestures) {
#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
{ /* Hold gesture. */
@ -5964,11 +6031,18 @@ static void global_handle_add(void *data,
else {
/* Not found. */
#ifdef USE_GNOME_NEEDS_LIBDECOR_HACK
if (STRPREFIX(interface, "gtk_shell")) { /* `gtk_shell1` at time of writing. */
/* `gtk_shell1` at time of writing. */
if (STRPREFIX(interface, "gtk_shell")) {
/* Only require `libdecor` when built with X11 support,
* otherwise there is nothing to fall back on. */
display->libdecor_required = true;
}
#endif
#ifdef USE_XDG_INIT_WINDOW_SIZE_HACK
/* `org_kde_plasma_shell` at time of writing. */
if (STRPREFIX(interface, "org_kde_plasma_shell")) {
display->xdg_decor_ignore_initial_window_size = true;
}
#endif
}
@ -6430,7 +6504,7 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const
if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat);
const GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat);
if (!seat_state_pointer) {
return GHOST_kFailure;
}
@ -7403,7 +7477,7 @@ GHOST_TCapabilityFlag GHOST_SystemWayland::getCapabilities() const
bool GHOST_SystemWayland::cursor_grab_use_software_display_get(const GHOST_TGrabCursorMode mode)
{
/* Caller must lock `server_mutex`. */
GWL_Seat *seat = gwl_display_seat_active_get(display_);
const GWL_Seat *seat = gwl_display_seat_active_get(display_);
if (UNLIKELY(!seat)) {
return false;
}
@ -7600,6 +7674,13 @@ zxdg_decoration_manager_v1 *GHOST_SystemWayland::xdg_decor_manager_get()
return display_->xdg_decor->manager;
}
#ifdef USE_XDG_INIT_WINDOW_SIZE_HACK
bool GHOST_SystemWayland::xdg_decor_needs_window_size_hack() const
{
return display_->xdg_decor_ignore_initial_window_size;
}
#endif
/* End `xdg_decor`. */
const std::vector<GWL_Output *> &GHOST_SystemWayland::outputs_get() const
@ -7607,6 +7688,20 @@ const std::vector<GWL_Output *> &GHOST_SystemWayland::outputs_get() const
return display_->outputs;
}
const GWL_Output *GHOST_SystemWayland::outputs_get_max_native_size() const
{
uint64_t area_best = 0;
const GWL_Output *output_best = nullptr;
for (const GWL_Output *output : display_->outputs) {
const uint64_t area_test = (uint64_t)output->size_native[0] * (uint64_t)output->size_native[1];
if (output_best == nullptr || area_best < area_test) {
output_best = output;
area_best = area_test;
}
}
return output_best;
}
wl_shm *GHOST_SystemWayland::wl_shm_get() const
{
return display_->wl.shm;
@ -7748,7 +7843,7 @@ GHOST_WindowWayland *ghost_wl_surface_user_data(wl_surface *wl_surface)
* Functionality only used for the WAYLAND implementation.
* \{ */
GHOST_TSuccess GHOST_SystemWayland::pushEvent_maybe_pending(GHOST_IEvent *event)
GHOST_TSuccess GHOST_SystemWayland::pushEvent_maybe_pending(const GHOST_IEvent *event)
{
#ifdef USE_EVENT_BACKGROUND_THREAD
if (main_thread_id != std::this_thread::get_id()) {

View File

@ -230,9 +230,14 @@ class GHOST_SystemWayland : public GHOST_System {
#endif
struct xdg_wm_base *xdg_decor_shell_get();
struct zxdg_decoration_manager_v1 *xdg_decor_manager_get();
#ifdef USE_XDG_INIT_WINDOW_SIZE_HACK
bool xdg_decor_needs_window_size_hack() const;
#endif
/* End `xdg_decor`. */
const std::vector<GWL_Output *> &outputs_get() const;
/** Return the output with the largest pixel-area. */
const GWL_Output *outputs_get_max_native_size() const;
struct wl_shm *wl_shm_get() const;
@ -248,7 +253,7 @@ class GHOST_SystemWayland : public GHOST_System {
* Push an event, with support for calling from a thread.
* NOTE: only needed for `USE_EVENT_BACKGROUND_THREAD`.
*/
GHOST_TSuccess pushEvent_maybe_pending(GHOST_IEvent *event);
GHOST_TSuccess pushEvent_maybe_pending(const GHOST_IEvent *event);
/** Set this seat to be active. */
void seat_active_set(const struct GWL_Seat *seat);

View File

@ -1761,7 +1761,8 @@ bool GHOST_SystemX11::generateWindowExposeEvents()
bool anyProcessed = false;
for (; w_start != w_end; ++w_start) {
GHOST_Event *g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, *w_start);
const GHOST_Event *g_event = new GHOST_Event(
getMilliSeconds(), GHOST_kEventWindowUpdate, *w_start);
(*w_start)->validate();

View File

@ -103,6 +103,9 @@ struct WGL_XDG_Decor_Window {
/** The window has been configured (see #xdg_surface_ack_configure). */
bool initial_configure_seen = false;
#ifdef USE_XDG_INIT_WINDOW_SIZE_HACK
bool initial_configure_seen_with_size = false;
#endif
};
static void gwl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor)
@ -988,11 +991,8 @@ static int outputs_uniform_scale_or_default(const std::vector<GWL_Output *> &out
static CLG_LogRef LOG_WL_XDG_TOPLEVEL = {"ghost.wl.handle.xdg_toplevel"};
#define LOG (&LOG_WL_XDG_TOPLEVEL)
static void xdg_toplevel_handle_configure(void *data,
xdg_toplevel * /*xdg_toplevel*/,
const int32_t width,
const int32_t height,
wl_array *states)
static void xdg_toplevel_handle_configure(
void *data, xdg_toplevel * /*xdg_toplevel*/, int32_t width, int32_t height, wl_array *states)
{
/* TODO: log `states`, not urgent. */
CLOG_INFO(LOG, 2, "configure (size=[%d, %d])", width, height);
@ -1003,17 +1003,6 @@ static void xdg_toplevel_handle_configure(void *data,
std::lock_guard lock_frame_guard{win->frame_pending_mutex};
#endif
const int32_t size[2] = {width, height};
for (int i = 0; i < 2; i++) {
if (size[i] == 0) {
/* Values may be zero, in this case the client should choose. */
continue;
}
win->frame_pending.size[i] = win->frame.fractional_scale ?
gwl_window_fractional_to_viewport_round(win->frame, size[i]) :
(size[i] * win->frame.buffer_scale);
}
win->frame_pending.is_maximised = false;
win->frame_pending.is_fullscreen = false;
win->frame_pending.is_active = false;
@ -1034,6 +1023,46 @@ static void xdg_toplevel_handle_configure(void *data,
break;
}
}
#ifdef USE_XDG_INIT_WINDOW_SIZE_HACK
if (width || height) {
WGL_XDG_Decor_Window &decor = *win->xdg_decor;
if (decor.initial_configure_seen_with_size == false) {
if (win->ghost_system->xdg_decor_needs_window_size_hack() &&
(decor.mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE) &&
(win->frame_pending.is_maximised == false &&
win->frame_pending.is_fullscreen == false) &&
/* Account for the initial size being smaller. */
((width <= win->frame.size[0]) && (height <= win->frame.size[1])))
{
/* Fail safe, check the window is *not* larger than all available outputs
* as this could cause files saved on other peoples systems to create
* unreasonably large windows. */
const GWL_Output *output_big = win->ghost_system->outputs_get_max_native_size();
if (output_big &&
((output_big->size_native[0] < width) || (output_big->size_native[1] < height))) {
/* Pass, the window exceeds the size of the largest output, ignore initial size. */
}
else {
width = win->frame.size[0];
height = win->frame.size[1];
}
}
decor.initial_configure_seen_with_size = true;
}
}
#endif /* USE_XDG_INIT_WINDOW_SIZE_HACK */
const int32_t size[2] = {width, height};
for (int i = 0; i < 2; i++) {
if (size[i] == 0) {
/* Values may be zero, in this case the client should choose. */
continue;
}
win->frame_pending.size[i] = win->frame.fractional_scale ?
gwl_window_fractional_to_viewport_round(win->frame, size[i]) :
(size[i] * win->frame.buffer_scale);
}
}
static void xdg_toplevel_handle_close(void *data, xdg_toplevel * /*xdg_toplevel*/)
@ -1141,7 +1170,7 @@ static void libdecor_frame_handle_configure(libdecor_frame *frame,
# ifdef USE_EVENT_BACKGROUND_THREAD
std::lock_guard lock_frame_guard{static_cast<GWL_Window *>(data)->frame_pending_mutex};
const bool is_main_thread = [data] {
GWL_Window *win = static_cast<GWL_Window *>(data);
const GWL_Window *win = static_cast<GWL_Window *>(data);
const GHOST_SystemWayland *system = win->ghost_system;
return system->main_thread_id == std::this_thread::get_id();
}();

View File

@ -54,6 +54,14 @@
*/
#define USE_EVENT_BACKGROUND_THREAD
/**
* Hack for KDE where the initial window size includes window decorations (title-bar, borders etc),
* making the usable region smaller than requested. As the size of decorations is unknown:
* account for this by ignoring the initial size and using the size requested from GHOST instead
* (with some exceptions & sanity checks for overly large windows), see: #113059.
*/
#define USE_XDG_INIT_WINDOW_SIZE_HACK
class GHOST_SystemWayland;
struct GWL_Output;

View File

@ -14,14 +14,44 @@ def keyconfig_update(keyconfig_data, keyconfig_version):
# Version the key-map.
import copy
# Only copy once.
has_copy = False
def get_transform_modal_map():
for km_name, _km_parms, km_items_data in keyconfig_data:
for km_name, _km_params, km_items_data in keyconfig_data:
if km_name == "Transform Modal Map":
return km_items_data
print("not found")
def remove_properties(op_prop_map):
nonlocal keyconfig_data
nonlocal has_copy
changed_items = []
for kmi_index, (km_name, _km_parms, km_items_data) in enumerate(keyconfig_data):
for kmi_item_index, (item_op, item_event, item_prop) in enumerate(km_items_data["items"]):
if item_prop and item_op in op_prop_map:
properties = item_prop.get("properties", [])
filtered_properties = [
prop for prop in properties if not any(
key in prop for key in op_prop_map[item_op])
]
if not filtered_properties:
filtered_properties = None
if filtered_properties is None or len(filtered_properties) < len(properties):
changed_items.append((kmi_index, kmi_item_index, filtered_properties))
if changed_items:
if not has_copy:
keyconfig_data = copy.deepcopy(keyconfig_data)
has_copy = True
for kmi_index, kmi_item_index, filtered_properties in changed_items:
item_op, item_event, item_prop = keyconfig_data[kmi_index][2]["items"][kmi_item_index]
item_prop["properties"] = filtered_properties
keyconfig_data[kmi_index][2]["items"][kmi_item_index] = (item_op, item_event, item_prop)
# Default repeat to false.
if keyconfig_version <= (2, 92, 0):
@ -97,6 +127,20 @@ def keyconfig_update(keyconfig_data, keyconfig_version):
km_items_data["items"].append(("EDIT_SNAP_SOURCE_OFF", {"type": 'B', "value": 'PRESS'}, None))
if keyconfig_version <= (4, 1, 5):
remove_properties({
"transform.translate": ["alt_navigation"],
"transform.rotate": ["alt_navigation"],
"transform.resize": ["alt_navigation"],
"view3d.edit_mesh_extrude_move_normal": ["alt_navigation"],
"armature.extrude_move": ["TRANSFORM_OT_translate"],
"curve.extrude_move": ["TRANSFORM_OT_translate"],
"gpencil.extrude_move": ["TRANSFORM_OT_translate"],
"mesh.rip_edge_move": ["TRANSFORM_OT_translate"],
"mesh.duplicate_move": ["TRANSFORM_OT_translate"],
"object.duplicate_move": ["TRANSFORM_OT_translate"],
"object.duplicate_move_linked": ["TRANSFORM_OT_translate"],
})
if km_items_data := get_transform_modal_map():
def use_alt_navigate():
km_item = next((i for i in km_items_data["items"] if i[0] ==

View File

@ -336,17 +336,14 @@ def draw_filtered(display_keymaps, filter_type, filter_text, layout):
if filtered_items:
col = layout.column()
row = col.row()
row = col.row(align=True)
row.label(text=km.name, icon='DOT',
text_ctxt=i18n_contexts.id_windowmanager)
row.label()
row.label()
if km.is_user_modified:
row.operator("preferences.keymap_restore", text="Restore")
else:
row.label()
subrow = row.row()
subrow.alignment = 'RIGHT'
subrow.operator("preferences.keymap_restore", text="Restore")
for kmi in filtered_items:
draw_kmi(display_keymaps, kc, km, kmi, col, 1)

View File

@ -407,8 +407,6 @@ class NODE_MT_geometry_node_GEO_MESH_OPERATIONS(Menu):
node_add_menu.add_node_type(layout, "GeometryNodeMeshBoolean")
node_add_menu.add_node_type(layout, "GeometryNodeMeshToCurve")
node_add_menu.add_node_type(layout, "GeometryNodeMeshToPoints")
if context.preferences.experimental.use_new_volume_nodes:
node_add_menu.add_node_type(layout, "GeometryNodeMeshToSDFVolume")
node_add_menu.add_node_type(layout, "GeometryNodeMeshToVolume")
node_add_menu.add_node_type(layout, "GeometryNodeScaleElements")
node_add_menu.add_node_type(layout, "GeometryNodeSplitEdges")
@ -475,8 +473,6 @@ class NODE_MT_category_GEO_POINT(Menu):
node_add_menu.add_node_type(layout, "GeometryNodePoints")
node_add_menu.add_node_type(layout, "GeometryNodePointsToCurves")
node_add_menu.add_node_type(layout, "GeometryNodePointsToVertices")
if context.preferences.experimental.use_new_volume_nodes:
node_add_menu.add_node_type(layout, "GeometryNodePointsToSDFVolume")
node_add_menu.add_node_type(layout, "GeometryNodePointsToVolume")
layout.separator()
node_add_menu.add_node_type(layout, "GeometryNodeSetPointRadius")
@ -637,13 +633,6 @@ class NODE_MT_category_GEO_VOLUME(Menu):
layout = self.layout
node_add_menu.add_node_type(layout, "GeometryNodeVolumeCube")
node_add_menu.add_node_type(layout, "GeometryNodeVolumeToMesh")
if context.preferences.experimental.use_new_volume_nodes:
layout.separator()
node_add_menu.add_node_type(layout, "GeometryNodeMeanFilterSDFVolume")
node_add_menu.add_node_type(layout, "GeometryNodeOffsetSDFVolume")
node_add_menu.add_node_type(layout, "GeometryNodeSampleVolume")
node_add_menu.add_node_type(layout, "GeometryNodeSDFVolumeSphere")
node_add_menu.add_node_type(layout, "GeometryNodeInputSignedDistance")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)

View File

@ -25,6 +25,7 @@ class GPENCIL_MT_material_context_menu(Menu):
layout.operator("grease_pencil.material_lock_all", icon='LOCKED', text="Lock All")
layout.operator("grease_pencil.material_unlock_all", icon='UNLOCKED', text="Unlock All")
layout.operator("grease_pencil.material_lock_unselected", text="Lock Unselected")
layout.operator("grease_pencil.material_lock_unused", text="Lock Unused")
else:
layout.operator("gpencil.material_reveal", icon='RESTRICT_VIEW_OFF', text="Show All")

View File

@ -194,7 +194,8 @@ int insert_key_action(Main *bmain,
eInsertKeyFlags insert_key_flag,
eBezTriple_KeyframeType key_type);
/** Insert keys to the ID of the given PointerRNA for the given RNA paths. Tries to create an
/**
* Insert keys to the ID of the given PointerRNA for the given RNA paths. Tries to create an
* action if none exists yet.
* \param scene_frame is expected to be not NLA mapped as that happens within the function.
*/

View File

@ -64,11 +64,13 @@ FCurve *action_fcurve_ensure(Main *bmain,
/* For Loc/Rot/Scale and also Color F-Curves, the color of the F-Curve in the Graph Editor,
* is determined by the array index for the F-Curve.
*/
PropertyRNA *prop;
PointerRNA r_ptr;
const bool resolved = RNA_path_resolve_property(ptr, rna_path, &r_ptr, &prop);
PropertyRNA *resolved_prop;
PointerRNA resolved_ptr;
PointerRNA id_ptr = RNA_id_pointer_create(ptr->owner_id);
const bool resolved = RNA_path_resolve_property(
&id_ptr, rna_path, &resolved_ptr, &resolved_prop);
if (resolved) {
PropertySubType prop_subtype = RNA_property_subtype(prop);
PropertySubType prop_subtype = RNA_property_subtype(resolved_prop);
if (ELEM(prop_subtype, PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR, PROP_COORDS)) {
fcu->color_mode = FCURVE_COLOR_AUTO_RGB;
}
@ -86,7 +88,7 @@ FCurve *action_fcurve_ensure(Main *bmain,
/* Sync bone group colors if applicable. */
if (ptr && (ptr->type == &RNA_PoseBone)) {
bPoseChannel *pchan = static_cast<bPoseChannel *>(ptr->data);
const bPoseChannel *pchan = static_cast<const bPoseChannel *>(ptr->data);
action_group_colors_set_from_posebone(agrp, pchan);
}
}

View File

@ -309,9 +309,11 @@ class AssetCatalogCollection {
static OwningAssetCatalogMap copy_catalog_map(const OwningAssetCatalogMap &orig);
};
/** Keeps track of which catalogs are defined in a certain file on disk.
/**
* Keeps track of which catalogs are defined in a certain file on disk.
* Only contains non-owning pointers to the #AssetCatalog instances, so ensure the lifetime of this
* class is shorter than that of the #`AssetCatalog`s themselves. */
* class is shorter than that of the #`AssetCatalog`s themselves.
*/
class AssetCatalogDefinitionFile {
protected:
/* Catalogs stored in this file. They are mapped by ID to make it possible to query whether a

View File

@ -42,8 +42,10 @@ void AS_asset_library_refresh_catalog_simplename(struct AssetLibrary *asset_libr
/** Return whether any loaded AssetLibrary has unsaved changes to its catalogs. */
bool AS_asset_library_has_any_unsaved_catalogs(void);
/** An asset library can include local IDs (IDs in the current file). Their pointers need to be
* remapped on change (or assets removed as IDs gets removed). */
/**
* An asset library can include local IDs (IDs in the current file). Their pointers need to be
* remapped on change (or assets removed as IDs gets removed).
*/
void AS_asset_library_remap_ids(const struct IDRemapper *mappings);
/**

View File

@ -19,8 +19,10 @@
namespace blender::asset_system::tests {
/** Sets up asset library loading so we have a library to load asset representations into (required
* for some functionality to perform work). */
/**
* Sets up asset library loading so we have a library to load asset representations into (required
* for some functionality to perform work).
*/
class AssetRepresentationTest : public AssetLibraryTestBase {
public:
AssetLibrary *get_builtin_library_from_type(eAssetLibraryType type)

View File

@ -29,7 +29,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 8
#define BLENDER_FILE_SUBVERSION 9
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to

View File

@ -11,9 +11,10 @@
#include <mutex>
#include "BLI_bit_vector.hh"
#include "BLI_bit_span.hh"
#include "BLI_kdopbvh.h"
#include "BLI_threads.h"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
struct BMEditMesh;
struct BVHCache;
@ -49,11 +50,12 @@ struct BVHTreeFromMesh {
BVHTree_RayCastCallback raycast_callback;
/* Vertex array, so that callbacks have instant access to data. */
const float (*vert_positions)[3];
const vec2i *edge;
blender::Span<blender::float3> vert_positions;
blender::Span<blender::int2> edges;
blender::Span<int> corner_verts;
blender::Span<MLoopTri> looptris;
const MFace *face;
const int *corner_verts;
const MLoopTri *looptri;
/* Private data */
bool cached;
@ -110,8 +112,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
* (else will be computed from mask).
*/
BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
const float (*vert_positions)[3],
int verts_num,
blender::Span<blender::float3> vert_positions,
blender::BitSpan verts_mask,
int verts_num_active,
float epsilon,
@ -141,9 +142,8 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
* (else will be computed from mask).
*/
BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
const float (*vert_positions)[3],
const blender::int2 *edge,
int edges_num,
blender::Span<blender::float3> vert_positions,
blender::Span<blender::int2> edges,
blender::BitSpan edges_mask,
int edges_num_active,
float epsilon,
@ -168,10 +168,9 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
* Builds a BVH-tree where nodes are the looptri faces of the given mesh.
*/
BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
const float (*vert_positions)[3],
const int *corner_verts,
const MLoopTri *looptri,
int looptri_num,
blender::Span<blender::float3> vert_positions,
blender::Span<int> corner_verts,
blender::Span<MLoopTri> looptris,
blender::BitSpan mask,
int looptri_num_active,
float epsilon,

View File

@ -220,8 +220,10 @@ struct ListBase BKE_collection_object_cache_get(struct Collection *collection);
ListBase BKE_collection_object_cache_instanced_get(struct Collection *collection);
/** Free the object cache of given `collection` and all of its ancestors (recursively). */
void BKE_collection_object_cache_free(struct Collection *collection);
/** Free the object cache of all collections in given `bmain`, including master collections of
* scenes. */
/**
* Free the object cache of all collections in given `bmain`, including master collections of
* scenes.
*/
void BKE_main_collections_object_cache_free(const struct Main *bmain);
struct Base *BKE_collection_or_layer_objects(const struct Scene *scene,
@ -312,8 +314,10 @@ bool BKE_collection_validate(struct Collection *collection);
/* .blend file I/O */
/** Perform some pre-writing cleanup on the COllection data itself (_not_ in any sub-data
* referenced by pointers). To be called before writing the Collection struct itself. */
/**
* Perform some pre-writing cleanup on the COllection data itself (_not_ in any sub-data
* referenced by pointers). To be called before writing the Collection struct itself.
*/
void BKE_collection_blend_write_prepare_nolib(struct BlendWriter *writer,
struct Collection *collection);
void BKE_collection_blend_write_nolib(struct BlendWriter *writer, struct Collection *collection);
@ -372,10 +376,11 @@ void BKE_scene_objects_iterator_begin(struct BLI_Iterator *iter, void *data_in);
void BKE_scene_objects_iterator_next(struct BLI_Iterator *iter);
void BKE_scene_objects_iterator_end(struct BLI_Iterator *iter);
/** Iterate over objects in the scene based on a flag.
/**
* Iterate over objects in the scene based on a flag.
*
* \note The object->flag is tested against flag.
* */
*/
typedef struct SceneObjectsIteratorExData {
struct Scene *scene;
int flag;

View File

@ -316,8 +316,8 @@ bool BKE_library_ID_is_indirectly_used(struct Main *bmain, void *idv);
*/
void BKE_library_ID_test_usages(struct Main *bmain,
void *idv,
bool *is_used_local,
bool *is_used_linked);
bool *r_is_used_local,
bool *r_is_used_linked);
/**
* Tag all unused IDs (a.k.a 'orphaned').

View File

@ -115,19 +115,6 @@ void BKE_mesh_ensure_default_orig_index_customdata(struct Mesh *mesh);
*/
void BKE_mesh_ensure_default_orig_index_customdata_no_check(struct Mesh *mesh);
#ifdef __cplusplus
/**
* Sets each output array element to the edge index if it is a real edge, or -1.
*/
void BKE_mesh_looptri_get_real_edges(const blender::int2 *edges,
const int *corner_verts,
const int *corner_edges,
const struct MLoopTri *tri,
int r_edges[3]);
#endif
/**
* Free (or release) any data used by this mesh (does not free the mesh itself).
* Only use for undo, in most cases `BKE_id_free(nullptr, me)` should be used.
@ -227,14 +214,6 @@ void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigne
void BKE_mesh_smooth_flag_set(struct Mesh *me, bool use_smooth);
void BKE_mesh_sharp_edges_set_from_angle(struct Mesh *me, float angle);
/**
* Used for unit testing; compares two meshes, checking only
* differences we care about. should be usable with leaf's
* testing framework I get RNA work done, will use hackish
* testing code for now.
*/
const char *BKE_mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh);
void BKE_mesh_texspace_calc(struct Mesh *me);
void BKE_mesh_texspace_ensure(struct Mesh *me);
void BKE_mesh_texspace_get(struct Mesh *me,
@ -299,26 +278,6 @@ void BKE_mesh_mselect_active_set(struct Mesh *me, int index, int type);
void BKE_mesh_count_selected_items(const struct Mesh *mesh, int r_count[3]);
float (*BKE_mesh_vert_coords_alloc(const struct Mesh *mesh, int *r_vert_len))[3];
void BKE_mesh_vert_coords_apply_with_mat4(struct Mesh *mesh,
const float (*vert_coords)[3],
const float mat[4][4]);
void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float (*vert_coords)[3]);
/* *** mesh_tessellate.cc *** */
/**
* See #bke::mesh::looptris_calc
*/
void BKE_mesh_recalc_looptri(const int *corner_verts,
const int *face_offsets,
const float (*vert_positions)[3],
int totvert,
int totloop,
int faces_num,
struct MLoopTri *mlooptri);
/* *** mesh_normals.cc *** */
/** Return true if the mesh vertex normals either are not stored or are dirty. */
@ -572,16 +531,6 @@ bool BKE_mesh_validate_material_indices(struct Mesh *me);
* Validate the mesh, \a do_fixes requires \a mesh to be non-null.
*
* \return false if no changes needed to be made.
*
* Vertex Normals
* ==============
*
* While zeroed normals are checked, these checks aren't comprehensive.
* Technically, to detect errors here a normal recalculation and comparison is necessary.
* However this function is mainly to prevent severe errors in geometry
* (invalid data that will crash Blender, or cause some features to behave incorrectly),
* not to detect subtle differences in the resulting normals which could be caused
* by importers that load normals (for example).
*/
bool BKE_mesh_validate_arrays(struct Mesh *me,
float (*vert_positions)[3],
@ -682,22 +631,6 @@ BLI_INLINE int *BKE_mesh_material_indices_for_write(Mesh *mesh)
&mesh->face_data, CD_PROP_INT32, CD_SET_DEFAULT, mesh->faces_num, "material_index");
}
BLI_INLINE const float (*BKE_mesh_vert_positions(const Mesh *mesh))[3]
{
return (const float(*)[3])CustomData_get_layer_named(
&mesh->vert_data, CD_PROP_FLOAT3, "position");
}
BLI_INLINE const int *BKE_mesh_face_offsets(const Mesh *mesh)
{
return mesh->face_offset_indices;
}
BLI_INLINE const int *BKE_mesh_corner_verts(const Mesh *mesh)
{
return (const int *)CustomData_get_layer_named(&mesh->loop_data, CD_PROP_INT32, ".corner_vert");
}
BLI_INLINE const MDeformVert *BKE_mesh_deform_verts(const Mesh *mesh)
{
return (const MDeformVert *)CustomData_get_layer(&mesh->vert_data, CD_MDEFORMVERT);

View File

@ -44,6 +44,12 @@ void looptris_calc_with_normals(Span<float3> vert_positions,
void looptris_calc_face_indices(OffsetIndices<int> faces, MutableSpan<int> looptri_faces);
/** Return the triangle's three edge indices they are real edges, otherwise -1. */
int3 looptri_get_real_edges(Span<int2> edges,
Span<int> corner_verts,
Span<int> corner_edges,
const MLoopTri &tri);
/** Calculate the average position of the vertices in the face. */
float3 face_center_calc(Span<float3> vert_positions, Span<int> face_verts);

View File

@ -30,7 +30,9 @@ enum eMeshFairingDepth {
* Affect_vertices is used to define the fairing area. Indexed by vertex index, set to true when
* the vertex should be modified by fairing.
*/
void BKE_bmesh_prefair_and_fair_verts(BMesh *bm, bool *affect_verts, eMeshFairingDepth depth);
void BKE_bmesh_prefair_and_fair_verts(BMesh *bm,
const bool affected_verts[],
eMeshFairingDepth depth);
/**
* This function can optionally use the vertex coordinates of deform_mverts to read and write the
@ -38,5 +40,5 @@ void BKE_bmesh_prefair_and_fair_verts(BMesh *bm, bool *affect_verts, eMeshFairin
*/
void BKE_mesh_prefair_and_fair_verts(Mesh *mesh,
blender::MutableSpan<blender::float3> deform_vert_positions,
bool *affect_verts,
const bool affected_verts[],
eMeshFairingDepth depth);

View File

@ -53,19 +53,19 @@ enum class MeshNormalDomain : int8_t {
* Only #Mesh::face_normals() is necessary. This case is generally the best
* for performance, since no mixing is necessary and multithreading is simple.
*/
Face,
Face = 0,
/**
* The mesh is completely smooth shaded; there are no sharp face or edges. Only
* #Mesh::vert_normals() is necessary. Calculating face normals is still necessary though,
* since they have to be mixed to become vertex normals.
*/
Point,
Point = 1,
/**
* The mesh has mixed smooth and sharp shading. In order to split the normals on each side of
* sharp edges, they need to be processed per-face-corner. Normals can be retrieved with
* #Mesh::corner_normals().
*/
Corner,
Corner = 2,
};
/**

View File

@ -46,21 +46,21 @@ struct ImBuf *BKE_movieclip_get_postprocessed_ibuf(struct MovieClip *clip,
int postprocess_flag);
struct ImBuf *BKE_movieclip_get_stable_ibuf(struct MovieClip *clip,
const struct MovieClipUser *user,
float loc[2],
float *scale,
float *angle,
int postprocess_flag);
int postprocess_flag,
float r_loc[2],
float *r_scale,
float *r_angle);
struct ImBuf *BKE_movieclip_get_ibuf_flag(struct MovieClip *clip,
const struct MovieClipUser *user,
int flag,
int cache_flag);
void BKE_movieclip_get_size(struct MovieClip *clip,
const struct MovieClipUser *user,
int *width,
int *height);
int *r_width,
int *r_height);
void BKE_movieclip_get_size_fl(struct MovieClip *clip,
const struct MovieClipUser *user,
float size[2]);
float r_size[2]);
int BKE_movieclip_get_duration(struct MovieClip *clip);
float BKE_movieclip_get_fps(struct MovieClip *clip);
void BKE_movieclip_get_aspect(struct MovieClip *clip, float *aspx, float *aspy);

View File

@ -78,10 +78,8 @@ Mesh *BKE_multires_create_mesh(Depsgraph *depsgraph, Object *object, MultiresMod
* Get coordinates of a deformed base mesh which is an input to the given multi-res modifier.
* \note The modifiers will be re-evaluated.
*/
float (*BKE_multires_create_deformed_base_mesh_vert_coords(Depsgraph *depsgraph,
Object *object,
MultiresModifierData *mmd,
int *r_num_deformed_verts))[3];
blender::Array<blender::float3> BKE_multires_create_deformed_base_mesh_vert_coords(
Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd);
/**
* \param direction: 1 for delete higher, 0 for lower (not implemented yet).

View File

@ -1291,17 +1291,17 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define GEO_NODE_IMAGE 1191
#define GEO_NODE_INTERPOLATE_CURVES 1192
#define GEO_NODE_EDGES_TO_FACE_GROUPS 1193
#define GEO_NODE_POINTS_TO_SDF_VOLUME 1194
#define GEO_NODE_MESH_TO_SDF_VOLUME 1195
#define GEO_NODE_SDF_VOLUME_SPHERE 1196
#define GEO_NODE_MEAN_FILTER_SDF_VOLUME 1197
#define GEO_NODE_OFFSET_SDF_VOLUME 1198
// #define GEO_NODE_POINTS_TO_SDF_VOLUME 1194
// #define GEO_NODE_MESH_TO_SDF_VOLUME 1195
// #define GEO_NODE_SDF_VOLUME_SPHERE 1196
// #define GEO_NODE_MEAN_FILTER_SDF_VOLUME 1197
// #define GEO_NODE_OFFSET_SDF_VOLUME 1198
#define GEO_NODE_INDEX_OF_NEAREST 1199
/* Function nodes use the range starting at 1200. */
#define GEO_NODE_SIMULATION_INPUT 2100
#define GEO_NODE_SIMULATION_OUTPUT 2101
#define GEO_NODE_INPUT_SIGNED_DISTANCE 2102
#define GEO_NODE_SAMPLE_VOLUME 2103
// #define GEO_NODE_INPUT_SIGNED_DISTANCE 2102
// #define GEO_NODE_SAMPLE_VOLUME 2103
#define GEO_NODE_MESH_TOPOLOGY_CORNERS_OF_EDGE 2104
/* Leaving out two indices to avoid crashes with files that were created during the development of
* the repeat zone. */

View File

@ -15,6 +15,7 @@
#include "BLI_bitmap.h"
#include "BLI_compiler_compat.h"
#include "BLI_function_ref.hh"
#include "BLI_index_mask.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_offset_indices.hh"
#include "BLI_span.hh"
@ -43,6 +44,7 @@ struct PBVHNode;
struct PBVHBatches;
struct PBVH_GPU_Args;
struct SculptSession;
struct SubdivCCGFace;
struct SubdivCCG;
struct TaskParallelSettings;
struct Image;
@ -214,12 +216,11 @@ void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, Mesh *mesh);
* Do a full rebuild with on Grids data structure.
*/
void BKE_pbvh_build_grids(PBVH *pbvh,
CCGElem **grids,
int totgrid,
blender::Span<CCGElem *> grids,
CCGKey *key,
blender::Span<int> grid_to_face_map,
DMFlagMat *flagmats,
unsigned int **grid_hidden,
blender::Span<DMFlagMat> flagmats,
blender::Span<BLI_bitmap *> grid_hidden,
Mesh *me,
SubdivCCG *subdiv_ccg);
/**
@ -331,14 +332,14 @@ void BKE_pbvh_bounding_box(const PBVH *pbvh, float min[3], float max[3]);
/**
* Multi-res hidden data, only valid for type == PBVH_GRIDS.
*/
unsigned int **BKE_pbvh_grid_hidden(const PBVH *pbvh);
blender::Span<const BLI_bitmap *> BKE_pbvh_get_grid_visibility(const PBVH *pbvh);
void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *me);
/**
* Returns the number of visible quads in the nodes' grids.
*/
int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
int BKE_pbvh_count_grid_quads(blender::Span<const BLI_bitmap *> grid_hidden,
const int *grid_indices,
int totgrid,
int gridsize,
@ -349,8 +350,7 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
*/
const CCGKey *BKE_pbvh_get_grid_key(const PBVH *pbvh);
CCGElem **BKE_pbvh_get_grids(const PBVH *pbvh);
BLI_bitmap **BKE_pbvh_get_grid_visibility(const PBVH *pbvh);
blender::Span<CCGElem *> BKE_pbvh_get_grids(const PBVH *pbvh);
int BKE_pbvh_get_grid_num_verts(const PBVH *pbvh);
int BKE_pbvh_get_grid_num_faces(const PBVH *pbvh);
@ -403,7 +403,7 @@ void BKE_pbvh_node_get_grids(PBVH *pbvh,
int *totgrid,
int *maxgrid,
int *gridsize,
CCGElem ***r_griddata);
CCGElem *const **r_griddata);
void BKE_pbvh_node_num_verts(const PBVH *pbvh,
const PBVHNode *node,
int *r_uniquevert,
@ -457,12 +457,14 @@ void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flags);
void BKE_pbvh_update_visibility(PBVH *pbvh);
void BKE_pbvh_update_normals(PBVH *pbvh, SubdivCCG *subdiv_ccg);
void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3]);
void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int *r_totface);
blender::IndexMask BKE_pbvh_get_grid_updates(const PBVH *pbvh,
blender::Span<const PBVHNode *> nodes,
blender::IndexMaskMemory &memory);
void BKE_pbvh_grids_update(PBVH *pbvh,
CCGElem **grids,
blender::Span<CCGElem *> grids,
blender::Span<int> grid_to_face_map,
DMFlagMat *flagmats,
unsigned int **grid_hidden,
blender::Span<DMFlagMat> flagmats,
blender::Span<BLI_bitmap *> grid_hidden,
CCGKey *key);
void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, SubdivCCG *subdiv_ccg);
@ -501,9 +503,9 @@ struct PBVHVertexIter {
/* grid */
CCGKey key;
CCGElem **grids;
CCGElem *const *grids;
CCGElem *grid;
BLI_bitmap **grid_hidden, *gh;
BLI_bitmap *const *grid_hidden, *gh;
const int *grid_indices;
int totgrid;
int gridsize;

View File

@ -18,16 +18,19 @@
extern "C" {
#endif
/** Reporting Information and Errors.
/**
* Reporting Information and Errors.
*
* These functions are thread-safe, unless otherwise specified.
*
* These functions also accept nullptr in case no error reporting is needed. The message are only
* printed to the console then. */
* printed to the console then.
*/
/* Report structures are stored in DNA. */
/** Initialize a #ReportList struct.
/**
* Initialize a #ReportList struct.
*
* \note: Not thread-safe, should only be called from the 'owner' thread of the report list.
*/

View File

@ -11,9 +11,9 @@
#include "BKE_bvhutils.hh"
#include "BLI_bitmap.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "BLI_math_vector_types.hh"
#include "BLI_offset_indices.hh"
#include "BLI_span.hh"
/*
* Shrinkwrap is composed by a set of functions and options that define the type of shrink.
@ -27,6 +27,7 @@ extern "C" {
* (So that you don't have to pass an enormous amount of arguments to functions)
*/
struct bContext;
struct BVHTree;
struct MDeformVert;
struct Mesh;
@ -37,15 +38,15 @@ struct ShrinkwrapModifierData;
struct SpaceTransform;
/* Information about boundary edges in the mesh. */
typedef struct ShrinkwrapBoundaryVertData {
struct ShrinkwrapBoundaryVertData {
/* Average direction of edges that meet here. */
float direction[3];
/* Closest vector to direction that is orthogonal to vertex normal. */
float normal_plane[3];
} ShrinkwrapBoundaryVertData;
};
typedef struct ShrinkwrapBoundaryData {
struct ShrinkwrapBoundaryData {
/* True if the edge belongs to exactly one face. */
const BLI_bitmap *edge_is_boundary;
/* True if the looptri has any boundary edges. */
@ -58,29 +59,30 @@ typedef struct ShrinkwrapBoundaryData {
/* Direction data about boundary vertices. */
const ShrinkwrapBoundaryVertData *boundary_verts;
} ShrinkwrapBoundaryData;
};
/**
* Free boundary data for target project.
*/
void BKE_shrinkwrap_boundary_data_free(ShrinkwrapBoundaryData *data);
void BKE_shrinkwrap_compute_boundary_data(struct Mesh *mesh);
void BKE_shrinkwrap_compute_boundary_data(Mesh *mesh);
/* Information about a mesh and BVH tree. */
typedef struct ShrinkwrapTreeData {
struct ShrinkwrapTreeData {
Mesh *mesh;
BVHTree *bvh;
BVHTreeFromMesh treeData;
const int *face_offsets;
const float (*vert_normals)[3];
const int *corner_edges;
const float (*face_normals)[3];
blender::OffsetIndices<int> faces;
blender::Span<int> corner_edges;
blender::Span<blender::float3> face_normals;
blender::Span<blender::float3> vert_normals;
blender::Span<blender::float3> corner_normals;
const bool *sharp_faces;
const float (*clnors)[3];
ShrinkwrapBoundaryData *boundary;
} ShrinkwrapTreeData;
};
/**
* Checks if the modifier needs target normals with these settings.
@ -90,33 +92,30 @@ bool BKE_shrinkwrap_needs_normals(int shrinkType, int shrinkMode);
/**
* Initializes the mesh data structure from the given mesh and settings.
*/
bool BKE_shrinkwrap_init_tree(struct ShrinkwrapTreeData *data,
Mesh *mesh,
int shrinkType,
int shrinkMode,
bool force_normals);
bool BKE_shrinkwrap_init_tree(
ShrinkwrapTreeData *data, Mesh *mesh, int shrinkType, int shrinkMode, bool force_normals);
/**
* Frees the tree data if necessary.
*/
void BKE_shrinkwrap_free_tree(struct ShrinkwrapTreeData *data);
void BKE_shrinkwrap_free_tree(ShrinkwrapTreeData *data);
/**
* Main shrink-wrap function (implementation of the shrink-wrap modifier).
*/
void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd,
const struct ModifierEvalContext *ctx,
struct Scene *scene,
struct Object *ob,
struct Mesh *mesh,
const struct MDeformVert *dvert,
void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd,
const ModifierEvalContext *ctx,
Scene *scene,
Object *ob,
Mesh *mesh,
const MDeformVert *dvert,
int defgrp_index,
float (*vertexCos)[3],
int numVerts);
/* Implementation of the Shrinkwrap Grease Pencil modifier. */
void shrinkwrapGpencilModifier_deform(struct ShrinkwrapGpencilModifierData *mmd,
struct Object *ob,
struct MDeformVert *dvert,
void shrinkwrapGpencilModifier_deform(ShrinkwrapGpencilModifierData *mmd,
Object *ob,
MDeformVert *dvert,
int defgrp_index,
float (*vertexCos)[3],
int numVerts);
@ -124,16 +123,12 @@ void shrinkwrapGpencilModifier_deform(struct ShrinkwrapGpencilModifierData *mmd,
/**
* Used in `editmesh_mask_extract.cc` to shrink-wrap the extracted mesh to the sculpt.
*/
void BKE_shrinkwrap_mesh_nearest_surface_deform(struct bContext *C,
struct Object *ob_source,
struct Object *ob_target);
void BKE_shrinkwrap_mesh_nearest_surface_deform(bContext *C, Object *ob_source, Object *ob_target);
/**
* Used in `object_remesh.cc` to preserve the details and volume in the voxel remesher.
*/
void BKE_shrinkwrap_remesh_target_project(struct Mesh *src_me,
struct Mesh *target_me,
struct Object *ob_target);
void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object *ob_target);
/**
* This function ray-cast a single vertex and updates the hit if the "hit" is considered valid.
@ -156,15 +151,15 @@ bool BKE_shrinkwrap_project_normal(char options,
const float vert[3],
const float dir[3],
float ray_radius,
const struct SpaceTransform *transf,
struct ShrinkwrapTreeData *tree,
const SpaceTransform *transf,
ShrinkwrapTreeData *tree,
BVHTreeRayHit *hit);
/**
* Maps the point to the nearest surface, either by simple nearest, or by target normal projection.
*/
void BKE_shrinkwrap_find_nearest_surface(struct ShrinkwrapTreeData *tree,
struct BVHTreeNearest *nearest,
void BKE_shrinkwrap_find_nearest_surface(ShrinkwrapTreeData *tree,
BVHTreeNearest *nearest,
float co[3],
int type);
@ -175,8 +170,8 @@ void BKE_shrinkwrap_find_nearest_surface(struct ShrinkwrapTreeData *tree,
* \param transform: transform from the hit coordinate space to the object space; may be null.
* \param r_no: output in hit coordinate space; may be shared with inputs.
*/
void BKE_shrinkwrap_compute_smooth_normal(const struct ShrinkwrapTreeData *tree,
const struct SpaceTransform *transform,
void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree,
const SpaceTransform *transform,
int looptri_idx,
const float hit_co[3],
const float hit_no[3],
@ -189,8 +184,8 @@ void BKE_shrinkwrap_compute_smooth_normal(const struct ShrinkwrapTreeData *tree,
* \param transform: transform from the hit coordinate space to the object space; may be null.
* \param r_point_co: may be the same memory location as `point_co`, `hit_co`, or `hit_no`.
*/
void BKE_shrinkwrap_snap_point_to_surface(const struct ShrinkwrapTreeData *tree,
const struct SpaceTransform *transform,
void BKE_shrinkwrap_snap_point_to_surface(const ShrinkwrapTreeData *tree,
const SpaceTransform *transform,
int mode,
int hit_idx,
const float hit_co[3],
@ -218,7 +213,3 @@ void BKE_shrinkwrap_snap_point_to_surface(const struct ShrinkwrapTreeData *tree,
{ \
0, \
}
#ifdef __cplusplus
}
#endif

View File

@ -132,10 +132,9 @@ struct SubdivCCG {
*/
/* Indexed by a grid index, points to a grid data which is stored in
* grids_storage. */
CCGElem **grids = nullptr;
blender::Array<CCGElem *> grids;
/* Flat array of all grids' data. */
unsigned char *grids_storage = nullptr;
int num_grids = -1;
blender::Array<uchar> grids_storage;
/* Loose edges, each array element contains grid_size elements
* corresponding to vertices created by subdividing coarse edges. */
CCGElem **edges = nullptr;
@ -157,25 +156,22 @@ struct SubdivCCG {
int mask_offset = -1;
/* Faces from which grids are emitted. */
int num_faces = -1;
SubdivCCGFace *faces = nullptr;
blender::Array<SubdivCCGFace> faces;
/* Indexed by grid index, points to corresponding face from `faces`. */
blender::Array<int> grid_to_face_map;
/* Edges which are adjacent to faces.
* Used for faster grid stitching, in the cost of extra memory.
* Used for faster grid stitching, at the cost of extra memory.
*/
int num_adjacent_edges = -1;
SubdivCCGAdjacentEdge *adjacent_edges = nullptr;
blender::Array<SubdivCCGAdjacentEdge> adjacent_edges;
/* Vertices which are adjacent to faces
* Used for faster grid stitching, in the cost of extra memory.
* Used for faster grid stitching, at the cost of extra memory.
*/
int num_adjacent_vertices = -1;
SubdivCCGAdjacentVertex *adjacent_vertices = nullptr;
blender::Array<SubdivCCGAdjacentVertex> adjacent_verts;
DMFlagMat *grid_flag_mats = nullptr;
BLI_bitmap **grid_hidden = nullptr;
blender::Array<DMFlagMat> grid_flag_mats;
blender::Array<BLI_bitmap *> grid_hidden;
/* TODO(sergey): Consider adding some accessors to a "decoded" geometry,
* to make integration with draw manager and such easy.
@ -198,7 +194,7 @@ struct SubdivCCG {
/* Cached values, are not supposed to be accessed directly. */
struct {
/* Indexed by face, indicates index of the first grid which corresponds to the face. */
int *start_face_grid_index = nullptr;
blender::Array<int> start_face_grid_index;
} cache_;
};
@ -213,8 +209,8 @@ struct SubdivCCG {
* TODO(sergey): Allow some user-counter or more explicit control over who owns
* the Subdiv. The goal should be to allow viewport GL Mesh and CCG to share
* same Subsurf without conflicts. */
SubdivCCG *BKE_subdiv_to_ccg(Subdiv *subdiv,
const SubdivToCCGSettings *settings,
SubdivCCG *BKE_subdiv_to_ccg(Subdiv &subdiv,
const SubdivToCCGSettings &settings,
SubdivCCGMaskEvaluator *mask_evaluator,
SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator);
@ -224,36 +220,33 @@ void BKE_subdiv_ccg_destroy(SubdivCCG *subdiv_ccg);
/* Helper function, creates Mesh structure which is properly setup to use
* grids.
*/
Mesh *BKE_subdiv_to_ccg_mesh(Subdiv *subdiv,
const SubdivToCCGSettings *settings,
const Mesh *coarse_mesh);
Mesh *BKE_subdiv_to_ccg_mesh(Subdiv &subdiv,
const SubdivToCCGSettings &settings,
const Mesh &coarse_mesh);
/* Create a key for accessing grid elements at a given level. */
void BKE_subdiv_ccg_key(CCGKey *key, const SubdivCCG *subdiv_ccg, int level);
void BKE_subdiv_ccg_key_top_level(CCGKey *key, const SubdivCCG *subdiv_ccg);
void BKE_subdiv_ccg_key(CCGKey &key, const SubdivCCG &subdiv_ccg, int level);
void BKE_subdiv_ccg_key_top_level(CCGKey &key, const SubdivCCG &subdiv_ccg);
/* Recalculate all normals based on grid element coordinates. */
void BKE_subdiv_ccg_recalc_normals(SubdivCCG *subdiv_ccg);
void BKE_subdiv_ccg_recalc_normals(SubdivCCG &subdiv_ccg);
/* Update normals of affected faces. */
void BKE_subdiv_ccg_update_normals(SubdivCCG *subdiv_ccg,
CCGFace **effected_faces,
int num_effected_faces);
void BKE_subdiv_ccg_update_normals(SubdivCCG &subdiv_ccg, const blender::IndexMask &face_mask);
/* Average grid coordinates and normals along the grid boundaries. */
void BKE_subdiv_ccg_average_grids(SubdivCCG *subdiv_ccg);
void BKE_subdiv_ccg_average_grids(SubdivCCG &subdiv_ccg);
/* Similar to above, but only updates given faces. */
void BKE_subdiv_ccg_average_stitch_faces(SubdivCCG *subdiv_ccg,
CCGFace **effected_faces,
int num_effected_faces);
void BKE_subdiv_ccg_average_stitch_faces(SubdivCCG &subdiv_ccg,
const blender::IndexMask &face_mask);
/* Get geometry counters at the current subdivision level. */
void BKE_subdiv_ccg_topology_counters(const SubdivCCG *subdiv_ccg,
int *r_num_vertices,
int *r_num_edges,
int *r_num_faces,
int *r_num_loops);
void BKE_subdiv_ccg_topology_counters(const SubdivCCG &subdiv_ccg,
int &r_num_vertices,
int &r_num_edges,
int &r_num_faces,
int &r_num_loops);
struct SubdivCCGNeighbors {
SubdivCCGCoord *coords;
@ -263,8 +256,8 @@ struct SubdivCCGNeighbors {
SubdivCCGCoord coords_fixed[256];
};
void BKE_subdiv_ccg_print_coord(const char *message, const SubdivCCGCoord *coord);
bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord);
void BKE_subdiv_ccg_print_coord(const char *message, const SubdivCCGCoord &coord);
bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord);
/* CCG element neighbors.
*
@ -286,14 +279,14 @@ bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG *subdiv_ccg, const SubdivC
*
* If include_duplicates is true, vertices in other grids that match
* the current vertex are added at the end of the coords array. */
void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg,
const SubdivCCGCoord *coord,
void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG &subdiv_ccg,
const SubdivCCGCoord &coord,
bool include_duplicates,
SubdivCCGNeighbors *r_neighbors);
SubdivCCGNeighbors &r_neighbors);
int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *subdiv_ccg, int grid_index);
void BKE_subdiv_ccg_eval_limit_point(const SubdivCCG *subdiv_ccg,
const SubdivCCGCoord *coord,
int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG &subdiv_ccg, int grid_index);
void BKE_subdiv_ccg_eval_limit_point(const SubdivCCG &subdiv_ccg,
const SubdivCCGCoord &coord,
float r_point[3]);
enum SubdivCCGAdjacencyType {
@ -306,12 +299,12 @@ enum SubdivCCGAdjacencyType {
* adjacent to an edge, r_v1 and r_v2 will be set to the two vertices of that edge. If it is
* adjacent to a vertex, r_v1 and r_v2 will be the index of that vertex. */
SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(
const SubdivCCG *subdiv_ccg,
const SubdivCCGCoord *coord,
const SubdivCCG &subdiv_ccg,
const SubdivCCGCoord &coord,
blender::Span<int> corner_verts,
blender::OffsetIndices<int> faces,
int *r_v1,
int *r_v2);
int &r_v1,
int &r_v2);
/* Get array which is indexed by face index and contains index of a first grid of the face.
*
@ -319,8 +312,8 @@ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(
* descriptor. This function is NOT safe for threading.
*
* The "get" version simply returns cached array. */
const int *BKE_subdiv_ccg_start_face_grid_index_ensure(SubdivCCG *subdiv_ccg);
const int *BKE_subdiv_ccg_start_face_grid_index_get(const SubdivCCG *subdiv_ccg);
const int *BKE_subdiv_ccg_start_face_grid_index_ensure(SubdivCCG &subdiv_ccg);
const int *BKE_subdiv_ccg_start_face_grid_index_get(const SubdivCCG &subdiv_ccg);
void BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG *subdiv_ccg, int grid_index);
void BKE_subdiv_ccg_grid_hidden_free(SubdivCCG *subdiv_ccg, int grid_index);
void BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG &subdiv_ccg, int grid_index);
void BKE_subdiv_ccg_grid_hidden_free(SubdivCCG &subdiv_ccg, int grid_index);

View File

@ -4,14 +4,12 @@
#pragma once
#include "BLI_sys_types.h"
/** \file
* \ingroup bke
*/
#ifdef __cplusplus
extern "C" {
#endif
struct UnitSettings;
/* In all cases the value is assumed to be scaled by the user-preference. */
@ -36,7 +34,7 @@ size_t BKE_unit_value_as_string(char *str,
double value,
int prec,
int type,
const struct UnitSettings *settings,
const UnitSettings *settings,
bool pad);
/**
@ -67,7 +65,7 @@ bool BKE_unit_string_contains_unit(const char *str, int type);
/**
* If user does not specify a unit, this converts it to the unit from the settings.
*/
double BKE_unit_apply_preferred_unit(const struct UnitSettings *settings, int type, double value);
double BKE_unit_apply_preferred_unit(const UnitSettings *settings, int type, double value);
/**
* Make string keyboard-friendly, e.g: `10µm -> 10um`.
@ -120,7 +118,3 @@ enum {
B_UNIT_TEMPERATURE = 12,
B_UNIT_TYPE_TOT = 13,
};
#ifdef __cplusplus
}
#endif

View File

@ -3,14 +3,12 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "BLI_sys_types.h"
/** \file
* \ingroup bke
*/
#ifdef __cplusplus
extern "C" {
#endif
struct CharInfo;
struct Curve;
struct Main;
@ -24,19 +22,19 @@ struct CharTrans {
char dobreak;
};
typedef struct EditFontSelBox {
struct EditFontSelBox {
float x, y, w, h;
float rot;
} EditFontSelBox;
};
/**
* Edit data for #Curve (a text curve, with an #Object::type of `OB_FONT`).
* */
typedef struct EditFont {
struct EditFont {
/** Array of UTF32 code-points. */
char32_t *textbuf;
/** Text style info (aligned with `textbuf`). */
struct CharInfo *textbufinfo;
CharInfo *textbufinfo;
/** Array of rectangles & rotation. */
float textcurs[4][2];
@ -65,10 +63,9 @@ typedef struct EditFont {
* Set #Main.is_memfile_undo_flush_needed when enabling.
*/
char needs_flush_to_id;
};
} EditFont;
typedef enum eEditFontMode {
enum eEditFontMode {
FO_EDIT = 0,
FO_CURS = 1,
FO_CURSUP = 2,
@ -77,62 +74,56 @@ typedef enum eEditFontMode {
FO_PAGEUP = 8,
FO_PAGEDOWN = 9,
FO_SELCHANGE = 10,
} eEditFontMode;
};
/* BKE_vfont_to_curve will move the cursor in these cases */
#define FO_CURS_IS_MOTION(mode) (ELEM(mode, FO_CURSUP, FO_CURSDOWN, FO_PAGEUP, FO_PAGEDOWN))
bool BKE_vfont_is_builtin(const struct VFont *vfont);
bool BKE_vfont_is_builtin(const VFont *vfont);
void BKE_vfont_builtin_register(const void *mem, int size);
void BKE_vfont_free_data(struct VFont *vfont);
void BKE_vfont_free_data(VFont *vfont);
/**
* Return the built-in #VFont, without adding a user (the user-count may be zero).
* The caller is responsible for adding a user.
*/
struct VFont *BKE_vfont_builtin_get(void);
struct VFont *BKE_vfont_load(struct Main *bmain, const char *filepath);
struct VFont *BKE_vfont_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists);
struct VFont *BKE_vfont_load_exists(struct Main *bmain, const char *filepath);
VFont *BKE_vfont_builtin_get();
VFont *BKE_vfont_load(Main *bmain, const char *filepath);
VFont *BKE_vfont_load_exists_ex(Main *bmain, const char *filepath, bool *r_exists);
VFont *BKE_vfont_load_exists(Main *bmain, const char *filepath);
bool BKE_vfont_to_curve_ex(struct Object *ob,
struct Curve *cu,
bool BKE_vfont_to_curve_ex(Object *ob,
Curve *cu,
eEditFontMode mode,
struct ListBase *r_nubase,
ListBase *r_nubase,
const char32_t **r_text,
int *r_text_len,
bool *r_text_free,
struct CharTrans **r_chartransdata);
bool BKE_vfont_to_curve_nubase(struct Object *ob, eEditFontMode mode, struct ListBase *r_nubase);
CharTrans **r_chartransdata);
bool BKE_vfont_to_curve_nubase(Object *ob, eEditFontMode mode, ListBase *r_nubase);
int BKE_vfont_cursor_to_text_index(struct Object *ob, float cursor_location[2]);
int BKE_vfont_cursor_to_text_index(Object *ob, float cursor_location[2]);
/**
* \warning Expects to have access to evaluated data (i.e. passed object should be evaluated one).
*/
bool BKE_vfont_to_curve(struct Object *ob, eEditFontMode mode);
void BKE_vfont_build_char(struct Curve *cu,
struct ListBase *nubase,
bool BKE_vfont_to_curve(Object *ob, eEditFontMode mode);
void BKE_vfont_build_char(Curve *cu,
ListBase *nubase,
unsigned int character,
struct CharInfo *info,
CharInfo *info,
float ofsx,
float ofsy,
float rot,
int charidx,
float fsize);
int BKE_vfont_select_get(struct Object *ob, int *r_start, int *r_end);
void BKE_vfont_select_clamp(struct Object *ob);
int BKE_vfont_select_get(Object *ob, int *r_start, int *r_end);
void BKE_vfont_select_clamp(Object *ob);
void BKE_vfont_clipboard_free(void);
void BKE_vfont_clipboard_set(const char32_t *text_buf,
const struct CharInfo *info_buf,
size_t len);
void BKE_vfont_clipboard_set(const char32_t *text_buf, const CharInfo *info_buf, size_t len);
void BKE_vfont_clipboard_get(char32_t **r_text_buf,
struct CharInfo **r_info_buf,
CharInfo **r_info_buf,
size_t *r_len_utf8,
size_t *r_len_utf32);
#ifdef __cplusplus
}
#endif

View File

@ -12,27 +12,24 @@
#include "DNA_listBase.h"
#ifdef __cplusplus
extern "C" {
#endif
struct GHash;
struct PackedFile;
struct VFont;
typedef struct VFontData {
struct GHash *characters;
struct VFontData {
GHash *characters;
char name[128];
float scale;
/* Calculated from the font. */
float em_height;
float ascender;
} VFontData;
};
typedef struct VChar {
struct VChar {
ListBase nurbsbase;
unsigned int index;
float width;
} VChar;
};
/**
* Construct a new #VFontData structure from free-type font data in `pf`.
@ -40,12 +37,8 @@ typedef struct VChar {
* \param pf: The font data.
* \retval A new #VFontData structure, or NULL if unable to load.
*/
VFontData *BKE_vfontdata_from_freetypefont(struct PackedFile *pf);
VFontData *BKE_vfontdata_from_freetypefont(PackedFile *pf);
VFontData *BKE_vfontdata_copy(const VFontData *vfont_src, int flag);
VChar *BKE_vfontdata_char_from_freetypefont(struct VFont *vfont, unsigned long character);
VChar *BKE_vfontdata_char_from_freetypefont(VFont *vfont, unsigned long character);
VChar *BKE_vfontdata_char_copy(const VChar *vchar_src);
#ifdef __cplusplus
}
#endif

View File

@ -10,10 +10,6 @@
#ifdef WITH_FFMPEG
# ifdef __cplusplus
extern "C" {
# endif
enum {
FFMPEG_MPEG1 = 0,
FFMPEG_MPEG2 = 1,
@ -48,37 +44,33 @@ struct ReportList;
struct Scene;
int BKE_ffmpeg_start(void *context_v,
const struct Scene *scene,
struct RenderData *rd,
const Scene *scene,
RenderData *rd,
int rectx,
int recty,
struct ReportList *reports,
ReportList *reports,
bool preview,
const char *suffix);
void BKE_ffmpeg_end(void *context_v);
int BKE_ffmpeg_append(void *context_v,
struct RenderData *rd,
RenderData *rd,
int start_frame,
int frame,
int *pixels,
int rectx,
int recty,
const char *suffix,
struct ReportList *reports);
ReportList *reports);
void BKE_ffmpeg_filepath_get(char filepath[/*FILE_MAX*/ 1024],
const struct RenderData *rd,
const RenderData *rd,
bool preview,
const char *suffix);
void BKE_ffmpeg_preset_set(struct RenderData *rd, int preset);
void BKE_ffmpeg_image_type_verify(struct RenderData *rd, const struct ImageFormatData *imf);
bool BKE_ffmpeg_alpha_channel_is_supported(const struct RenderData *rd);
void BKE_ffmpeg_preset_set(RenderData *rd, int preset);
void BKE_ffmpeg_image_type_verify(RenderData *rd, const ImageFormatData *imf);
bool BKE_ffmpeg_alpha_channel_is_supported(const RenderData *rd);
void *BKE_ffmpeg_context_create(void);
void BKE_ffmpeg_context_free(void *context_v);
# ifdef __cplusplus
}
# endif
#endif

View File

@ -481,7 +481,7 @@ set(SRC
BKE_screen.hh
BKE_sequencer_offscreen.h
BKE_shader_fx.h
BKE_shrinkwrap.h
BKE_shrinkwrap.hh
BKE_softbody.h
BKE_sound.h
BKE_speaker.h
@ -501,9 +501,9 @@ set(SRC
BKE_tracking.h
BKE_type_conversions.hh
BKE_undo_system.h
BKE_unit.h
BKE_vfont.h
BKE_vfontdata.h
BKE_unit.hh
BKE_vfont.hh
BKE_vfontdata.hh
BKE_viewer_path.hh
BKE_volume.hh
BKE_volume_openvdb.hh
@ -638,8 +638,8 @@ endif()
if(WITH_CODEC_FFMPEG)
list(APPEND SRC
intern/writeffmpeg.c
BKE_writeffmpeg.h
intern/writeffmpeg.cc
BKE_writeffmpeg.hh
)
list(APPEND INC
../../../intern/ffmpeg

View File

@ -60,7 +60,7 @@
#include "BLI_sys_types.h" /* for intptr_t support */
#include "BKE_shrinkwrap.h"
#include "BKE_shrinkwrap.hh"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"
@ -391,7 +391,9 @@ static Mesh *create_orco_mesh(Object *ob, Mesh *me, BMEditMesh *em, int layer)
orco = get_orco_coords(ob, em, layer, &free);
if (orco) {
BKE_mesh_vert_coords_apply(mesh, orco);
mesh->vert_positions_for_write().copy_from(
{reinterpret_cast<const float3 *>(orco), mesh->totvert});
BKE_mesh_tag_positions_changed(mesh);
if (free) {
MEM_freeN(orco);
}

View File

@ -2578,6 +2578,12 @@ static int rebuild_pose_bone(
pchan->bone = bone;
pchan->parent = parchan;
/* Prevent custom bone colors from having alpha zero.
* Part of the fix for issue #115434. */
pchan->color.custom.solid[3] = 255;
pchan->color.custom.select[3] = 255;
pchan->color.custom.active[3] = 255;
/* We ensure the current pchan is immediately after the one we just generated/updated in the
* previous call to `rebuild_pose_bone`.
*

View File

@ -306,14 +306,16 @@ static bool reuse_bmain_data_remapper_is_id_remapped(IDRemapper *remapper, ID *i
return false;
}
/** Does a complete replacement of data in `new_bmain` by data from `old_bmain. Original new data
/**
* Does a complete replacement of data in `new_bmain` by data from `old_bmain. Original new data
* are moved to the `old_bmain`, and will be freed together with it.
*
* WARNING: Currently only expects to work on local data, won't work properly if some of the IDs of
* given type are linked.
*
* NOTE: There is no support at all for potential dependencies of the IDs moved around. This is not
* expected to be necessary for the current use cases (UI-related IDs). */
* expected to be necessary for the current use cases (UI-related IDs).
*/
static void swap_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, const short id_code)
{
Main *new_bmain = reuse_data->new_bmain;
@ -382,9 +384,11 @@ static void swap_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, con
FOREACH_MAIN_LISTBASE_ID_END;
}
/** Similar to #swap_old_bmain_data_for_blendfile, but with special handling for WM ID. Tightly
/**
* Similar to #swap_old_bmain_data_for_blendfile, but with special handling for WM ID. Tightly
* related to further WM post-processing from calling WM code (see #WM_file_read and
* #wm_homefile_read_ex). */
* #wm_homefile_read_ex).
*/
static void swap_wm_data_for_blendfile(ReuseOldBMainData *reuse_data, const bool load_ui)
{
Main *old_bmain = reuse_data->old_bmain;

View File

@ -63,7 +63,7 @@
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_vfont.h"
#include "BKE_vfont.hh"
#include "BKE_bpath.h" /* own include */

View File

@ -241,14 +241,13 @@ static void mesh_faces_nearest_point(void *userdata,
BVHTreeNearest *nearest)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->vert_positions;
const MFace *face = data->face + index;
const float *t0, *t1, *t2, *t3;
t0 = positions[face->v1];
t1 = positions[face->v2];
t2 = positions[face->v3];
t3 = face->v4 ? positions[face->v4] : nullptr;
t0 = data->vert_positions[face->v1];
t1 = data->vert_positions[face->v2];
t2 = data->vert_positions[face->v3];
t3 = face->v4 ? &data->vert_positions[face->v4].x : nullptr;
do {
float nearest_tmp[3], dist_sq;
@ -276,12 +275,11 @@ static void mesh_looptri_nearest_point(void *userdata,
BVHTreeNearest *nearest)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->vert_positions;
const MLoopTri *lt = &data->looptri[index];
const MLoopTri *lt = &data->looptris[index];
const float *vtri_co[3] = {
positions[data->corner_verts[lt->tri[0]]],
positions[data->corner_verts[lt->tri[1]]],
positions[data->corner_verts[lt->tri[2]]],
data->vert_positions[data->corner_verts[lt->tri[0]]],
data->vert_positions[data->corner_verts[lt->tri[1]]],
data->vert_positions[data->corner_verts[lt->tri[2]]],
};
float nearest_tmp[3], dist_sq;
@ -336,14 +334,13 @@ static void mesh_faces_spherecast(void *userdata,
BVHTreeRayHit *hit)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->vert_positions;
const MFace *face = &data->face[index];
const float *t0, *t1, *t2, *t3;
t0 = positions[face->v1];
t1 = positions[face->v2];
t2 = positions[face->v3];
t3 = face->v4 ? positions[face->v4] : nullptr;
t0 = data->vert_positions[face->v1];
t1 = data->vert_positions[face->v2];
t2 = data->vert_positions[face->v3];
t3 = face->v4 ? &data->vert_positions[face->v4].x : nullptr;
do {
float dist;
@ -375,8 +372,8 @@ static void mesh_looptri_spherecast(void *userdata,
BVHTreeRayHit *hit)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->vert_positions;
const MLoopTri *lt = &data->looptri[index];
const Span<float3> positions = data->vert_positions;
const MLoopTri *lt = &data->looptris[index];
const float *vtri_co[3] = {
positions[data->corner_verts[lt->tri[0]]],
positions[data->corner_verts[lt->tri[1]]],
@ -444,8 +441,8 @@ static void mesh_edges_nearest_point(void *userdata,
BVHTreeNearest *nearest)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->vert_positions;
const blender::int2 &edge = reinterpret_cast<const blender::int2 *>(data->edge)[index];
const Span<float3> positions = data->vert_positions;
const blender::int2 edge = data->edges[index];
float nearest_tmp[3], dist_sq;
const float *t0, *t1;
@ -526,8 +523,8 @@ static void mesh_edges_spherecast(void *userdata,
BVHTreeRayHit *hit)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->vert_positions;
const blender::int2 &edge = reinterpret_cast<const blender::int2 *>(data->edge)[index];
const Span<float3> positions = data->vert_positions;
const blender::int2 edge = data->edges[index];
const float radius_sq = square_f(ray->radius);
float dist;
@ -577,22 +574,22 @@ static void mesh_edges_spherecast(void *userdata,
static void bvhtree_from_mesh_setup_data(BVHTree *tree,
const BVHCacheType bvh_cache_type,
const float (*positions)[3],
const blender::int2 *edge,
const MFace *face,
const int *corner_verts,
const Span<float3> positions,
const Span<blender::int2> edges,
const Span<int> corner_verts,
const Span<MLoopTri> looptris,
const MFace *face,
BVHTreeFromMesh *r_data)
{
memset(r_data, 0, sizeof(*r_data));
*r_data = {};
r_data->tree = tree;
r_data->vert_positions = positions;
r_data->edge = reinterpret_cast<const vec2i *>(edge);
r_data->edges = edges;
r_data->face = face;
r_data->corner_verts = corner_verts;
r_data->looptri = looptris.data();
r_data->looptris = looptris;
switch (bvh_cache_type) {
case BVHTREE_FROM_VERTS:
@ -715,17 +712,16 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree(float epsilon,
static BVHTree *bvhtree_from_mesh_verts_create_tree(float epsilon,
int tree_type,
int axis,
const float (*positions)[3],
const int verts_num,
const Span<float3> positions,
const BitSpan verts_mask,
int verts_num_active)
{
BVHTree *tree = bvhtree_new_common(epsilon, tree_type, axis, verts_num, verts_num_active);
BVHTree *tree = bvhtree_new_common(epsilon, tree_type, axis, positions.size(), verts_num_active);
if (!tree) {
return nullptr;
}
for (int i = 0; i < verts_num; i++) {
for (const int i : positions.index_range()) {
if (!verts_mask.is_empty() && !verts_mask[i]) {
continue;
}
@ -763,8 +759,7 @@ BVHTree *bvhtree_from_editmesh_verts(
}
BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
const float (*vert_positions)[3],
const int verts_num,
const Span<float3> vert_positions,
const BitSpan verts_mask,
int verts_num_active,
float epsilon,
@ -772,14 +767,13 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
int axis)
{
BVHTree *tree = bvhtree_from_mesh_verts_create_tree(
epsilon, tree_type, axis, vert_positions, verts_num, verts_mask, verts_num_active);
epsilon, tree_type, axis, vert_positions, verts_mask, verts_num_active);
bvhtree_balance(tree, false);
if (data) {
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(
tree, BVHTREE_FROM_VERTS, vert_positions, nullptr, nullptr, nullptr, {}, data);
bvhtree_from_mesh_setup_data(tree, BVHTREE_FROM_VERTS, vert_positions, {}, {}, {}, {}, data);
}
return tree;
@ -825,8 +819,8 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree(float epsilon,
return tree;
}
static BVHTree *bvhtree_from_mesh_edges_create_tree(const float (*positions)[3],
blender::Span<blender::int2> edges,
static BVHTree *bvhtree_from_mesh_edges_create_tree(const Span<float3> positions,
const blender::Span<blender::int2> edges,
const BitSpan edges_mask,
int edges_num_active,
float epsilon,
@ -879,9 +873,8 @@ BVHTree *bvhtree_from_editmesh_edges(
}
BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
const float (*vert_positions)[3],
const blender::int2 *edge,
const int edges_num,
const Span<float3> vert_positions,
const Span<blender::int2> edges,
const BitSpan edges_mask,
int edges_num_active,
float epsilon,
@ -889,14 +882,14 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
int axis)
{
BVHTree *tree = bvhtree_from_mesh_edges_create_tree(
vert_positions, {edge, edges_num}, edges_mask, edges_num_active, epsilon, tree_type, axis);
vert_positions, edges, edges_mask, edges_num_active, epsilon, tree_type, axis);
bvhtree_balance(tree, false);
if (data) {
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(
tree, BVHTREE_FROM_EDGES, vert_positions, edge, nullptr, nullptr, {}, data);
tree, BVHTREE_FROM_EDGES, vert_positions, edges, {}, {}, {}, data);
}
return tree;
@ -911,7 +904,7 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
static BVHTree *bvhtree_from_mesh_faces_create_tree(float epsilon,
int tree_type,
int axis,
const float (*positions)[3],
const Span<float3> positions,
const MFace *face,
const int faces_num,
const BitSpan faces_mask,
@ -922,7 +915,7 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree(float epsilon,
return nullptr;
}
if (positions && face) {
if (!positions.is_empty() && face) {
for (int i = 0; i < faces_num; i++) {
float co[4][3];
if (!faces_mask.is_empty() && !faces_mask[i]) {
@ -992,13 +985,13 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(float epsilon,
static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon,
int tree_type,
int axis,
const float (*positions)[3],
const int *corner_verts,
const Span<float3> positions,
const Span<int> corner_verts,
const Span<MLoopTri> looptris,
const BitSpan looptri_mask,
int looptri_num_active)
{
if (positions == nullptr) {
if (positions.is_empty()) {
return nullptr;
}
@ -1055,10 +1048,9 @@ BVHTree *bvhtree_from_editmesh_looptri(
}
BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
const float (*vert_positions)[3],
const int *corner_verts,
const MLoopTri *looptri,
const int looptri_num,
const Span<float3> vert_positions,
const Span<int> corner_verts,
const Span<MLoopTri> looptris,
const BitSpan looptri_mask,
int looptri_num_active,
float epsilon,
@ -1070,7 +1062,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
axis,
vert_positions,
corner_verts,
{looptri, looptri_num},
looptris,
looptri_mask,
looptri_num_active);
@ -1078,14 +1070,8 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
if (data) {
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(tree,
BVHTREE_FROM_LOOPTRI,
vert_positions,
nullptr,
nullptr,
corner_verts,
{looptri, looptri_num},
data);
bvhtree_from_mesh_setup_data(
tree, BVHTREE_FROM_LOOPTRI, vert_positions, {}, corner_verts, looptris, nullptr, data);
}
return tree;
@ -1134,7 +1120,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
if (ELEM(bvh_cache_type, BVHTREE_FROM_LOOPTRI, BVHTREE_FROM_LOOPTRI_NO_HIDDEN)) {
looptris = mesh->looptris();
}
const float(*positions)[3] = reinterpret_cast<const float(*)[3]>(mesh->vert_positions().data());
const Span<float3> positions = mesh->vert_positions();
const Span<blender::int2> edges = mesh->edges();
const Span<int> corner_verts = mesh->corner_verts();
@ -1142,10 +1129,10 @@ BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
bvhtree_from_mesh_setup_data(nullptr,
bvh_cache_type,
positions,
edges.data(),
(const MFace *)CustomData_get_layer(&mesh->fdata_legacy, CD_MFACE),
corner_verts.data(),
edges,
corner_verts,
looptris,
(const MFace *)CustomData_get_layer(&mesh->fdata_legacy, CD_MFACE),
data);
bool lock_started = false;
@ -1164,18 +1151,12 @@ BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
switch (bvh_cache_type) {
case BVHTREE_FROM_LOOSEVERTS: {
const blender::bke::LooseVertCache &loose_verts = mesh->loose_verts();
data->tree = bvhtree_from_mesh_verts_create_tree(0.0f,
tree_type,
6,
positions,
mesh->totvert,
loose_verts.is_loose_bits,
loose_verts.count);
data->tree = bvhtree_from_mesh_verts_create_tree(
0.0f, tree_type, 6, positions, loose_verts.is_loose_bits, loose_verts.count);
break;
}
case BVHTREE_FROM_VERTS: {
data->tree = bvhtree_from_mesh_verts_create_tree(
0.0f, tree_type, 6, positions, mesh->totvert, {}, -1);
data->tree = bvhtree_from_mesh_verts_create_tree(0.0f, tree_type, 6, positions, {}, -1);
break;
}
case BVHTREE_FROM_LOOSEEDGES: {
@ -1211,12 +1192,12 @@ BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
looptris.size(),
&mask_bits_act_len);
data->tree = bvhtree_from_mesh_looptri_create_tree(
0.0f, tree_type, 6, positions, corner_verts.data(), looptris, mask, mask_bits_act_len);
0.0f, tree_type, 6, positions, corner_verts, looptris, mask, mask_bits_act_len);
break;
}
case BVHTREE_FROM_LOOPTRI: {
data->tree = bvhtree_from_mesh_looptri_create_tree(
0.0f, tree_type, 6, positions, corner_verts.data(), looptris, {}, -1);
0.0f, tree_type, 6, positions, corner_verts, looptris, {}, -1);
break;
}
case BVHTREE_FROM_EM_LOOSEVERTS:
@ -1361,7 +1342,7 @@ void free_bvhtree_from_mesh(BVHTreeFromMesh *data)
BLI_bvhtree_free(data->tree);
}
memset(data, 0, sizeof(*data));
*data = {};
}
/** \} */

View File

@ -1420,7 +1420,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata,
treedata->tree, new_co, no, radius, &rayhit, treedata->raycast_callback, treedata);
int vert_idx = -1;
const int *corner_verts = treedata->corner_verts;
const int *corner_verts = treedata->corner_verts.data();
const MLoopTri *lt = nullptr;
if (rayhit.index != -1 && rayhit.dist <= max_length) {
@ -1430,7 +1430,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata,
}
float min_len = FLT_MAX;
lt = &treedata->looptri[rayhit.index];
lt = &treedata->looptris[rayhit.index];
for (int i = 0; i < 3; i++) {
int tmp_vert_idx = corner_verts[lt->tri[i]];

View File

@ -1047,8 +1047,10 @@ static void collection_gobject_hash_ensure(Collection *collection)
collection_gobject_assert_internal_consistency(collection, true);
}
/** Similar to #collection_gobject_hash_ensure/#collection_gobject_hash_create, but does fix
* inconsistencies in the collection objects list. */
/**
* Similar to #collection_gobject_hash_ensure/#collection_gobject_hash_create, but does fix
* inconsistencies in the collection objects list.
*/
static void collection_gobject_hash_ensure_fix(Collection *collection)
{
bool changed = false;

View File

@ -66,7 +66,7 @@
#include "BKE_object.hh"
#include "BKE_object_types.hh"
#include "BKE_scene.h"
#include "BKE_shrinkwrap.h"
#include "BKE_shrinkwrap.hh"
#include "BKE_tracking.h"
#include "BIK_api.h"
@ -354,7 +354,8 @@ void BKE_constraint_mat_convertspace(Object *ob,
/* local to pose - do inverse procedure that was done for pose to local */
else {
if (pchan->bone) {
/* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */
/* We need the:
* `posespace_matrix = local_matrix + (parent_posespace_matrix + restpos)`. */
BKE_armature_mat_bone_to_pose(pchan, mat, mat);
}

View File

@ -51,7 +51,7 @@
#include "BKE_main.h"
#include "BKE_object.hh"
#include "BKE_object_types.hh"
#include "BKE_vfont.h"
#include "BKE_vfont.hh"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"

View File

@ -16,7 +16,7 @@
#include "BKE_displist.h"
#include "BKE_lib_id.h"
#include "BKE_modifier.hh"
#include "BKE_vfont.h"
#include "BKE_vfont.hh"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"

View File

@ -41,7 +41,7 @@
#include "BKE_modifier.hh"
#include "BKE_object.hh"
#include "BKE_object_types.hh"
#include "BKE_vfont.h"
#include "BKE_vfont.hh"
#include "BLI_sys_types.h" /* For #intptr_t support. */

View File

@ -3448,9 +3448,9 @@ static void mesh_tris_spherecast_dp(void *userdata,
BVHTreeRayHit *hit)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->vert_positions;
const MLoopTri *looptris = data->looptri;
const int *corner_verts = data->corner_verts;
const blender::Span<blender::float3> positions = data->vert_positions;
const MLoopTri *looptris = data->looptris.data();
const int *corner_verts = data->corner_verts.data();
const float *t0, *t1, *t2;
float dist;
@ -3480,9 +3480,9 @@ static void mesh_tris_nearest_point_dp(void *userdata,
BVHTreeNearest *nearest)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->vert_positions;
const MLoopTri *looptris = data->looptri;
const int *corner_verts = data->corner_verts;
const blender::Span<blender::float3> positions = data->vert_positions;
const MLoopTri *looptris = data->looptris.data();
const int *corner_verts = data->corner_verts.data();
float nearest_tmp[3], dist_sq;
const float *t0, *t1, *t2;

View File

@ -670,8 +670,8 @@ bool closest_point_on_surface(SurfaceModifierData *surmd,
}
if (surface_vel) {
const int *corner_verts = bvhtree->corner_verts;
const MLoopTri *lt = &bvhtree->looptri[nearest.index];
const int *corner_verts = bvhtree->corner_verts.data();
const MLoopTri *lt = &bvhtree->looptris[nearest.index];
copy_v3_v3(surface_vel, surmd->runtime.vert_velocities[corner_verts[lt->tri[0]]]);
add_v3_v3(surface_vel, surmd->runtime.vert_velocities[corner_verts[lt->tri[1]]]);

View File

@ -219,7 +219,7 @@ static Collection *gpencil_get_parent_collection(Scene *scene, Object *ob)
return mycol;
}
static int gpencil_get_stroke_material_fromcurve(
Main *bmain, Object *ob_gp, Object *ob_cu, bool *do_stroke, bool *do_fill)
Main *bmain, Object *ob_gp, Object *ob_cu, bool *r_do_stroke, bool *r_do_fill)
{
Curve *cu = (Curve *)ob_cu->data;
@ -234,21 +234,21 @@ static int gpencil_get_stroke_material_fromcurve(
* If the has only one material, if the name contains "_stroke",
* it's used as a stroke, otherwise as fill. */
if (ob_cu->totcol >= 2) {
*do_stroke = true;
*do_fill = true;
*r_do_stroke = true;
*r_do_fill = true;
mat_curve_fill = BKE_object_material_get(ob_cu, 1);
mat_curve_stroke = BKE_object_material_get(ob_cu, 2);
}
else if (ob_cu->totcol == 1) {
mat_curve_stroke = BKE_object_material_get(ob_cu, 1);
if ((mat_curve_stroke) && (strstr(mat_curve_stroke->id.name, "_stroke") != nullptr)) {
*do_stroke = true;
*do_fill = false;
*r_do_stroke = true;
*r_do_fill = false;
mat_curve_fill = nullptr;
}
else {
*do_stroke = false;
*do_fill = true;
*r_do_stroke = false;
*r_do_fill = true;
/* Invert materials. */
mat_curve_fill = mat_curve_stroke;
mat_curve_stroke = nullptr;
@ -256,7 +256,7 @@ static int gpencil_get_stroke_material_fromcurve(
}
else {
/* No materials in the curve. */
*do_fill = false;
*r_do_fill = false;
return -1;
}
@ -268,11 +268,11 @@ static int gpencil_get_stroke_material_fromcurve(
}
int r_idx = gpencil_check_same_material_color(
ob_gp, color_stroke, color_fill, *do_stroke, *do_fill, &mat_gp);
ob_gp, color_stroke, color_fill, *r_do_stroke, *r_do_fill, &mat_gp);
if ((ob_gp->totcol < r_idx) || (r_idx < 0)) {
mat_gp = gpencil_add_from_curve_material(
bmain, ob_gp, color_stroke, color_fill, *do_stroke, *do_fill, &r_idx);
bmain, ob_gp, color_stroke, color_fill, *r_do_stroke, *r_do_fill, &r_idx);
}
/* Set fill and stroke depending of curve type (3D or 2D). */

View File

@ -42,7 +42,7 @@
#include "BKE_object.hh"
#include "BKE_object_types.hh"
#include "BKE_screen.hh"
#include "BKE_shrinkwrap.h"
#include "BKE_shrinkwrap.hh"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"

View File

@ -4828,17 +4828,16 @@ void BKE_image_pool_free(ImagePool *pool)
}
BLI_INLINE ImBuf *image_pool_find_item(
ImagePool *pool, Image *image, int entry, int index, bool *found)
ImagePool *pool, Image *image, int entry, int index, bool *r_found)
{
*found = false;
LISTBASE_FOREACH (ImagePoolItem *, item, &pool->image_buffers) {
if (item->image == image && item->entry == entry && item->index == index) {
*found = true;
*r_found = true;
return item->ibuf;
}
}
*r_found = false;
return nullptr;
}

View File

@ -238,80 +238,80 @@ static AdrBit2Path *adrcode_bitmaps_to_paths(int blocktype, int adrcode, int *to
/* ADRCODE to RNA-Path Conversion Code - Standard */
/* Object types */
static const char *ob_adrcodes_to_paths(int adrcode, int *array_index)
static const char *ob_adrcodes_to_paths(int adrcode, int *r_array_index)
{
/* Set array index like this in-case nothing sets it correctly. */
*array_index = 0;
*r_array_index = 0;
/* result depends on adrcode */
switch (adrcode) {
case OB_LOC_X:
*array_index = 0;
*r_array_index = 0;
return "location";
case OB_LOC_Y:
*array_index = 1;
*r_array_index = 1;
return "location";
case OB_LOC_Z:
*array_index = 2;
*r_array_index = 2;
return "location";
case OB_DLOC_X:
*array_index = 0;
*r_array_index = 0;
return "delta_location";
case OB_DLOC_Y:
*array_index = 1;
*r_array_index = 1;
return "delta_location";
case OB_DLOC_Z:
*array_index = 2;
*r_array_index = 2;
return "delta_location";
case OB_ROT_X:
*array_index = 0;
*r_array_index = 0;
return "rotation_euler";
case OB_ROT_Y:
*array_index = 1;
*r_array_index = 1;
return "rotation_euler";
case OB_ROT_Z:
*array_index = 2;
*r_array_index = 2;
return "rotation_euler";
case OB_DROT_X:
*array_index = 0;
*r_array_index = 0;
return "delta_rotation_euler";
case OB_DROT_Y:
*array_index = 1;
*r_array_index = 1;
return "delta_rotation_euler";
case OB_DROT_Z:
*array_index = 2;
*r_array_index = 2;
return "delta_rotation_euler";
case OB_SIZE_X:
*array_index = 0;
*r_array_index = 0;
return "scale";
case OB_SIZE_Y:
*array_index = 1;
*r_array_index = 1;
return "scale";
case OB_SIZE_Z:
*array_index = 2;
*r_array_index = 2;
return "scale";
case OB_DSIZE_X:
*array_index = 0;
*r_array_index = 0;
return "delta_scale";
case OB_DSIZE_Y:
*array_index = 1;
*r_array_index = 1;
return "delta_scale";
case OB_DSIZE_Z:
*array_index = 2;
*r_array_index = 2;
return "delta_scale";
case OB_COL_R:
*array_index = 0;
*r_array_index = 0;
return "color";
case OB_COL_G:
*array_index = 1;
*r_array_index = 1;
return "color";
case OB_COL_B:
*array_index = 2;
*r_array_index = 2;
return "color";
case OB_COL_A:
*array_index = 3;
*r_array_index = 3;
return "color";
#if 0
case OB_PD_FSTR:
@ -353,54 +353,54 @@ static const char *ob_adrcodes_to_paths(int adrcode, int *array_index)
/* PoseChannel types
* NOTE: pchan name comes from 'actname' added earlier...
*/
static const char *pchan_adrcodes_to_paths(int adrcode, int *array_index)
static const char *pchan_adrcodes_to_paths(int adrcode, int *r_array_index)
{
/* Set array index like this in-case nothing sets it correctly. */
*array_index = 0;
*r_array_index = 0;
/* result depends on adrcode */
switch (adrcode) {
case AC_QUAT_W:
*array_index = 0;
*r_array_index = 0;
return "rotation_quaternion";
case AC_QUAT_X:
*array_index = 1;
*r_array_index = 1;
return "rotation_quaternion";
case AC_QUAT_Y:
*array_index = 2;
*r_array_index = 2;
return "rotation_quaternion";
case AC_QUAT_Z:
*array_index = 3;
*r_array_index = 3;
return "rotation_quaternion";
case AC_EUL_X:
*array_index = 0;
*r_array_index = 0;
return "rotation_euler";
case AC_EUL_Y:
*array_index = 1;
*r_array_index = 1;
return "rotation_euler";
case AC_EUL_Z:
*array_index = 2;
*r_array_index = 2;
return "rotation_euler";
case AC_LOC_X:
*array_index = 0;
*r_array_index = 0;
return "location";
case AC_LOC_Y:
*array_index = 1;
*r_array_index = 1;
return "location";
case AC_LOC_Z:
*array_index = 2;
*r_array_index = 2;
return "location";
case AC_SIZE_X:
*array_index = 0;
*r_array_index = 0;
return "scale";
case AC_SIZE_Y:
*array_index = 1;
*r_array_index = 1;
return "scale";
case AC_SIZE_Z:
*array_index = 2;
*r_array_index = 2;
return "scale";
}
@ -410,10 +410,10 @@ static const char *pchan_adrcodes_to_paths(int adrcode, int *array_index)
}
/* Constraint types */
static const char *constraint_adrcodes_to_paths(int adrcode, int *array_index)
static const char *constraint_adrcodes_to_paths(int adrcode, int *r_array_index)
{
/* Set array index like this in-case nothing sets it correctly. */
*array_index = 0;
*r_array_index = 0;
/* result depends on adrcode */
switch (adrcode) {
@ -431,7 +431,7 @@ static const char *constraint_adrcodes_to_paths(int adrcode, int *array_index)
* NOTE: as we don't have access to the keyblock where the data comes from (for now),
* we'll just use numerical indices for now...
*/
static char *shapekey_adrcodes_to_paths(ID *id, int adrcode, int * /*array_index*/)
static char *shapekey_adrcodes_to_paths(ID *id, int adrcode, int * /*r_array_index*/)
{
static char buf[128];
@ -461,7 +461,7 @@ static char *shapekey_adrcodes_to_paths(ID *id, int adrcode, int * /*array_index
}
/* MTex (Texture Slot) types */
static const char *mtex_adrcodes_to_paths(int adrcode, int * /*array_index*/)
static const char *mtex_adrcodes_to_paths(int adrcode, int * /*r_array_index*/)
{
const char *base = nullptr, *prop = nullptr;
static char buf[128];
@ -581,10 +581,10 @@ static const char *mtex_adrcodes_to_paths(int adrcode, int * /*array_index*/)
}
/* Texture types */
static const char *texture_adrcodes_to_paths(int adrcode, int *array_index)
static const char *texture_adrcodes_to_paths(int adrcode, int *r_array_index)
{
/* Set array index like this in-case nothing sets it correctly. */
*array_index = 0;
*r_array_index = 0;
/* result depends on adrcode */
switch (adrcode) {
@ -607,16 +607,16 @@ static const char *texture_adrcodes_to_paths(int adrcode, int *array_index)
/* voronoi */
case TE_VNW1:
*array_index = 0;
*r_array_index = 0;
return "feature_weights";
case TE_VNW2:
*array_index = 1;
*r_array_index = 1;
return "feature_weights";
case TE_VNW3:
*array_index = 2;
*r_array_index = 2;
return "feature_weights";
case TE_VNW4:
*array_index = 3;
*r_array_index = 3;
return "feature_weights";
case TE_VNMEXP:
return "minkovsky_exponent";
@ -649,13 +649,13 @@ static const char *texture_adrcodes_to_paths(int adrcode, int *array_index)
return "gain";
case TE_COL_R:
*array_index = 0;
*r_array_index = 0;
return "rgb_factor";
case TE_COL_G:
*array_index = 1;
*r_array_index = 1;
return "rgb_factor";
case TE_COL_B:
*array_index = 2;
*r_array_index = 2;
return "rgb_factor";
case TE_BRIGHT:
@ -668,41 +668,41 @@ static const char *texture_adrcodes_to_paths(int adrcode, int *array_index)
}
/* Material Types */
static const char *material_adrcodes_to_paths(int adrcode, int *array_index)
static const char *material_adrcodes_to_paths(int adrcode, int *r_array_index)
{
/* Set array index like this in-case nothing sets it correctly. */
*array_index = 0;
*r_array_index = 0;
/* result depends on adrcode */
switch (adrcode) {
case MA_COL_R:
*array_index = 0;
*r_array_index = 0;
return "diffuse_color";
case MA_COL_G:
*array_index = 1;
*r_array_index = 1;
return "diffuse_color";
case MA_COL_B:
*array_index = 2;
*r_array_index = 2;
return "diffuse_color";
case MA_SPEC_R:
*array_index = 0;
*r_array_index = 0;
return "specular_color";
case MA_SPEC_G:
*array_index = 1;
*r_array_index = 1;
return "specular_color";
case MA_SPEC_B:
*array_index = 2;
*r_array_index = 2;
return "specular_color";
case MA_MIR_R:
*array_index = 0;
*r_array_index = 0;
return "mirror_color";
case MA_MIR_G:
*array_index = 1;
*r_array_index = 1;
return "mirror_color";
case MA_MIR_B:
*array_index = 2;
*r_array_index = 2;
return "mirror_color";
case MA_ALPHA:
@ -754,17 +754,17 @@ static const char *material_adrcodes_to_paths(int adrcode, int *array_index)
return "halo.add";
default: /* for now, we assume that the others were MTex channels */
return mtex_adrcodes_to_paths(adrcode, array_index);
return mtex_adrcodes_to_paths(adrcode, r_array_index);
}
return nullptr;
}
/* Camera Types */
static const char *camera_adrcodes_to_paths(int adrcode, int *array_index)
static const char *camera_adrcodes_to_paths(int adrcode, int *r_array_index)
{
/* Set array index like this in-case nothing sets it correctly. */
*array_index = 0;
*r_array_index = 0;
/* result depends on adrcode */
switch (adrcode) {
@ -806,10 +806,10 @@ static const char *camera_adrcodes_to_paths(int adrcode, int *array_index)
}
/* Light Types */
static const char *light_adrcodes_to_paths(int adrcode, int *array_index)
static const char *light_adrcodes_to_paths(int adrcode, int *r_array_index)
{
/* Set array index like this in-case nothing sets it correctly. */
*array_index = 0;
*r_array_index = 0;
/* result depends on adrcode */
switch (adrcode) {
@ -817,13 +817,13 @@ static const char *light_adrcodes_to_paths(int adrcode, int *array_index)
return "energy";
case LA_COL_R:
*array_index = 0;
*r_array_index = 0;
return "color";
case LA_COL_G:
*array_index = 1;
*r_array_index = 1;
return "color";
case LA_COL_B:
*array_index = 2;
*r_array_index = 2;
return "color";
case LA_DIST:
@ -843,7 +843,7 @@ static const char *light_adrcodes_to_paths(int adrcode, int *array_index)
return "halo_intensity";
default: /* for now, we assume that the others were MTex channels */
return mtex_adrcodes_to_paths(adrcode, array_index);
return mtex_adrcodes_to_paths(adrcode, r_array_index);
}
/* unrecognized adrcode, or not-yet-handled ones! */
@ -851,10 +851,10 @@ static const char *light_adrcodes_to_paths(int adrcode, int *array_index)
}
/* Sound Types */
static const char *sound_adrcodes_to_paths(int adrcode, int *array_index)
static const char *sound_adrcodes_to_paths(int adrcode, int *r_array_index)
{
/* Set array index like this in-case nothing sets it correctly. */
*array_index = 0;
*r_array_index = 0;
/* result depends on adrcode */
switch (adrcode) {
@ -877,30 +877,30 @@ static const char *sound_adrcodes_to_paths(int adrcode, int *array_index)
}
/* World Types */
static const char *world_adrcodes_to_paths(int adrcode, int *array_index)
static const char *world_adrcodes_to_paths(int adrcode, int *r_array_index)
{
/* Set array index like this in-case nothing sets it correctly. */
*array_index = 0;
*r_array_index = 0;
/* result depends on adrcode */
switch (adrcode) {
case WO_HOR_R:
*array_index = 0;
*r_array_index = 0;
return "horizon_color";
case WO_HOR_G:
*array_index = 1;
*r_array_index = 1;
return "horizon_color";
case WO_HOR_B:
*array_index = 2;
*r_array_index = 2;
return "horizon_color";
case WO_ZEN_R:
*array_index = 0;
*r_array_index = 0;
return "zenith_color";
case WO_ZEN_G:
*array_index = 1;
*r_array_index = 1;
return "zenith_color";
case WO_ZEN_B:
*array_index = 2;
*r_array_index = 2;
return "zenith_color";
case WO_EXPOS:
@ -916,17 +916,17 @@ static const char *world_adrcodes_to_paths(int adrcode, int *array_index)
return "mist.height";
default: /* for now, we assume that the others were MTex channels */
return mtex_adrcodes_to_paths(adrcode, array_index);
return mtex_adrcodes_to_paths(adrcode, r_array_index);
}
return nullptr;
}
/* Particle Types */
static const char *particle_adrcodes_to_paths(int adrcode, int *array_index)
static const char *particle_adrcodes_to_paths(int adrcode, int *r_array_index)
{
/* Set array index like this in-case nothing sets it correctly. */
*array_index = 0;
*r_array_index = 0;
/* result depends on adrcode */
switch (adrcode) {
@ -945,13 +945,13 @@ static const char *particle_adrcodes_to_paths(int adrcode, int *array_index)
case PART_LENGTH:
return "settings.length";
case PART_GRAV_X:
*array_index = 0;
*r_array_index = 0;
return "settings.acceleration";
case PART_GRAV_Y:
*array_index = 1;
*r_array_index = 1;
return "settings.acceleration";
case PART_GRAV_Z:
*array_index = 2;
*r_array_index = 2;
return "settings.acceleration";
case PART_KINK_AMP:
return "settings.kink_amplitude";
@ -1015,7 +1015,7 @@ static const char *particle_adrcodes_to_paths(int adrcode, int *array_index)
* - blocktype, adrcode - determines setting to get
* - actname, constname, seq - used to build path
* Output:
* - array_index - index in property's array (if applicable) to use
* - r_array_index - index in property's array (if applicable) to use
* - return - the allocated path...
*/
static char *get_rna_access(ID *id,
@ -1024,7 +1024,7 @@ static char *get_rna_access(ID *id,
char actname[],
char constname[],
Sequence *seq,
int *array_index)
int *r_array_index)
{
DynStr *path = BLI_dynstr_new();
const char *propname = nullptr;
@ -1125,8 +1125,8 @@ static char *get_rna_access(ID *id,
*/
if ((propname == nullptr) && (blocktype > 0)) {
/* nothing was found, so exit */
if (array_index) {
*array_index = 0;
if (r_array_index) {
*r_array_index = 0;
}
BLI_dynstr_free(path);
@ -1134,8 +1134,8 @@ static char *get_rna_access(ID *id,
return nullptr;
}
if (array_index) {
*array_index = dummy_index;
if (r_array_index) {
*r_array_index = dummy_index;
}
/* 'buf' _must_ be initialized in this block */
@ -1193,7 +1193,7 @@ static char *get_rna_access(ID *id,
BLI_dynstr_append(path, propname);
/* if there was no array index pointer provided, add it to the path */
if (array_index == nullptr) {
if (r_array_index == nullptr) {
SNPRINTF(buf, "[\"%d\"]", dummy_index);
BLI_dynstr_append(path, buf);
}

View File

@ -641,34 +641,35 @@ static char *key_block_get_data(Key *key, KeyBlock *actkb, KeyBlock *kb, char **
return static_cast<char *>(kb->data);
}
/* currently only the first value of 'ofs' may be set. */
static bool key_pointer_size(const Key *key, const int mode, int *poinsize, int *ofs, int *step)
/* currently only the first value of 'r_ofs' may be set. */
static bool key_pointer_size(
const Key *key, const int mode, int *r_poinsize, int *r_ofs, int *r_step)
{
if (key->from == nullptr) {
return false;
}
*step = 1;
*r_step = 1;
switch (GS(key->from->name)) {
case ID_ME:
*ofs = sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
*poinsize = *ofs;
*r_ofs = sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
*r_poinsize = *r_ofs;
break;
case ID_LT:
*ofs = sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
*poinsize = *ofs;
*r_ofs = sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
*r_poinsize = *r_ofs;
break;
case ID_CU_LEGACY:
if (mode == KEY_MODE_BPOINT) {
*ofs = sizeof(float[KEYELEM_FLOAT_LEN_BPOINT]);
*step = KEYELEM_ELEM_LEN_BPOINT;
*r_ofs = sizeof(float[KEYELEM_FLOAT_LEN_BPOINT]);
*r_step = KEYELEM_ELEM_LEN_BPOINT;
}
else {
*ofs = sizeof(float[KEYELEM_FLOAT_LEN_BEZTRIPLE]);
*step = KEYELEM_ELEM_LEN_BEZTRIPLE;
*r_ofs = sizeof(float[KEYELEM_FLOAT_LEN_BEZTRIPLE]);
*r_step = KEYELEM_ELEM_LEN_BEZTRIPLE;
}
*poinsize = sizeof(float[KEYELEM_ELEM_SIZE_CURVE]);
*r_poinsize = sizeof(float[KEYELEM_ELEM_SIZE_CURVE]);
break;
default:
BLI_assert_msg(0, "invalid 'key->from' ID type");
@ -1605,6 +1606,7 @@ float *BKE_key_evaluate_object_ex(
const int totvert = min_ii(tot, mesh->totvert);
mesh->vert_positions_for_write().take_front(totvert).copy_from(
{reinterpret_cast<const blender::float3 *>(out), totvert});
BKE_mesh_tag_positions_changed(mesh);
break;
}
case ID_LT: {

View File

@ -94,9 +94,11 @@ BLI_INLINE IDOverrideLibraryRuntime *override_library_runtime_ensure(
return liboverride->runtime;
}
/** Helper to preserve Pose mode on override objects.
/**
* Helper to preserve Pose mode on override objects.
* A bit annoying to have this special case, but not much to be done here currently, since the
* matching RNA property is read-only. */
* matching RNA property is read-only.
*/
BLI_INLINE void lib_override_object_posemode_transfer(ID *id_dst, ID *id_src)
{
if (GS(id_src->name) == ID_OB && GS(id_dst->name) == ID_OB) {
@ -3420,10 +3422,12 @@ static int lib_override_sort_libraries_func(LibraryIDLinkCallbackData *cb_data)
return IDWALK_RET_NOP;
}
/** Define the `temp_index` of libraries from their highest level of indirect usage.
/**
* Define the `temp_index` of libraries from their highest level of indirect usage.
*
* E.g. if lib_a uses lib_b, lib_c and lib_d, and lib_b also uses lib_d, then lib_a has an index of
* 1, lib_b and lib_c an index of 2, and lib_d an index of 3. */
* 1, lib_b and lib_c an index of 2, and lib_d an index of 3.
*/
static int lib_override_libraries_index_define(Main *bmain)
{
LISTBASE_FOREACH (Library *, library, &bmain->libraries) {

View File

@ -653,7 +653,10 @@ bool BKE_library_ID_is_indirectly_used(Main *bmain, void *idv)
return library_ID_is_used(bmain, idv, true);
}
void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, bool *is_used_linked)
void BKE_library_ID_test_usages(Main *bmain,
void *idv,
bool *r_is_used_local,
bool *r_is_used_linked)
{
IDUsersIter iter;
ListBase *lb_array[INDEX_ID_MAX];
@ -683,8 +686,8 @@ void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, boo
}
}
*is_used_local = (iter.count_direct != 0);
*is_used_linked = (iter.count_indirect != 0);
*r_is_used_local = (iter.count_direct != 0);
*r_is_used_linked = (iter.count_indirect != 0);
}
/* ***** IDs usages.checking/tagging. ***** */

View File

@ -68,7 +68,7 @@
#include "BKE_object_types.hh"
#include "BKE_preview_image.hh"
#include "BKE_scene.h"
#include "BKE_vfont.h"
#include "BKE_vfont.hh"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_build.hh"

View File

@ -278,7 +278,9 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
CustomData_blend_write_prepare(mesh->edge_data, edge_layers, {});
CustomData_blend_write_prepare(mesh->loop_data, loop_layers, {});
CustomData_blend_write_prepare(mesh->face_data, face_layers, {});
mesh_sculpt_mask_to_legacy(vert_layers);
if (!is_undo) {
mesh_sculpt_mask_to_legacy(vert_layers);
}
}
mesh->runtime = nullptr;
@ -1078,27 +1080,6 @@ void BKE_mesh_sharp_edges_set_from_angle(Mesh *me, const float angle)
sharp_edges.finish();
}
void BKE_mesh_looptri_get_real_edges(const blender::int2 *edges,
const int *corner_verts,
const int *corner_edges,
const MLoopTri *tri,
int r_edges[3])
{
for (int i = 2, i_next = 0; i_next < 3; i = i_next++) {
const int corner_1 = tri->tri[i];
const int corner_2 = tri->tri[i_next];
const int vert_1 = corner_verts[corner_1];
const int vert_2 = corner_verts[corner_2];
const int edge_i = corner_edges[corner_1];
const blender::int2 &edge = edges[edge_i];
bool is_real = (vert_1 == edge[0] && vert_2 == edge[1]) ||
(vert_1 == edge[1] && vert_2 == edge[0]);
r_edges[i] = is_real ? edge_i : -1;
}
}
std::optional<blender::Bounds<blender::float3>> Mesh::bounds_min_max() const
{
using namespace blender;
@ -1322,37 +1303,6 @@ void BKE_mesh_count_selected_items(const Mesh *mesh, int r_count[3])
/* We could support faces in paint modes. */
}
float (*BKE_mesh_vert_coords_alloc(const Mesh *mesh, int *r_vert_len))[3]
{
float(*vert_coords)[3] = (float(*)[3])MEM_mallocN(sizeof(float[3]) * mesh->totvert, __func__);
MutableSpan(reinterpret_cast<float3 *>(vert_coords), mesh->totvert)
.copy_from(mesh->vert_positions());
if (r_vert_len) {
*r_vert_len = mesh->totvert;
}
return vert_coords;
}
void BKE_mesh_vert_coords_apply(Mesh *mesh, const float (*vert_coords)[3])
{
MutableSpan<float3> positions = mesh->vert_positions_for_write();
for (const int i : positions.index_range()) {
copy_v3_v3(positions[i], vert_coords[i]);
}
BKE_mesh_tag_positions_changed(mesh);
}
void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
const float (*vert_coords)[3],
const float mat[4][4])
{
MutableSpan<float3> positions = mesh->vert_positions_for_write();
for (const int i : positions.index_range()) {
mul_v3_m4v3(positions[i], mat, vert_coords[i]);
}
BKE_mesh_tag_positions_changed(mesh);
}
/* **** Depsgraph evaluation **** */
void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh)

View File

@ -39,13 +39,13 @@ using std::array;
class VertexWeight {
public:
virtual float weight_at_index(const int index) = 0;
virtual float weight_at_index(const int index) const = 0;
virtual ~VertexWeight() = default;
};
class LoopWeight {
public:
virtual float weight_at_index(const int index) = 0;
virtual float weight_at_index(const int index) const = 0;
virtual ~LoopWeight() = default;
};
@ -81,13 +81,13 @@ class FairingContext {
virtual ~FairingContext() = default;
void fair_verts(bool *affected,
void fair_verts(const bool affected_verts[],
const eMeshFairingDepth depth,
VertexWeight *vertex_weight,
LoopWeight *loop_weight)
const VertexWeight *vertex_weight,
const LoopWeight *loop_weight)
{
fair_verts_ex(affected, int(depth), vertex_weight, loop_weight);
fair_verts_ex(affected_verts, int(depth), vertex_weight, loop_weight);
}
protected:
@ -105,8 +105,8 @@ class FairingContext {
float multiplier,
const int depth,
Map<int, int> &vert_col_map,
VertexWeight *vertex_weight,
LoopWeight *loop_weight)
const VertexWeight *vertex_weight,
const LoopWeight *loop_weight)
{
if (depth == 0) {
if (vert_col_map.contains(v)) {
@ -147,15 +147,15 @@ class FairingContext {
loop_weight);
}
void fair_verts_ex(const bool *affected,
void fair_verts_ex(const bool affected_verts[],
const int order,
VertexWeight *vertex_weight,
LoopWeight *loop_weight)
const VertexWeight *vertex_weight,
const LoopWeight *loop_weight)
{
Map<int, int> vert_col_map;
int affected_verts_num = 0;
for (int i = 0; i < totvert_; i++) {
if (!affected[i]) {
if (!affected_verts[i]) {
continue;
}
vert_col_map.add(i, affected_verts_num);
@ -331,7 +331,7 @@ class UniformVertexWeight : public VertexWeight {
}
}
float weight_at_index(const int index) override
float weight_at_index(const int index) const override
{
return vertex_weights_[index];
}
@ -384,7 +384,7 @@ class VoronoiVertexWeight : public VertexWeight {
}
}
float weight_at_index(const int index) override
float weight_at_index(const int index) const override
{
return vertex_weights_[index];
}
@ -425,14 +425,14 @@ class VoronoiVertexWeight : public VertexWeight {
class UniformLoopWeight : public LoopWeight {
public:
float weight_at_index(const int /*index*/) override
float weight_at_index(const int /*index*/) const override
{
return 1.0f;
}
};
static void prefair_and_fair_verts(FairingContext *fairing_context,
bool *affected_verts,
const bool affected_verts[],
const eMeshFairingDepth depth)
{
/* Pre-fair. */
@ -452,7 +452,7 @@ static void prefair_and_fair_verts(FairingContext *fairing_context,
void BKE_mesh_prefair_and_fair_verts(Mesh *mesh,
blender::MutableSpan<float3> deform_vert_positions,
bool *affect_verts,
const bool affected_verts[],
const eMeshFairingDepth depth)
{
MutableSpan<float3> deform_positions_span;
@ -460,13 +460,15 @@ void BKE_mesh_prefair_and_fair_verts(Mesh *mesh,
deform_positions_span = deform_vert_positions;
}
MeshFairingContext *fairing_context = new MeshFairingContext(mesh, deform_positions_span);
prefair_and_fair_verts(fairing_context, affect_verts, depth);
prefair_and_fair_verts(fairing_context, affected_verts, depth);
delete fairing_context;
}
void BKE_bmesh_prefair_and_fair_verts(BMesh *bm, bool *affect_verts, const eMeshFairingDepth depth)
void BKE_bmesh_prefair_and_fair_verts(BMesh *bm,
const bool affected_verts[],
const eMeshFairingDepth depth)
{
BMeshFairingContext *fairing_context = new BMeshFairingContext(bm);
prefair_and_fair_verts(fairing_context, affect_verts, depth);
prefair_and_fair_verts(fairing_context, affected_verts, depth);
delete fairing_context;
}

View File

@ -403,6 +403,7 @@ GroupedSpan<int> build_vert_to_edge_map(const Span<int2> edges,
}
}
});
sort_small_groups(offsets, 1024, r_indices);
return {offsets, r_indices};
}

View File

@ -1431,14 +1431,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
}
}
}
bvhtree_from_mesh_verts_ex(&treedata[tindex],
reinterpret_cast<const float(*)[3]>(positions_src.data()),
num_verts_src,
verts_active,
num_verts_active,
0.0,
2,
6);
bvhtree_from_mesh_verts_ex(
&treedata[tindex], positions_src, verts_active, num_verts_active, 0.0, 2, 6);
}
}
else {
@ -1463,10 +1457,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
}
}
bvhtree_from_mesh_looptri_ex(&treedata[tindex],
reinterpret_cast<const float(*)[3]>(positions_src.data()),
corner_verts_src.data(),
looptris_src.data(),
int(looptris_src.size()),
positions_src,
corner_verts_src,
looptris_src,
looptri_active,
num_looptri_active,
0.0,

View File

@ -25,7 +25,7 @@
#include "BKE_mesh.hh"
#include "BKE_mesh_mapping.hh"
#include "BKE_mesh_runtime.hh"
#include "BKE_shrinkwrap.h"
#include "BKE_shrinkwrap.hh"
#include "BKE_subdiv_ccg.hh"
using blender::float3;

View File

@ -324,19 +324,26 @@ void looptris_calc_with_normals(const Span<float3> vert_positions,
/** \} */
} // namespace blender::bke::mesh
void BKE_mesh_recalc_looptri(const int *corner_verts,
const int *face_offsets,
const float (*vert_positions)[3],
int totvert,
int totloop,
int faces_num,
MLoopTri *mlooptri)
int3 looptri_get_real_edges(const Span<int2> edges,
const Span<int> corner_verts,
const Span<int> corner_edges,
const MLoopTri &tri)
{
blender::bke::mesh::looptris_calc(
{reinterpret_cast<const blender::float3 *>(vert_positions), totvert},
blender::Span(face_offsets, faces_num + 1),
{corner_verts, totloop},
{mlooptri, poly_to_tri_count(faces_num, totloop)});
int3 real_edges;
for (int i = 2, i_next = 0; i_next < 3; i = i_next++) {
const int corner_1 = int(tri.tri[i]);
const int corner_2 = int(tri.tri[i_next]);
const int vert_1 = corner_verts[corner_1];
const int vert_2 = corner_verts[corner_2];
const int edge_i = corner_edges[corner_1];
const int2 edge = edges[edge_i];
const bool is_real = (vert_1 == edge[0] && vert_2 == edge[1]) ||
(vert_1 == edge[1] && vert_2 == edge[0]);
real_edges[i] = is_real ? edge_i : -1;
}
return real_edges;
}
} // namespace blender::bke::mesh

View File

@ -1427,10 +1427,10 @@ static ImBuf *put_stabilized_frame_to_cache(MovieClip *clip,
ImBuf *BKE_movieclip_get_stable_ibuf(MovieClip *clip,
const MovieClipUser *user,
float loc[2],
float *scale,
float *angle,
const int postprocess_flag)
const int postprocess_flag,
float r_loc[2],
float *r_scale,
float *r_angle)
{
ImBuf *ibuf, *stableibuf = nullptr;
int framenr = user->framenr;
@ -1450,29 +1450,29 @@ ImBuf *BKE_movieclip_get_stable_ibuf(MovieClip *clip,
stableibuf = put_stabilized_frame_to_cache(clip, user, ibuf, framenr, postprocess_flag);
}
if (loc) {
copy_v2_v2(loc, cache->stabilized.loc);
if (r_loc) {
copy_v2_v2(r_loc, cache->stabilized.loc);
}
if (scale) {
*scale = cache->stabilized.scale;
if (r_scale) {
*r_scale = cache->stabilized.scale;
}
if (angle) {
*angle = cache->stabilized.angle;
if (r_angle) {
*r_angle = cache->stabilized.angle;
}
}
else {
if (loc) {
zero_v2(loc);
if (r_loc) {
zero_v2(r_loc);
}
if (scale) {
*scale = 1.0f;
if (r_scale) {
*r_scale = 1.0f;
}
if (angle) {
*angle = 0.0f;
if (r_angle) {
*r_angle = 0.0f;
}
stableibuf = ibuf;
@ -1498,22 +1498,25 @@ bool BKE_movieclip_has_frame(MovieClip *clip, const MovieClipUser *user)
return false;
}
void BKE_movieclip_get_size(MovieClip *clip, const MovieClipUser *user, int *width, int *height)
void BKE_movieclip_get_size(MovieClip *clip,
const MovieClipUser *user,
int *r_width,
int *r_height)
{
/* TODO(sergey): Support reading sequences of different resolution. */
if (clip->lastsize[0] != 0 && clip->lastsize[1] != 0) {
*width = clip->lastsize[0];
*height = clip->lastsize[1];
*r_width = clip->lastsize[0];
*r_height = clip->lastsize[1];
}
else {
ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
if (ibuf && ibuf->x && ibuf->y) {
real_ibuf_size(clip, user, ibuf, width, height);
real_ibuf_size(clip, user, ibuf, r_width, r_height);
}
else {
*width = clip->lastsize[0];
*height = clip->lastsize[1];
*r_width = clip->lastsize[0];
*r_height = clip->lastsize[1];
}
if (ibuf) {
@ -1521,13 +1524,13 @@ void BKE_movieclip_get_size(MovieClip *clip, const MovieClipUser *user, int *wid
}
}
}
void BKE_movieclip_get_size_fl(MovieClip *clip, const MovieClipUser *user, float size[2])
void BKE_movieclip_get_size_fl(MovieClip *clip, const MovieClipUser *user, float r_size[2])
{
int width, height;
BKE_movieclip_get_size(clip, user, &width, &height);
size[0] = float(width);
size[1] = float(height);
r_size[0] = float(width);
r_size[1] = float(height);
}
int BKE_movieclip_get_duration(MovieClip *clip)
@ -1550,7 +1553,7 @@ float BKE_movieclip_get_fps(MovieClip *clip)
}
short frs_sec;
float frs_sec_base;
if (IMB_anim_get_fps(clip->anim, &frs_sec, &frs_sec_base, true)) {
if (IMB_anim_get_fps(clip->anim, true, &frs_sec, &frs_sec_base)) {
return float(frs_sec) / frs_sec_base;
}
return 0.0f;

View File

@ -246,8 +246,8 @@ Mesh *BKE_multires_create_mesh(Depsgraph *depsgraph, Object *object, MultiresMod
return result;
}
float (*BKE_multires_create_deformed_base_mesh_vert_coords(
Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd, int *r_num_deformed_verts))[3]
blender::Array<blender::float3> BKE_multires_create_deformed_base_mesh_vert_coords(
Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd)
{
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
@ -272,34 +272,22 @@ float (*BKE_multires_create_deformed_base_mesh_vert_coords(
Mesh *base_mesh = static_cast<Mesh *>(object->data);
int num_deformed_verts;
float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(base_mesh, &num_deformed_verts);
blender::Array<blender::float3> deformed_verts(base_mesh->vert_positions());
for (ModifierData *md = first_md; md != nullptr; md = md->next) {
const ModifierTypeInfo *mti = BKE_modifier_get_info(ModifierType(md->type));
if (md == &mmd->modifier) {
break;
}
if (!BKE_modifier_is_enabled(scene_eval, md, required_mode)) {
continue;
}
if (mti->type != ModifierTypeType::OnlyDeform) {
break;
}
BKE_modifier_deform_verts(
md,
&mesh_eval_context,
base_mesh,
{reinterpret_cast<blender::float3 *>(deformed_verts), num_deformed_verts});
BKE_modifier_deform_verts(md, &mesh_eval_context, base_mesh, deformed_verts);
}
if (r_num_deformed_verts != nullptr) {
*r_num_deformed_verts = num_deformed_verts;
}
return deformed_verts;
}
@ -1228,12 +1216,11 @@ void multires_stitch_grids(Object *ob)
/* NOTE: Currently CCG does not keep track of faces, making it impossible
* to use BKE_pbvh_get_grid_updates().
*/
CCGFace **faces;
int num_faces;
BKE_pbvh_get_grid_updates(pbvh, false, (void ***)&faces, &num_faces);
if (num_faces) {
BKE_subdiv_ccg_average_stitch_faces(subdiv_ccg, faces, num_faces);
MEM_freeN(faces);
blender::IndexMaskMemory memory;
blender::Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(pbvh, {});
const blender::IndexMask mask = BKE_pbvh_get_grid_updates(pbvh, nodes, memory);
if (!mask.is_empty()) {
BKE_subdiv_ccg_average_stitch_faces(*subdiv_ccg, mask);
}
}

View File

@ -89,6 +89,7 @@ bool multiresModifier_reshapeFromDeformModifier(Depsgraph *depsgraph,
MultiresModifierData *mmd,
ModifierData *deform_md)
{
using namespace blender;
MultiresModifierData highest_mmd = blender::dna::shallow_copy(*mmd);
highest_mmd.sculptlvl = highest_mmd.totlvl;
highest_mmd.lvl = highest_mmd.totlvl;
@ -97,8 +98,7 @@ bool multiresModifier_reshapeFromDeformModifier(Depsgraph *depsgraph,
/* Create mesh for the multires, ignoring any further modifiers (leading
* deformation modifiers will be applied though). */
Mesh *multires_mesh = BKE_multires_create_mesh(depsgraph, object, &highest_mmd);
int num_deformed_verts;
float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(multires_mesh, &num_deformed_verts);
Array<float3> deformed_verts(multires_mesh->vert_positions());
/* Apply deformation modifier on the multires, */
ModifierEvalContext modifier_ctx{};
@ -106,19 +106,16 @@ bool multiresModifier_reshapeFromDeformModifier(Depsgraph *depsgraph,
modifier_ctx.object = object;
modifier_ctx.flag = MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY;
BKE_modifier_deform_verts(
deform_md,
&modifier_ctx,
multires_mesh,
{reinterpret_cast<blender::float3 *>(deformed_verts), num_deformed_verts});
BKE_modifier_deform_verts(deform_md, &modifier_ctx, multires_mesh, deformed_verts);
BKE_id_free(nullptr, multires_mesh);
/* Reshaping */
bool result = multiresModifier_reshapeFromVertcos(
depsgraph, object, &highest_mmd, deformed_verts, num_deformed_verts);
/* Cleanup */
MEM_freeN(deformed_verts);
depsgraph,
object,
&highest_mmd,
reinterpret_cast<float(*)[3]>(deformed_verts.data()),
deformed_verts.size());
return result;
}

View File

@ -159,11 +159,10 @@ void multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext *resh
BLI_assert(object != nullptr);
BLI_assert(mmd != nullptr);
float(*deformed_verts)[3] = BKE_multires_create_deformed_base_mesh_vert_coords(
depsgraph, object, mmd, nullptr);
blender::Array<blender::float3> deformed_verts =
BKE_multires_create_deformed_base_mesh_vert_coords(depsgraph, object, mmd);
BKE_subdiv_eval_refine_from_mesh(
reshape_context->subdiv, reshape_context->base_mesh, deformed_verts);
MEM_freeN(deformed_verts);
BKE_subdiv_eval_refine_from_mesh(reshape_context->subdiv,
reshape_context->base_mesh,
reinterpret_cast<float(*)[3]>(deformed_verts.data()));
}

View File

@ -19,12 +19,12 @@ bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext
SubdivCCG *subdiv_ccg)
{
CCGKey reshape_level_key;
BKE_subdiv_ccg_key(&reshape_level_key, subdiv_ccg, reshape_context->reshape.level);
BKE_subdiv_ccg_key(reshape_level_key, *subdiv_ccg, reshape_context->reshape.level);
const int reshape_grid_size = reshape_context->reshape.grid_size;
const float reshape_grid_size_1_inv = 1.0f / (float(reshape_grid_size) - 1.0f);
int num_grids = subdiv_ccg->num_grids;
int num_grids = subdiv_ccg->grids.size();
for (int grid_index = 0; grid_index < num_grids; ++grid_index) {
CCGElem *ccg_grid = subdiv_ccg->grids[grid_index];
for (int y = 0; y < reshape_grid_size; ++y) {
@ -46,7 +46,7 @@ bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext
sizeof(float[3]));
/* NOTE: The sculpt mode might have SubdivCCG's data out of sync from what is stored in
* the original object. This happens upon the following scenario:
* the original object. This happens in the following scenario:
*
* - User enters sculpt mode of the default cube object.
* - Sculpt mode creates new `layer`
@ -61,9 +61,9 @@ bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext
* for example, that if the undo system says object does not have paint mask layer, it is
* not to be updated.
*
* This is a fragile logic, and is only working correctly because the code path is only
* This is fragile logic, and is only working correctly because the code path is only
* used by sculpt changes. In other use cases the code might not catch inconsistency and
* silently do wrong decision. */
* silently make the wrong decision. */
/* NOTE: There is a known bug in Undo code that results in first Sculpt step
* after a Memfile one to never be undone (see #83806). This might be the root cause of
* this inconsistency. */

View File

@ -129,7 +129,7 @@
#include "BKE_speaker.h"
#include "BKE_subdiv_ccg.hh"
#include "BKE_subsurf.hh"
#include "BKE_vfont.h"
#include "BKE_vfont.hh"
#include "BKE_volume.hh"
#include "DEG_depsgraph.hh"

View File

@ -59,7 +59,7 @@
#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_type_conversions.hh"
#include "BKE_vfont.h"
#include "BKE_vfont.hh"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"

View File

@ -34,7 +34,7 @@
#include "BKE_packedFile.h"
#include "BKE_report.h"
#include "BKE_sound.h"
#include "BKE_vfont.h"
#include "BKE_vfont.hh"
#include "BKE_volume.hh"
#include "IMB_imbuf.h"

View File

@ -2150,24 +2150,24 @@ void BKE_sculpt_sync_face_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv_ccg)
".hide_poly", ATTR_DOMAIN_FACE, false);
if (hide_poly.is_single() && !hide_poly.get_internal_single()) {
/* Nothing is hidden, so we can just remove all visibility bitmaps. */
for (const int i : IndexRange(subdiv_ccg->num_grids)) {
BKE_subdiv_ccg_grid_hidden_free(subdiv_ccg, i);
for (const int i : subdiv_ccg->grid_hidden.index_range()) {
BKE_subdiv_ccg_grid_hidden_free(*subdiv_ccg, i);
}
return;
}
const VArraySpan<bool> hide_poly_span(hide_poly);
CCGKey key;
BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
BKE_subdiv_ccg_key_top_level(key, *subdiv_ccg);
for (int i = 0; i < mesh->totloop; i++) {
const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, i);
const int face_index = BKE_subdiv_ccg_grid_to_face_index(*subdiv_ccg, i);
const bool is_hidden = hide_poly_span[face_index];
/* Avoid creating and modifying the grid_hidden bitmap if the base mesh face is visible and
* there is not bitmap for the grid. This is because missing grid_hidden implies grid is fully
* visible. */
if (is_hidden) {
BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg, i);
BKE_subdiv_ccg_grid_hidden_ensure(*subdiv_ccg, i);
}
BLI_bitmap *gh = subdiv_ccg->grid_hidden[i];
@ -2209,7 +2209,7 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform)
static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg)
{
CCGKey key;
BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
BKE_subdiv_ccg_key_top_level(key, *subdiv_ccg);
PBVH *pbvh = BKE_pbvh_new(PBVH_GRIDS);
Mesh *base_mesh = BKE_mesh_from_object(ob);
@ -2217,7 +2217,6 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg)
BKE_pbvh_build_grids(pbvh,
subdiv_ccg->grids,
subdiv_ccg->num_grids,
&key,
subdiv_ccg->grid_to_face_map,
subdiv_ccg->grid_flag_mats,
@ -2304,7 +2303,7 @@ bool BKE_object_sculpt_use_dyntopo(const Object *object)
void BKE_sculpt_bvh_update_from_ccg(PBVH *pbvh, SubdivCCG *subdiv_ccg)
{
CCGKey key;
BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
BKE_subdiv_ccg_key_top_level(key, *subdiv_ccg);
BKE_pbvh_grids_update(pbvh,
subdiv_ccg->grids,

View File

@ -236,10 +236,10 @@ static int partition_indices_grids(blender::MutableSpan<int> prim_indices,
int i1 = lo, i2 = 0;
while (i1 < hi) {
int face_i = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, prim_scratch[i2]);
int face_i = BKE_subdiv_ccg_grid_to_face_index(*subdiv_ccg, prim_scratch[i2]);
bool side = prim_bbc[prim_scratch[i2]].bcentroid[axis] >= mid;
while (i1 < hi && BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, prim_scratch[i2]) == face_i) {
while (i1 < hi && BKE_subdiv_ccg_grid_to_face_index(*subdiv_ccg, prim_scratch[i2]) == face_i) {
prim_indices[side ? hi2-- : lo2++] = prim_scratch[i2];
i1++;
i2++;
@ -254,7 +254,7 @@ static int partition_indices_material(
PBVH *pbvh, const int *material_indices, const bool *sharp_faces, int lo, int hi)
{
const Span<int> looptri_faces = pbvh->looptri_faces;
const DMFlagMat *flagmats = pbvh->grid_flag_mats;
const Span<DMFlagMat> flagmats = pbvh->grid_flag_mats;
MutableSpan<int> indices = pbvh->prim_indices;
int i = lo, j = hi;
@ -374,7 +374,7 @@ static void update_vb(PBVH *pbvh, PBVHNode *node, const Span<BBC> prim_bbc, int
node->orig_vb = node->vb;
}
int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
int BKE_pbvh_count_grid_quads(const Span<const BLI_bitmap *> grid_hidden,
const int *grid_indices,
int totgrid,
int gridsize,
@ -661,7 +661,6 @@ static void pbvh_draw_args_init(const Mesh &mesh, PBVH *pbvh, PBVH_GPU_Args *arg
memset((void *)args, 0, sizeof(*args));
args->pbvh_type = pbvh->header.type;
args->mesh_grids_num = pbvh->totgrid;
args->node = node;
args->grid_hidden = pbvh->grid_hidden;
@ -707,7 +706,6 @@ static void pbvh_draw_args_init(const Mesh &mesh, PBVH *pbvh, PBVH_GPU_Args *arg
args->subdiv_ccg = pbvh->subdiv_ccg;
args->faces = pbvh->faces;
args->mesh_grids_num = pbvh->totgrid;
args->grids = pbvh->grids;
args->grid_flag_mats = pbvh->grid_flag_mats;
args->vert_normals = pbvh->vert_normals;
@ -900,12 +898,11 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh)
}
void BKE_pbvh_build_grids(PBVH *pbvh,
CCGElem **grids,
int totgrid,
const Span<CCGElem *> grids,
CCGKey *key,
blender::Span<int> grid_to_face_map,
DMFlagMat *flagmats,
BLI_bitmap **grid_hidden,
const Span<int> grid_to_face_map,
const Span<DMFlagMat> flagmats,
const Span<BLI_bitmap *> grid_hidden,
Mesh *me,
SubdivCCG *subdiv_ccg)
{
@ -915,7 +912,6 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
pbvh->grids = grids;
pbvh->grid_to_face_map = grid_to_face_map;
pbvh->grid_flag_mats = flagmats;
pbvh->totgrid = totgrid;
pbvh->gridkey = *key;
pbvh->grid_hidden = grid_hidden;
pbvh->subdiv_ccg = subdiv_ccg;
@ -946,11 +942,11 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
pbvh->mesh = me;
/* For each grid, store the AABB and the AABB centroid */
blender::Array<BBC> prim_bbc(totgrid);
blender::Array<BBC> prim_bbc(grids.size());
BB cb;
BB_reset(&cb);
cb = blender::threading::parallel_reduce(
blender::IndexRange(totgrid),
grids.index_range(),
1024,
cb,
[&](const blender::IndexRange range, const BB &init) {
@ -973,12 +969,12 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
return current;
});
if (totgrid) {
if (!grids.is_empty()) {
const int *material_indices = static_cast<const int *>(
CustomData_get_layer_named(&me->face_data, CD_PROP_INT32, "material_index"));
const bool *sharp_faces = (const bool *)CustomData_get_layer_named(
&me->face_data, CD_PROP_BOOL, "sharp_face");
pbvh_build(pbvh, material_indices, sharp_faces, &cb, prim_bbc, totgrid);
pbvh_build(pbvh, material_indices, sharp_faces, &cb, prim_bbc, grids.size());
#ifdef TEST_PBVH_FACE_SPLIT
test_face_boundaries(pbvh);
@ -1602,18 +1598,17 @@ static void pbvh_faces_node_visibility_update(PBVH *pbvh, PBVHNode *node)
static void pbvh_grids_node_visibility_update(PBVH *pbvh, PBVHNode *node)
{
CCGElem **grids;
BLI_bitmap **grid_hidden;
CCGElem *const *grids;
const int *grid_indices;
int totgrid, i;
BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, nullptr, nullptr, &grids);
grid_hidden = BKE_pbvh_grid_hidden(pbvh);
const Span<const BLI_bitmap *> grid_hidden = BKE_pbvh_get_grid_visibility(pbvh);
CCGKey key = *BKE_pbvh_get_grid_key(pbvh);
for (i = 0; i < totgrid; i++) {
int g = grid_indices[i], x, y;
BLI_bitmap *gh = grid_hidden[g];
const BLI_bitmap *gh = grid_hidden[g];
if (!gh) {
BKE_pbvh_node_fully_hidden_set(node, false);
@ -1712,53 +1707,24 @@ void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3])
copy_v3_v3(bb_max, bb.bmax);
}
void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int *r_totface)
blender::IndexMask BKE_pbvh_get_grid_updates(const PBVH *pbvh,
const Span<const PBVHNode *> nodes,
blender::IndexMaskMemory &memory)
{
if (pbvh->nodes.is_empty()) {
return;
}
GSet *face_set = BLI_gset_ptr_new(__func__);
PBVHNode *node;
PBVHIter iter;
pbvh_iter_begin(&iter, pbvh, {});
SubdivCCGFace *all_faces = pbvh->subdiv_ccg->faces;
while ((node = pbvh_iter_next(&iter, PBVH_Leaf))) {
if (node->flag & PBVH_UpdateNormals) {
using namespace blender;
/* Using a #VectorSet for index deduplication would also work, but the performance gets much
* worse with large selections since the loop would be single-threaded. A boolean array has an
* overhead regardless of selection size, but that is small. */
Array<bool> faces_to_update(pbvh->faces_num, false);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (const PBVHNode *node : nodes.slice(range)) {
for (const int grid : node->prim_indices) {
void *face = &all_faces[pbvh->grid_to_face_map[grid]];
BLI_gset_add(face_set, face);
}
if (clear) {
node->flag &= ~PBVH_UpdateNormals;
const int face = pbvh->grid_to_face_map[grid];
faces_to_update[face] = true;
}
}
}
pbvh_iter_end(&iter);
const int tot = BLI_gset_len(face_set);
if (tot == 0) {
*r_totface = 0;
*r_gridfaces = nullptr;
BLI_gset_free(face_set, nullptr);
return;
}
void **faces = static_cast<void **>(MEM_mallocN(sizeof(*faces) * tot, __func__));
GSetIterator gs_iter;
int i;
GSET_ITER_INDEX (gs_iter, face_set, i) {
faces[i] = BLI_gsetIterator_getKey(&gs_iter);
}
BLI_gset_free(face_set, nullptr);
*r_totface = tot;
*r_gridfaces = faces;
});
return IndexMask::from_bools(faces_to_update, memory);
}
/***************************** PBVH Access ***********************************/
@ -1784,7 +1750,7 @@ void BKE_pbvh_bounding_box(const PBVH *pbvh, float min[3], float max[3])
copy_v3_v3(max, bb->bmax);
}
BLI_bitmap **BKE_pbvh_grid_hidden(const PBVH *pbvh)
Span<const BLI_bitmap *> BKE_pbvh_get_grid_visibility(const PBVH *pbvh)
{
BLI_assert(pbvh->header.type == PBVH_GRIDS);
return pbvh->grid_hidden;
@ -1796,28 +1762,22 @@ const CCGKey *BKE_pbvh_get_grid_key(const PBVH *pbvh)
return &pbvh->gridkey;
}
CCGElem **BKE_pbvh_get_grids(const PBVH *pbvh)
Span<CCGElem *> BKE_pbvh_get_grids(const PBVH *pbvh)
{
BLI_assert(pbvh->header.type == PBVH_GRIDS);
return pbvh->grids;
}
BLI_bitmap **BKE_pbvh_get_grid_visibility(const PBVH *pbvh)
{
BLI_assert(pbvh->header.type == PBVH_GRIDS);
return pbvh->grid_hidden;
}
int BKE_pbvh_get_grid_num_verts(const PBVH *pbvh)
{
BLI_assert(pbvh->header.type == PBVH_GRIDS);
return pbvh->totgrid * pbvh->gridkey.grid_area;
return pbvh->grids.size() * pbvh->gridkey.grid_area;
}
int BKE_pbvh_get_grid_num_faces(const PBVH *pbvh)
{
BLI_assert(pbvh->header.type == PBVH_GRIDS);
return pbvh->totgrid * (pbvh->gridkey.grid_size - 1) * (pbvh->gridkey.grid_size - 1);
return pbvh->grids.size() * (pbvh->gridkey.grid_size - 1) * (pbvh->gridkey.grid_size - 1);
}
/***************************** Node Access ***********************************/
@ -1990,7 +1950,7 @@ blender::Vector<int> BKE_pbvh_node_calc_face_indices(const PBVH &pbvh, const PBV
const SubdivCCG &subdiv_ccg = *pbvh.subdiv_ccg;
int prev_face = -1;
for (const int prim : node.prim_indices) {
const int face = BKE_subdiv_ccg_grid_to_face_index(&subdiv_ccg, prim);
const int face = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, prim);
if (face != prev_face) {
faces.append(face);
prev_face = face;
@ -2063,7 +2023,7 @@ void BKE_pbvh_node_get_grids(PBVH *pbvh,
int *r_totgrid,
int *r_maxgrid,
int *r_gridsize,
CCGElem ***r_griddata)
CCGElem *const **r_griddata)
{
switch (pbvh->header.type) {
case PBVH_GRIDS:
@ -2074,13 +2034,13 @@ void BKE_pbvh_node_get_grids(PBVH *pbvh,
*r_totgrid = node->prim_indices.size();
}
if (r_maxgrid) {
*r_maxgrid = pbvh->totgrid;
*r_maxgrid = pbvh->grids.size();
}
if (r_gridsize) {
*r_gridsize = pbvh->gridkey.grid_size;
}
if (r_griddata) {
*r_griddata = pbvh->grids;
*r_griddata = pbvh->grids.data();
}
break;
case PBVH_FACES:
@ -2861,6 +2821,7 @@ bool BKE_pbvh_node_frustum_exclude_AABB(PBVHNode *node, PBVHFrustumPlanes *data)
void BKE_pbvh_update_normals(PBVH *pbvh, SubdivCCG *subdiv_ccg)
{
using namespace blender;
/* Update normals */
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(
pbvh, [&](PBVHNode &node) { return update_search(&node, PBVH_UpdateNormals); });
@ -2872,12 +2833,11 @@ void BKE_pbvh_update_normals(PBVH *pbvh, SubdivCCG *subdiv_ccg)
pbvh_faces_update_normals(pbvh, nodes, *pbvh->mesh);
}
else if (pbvh->header.type == PBVH_GRIDS) {
CCGFace **faces;
int num_faces;
BKE_pbvh_get_grid_updates(pbvh, true, (void ***)&faces, &num_faces);
if (num_faces > 0) {
BKE_subdiv_ccg_update_normals(subdiv_ccg, faces, num_faces);
MEM_freeN(faces);
IndexMaskMemory memory;
const IndexMask faces_to_update = BKE_pbvh_get_grid_updates(pbvh, nodes, memory);
BKE_subdiv_ccg_update_normals(*subdiv_ccg, faces_to_update);
for (PBVHNode *node : nodes) {
node->flag &= ~PBVH_UpdateNormals;
}
}
}
@ -2990,17 +2950,19 @@ void BKE_pbvh_draw_debug_cb(PBVH *pbvh,
}
void BKE_pbvh_grids_update(PBVH *pbvh,
CCGElem **grids,
blender::Span<int> grid_to_face_map,
DMFlagMat *flagmats,
BLI_bitmap **grid_hidden,
const blender::Span<CCGElem *> grids,
const blender::Span<int> grid_to_face_map,
const blender::Span<DMFlagMat> flagmats,
const blender::Span<BLI_bitmap *> grid_hidden,
CCGKey *key)
{
pbvh->gridkey = *key;
pbvh->grids = grids;
pbvh->grid_to_face_map = grid_to_face_map;
if (flagmats != pbvh->grid_flag_mats || pbvh->grid_hidden != grid_hidden) {
if (flagmats.data() != pbvh->grid_flag_mats.data() ||
pbvh->grid_hidden.data() != grid_hidden.data())
{
pbvh->grid_flag_mats = flagmats;
pbvh->grid_hidden = grid_hidden;
@ -3105,7 +3067,7 @@ void BKE_pbvh_node_color_buffer_free(PBVH *pbvh)
void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int mode)
{
CCGElem **grids;
CCGElem *const *grids;
const int *grid_indices;
int totgrid, gridsize, uniq_verts, totvert;
@ -3146,7 +3108,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
vi->gh = nullptr;
if (vi->grids && mode == PBVH_ITER_UNIQUE) {
vi->grid_hidden = pbvh->grid_hidden;
vi->grid_hidden = pbvh->grid_hidden.data();
}
vi->mask = 0.0f;

View File

@ -178,11 +178,10 @@ struct PBVH {
/* Grid Data */
CCGKey gridkey;
CCGElem **grids;
blender::Span<CCGElem *> grids;
blender::Span<int> grid_to_face_map;
const DMFlagMat *grid_flag_mats;
int totgrid;
BLI_bitmap **grid_hidden;
blender::Span<DMFlagMat> grid_flag_mats;
blender::Span<BLI_bitmap *> grid_hidden;
/* Used during BVH build and later to mark that a vertex needs to update
* (its normal must be recalculated). */

View File

@ -1876,7 +1876,7 @@ static int ptcache_old_elemsize(PTCacheID *pid)
return 0;
}
static void ptcache_find_frames_around(PTCacheID *pid, uint frame, int *fra1, int *fra2)
static void ptcache_find_frames_around(PTCacheID *pid, uint frame, int *r_fra1, int *r_fra2)
{
if (pid->cache->flag & PTCACHE_DISK_CACHE) {
int cfra1 = frame, cfra2 = frame + 1;
@ -1898,12 +1898,12 @@ static void ptcache_find_frames_around(PTCacheID *pid, uint frame, int *fra1, in
}
if (cfra1 && !cfra2) {
*fra1 = 0;
*fra2 = cfra1;
*r_fra1 = 0;
*r_fra2 = cfra1;
}
else {
*fra1 = cfra1;
*fra2 = cfra2;
*r_fra1 = cfra1;
*r_fra2 = cfra2;
}
}
else if (pid->cache->mem_cache.first) {
@ -1924,12 +1924,12 @@ static void ptcache_find_frames_around(PTCacheID *pid, uint frame, int *fra1, in
}
if (!pm2) {
*fra1 = 0;
*fra2 = pm->frame;
*r_fra1 = 0;
*r_fra2 = pm->frame;
}
else {
*fra1 = pm->frame;
*fra2 = pm2->frame;
*r_fra1 = pm->frame;
*r_fra2 = pm2->frame;
}
}
}

View File

@ -674,14 +674,14 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
const blender::Span<blender::float3> positions = mesh->vert_positions();
const blender::Span<MLoopTri> looptris = mesh->looptris();
const int *corner_verts = BKE_mesh_corner_verts(mesh);
const blender::Span<int> corner_verts = mesh->corner_verts();
if (!positions.is_empty() && !looptris.is_empty()) {
BKE_mesh_calc_volume(reinterpret_cast<const float(*)[3]>(positions.data()),
positions.size(),
looptris.data(),
looptris.size(),
corner_verts,
corner_verts.data(),
&volume,
nullptr);
const float volume_scale = mat4_to_volume_scale(ob->object_to_world);

View File

@ -88,7 +88,7 @@
#include "BKE_scene.h"
#include "BKE_screen.hh"
#include "BKE_sound.h"
#include "BKE_unit.h"
#include "BKE_unit.hh"
#include "BKE_workspace.h"
#include "BKE_world.h"

View File

@ -33,7 +33,7 @@
#include "BKE_lattice.hh"
#include "BKE_lib_id.h"
#include "BKE_modifier.hh"
#include "BKE_shrinkwrap.h"
#include "BKE_shrinkwrap.hh"
#include "BKE_deform.h"
#include "BKE_editmesh.hh"
@ -102,7 +102,7 @@ bool BKE_shrinkwrap_needs_normals(int shrinkType, int shrinkMode)
bool BKE_shrinkwrap_init_tree(
ShrinkwrapTreeData *data, Mesh *mesh, int shrinkType, int shrinkMode, bool force_normals)
{
memset(data, 0, sizeof(*data));
*data = {};
if (mesh == nullptr) {
return false;
@ -118,11 +118,11 @@ bool BKE_shrinkwrap_init_tree(
}
data->mesh = mesh;
data->face_offsets = mesh->face_offsets().data();
data->corner_edges = mesh->corner_edges().data();
data->vert_normals = reinterpret_cast<const float(*)[3]>(mesh->vert_normals().data());
data->faces = mesh->faces();
data->corner_edges = mesh->corner_edges();
data->vert_normals = mesh->vert_normals();
data->sharp_faces = static_cast<const bool *>(
CustomData_get_layer_named(&mesh->edge_data, CD_PROP_BOOL, "sharp_face"));
CustomData_get_layer_named(&mesh->face_data, CD_PROP_BOOL, "sharp_face"));
if (shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX) {
data->bvh = BKE_bvhtree_from_mesh_get(&data->treeData, mesh, BVHTREE_FROM_VERTS, 2);
@ -141,9 +141,9 @@ bool BKE_shrinkwrap_init_tree(
}
if (force_normals || BKE_shrinkwrap_needs_normals(shrinkType, shrinkMode)) {
data->face_normals = reinterpret_cast<const float(*)[3]>(mesh->face_normals().data());
data->face_normals = mesh->face_normals();
if (mesh->normals_domain() == blender::bke::MeshNormalDomain::Corner) {
data->clnors = reinterpret_cast<const float(*)[3]>(mesh->corner_normals().data());
data->corner_normals = mesh->corner_normals();
}
}
@ -246,9 +246,8 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
"ShrinkwrapBoundaryData::looptri_is_boundary");
for (const int64_t i : looptris.index_range()) {
int real_edges[3];
BKE_mesh_looptri_get_real_edges(
edges.data(), corner_verts.data(), corner_edges.data(), &looptris[i], real_edges);
const int3 real_edges = bke::mesh::looptri_get_real_edges(
edges, corner_verts, corner_edges, looptris[i]);
for (int j = 0; j < 3; j++) {
if (real_edges[j] >= 0 && edge_mode[real_edges[j]]) {
@ -947,7 +946,7 @@ static void target_project_edge(const ShrinkwrapTreeData *tree,
int eidx)
{
const BVHTreeFromMesh *data = &tree->treeData;
const blender::int2 &edge = reinterpret_cast<const blender::int2 *>(data->edge)[eidx];
const blender::int2 &edge = data->edges[eidx];
const float *vedge_co[2] = {data->vert_positions[edge[0]], data->vert_positions[edge[1]]};
#ifdef TRACE_TARGET_PROJECT
@ -1021,9 +1020,10 @@ static void mesh_looptri_target_project(void *userdata,
const float co[3],
BVHTreeNearest *nearest)
{
using namespace blender;
const ShrinkwrapTreeData *tree = (ShrinkwrapTreeData *)userdata;
const BVHTreeFromMesh *data = &tree->treeData;
const MLoopTri *lt = &data->looptri[index];
const MLoopTri *lt = &data->looptris[index];
const int tri_verts[3] = {data->corner_verts[lt->tri[0]],
data->corner_verts[lt->tri[1]],
data->corner_verts[lt->tri[2]]};
@ -1062,13 +1062,8 @@ static void mesh_looptri_target_project(void *userdata,
/* Boundary edges */
else if (tree->boundary && BLI_BITMAP_TEST(tree->boundary->looptri_has_boundary, index)) {
const BLI_bitmap *is_boundary = tree->boundary->edge_is_boundary;
int edges[3];
BKE_mesh_looptri_get_real_edges(reinterpret_cast<const blender::int2 *>(data->edge),
data->corner_verts,
tree->corner_edges,
lt,
edges);
const int3 edges = bke::mesh::looptri_get_real_edges(
data->edges, data->corner_verts, tree->corner_edges, *lt);
for (int i = 0; i < 3; i++) {
if (edges[i] >= 0 && BLI_BITMAP_TEST(is_boundary, edges[i])) {
@ -1190,8 +1185,7 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree,
float r_no[3])
{
const BVHTreeFromMesh *treeData = &tree->treeData;
const MLoopTri *tri = &treeData->looptri[looptri_idx];
const float(*vert_normals)[3] = tree->vert_normals;
const MLoopTri *tri = &treeData->looptris[looptri_idx];
const int face_i = tree->mesh->looptri_faces()[looptri_idx];
/* Interpolate smooth normals if enabled. */
@ -1202,16 +1196,16 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree,
float w[3], no[3][3], tmp_co[3];
/* Custom and auto smooth split normals. */
if (tree->clnors) {
copy_v3_v3(no[0], tree->clnors[tri->tri[0]]);
copy_v3_v3(no[1], tree->clnors[tri->tri[1]]);
copy_v3_v3(no[2], tree->clnors[tri->tri[2]]);
if (!tree->corner_normals.is_empty()) {
copy_v3_v3(no[0], tree->corner_normals[tri->tri[0]]);
copy_v3_v3(no[1], tree->corner_normals[tri->tri[1]]);
copy_v3_v3(no[2], tree->corner_normals[tri->tri[2]]);
}
/* Ordinary vertex normals. */
else {
copy_v3_v3(no[0], vert_normals[vert_indices[0]]);
copy_v3_v3(no[1], vert_normals[vert_indices[1]]);
copy_v3_v3(no[2], vert_normals[vert_indices[2]]);
copy_v3_v3(no[0], tree->vert_normals[vert_indices[0]]);
copy_v3_v3(no[1], tree->vert_normals[vert_indices[1]]);
copy_v3_v3(no[2], tree->vert_normals[vert_indices[2]]);
}
/* Barycentric weights from hit point. */
@ -1238,7 +1232,7 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree,
}
}
/* Use the face normal if flat. */
else if (tree->face_normals != nullptr) {
else if (!tree->face_normals.is_empty()) {
copy_v3_v3(r_no, tree->face_normals[face_i]);
}
/* Finally fallback to the looptri normal. */

View File

@ -56,7 +56,7 @@
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_layer.h"
#include "BKE_mesh.h"
#include "BKE_mesh.hh"
#include "BKE_modifier.hh"
#include "BKE_pointcache.h"
#include "BKE_scene.h"
@ -571,13 +571,10 @@ static void ccd_update_deflector_hash(Depsgraph *depsgraph,
static int count_mesh_quads(Mesh *me)
{
int result = 0;
const int *face_offsets = BKE_mesh_face_offsets(me);
if (face_offsets) {
for (int i = 0; i < me->faces_num; i++) {
const int poly_size = face_offsets[i + 1] - face_offsets[i];
if (poly_size == 4) {
result++;
}
const blender::OffsetIndices faces = me->faces();
for (const int i : faces.index_range()) {
if (faces[i].size() == 4) {
result++;
}
}
return result;
@ -593,8 +590,8 @@ static void add_mesh_quad_diag_springs(Object *ob)
nofquads = count_mesh_quads(me);
if (nofquads) {
const int *corner_verts = BKE_mesh_corner_verts(me);
const int *face_offsets = BKE_mesh_face_offsets(me);
const blender::OffsetIndices faces = me->faces();
const blender::Span<int> corner_verts = me->corner_verts();
BodySpring *bs;
/* resize spring-array to hold additional quad springs */
@ -605,14 +602,14 @@ static void add_mesh_quad_diag_springs(Object *ob)
bs = &ob->soft->bspring[ob->soft->totspring];
// bp = ob->soft->bpoint; /* UNUSED */
for (int a = 0; a < me->faces_num; a++) {
const int poly_size = face_offsets[a + 1] - face_offsets[a];
const int poly_size = faces[a].size();
if (poly_size == 4) {
bs->v1 = corner_verts[face_offsets[a] + 0];
bs->v2 = corner_verts[face_offsets[a] + 2];
bs->v1 = corner_verts[faces[a].start() + 0];
bs->v2 = corner_verts[faces[a].start() + 2];
bs->springtype = SB_STIFFQUAD;
bs++;
bs->v1 = corner_verts[face_offsets[a] + 1];
bs->v2 = corner_verts[face_offsets[a] + 3];
bs->v1 = corner_verts[faces[a].start() + 1];
bs->v2 = corner_verts[faces[a].start() + 3];
bs->springtype = SB_STIFFQUAD;
bs++;
}
@ -2651,7 +2648,7 @@ static void springs_from_mesh(Object *ob)
BodyPoint *bp;
int a;
float scale = 1.0f;
const float(*vert_positions)[3] = BKE_mesh_vert_positions(me);
const blender::Span<blender::float3> positions = me->vert_positions();
sb = ob->soft;
if (me && sb) {
@ -2662,7 +2659,7 @@ static void springs_from_mesh(Object *ob)
if (me->totvert) {
bp = ob->soft->bpoint;
for (a = 0; a < me->totvert; a++, bp++) {
copy_v3_v3(bp->origS, vert_positions[a]);
copy_v3_v3(bp->origS, positions[a]);
mul_m4_v3(ob->object_to_world, bp->origS);
}
}
@ -2772,25 +2769,19 @@ static void mesh_faces_to_scratch(Object *ob)
{
SoftBody *sb = ob->soft;
const Mesh *me = static_cast<const Mesh *>(ob->data);
MLoopTri *looptri, *lt;
MLoopTri *lt;
BodyFace *bodyface;
int a;
const float(*vert_positions)[3] = BKE_mesh_vert_positions(me);
const int *face_offsets = BKE_mesh_face_offsets(me);
const int *corner_verts = BKE_mesh_corner_verts(me);
const blender::Span<int> corner_verts = me->corner_verts();
/* Allocate and copy faces. */
sb->scratch->totface = poly_to_tri_count(me->faces_num, me->totloop);
looptri = lt = static_cast<MLoopTri *>(
MEM_mallocN(sizeof(*looptri) * sb->scratch->totface, __func__));
BKE_mesh_recalc_looptri(corner_verts,
face_offsets,
vert_positions,
me->totvert,
me->totloop,
me->faces_num,
looptri);
blender::Array<MLoopTri> looptri(me->totvert);
blender::bke::mesh::looptris_calc(
me->vert_positions(), me->faces(), me->corner_verts(), looptri);
lt = looptri.data();
bodyface = sb->scratch->bodyface = static_cast<BodyFace *>(
MEM_mallocN(sizeof(BodyFace) * sb->scratch->totface, "SB_body_Faces"));
@ -2803,8 +2794,6 @@ static void mesh_faces_to_scratch(Object *ob)
bodyface->ext_force[0] = bodyface->ext_force[1] = bodyface->ext_force[2] = 0.0f;
bodyface->flag = 0;
}
MEM_freeN(looptri);
}
static void reference_to_scratch(Object *ob)
{

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@
#include "DNA_scene_types.h"
#include "BKE_unit.h" /* own include */
#include "BKE_unit.hh" /* own include */
#ifdef WIN32
# include "BLI_winstuff.h"

View File

@ -44,8 +44,8 @@
#include "BKE_main.h"
#include "BKE_object_types.hh"
#include "BKE_packedFile.h"
#include "BKE_vfont.h"
#include "BKE_vfontdata.h"
#include "BKE_vfont.hh"
#include "BKE_vfontdata.hh"
#include "BLO_read_write.hh"

View File

@ -22,8 +22,8 @@
#include "BLI_string_utf8.h"
#include "BKE_curve.hh"
#include "BKE_vfont.h"
#include "BKE_vfontdata.h"
#include "BKE_vfont.hh"
#include "BKE_vfontdata.hh"
#include "DNA_packedFile_types.h"
#include "DNA_vfont_types.h"

View File

@ -92,7 +92,7 @@ static void context_free_avi(void *context_v);
#endif /* WITH_AVI */
#ifdef WITH_FFMPEG
# include "BKE_writeffmpeg.h"
# include "BKE_writeffmpeg.hh"
#endif
bMovieHandle *BKE_movie_handle_get(const char imtype)

View File

@ -36,12 +36,13 @@
# include "BKE_main.h"
# include "BKE_report.h"
# include "BKE_sound.h"
# include "BKE_writeffmpeg.h"
# include "BKE_writeffmpeg.hh"
# include "IMB_imbuf.h"
/* This needs to be included after BLI_math_base.h otherwise it will redefine some math defines
* like M_SQRT1_2 leading to warnings with MSVC */
extern "C" {
# include <libavcodec/avcodec.h>
# include <libavformat/avformat.h>
# include <libavutil/channel_layout.h>
@ -52,13 +53,14 @@
# include <libswscale/swscale.h>
# include "ffmpeg_compat.h"
}
struct StampData;
typedef struct FFMpegContext {
struct FFMpegContext {
int ffmpeg_type;
int ffmpeg_codec;
int ffmpeg_audio_codec;
AVCodecID ffmpeg_codec;
AVCodecID ffmpeg_audio_codec;
int ffmpeg_video_bitrate;
int ffmpeg_audio_bitrate;
int ffmpeg_gop_size;
@ -80,7 +82,7 @@ typedef struct FFMpegContext {
/* Image frame in Blender's own pixel format, may need conversion to the output pixel format. */
AVFrame *img_convert_frame;
struct SwsContext *img_convert_ctx;
SwsContext *img_convert_ctx;
uint8_t *audio_input_buffer;
uint8_t *audio_deinterleave_buffer;
@ -90,12 +92,12 @@ typedef struct FFMpegContext {
bool audio_deinterleave;
int audio_sample_size;
struct StampData *stamp_data;
StampData *stamp_data;
# ifdef WITH_AUDASPACE
AUD_Device *audio_mixdown_device;
# endif
} FFMpegContext;
};
# define FFMPEG_AUTOSPLIT_SIZE 2000000000
@ -133,7 +135,7 @@ static int request_float_audio_buffer(int codec_id)
static int write_audio_frame(FFMpegContext *context)
{
AVFrame *frame = NULL;
AVFrame *frame = nullptr;
AVCodecContext *c = context->audio_codec;
AUD_Device_read(
@ -181,10 +183,12 @@ static int write_audio_frame(FFMpegContext *context)
int success = 1;
char error_str[AV_ERROR_MAX_STRING_SIZE];
int ret = avcodec_send_frame(c, frame);
if (ret < 0) {
/* Can't send frame to encoder. This shouldn't happen. */
fprintf(stderr, "Can't send audio frame: %s\n", av_err2str(ret));
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
fprintf(stderr, "Can't send audio frame: %s\n", error_str);
success = -1;
}
@ -197,7 +201,8 @@ static int write_audio_frame(FFMpegContext *context)
break;
}
if (ret < 0) {
fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret));
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
fprintf(stderr, "Error encoding audio frame: %s\n", error_str);
success = -1;
}
@ -211,7 +216,8 @@ static int write_audio_frame(FFMpegContext *context)
int write_ret = av_interleaved_write_frame(context->outfile, pkt);
if (write_ret != 0) {
fprintf(stderr, "Error writing audio packet: %s\n", av_err2str(write_ret));
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
fprintf(stderr, "Error writing audio packet: %s\n", error_str);
success = -1;
break;
}
@ -225,7 +231,7 @@ static int write_audio_frame(FFMpegContext *context)
# endif /* #ifdef WITH_AUDASPACE */
/* Allocate a temporary frame */
static AVFrame *alloc_picture(int pix_fmt, int width, int height)
static AVFrame *alloc_picture(AVPixelFormat pix_fmt, int width, int height)
{
AVFrame *f;
uint8_t *buf;
@ -234,14 +240,14 @@ static AVFrame *alloc_picture(int pix_fmt, int width, int height)
/* allocate space for the struct */
f = av_frame_alloc();
if (!f) {
return NULL;
return nullptr;
}
size = av_image_get_buffer_size(pix_fmt, width, height, 1);
/* allocate the actual picture buffer */
buf = MEM_mallocN(size, "AVFrame buffer");
buf = static_cast<uint8_t *>(MEM_mallocN(size, "AVFrame buffer"));
if (!buf) {
free(f);
return NULL;
return nullptr;
}
av_image_fill_arrays(f->data, f->linesize, buf, pix_fmt, width, height, 1);
@ -258,62 +264,62 @@ static const char **get_file_extensions(int format)
{
switch (format) {
case FFMPEG_DV: {
static const char *rv[] = {".dv", NULL};
static const char *rv[] = {".dv", nullptr};
return rv;
}
case FFMPEG_MPEG1: {
static const char *rv[] = {".mpg", ".mpeg", NULL};
static const char *rv[] = {".mpg", ".mpeg", nullptr};
return rv;
}
case FFMPEG_MPEG2: {
static const char *rv[] = {".dvd", ".vob", ".mpg", ".mpeg", NULL};
static const char *rv[] = {".dvd", ".vob", ".mpg", ".mpeg", nullptr};
return rv;
}
case FFMPEG_MPEG4: {
static const char *rv[] = {".mp4", ".mpg", ".mpeg", NULL};
static const char *rv[] = {".mp4", ".mpg", ".mpeg", nullptr};
return rv;
}
case FFMPEG_AVI: {
static const char *rv[] = {".avi", NULL};
static const char *rv[] = {".avi", nullptr};
return rv;
}
case FFMPEG_MOV: {
static const char *rv[] = {".mov", NULL};
static const char *rv[] = {".mov", nullptr};
return rv;
}
case FFMPEG_H264: {
/* FIXME: avi for now... */
static const char *rv[] = {".avi", NULL};
static const char *rv[] = {".avi", nullptr};
return rv;
}
case FFMPEG_XVID: {
/* FIXME: avi for now... */
static const char *rv[] = {".avi", NULL};
static const char *rv[] = {".avi", nullptr};
return rv;
}
case FFMPEG_FLV: {
static const char *rv[] = {".flv", NULL};
static const char *rv[] = {".flv", nullptr};
return rv;
}
case FFMPEG_MKV: {
static const char *rv[] = {".mkv", NULL};
static const char *rv[] = {".mkv", nullptr};
return rv;
}
case FFMPEG_OGG: {
static const char *rv[] = {".ogv", ".ogg", NULL};
static const char *rv[] = {".ogv", ".ogg", nullptr};
return rv;
}
case FFMPEG_WEBM: {
static const char *rv[] = {".webm", NULL};
static const char *rv[] = {".webm", nullptr};
return rv;
}
case FFMPEG_AV1: {
static const char *rv[] = {".mp4", ".mkv", NULL};
static const char *rv[] = {".mp4", ".mkv", nullptr};
return rv;
}
default:
return NULL;
return nullptr;
}
}
@ -328,10 +334,12 @@ static int write_video_frame(FFMpegContext *context, AVFrame *frame, ReportList
frame->pts = context->video_time;
context->video_time++;
char error_str[AV_ERROR_MAX_STRING_SIZE];
ret = avcodec_send_frame(c, frame);
if (ret < 0) {
/* Can't send frame to encoder. This shouldn't happen. */
fprintf(stderr, "Can't send video frame: %s\n", av_err2str(ret));
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
fprintf(stderr, "Can't send video frame: %s\n", error_str);
success = -1;
}
@ -343,7 +351,8 @@ static int write_video_frame(FFMpegContext *context, AVFrame *frame, ReportList
break;
}
if (ret < 0) {
fprintf(stderr, "Error encoding frame: %s\n", av_err2str(ret));
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
fprintf(stderr, "Error encoding frame: %s\n", error_str);
break;
}
@ -361,7 +370,8 @@ static int write_video_frame(FFMpegContext *context, AVFrame *frame, ReportList
if (!success) {
BKE_report(reports, RPT_ERROR, "Error writing frame");
PRINT("Error writing frame: %s\n", av_err2str(ret));
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
PRINT("Error writing frame: %s\n", error_str);
}
av_packet_free(&packet);
@ -376,7 +386,7 @@ static AVFrame *generate_video_frame(FFMpegContext *context, const uint8_t *pixe
int height = codec->height;
AVFrame *rgb_frame;
if (context->img_convert_frame != NULL) {
if (context->img_convert_frame != nullptr) {
/* Pixel format conversion is needed. */
rgb_frame = context->img_convert_frame;
}
@ -412,7 +422,7 @@ static AVFrame *generate_video_frame(FFMpegContext *context, const uint8_t *pixe
}
/* Convert to the output pixel format, if it's different that Blender's internal one. */
if (context->img_convert_frame != NULL) {
if (context->img_convert_frame != nullptr) {
BLI_assert(context->img_convert_ctx != NULL);
sws_scale(context->img_convert_ctx,
(const uint8_t *const *)rgb_frame->data,
@ -438,14 +448,14 @@ static AVRational calc_time_base(uint den, double num, int codec_id)
/* Calculate the precision of the initial floating point number. */
if (num > 1.0) {
const uint num_integer_bits = log2_floor_u((uint)num);
const uint num_integer_bits = log2_floor_u(uint(num));
/* Formula for calculating the epsilon value: (power of two range) / (pow mantissa bits)
* For example, a float has 23 mantissa bits and the float value 3.5f as a pow2 range of
* (4-2=2):
* (2) / pow2(23) = floating point precision for 3.5f
*/
eps = (float)(1 << num_integer_bits) * FLT_EPSILON;
eps = float(1 << num_integer_bits) * FLT_EPSILON;
}
/* Calculate how many decimal shifts we can do until we run out of precision. */
@ -463,7 +473,7 @@ static AVRational calc_time_base(uint den, double num, int codec_id)
AVRational time_base;
time_base.den = den;
time_base.num = (int)num;
time_base.num = int(num);
return time_base;
}
@ -475,7 +485,7 @@ static const AVCodec *get_av1_encoder(
* tends to give the best compression quality while `libsvtav1` tends to be the fastest encoder.
* One of each will be picked based on the preset setting, and if a particular encoder is not
* available, then use the default returned by FFMpeg. */
const AVCodec *codec = NULL;
const AVCodec *codec = nullptr;
switch (context->ffmpeg_preset) {
case FFM_PRESET_BEST:
/* `libaom-av1` may produce better VMAF-scoring videos in several cases, but there are cases
@ -529,7 +539,7 @@ static const AVCodec *get_av1_encoder(
if (context->ffmpeg_crf >= 0) {
/* librav1e does not use `-crf`, but uses `-qp` in the range of 0-255.
* Calculates the roughly equivalent float, and truncates it to an integer. */
uint qp_value = ((float)context->ffmpeg_crf) * 255.0f / 51.0f;
uint qp_value = float(context->ffmpeg_crf) * 255.0f / 51.0f;
if (qp_value > 255) {
qp_value = 255;
}
@ -565,7 +575,7 @@ static const AVCodec *get_av1_encoder(
else if (STREQ(codec->name, "libaom-av1")) {
/* Speed up libaom-av1 encoding by enabling multi-threading and setting tiles. */
ffmpeg_dict_set_int(opts, "row-mt", 1);
const char *tiles_string = NULL;
const char *tiles_string = nullptr;
bool tiles_string_is_dynamic = false;
if (rd->threads > 0) {
/* See if threads is a square. */
@ -594,7 +604,7 @@ static const AVCodec *get_av1_encoder(
/* Ensure a default minimum. */
sqrt_p2 = 2;
}
int sqrt_p2_next = power_of_2_min_i((int)rd->threads / sqrt_p2);
int sqrt_p2_next = power_of_2_min_i(int(rd->threads) / sqrt_p2);
if (sqrt_p2_next < 1) {
sqrt_p2_next = 1;
}
@ -671,7 +681,7 @@ static const AVCodec *get_av1_encoder(
static AVStream *alloc_video_stream(FFMpegContext *context,
RenderData *rd,
int codec_id,
AVCodecID codec_id,
AVFormatContext *of,
int rectx,
int recty,
@ -680,13 +690,13 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
{
AVStream *st;
const AVCodec *codec;
AVDictionary *opts = NULL;
AVDictionary *opts = nullptr;
error[0] = '\0';
st = avformat_new_stream(of, NULL);
st = avformat_new_stream(of, nullptr);
if (!st) {
return NULL;
return nullptr;
}
st->id = 0;
@ -702,8 +712,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
}
if (!codec) {
fprintf(stderr, "Couldn't find valid video codec\n");
context->video_codec = NULL;
return NULL;
context->video_codec = nullptr;
return nullptr;
}
context->video_codec = avcodec_alloc_context3(codec);
@ -719,9 +729,9 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
c->time_base.den = 2997;
c->time_base.num = 100;
}
else if ((float)((int)rd->frs_sec_base) == rd->frs_sec_base) {
else if (float(int(rd->frs_sec_base)) == rd->frs_sec_base) {
c->time_base.den = rd->frs_sec;
c->time_base.num = (int)rd->frs_sec_base;
c->time_base.num = int(rd->frs_sec_base);
}
else {
c->time_base = calc_time_base(rd->frs_sec, rd->frs_sec_base, codec_id);
@ -769,8 +779,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
/* 'preset' is used by h.264, 'deadline' is used by webm/vp9. I'm not
* setting those properties conditionally based on the video codec,
* as the FFmpeg encoder simply ignores unknown settings anyway. */
char const *preset_name = NULL; /* used by h.264 */
char const *deadline_name = NULL; /* used by webm/vp9 */
char const *preset_name = nullptr; /* used by h.264 */
char const *deadline_name = nullptr; /* used by webm/vp9 */
switch (context->ffmpeg_preset) {
case FFM_PRESET_GOOD:
preset_name = "medium";
@ -792,7 +802,7 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
if (preset_name != NULL && codec_id != AV_CODEC_ID_AV1) {
av_dict_set(&opts, "preset", preset_name, 0);
}
if (deadline_name != NULL) {
if (deadline_name != nullptr) {
av_dict_set(&opts, "deadline", deadline_name, 0);
}
}
@ -861,7 +871,7 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
/* xasp & yasp got float lately... */
st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q(((double)rd->xasp / (double)rd->yasp),
st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q((double(rd->xasp) / double(rd->yasp)),
255);
st->avg_frame_rate = av_inv_q(c->time_base);
@ -882,12 +892,14 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
int ret = avcodec_open2(c, codec, &opts);
if (ret < 0) {
fprintf(stderr, "Couldn't initialize video codec: %s\n", av_err2str(ret));
char error_str[AV_ERROR_MAX_STRING_SIZE];
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
fprintf(stderr, "Couldn't initialize video codec: %s\n", error_str);
BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
av_dict_free(&opts);
avcodec_free_context(&c);
context->video_codec = NULL;
return NULL;
context->video_codec = nullptr;
return nullptr;
}
av_dict_free(&opts);
@ -896,8 +908,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
if (c->pix_fmt == AV_PIX_FMT_RGBA) {
/* Output pixel format is the same we use internally, no conversion necessary. */
context->img_convert_frame = NULL;
context->img_convert_ctx = NULL;
context->img_convert_frame = nullptr;
context->img_convert_ctx = nullptr;
}
else {
/* Output pixel format is different, allocate frame for conversion. */
@ -909,9 +921,9 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
c->height,
c->pix_fmt,
SWS_BICUBIC,
NULL,
NULL,
NULL);
nullptr,
nullptr,
nullptr);
}
avcodec_parameters_from_context(st->codecpar, c);
@ -923,7 +935,7 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
static AVStream *alloc_audio_stream(FFMpegContext *context,
RenderData *rd,
int codec_id,
AVCodecID codec_id,
AVFormatContext *of,
char *error,
int error_size)
@ -933,17 +945,17 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
error[0] = '\0';
st = avformat_new_stream(of, NULL);
st = avformat_new_stream(of, nullptr);
if (!st) {
return NULL;
return nullptr;
}
st->id = 1;
codec = avcodec_find_encoder(codec_id);
if (!codec) {
fprintf(stderr, "Couldn't find valid audio codec\n");
context->audio_codec = NULL;
return NULL;
context->audio_codec = nullptr;
return nullptr;
}
context->audio_codec = avcodec_alloc_context3(codec);
@ -1026,14 +1038,16 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
int ret = avcodec_open2(c, codec, NULL);
int ret = avcodec_open2(c, codec, nullptr);
if (ret < 0) {
fprintf(stderr, "Couldn't initialize audio codec: %s\n", av_err2str(ret));
char error_str[AV_ERROR_MAX_STRING_SIZE];
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
fprintf(stderr, "Couldn't initialize audio codec: %s\n", error_str);
BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
avcodec_free_context(&c);
context->audio_codec = NULL;
return NULL;
context->audio_codec = nullptr;
return nullptr;
}
/* Need to prevent floating point exception when using VORBIS audio codec,
@ -1083,7 +1097,7 @@ static void ffmpeg_dict_set_int(AVDictionary **dict, const char *key, int value)
static void ffmpeg_add_metadata_callback(void *data,
const char *propname,
char *propvalue,
int UNUSED(propvalue_maxncpy))
int /*propvalue_maxncpy*/)
{
AVDictionary **metadata = (AVDictionary **)data;
av_dict_set(metadata, propname, propvalue, 0);
@ -1101,10 +1115,11 @@ static int start_ffmpeg_impl(FFMpegContext *context,
const AVOutputFormat *fmt;
char filepath[FILE_MAX], error[1024];
const char **exts;
int ret = 0;
context->ffmpeg_type = rd->ffcodecdata.type;
context->ffmpeg_codec = rd->ffcodecdata.codec;
context->ffmpeg_audio_codec = rd->ffcodecdata.audio_codec;
context->ffmpeg_codec = AVCodecID(rd->ffcodecdata.codec);
context->ffmpeg_audio_codec = AVCodecID(rd->ffcodecdata.audio_codec);
context->ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate;
context->ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate;
context->ffmpeg_gop_size = rd->ffcodecdata.gop_size;
@ -1142,7 +1157,7 @@ static int start_ffmpeg_impl(FFMpegContext *context,
return 0;
}
fmt = av_guess_format(NULL, exts[0], NULL);
fmt = av_guess_format(NULL, exts[0], nullptr);
if (!fmt) {
BKE_report(reports, RPT_ERROR, "No valid formats found");
return 0;
@ -1265,17 +1280,19 @@ static int start_ffmpeg_impl(FFMpegContext *context,
}
}
if (context->stamp_data != NULL) {
if (context->stamp_data != nullptr) {
BKE_stamp_info_callback(
&of->metadata, context->stamp_data, ffmpeg_add_metadata_callback, false);
}
int ret = avformat_write_header(of, NULL);
ret = avformat_write_header(of, nullptr);
if (ret < 0) {
BKE_report(reports,
RPT_ERROR,
"Could not initialize streams, probably unsupported codec combination");
PRINT("Could not write media header: %s\n", av_err2str(ret));
char error_str[AV_ERROR_MAX_STRING_SIZE];
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
PRINT("Could not write media header: %s\n", error_str);
goto fail;
}
@ -1290,11 +1307,11 @@ fail:
}
if (context->video_stream) {
context->video_stream = NULL;
context->video_stream = nullptr;
}
if (context->audio_stream) {
context->audio_stream = NULL;
context->audio_stream = nullptr;
}
avformat_free_context(of);
@ -1320,9 +1337,10 @@ fail:
*/
static void flush_ffmpeg(AVCodecContext *c, AVStream *stream, AVFormatContext *outfile)
{
char error_str[AV_ERROR_MAX_STRING_SIZE];
AVPacket *packet = av_packet_alloc();
avcodec_send_frame(c, NULL);
avcodec_send_frame(c, nullptr);
/* Get the packets frames. */
int ret = 1;
@ -1334,7 +1352,8 @@ static void flush_ffmpeg(AVCodecContext *c, AVStream *stream, AVFormatContext *o
break;
}
if (ret < 0) {
fprintf(stderr, "Error encoding delayed frame: %s\n", av_err2str(ret));
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
fprintf(stderr, "Error encoding delayed frame: %s\n", error_str);
break;
}
@ -1346,7 +1365,8 @@ static void flush_ffmpeg(AVCodecContext *c, AVStream *stream, AVFormatContext *o
int write_ret = av_interleaved_write_frame(outfile, packet);
if (write_ret != 0) {
fprintf(stderr, "Error writing delayed frame: %s\n", av_err2str(write_ret));
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
fprintf(stderr, "Error writing delayed frame: %s\n", error_str);
break;
}
}
@ -1405,7 +1425,7 @@ static void ffmpeg_filepath_get(FFMpegContext *context,
fe++;
}
if (*fe == NULL) {
if (*fe == nullptr) {
BLI_strncat(filepath, autosplit, FILE_MAX);
BLI_path_frame_range(filepath, FILE_MAX, sfra, efra, 4);
@ -1433,7 +1453,7 @@ void BKE_ffmpeg_filepath_get(char filepath[/*FILE_MAX*/ 1024],
bool preview,
const char *suffix)
{
ffmpeg_filepath_get(NULL, filepath, rd, preview, suffix);
ffmpeg_filepath_get(nullptr, filepath, rd, preview, suffix);
}
int BKE_ffmpeg_start(void *context_v,
@ -1446,7 +1466,7 @@ int BKE_ffmpeg_start(void *context_v,
const char *suffix)
{
int success;
FFMpegContext *context = context_v;
FFMpegContext *context = static_cast<FFMpegContext *>(context_v);
context->ffmpeg_autosplit_count = 0;
context->ffmpeg_preview = preview;
@ -1459,9 +1479,9 @@ int BKE_ffmpeg_start(void *context_v,
AUD_DeviceSpecs specs;
# ifdef FFMPEG_USE_OLD_CHANNEL_VARS
specs.channels = c->channels;
specs.channels = AUD_Channels(c->channels);
# else
specs.channels = c->ch_layout.nb_channels;
specs.channels = AUD_Channels(c->ch_layout.nb_channels);
# endif
switch (av_get_packed_sample_fmt(c->sample_fmt)) {
@ -1503,8 +1523,8 @@ static void write_audio_frames(FFMpegContext *context, double to_pts)
if ((context->audio_time_total >= to_pts) || !write_audio_frame(context)) {
break;
}
context->audio_time_total += (double)context->audio_input_samples / (double)c->sample_rate;
context->audio_time += (double)context->audio_input_samples / (double)c->sample_rate;
context->audio_time_total += double(context->audio_input_samples) / double(c->sample_rate);
context->audio_time += double(context->audio_input_samples) / double(c->sample_rate);
}
}
# endif
@ -1519,7 +1539,7 @@ int BKE_ffmpeg_append(void *context_v,
const char *suffix,
ReportList *reports)
{
FFMpegContext *context = context_v;
FFMpegContext *context = static_cast<FFMpegContext *>(context_v);
AVFrame *avframe;
int success = 1;
@ -1531,7 +1551,7 @@ int BKE_ffmpeg_append(void *context_v,
# ifdef WITH_AUDASPACE
/* Add +1 frame because we want to encode audio up until the next video frame. */
write_audio_frames(
context, (frame - start_frame + 1) / (((double)rd->frs_sec) / (double)rd->frs_sec_base));
context, (frame - start_frame + 1) / (double(rd->frs_sec) / double(rd->frs_sec_base)));
# else
UNUSED_VARS(start_frame);
# endif
@ -1557,7 +1577,7 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
if (is_autosplit == false) {
if (context->audio_mixdown_device) {
AUD_Device_free(context->audio_mixdown_device);
context->audio_mixdown_device = NULL;
context->audio_mixdown_device = nullptr;
}
}
# else
@ -1580,23 +1600,23 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
/* Close the video codec */
if (context->video_stream != NULL) {
if (context->video_stream != nullptr) {
PRINT("zero video stream %p\n", context->video_stream);
context->video_stream = NULL;
context->video_stream = nullptr;
}
if (context->audio_stream != NULL) {
context->audio_stream = NULL;
if (context->audio_stream != nullptr) {
context->audio_stream = nullptr;
}
/* free the temp buffer */
if (context->current_frame != NULL) {
if (context->current_frame != nullptr) {
delete_picture(context->current_frame);
context->current_frame = NULL;
context->current_frame = nullptr;
}
if (context->img_convert_frame != NULL) {
if (context->img_convert_frame != nullptr) {
delete_picture(context->img_convert_frame);
context->img_convert_frame = NULL;
context->img_convert_frame = nullptr;
}
if (context->outfile != NULL && context->outfile->oformat) {
@ -1605,38 +1625,38 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
}
}
if (context->video_codec != NULL) {
if (context->video_codec != nullptr) {
avcodec_free_context(&context->video_codec);
context->video_codec = NULL;
context->video_codec = nullptr;
}
if (context->audio_codec != NULL) {
if (context->audio_codec != nullptr) {
avcodec_free_context(&context->audio_codec);
context->audio_codec = NULL;
context->audio_codec = nullptr;
}
if (context->outfile != NULL) {
if (context->outfile != nullptr) {
avformat_free_context(context->outfile);
context->outfile = NULL;
context->outfile = nullptr;
}
if (context->audio_input_buffer != NULL) {
if (context->audio_input_buffer != nullptr) {
av_free(context->audio_input_buffer);
context->audio_input_buffer = NULL;
context->audio_input_buffer = nullptr;
}
if (context->audio_deinterleave_buffer != NULL) {
if (context->audio_deinterleave_buffer != nullptr) {
av_free(context->audio_deinterleave_buffer);
context->audio_deinterleave_buffer = NULL;
context->audio_deinterleave_buffer = nullptr;
}
if (context->img_convert_ctx != NULL) {
if (context->img_convert_ctx != nullptr) {
sws_freeContext(context->img_convert_ctx);
context->img_convert_ctx = NULL;
context->img_convert_ctx = nullptr;
}
}
void BKE_ffmpeg_end(void *context_v)
{
FFMpegContext *context = context_v;
FFMpegContext *context = static_cast<FFMpegContext *>(context_v);
end_ffmpeg_impl(context, false);
}
@ -1803,12 +1823,11 @@ bool BKE_ffmpeg_alpha_channel_is_supported(const RenderData *rd)
AV_CODEC_ID_HUFFYUV);
}
void *BKE_ffmpeg_context_create(void)
void *BKE_ffmpeg_context_create()
{
FFMpegContext *context;
/* new ffmpeg data struct */
context = MEM_callocN(sizeof(FFMpegContext), "new ffmpeg context");
FFMpegContext *context = static_cast<FFMpegContext *>(
MEM_callocN(sizeof(FFMpegContext), "new ffmpeg context"));
context->ffmpeg_codec = AV_CODEC_ID_MPEG4;
context->ffmpeg_audio_codec = AV_CODEC_ID_NONE;
@ -1818,7 +1837,7 @@ void *BKE_ffmpeg_context_create(void)
context->ffmpeg_autosplit = 0;
context->ffmpeg_autosplit_count = 0;
context->ffmpeg_preview = false;
context->stamp_data = NULL;
context->stamp_data = nullptr;
context->audio_time_total = 0.0;
return context;
@ -1826,8 +1845,8 @@ void *BKE_ffmpeg_context_create(void)
void BKE_ffmpeg_context_free(void *context_v)
{
FFMpegContext *context = context_v;
if (context == NULL) {
FFMpegContext *context = static_cast<FFMpegContext *>(context_v);
if (context == nullptr) {
return;
}
if (context->stamp_data) {

View File

@ -423,7 +423,7 @@ const IndexMask &get_static_index_mask_for_min_size(const int64_t min_size);
std::ostream &operator<<(std::ostream &stream, const IndexMask &mask);
/* -------------------------------------------------------------------- */
/** \name Inline Utilities
/** \name Utilities
* \{ */
inline const std::array<int16_t, max_segment_size> &get_static_indices_array()
@ -439,6 +439,13 @@ inline void masked_fill(MutableSpan<T> data, const T &value, const IndexMask &ma
mask.foreach_index_optimized<int64_t>([&](const int64_t i) { data[i] = value; });
}
/**
* Fill masked indices of \a r_mask with the index of that item in the mask such that
* `r_map[mask[i]] == i` for the whole mask. The size of `r_map` needs to be at least
* `mask.min_array_size()`.
*/
template<typename T> void build_reverse_map(const IndexMask &mask, MutableSpan<T> r_map);
/* -------------------------------------------------------------------- */
/** \name #RawMaskIterator Inline Methods
* \{ */

View File

@ -197,8 +197,10 @@ BVHTreeOverlap *BLI_bvhtree_overlap(const BVHTree *tree1,
unsigned int *r_overlap_num,
BVHTree_OverlapCallback callback,
void *userdata);
/** Compute overlaps of the tree with itself. This is faster than BLI_bvhtree_overlap
* because it only tests and returns each symmetrical pair once. */
/**
* Compute overlaps of the tree with itself. This is faster than #BLI_bvhtree_overlap
* because it only tests and returns each symmetrical pair once.
*/
BVHTreeOverlap *BLI_bvhtree_overlap_self(const BVHTree *tree,
unsigned int *r_overlap_num,
BVHTree_OverlapCallback callback,

View File

@ -1,85 +0,0 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bli
*/
#include "BLI_compiler_attrs.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uintptr_t key;
void *val;
} SmallHashEntry;
/**
* How much stack space to use before dynamically allocating memory.
* set to match one of the values in 'hashsizes' to avoid too many mallocs.
*/
#define SMSTACKSIZE 131
typedef struct SmallHash {
unsigned int nbuckets;
unsigned int nentries;
unsigned int cursize;
SmallHashEntry *buckets;
SmallHashEntry buckets_stack[SMSTACKSIZE];
} SmallHash;
typedef struct {
const SmallHash *sh;
unsigned int i;
} SmallHashIter;
void BLI_smallhash_init_ex(SmallHash *sh, unsigned int nentries_reserve) ATTR_NONNULL(1);
void BLI_smallhash_init(SmallHash *sh) ATTR_NONNULL(1);
/**
* \note does *not* free *sh itself! only the direct data!
*/
void BLI_smallhash_release(SmallHash *sh) ATTR_NONNULL(1);
void BLI_smallhash_insert(SmallHash *sh, uintptr_t key, void *item) ATTR_NONNULL(1);
/**
* Inserts a new value to a key that may already be in #GHash.
*
* Avoids #BLI_smallhash_remove, #BLI_smallhash_insert calls (double lookups)
*
* \returns true if a new key has been added.
*/
bool BLI_smallhash_reinsert(SmallHash *sh, uintptr_t key, void *item) ATTR_NONNULL(1);
bool BLI_smallhash_remove(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
void *BLI_smallhash_lookup(const SmallHash *sh, uintptr_t key)
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
void **BLI_smallhash_lookup_p(const SmallHash *sh, uintptr_t key)
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
bool BLI_smallhash_haskey(const SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
int BLI_smallhash_len(const SmallHash *sh) ATTR_NONNULL(1);
void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
void **BLI_smallhash_iternext_p(SmallHashIter *iter, uintptr_t *key)
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
void *BLI_smallhash_iternew(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
// void BLI_smallhash_print(SmallHash *sh); /* UNUSED. */
#ifdef DEBUG
/**
* Measure how well the hash function performs
* (1.0 is perfect - no stepping needed).
*
* Smaller is better!
*/
double BLI_smallhash_calc_quality(SmallHash *sh);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -1,67 +0,0 @@
/* SPDX-FileCopyrightText: 2012 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
struct ListBase;
/** \file
* \ingroup bli
*/
#ifdef __cplusplus
extern "C" {
#endif
typedef struct VoronoiSite {
float co[2];
float color[3];
} VoronoiSite;
typedef struct VoronoiEdge {
struct VoronoiEdge *next, *prev;
/* start and end points */
float start[2], end[2];
/* this fields are used during diagram computation only */
/* directional vector, from "start", points to "end", normal of |left, right| */
float direction[2];
/* point on Voronoi place on the left side of edge */
float left[2];
/* point on Voronoi place on the right side of edge */
float right[2];
/* Directional coefficients satisfying equation `y = f * x + g` (edge lies on this line). */
float f, g;
/* some edges consist of two parts,
* so we add the pointer to another part to connect them at the end of an algorithm */
struct VoronoiEdge *neighbor;
} VoronoiEdge;
typedef struct VoronoiTriangulationPoint {
float co[2];
float color[3];
int power;
} VoronoiTriangulationPoint;
void BLI_voronoi_compute(
const VoronoiSite *sites, int sites_total, int width, int height, struct ListBase *edges);
void BLI_voronoi_triangulate(const VoronoiSite *sites,
int sites_total,
struct ListBase *edges,
int width,
int height,
VoronoiTriangulationPoint **r_triangulated_points,
int *r_triangulated_points_total,
int (**r_triangles)[3],
int *r_triangles_total);
#ifdef __cplusplus
}
#endif

View File

@ -19,13 +19,7 @@ extern "C" {
/* All input coordinates must be in bounding box 0.0 - 1.0. */
float BLI_voxel_sample_nearest(const float *data, const int res[3], const float co[3]);
float BLI_voxel_sample_trilinear(const float *data, const int res[3], const float co[3]);
float BLI_voxel_sample_triquadratic(const float *data, const int res[3], const float co[3]);
float BLI_voxel_sample_tricubic(const float *data,
const int res[3],
const float co[3],
int bspline);
#ifdef __cplusplus
}

View File

@ -134,7 +134,6 @@ set(SRC
intern/serialize.cc
intern/session_uuid.c
intern/smaa_textures.c
intern/smallhash.c
intern/sort.c
intern/sort_utils.c
intern/stack.c
@ -160,7 +159,6 @@ set(SRC
intern/uvproject.c
intern/vector.cc
intern/virtual_array.cc
intern/voronoi_2d.c
intern/voxel.c
intern/winstuff.cc
intern/winstuff_dir.cc
@ -342,7 +340,6 @@ set(SRC
BLI_shared_cache.hh
BLI_simd.h
BLI_smaa_textures.h
BLI_smallhash.h
BLI_sort.h
BLI_sort.hh
BLI_sort_utils.h
@ -382,7 +379,6 @@ set(SRC
BLI_vector_set_slots.hh
BLI_virtual_array.hh
BLI_virtual_vector_array.hh
BLI_voronoi_2d.h
BLI_voxel.h
BLI_winstuff.h
BLI_winstuff_com.hh

View File

@ -35,16 +35,12 @@
/**
* Next prime after `2^n` (skipping 2 & 3).
*
* \note Also used by: `BLI_smallhash`.
*/
extern const uint BLI_ghash_hash_sizes[]; /* Quiet warning, this is only used by smallhash.c */
const uint BLI_ghash_hash_sizes[] = {
static const uint hashsizes[] = {
5, 11, 17, 37, 67, 131, 257, 521, 1031,
2053, 4099, 8209, 16411, 32771, 65537, 131101, 262147, 524309,
1048583, 2097169, 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459,
};
#define hashsizes BLI_ghash_hash_sizes
#ifdef GHASH_USE_MODULO_BUCKETS
# define GHASH_MAX_SIZE 27

View File

@ -20,6 +20,19 @@
namespace blender::index_mask {
template<typename T> void build_reverse_map(const IndexMask &mask, MutableSpan<T> r_map)
{
#ifdef DEBUG
/* Catch errors with asserts in debug builds. */
r_map.fill(-1);
#endif
BLI_assert(r_map.size() >= mask.min_array_size());
mask.foreach_index_optimized<T>(GrainSize(4096),
[&](const T src, const T dst) { r_map[src] = dst; });
}
template void build_reverse_map<int>(const IndexMask &mask, MutableSpan<int> r_map);
std::array<int16_t, max_segment_size> build_static_indices_array()
{
std::array<int16_t, max_segment_size> data;

View File

@ -2253,7 +2253,7 @@ static void propagate_windings_and_in_output_volume(PatchesInfo &pinfo,
}
/**
* Given an array of winding numbers, where the ith entry is a cell's winding
* Given an array of winding numbers, where the `i-th` entry is a cell's winding
* number with respect to input shape (mesh part) i, return true if the
* cell should be included in the output of the boolean operation.
* Intersection: all the winding numbers must be nonzero.

View File

@ -896,14 +896,14 @@ bool BLI_path_parent_dir_until_exists(char *dir)
/**
* Looks for a sequence of "#" characters in the last slash-separated component of `path`,
* returning the indexes of the first and one past the last character in the sequence in
* `char_start` and `char_end` respectively.
* `r_char_start` and `r_char_end` respectively.
*
* \param char_start: The first `#` character.
* \param char_end: The last `#` character +1.
* \param r_char_start: The first `#` character.
* \param r_char_end: The last `#` character +1.
*
* \return true if a frame sequence range was found.
*/
static bool path_frame_chars_find_range(const char *path, int *char_start, int *char_end)
static bool path_frame_chars_find_range(const char *path, int *r_char_start, int *r_char_end)
{
uint ch_sta, ch_end, i;
/* Insert current frame: `file###` -> `file001`. */
@ -925,13 +925,13 @@ static bool path_frame_chars_find_range(const char *path, int *char_start, int *
}
if (ch_end) {
*char_start = ch_sta;
*char_end = ch_end;
*r_char_start = ch_sta;
*r_char_end = ch_end;
return true;
}
*char_start = -1;
*char_end = -1;
*r_char_start = -1;
*r_char_end = -1;
return false;
}

View File

@ -1,399 +0,0 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bli
*
* A light stack-friendly hash library, it uses stack space for relatively small,
* fixed size hash tables but falls back to heap memory once the stack limits reached
* (#SMSTACKSIZE).
*
* based on a doubling hashing approach (non-chaining) which uses more buckets than entries
* stepping over buckets when two keys share the same hash so any key can find a free bucket.
*
* See: https://en.wikipedia.org/wiki/Double_hashing
*
* \warning This should _only_ be used for small hashes
* where allocating a hash every time is unacceptable.
* Otherwise #GHash should be used instead.
*
* #SmallHashEntry.key
* - `SMHASH_KEY_UNUSED` means the key in the cell has not been initialized.
*
* #SmallHashEntry.val
* - `SMHASH_CELL_UNUSED` means this cell is inside a key series.
* - `SMHASH_CELL_FREE` means this cell terminates a key series.
*
* Note that the values and keys are often pointers or index values,
* use the maximum values to avoid real pointers colliding with magic numbers.
*/
#include <stdlib.h>
#include <string.h>
#include "BLI_sys_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_smallhash.h"
#include "BLI_strict_flags.h"
#define SMHASH_KEY_UNUSED ((uintptr_t)(UINTPTR_MAX - 0))
#define SMHASH_CELL_FREE ((void *)(UINTPTR_MAX - 1))
#define SMHASH_CELL_UNUSED ((void *)(UINTPTR_MAX - 2))
/* typically this re-assigns 'h' */
#define SMHASH_NEXT(h, hoff) \
(CHECK_TYPE_INLINE(&(h), uint *), \
CHECK_TYPE_INLINE(&(hoff), uint *), \
((h) + (((hoff) = ((hoff)*2) + 1), (hoff))))
/* nothing uses BLI_smallhash_remove yet */
// #define USE_REMOVE
BLI_INLINE bool smallhash_val_is_used(const void *val)
{
#ifdef USE_REMOVE
return !ELEM(val, SMHASH_CELL_FREE, SMHASH_CELL_UNUSED);
#else
return (val != SMHASH_CELL_FREE);
#endif
}
extern const uint BLI_ghash_hash_sizes[];
#define hashsizes BLI_ghash_hash_sizes
BLI_INLINE uint smallhash_key(const uintptr_t key)
{
return (uint)key;
}
/**
* Check if the number of items in the smallhash is large enough to require more buckets.
*/
BLI_INLINE bool smallhash_test_expand_buckets(const uint nentries, const uint nbuckets)
{
/* (approx * 1.5) */
return (nentries + (nentries >> 1)) > nbuckets;
}
BLI_INLINE void smallhash_init_empty(SmallHash *sh)
{
uint i;
for (i = 0; i < sh->nbuckets; i++) {
sh->buckets[i].key = SMHASH_KEY_UNUSED;
sh->buckets[i].val = SMHASH_CELL_FREE;
}
}
/**
* Increase initial bucket size to match a reserved amount.
*/
BLI_INLINE void smallhash_buckets_reserve(SmallHash *sh, const uint nentries_reserve)
{
while (smallhash_test_expand_buckets(nentries_reserve, sh->nbuckets)) {
sh->nbuckets = hashsizes[++sh->cursize];
}
}
BLI_INLINE SmallHashEntry *smallhash_lookup(const SmallHash *sh, const uintptr_t key)
{
SmallHashEntry *e;
uint h = smallhash_key(key);
uint hoff = 1;
BLI_assert(key != SMHASH_KEY_UNUSED);
/* NOTE: there are always more buckets than entries,
* so we know there will always be a free bucket if the key isn't found. */
for (e = &sh->buckets[h % sh->nbuckets]; e->val != SMHASH_CELL_FREE;
h = SMHASH_NEXT(h, hoff), e = &sh->buckets[h % sh->nbuckets])
{
if (e->key == key) {
/* should never happen because unused keys are zero'd */
BLI_assert(e->val != SMHASH_CELL_UNUSED);
return e;
}
}
return NULL;
}
BLI_INLINE SmallHashEntry *smallhash_lookup_first_free(SmallHash *sh, const uintptr_t key)
{
SmallHashEntry *e;
uint h = smallhash_key(key);
uint hoff = 1;
for (e = &sh->buckets[h % sh->nbuckets]; smallhash_val_is_used(e->val);
h = SMHASH_NEXT(h, hoff), e = &sh->buckets[h % sh->nbuckets])
{
/* pass */
}
return e;
}
BLI_INLINE void smallhash_resize_buckets(SmallHash *sh, const uint nbuckets)
{
SmallHashEntry *buckets_old = sh->buckets;
const uint nbuckets_old = sh->nbuckets;
const bool was_alloc = (buckets_old != sh->buckets_stack);
uint i = 0;
BLI_assert(sh->nbuckets != nbuckets);
if (nbuckets <= SMSTACKSIZE) {
const size_t size = sizeof(*buckets_old) * nbuckets_old;
buckets_old = alloca(size);
memcpy(buckets_old, sh->buckets, size);
sh->buckets = sh->buckets_stack;
}
else {
sh->buckets = MEM_mallocN(sizeof(*sh->buckets) * nbuckets, __func__);
}
sh->nbuckets = nbuckets;
smallhash_init_empty(sh);
for (i = 0; i < nbuckets_old; i++) {
if (smallhash_val_is_used(buckets_old[i].val)) {
SmallHashEntry *e = smallhash_lookup_first_free(sh, buckets_old[i].key);
e->key = buckets_old[i].key;
e->val = buckets_old[i].val;
}
}
if (was_alloc) {
MEM_freeN(buckets_old);
}
}
void BLI_smallhash_init_ex(SmallHash *sh, const uint nentries_reserve)
{
/* assume 'sh' is uninitialized */
sh->nentries = 0;
sh->cursize = 2;
sh->nbuckets = hashsizes[sh->cursize];
sh->buckets = sh->buckets_stack;
if (nentries_reserve) {
smallhash_buckets_reserve(sh, nentries_reserve);
if (sh->nbuckets > SMSTACKSIZE) {
sh->buckets = MEM_mallocN(sizeof(*sh->buckets) * sh->nbuckets, __func__);
}
}
smallhash_init_empty(sh);
}
void BLI_smallhash_init(SmallHash *sh)
{
BLI_smallhash_init_ex(sh, 0);
}
void BLI_smallhash_release(SmallHash *sh)
{
if (sh->buckets != sh->buckets_stack) {
MEM_freeN(sh->buckets);
}
}
void BLI_smallhash_insert(SmallHash *sh, uintptr_t key, void *item)
{
SmallHashEntry *e;
BLI_assert(key != SMHASH_KEY_UNUSED);
BLI_assert(smallhash_val_is_used(item));
BLI_assert(BLI_smallhash_haskey(sh, key) == false);
if (UNLIKELY(smallhash_test_expand_buckets(++sh->nentries, sh->nbuckets))) {
smallhash_resize_buckets(sh, hashsizes[++sh->cursize]);
}
e = smallhash_lookup_first_free(sh, key);
e->key = key;
e->val = item;
}
bool BLI_smallhash_reinsert(SmallHash *sh, uintptr_t key, void *item)
{
SmallHashEntry *e = smallhash_lookup(sh, key);
if (e) {
e->val = item;
return false;
}
BLI_smallhash_insert(sh, key, item);
return true;
}
#ifdef USE_REMOVE
bool BLI_smallhash_remove(SmallHash *sh, uintptr_t key)
{
SmallHashEntry *e = smallhash_lookup(sh, key);
if (e) {
e->key = SMHASH_KEY_UNUSED;
e->val = SMHASH_CELL_UNUSED;
sh->nentries--;
return true;
}
else {
return false;
}
}
#endif
void *BLI_smallhash_lookup(const SmallHash *sh, uintptr_t key)
{
SmallHashEntry *e = smallhash_lookup(sh, key);
return e ? e->val : NULL;
}
void **BLI_smallhash_lookup_p(const SmallHash *sh, uintptr_t key)
{
SmallHashEntry *e = smallhash_lookup(sh, key);
return e ? &e->val : NULL;
}
bool BLI_smallhash_haskey(const SmallHash *sh, uintptr_t key)
{
SmallHashEntry *e = smallhash_lookup(sh, key);
return (e != NULL);
}
int BLI_smallhash_len(const SmallHash *sh)
{
return (int)sh->nentries;
}
BLI_INLINE SmallHashEntry *smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
{
while (iter->i < iter->sh->nbuckets) {
if (smallhash_val_is_used(iter->sh->buckets[iter->i].val)) {
if (key) {
*key = iter->sh->buckets[iter->i].key;
}
return &iter->sh->buckets[iter->i++];
}
iter->i++;
}
return NULL;
}
void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
{
SmallHashEntry *e = smallhash_iternext(iter, key);
return e ? e->val : NULL;
}
void **BLI_smallhash_iternext_p(SmallHashIter *iter, uintptr_t *key)
{
SmallHashEntry *e = smallhash_iternext(iter, key);
return e ? &e->val : NULL;
}
void *BLI_smallhash_iternew(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
{
iter->sh = sh;
iter->i = 0;
return BLI_smallhash_iternext(iter, key);
}
void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
{
iter->sh = sh;
iter->i = 0;
return BLI_smallhash_iternext_p(iter, key);
}
/* -------------------------------------------------------------------- */
/** \name Debugging & Introspection
* \{ */
/* NOTE(@ideasman42): useful for debugging but may not be intended for general use. */
#if 0
void BLI_smallhash_print(SmallHash *sh)
{
uint i, linecol = 79, c = 0;
printf("{");
for (i = 0; i < sh->nbuckets; i++) {
if (sh->buckets[i].val == SMHASH_CELL_UNUSED) {
printf("--u-");
}
else if (sh->buckets[i].val == SMHASH_CELL_FREE) {
printf("--f-");
}
else {
printf("%2x", (uint)sh->buckets[i].key);
}
if (i != sh->nbuckets - 1) {
printf(", ");
}
c += 6;
if (c >= linecol) {
printf("\n ");
c = 0;
}
}
fflush(stdout);
}
#endif
#ifdef DEBUG
double BLI_smallhash_calc_quality(SmallHash *sh)
{
uint64_t sum = 0;
uint i;
if (sh->nentries == 0) {
return -1.0;
}
for (i = 0; i < sh->nbuckets; i++) {
if (sh->buckets[i].key != SMHASH_KEY_UNUSED) {
uint64_t count = 0;
SmallHashEntry *e, *e_final = &sh->buckets[i];
uint h = smallhash_key(e_final->key);
uint hoff = 1;
for (e = &sh->buckets[h % sh->nbuckets]; e != e_final;
h = SMHASH_NEXT(h, hoff), e = &sh->buckets[h % sh->nbuckets])
{
count += 1;
}
sum += count;
}
}
return ((double)(sh->nentries + sum) / (double)sh->nentries);
}
#endif
/** \} */

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