Collection IO: Enable file exporters to be specified on Collections #116646

Merged
Jesse Yurkovich merged 56 commits from deadpin/blender:collection-io into main 2024-04-08 22:10:52 +02:00
942 changed files with 9444 additions and 5665 deletions
Showing only changes of commit de1bdcee61 - Show all commits

View File

@ -279,5 +279,5 @@ StatementMacros:
MacroBlockBegin: "^OSL_CLOSURE_STRUCT_BEGIN$"
MacroBlockEnd: "^OSL_CLOSURE_STRUCT_END$"
# Ensure lew line at the end of source files.
# Ensure new line at the end of source files.
InsertNewlineAtEOF: True

View File

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

View File

@ -535,7 +535,7 @@ check_spelling_shaders: .FORCE
"$(BLENDER_DIR)/source/"
check_descriptions: .FORCE
@$(BLENDER_BIN) --background -noaudio --factory-startup --python \
@$(BLENDER_BIN) --background --factory-startup --python \
"$(BLENDER_DIR)/tools/check_source/check_descriptions.py"
check_deprecated: .FORCE
@ -598,7 +598,7 @@ format: .FORCE
doc_py: .FORCE
@ASAN_OPTIONS=halt_on_error=0:${ASAN_OPTIONS} \
$(BLENDER_BIN) \
--background -noaudio --factory-startup \
--background --factory-startup \
--python doc/python_api/sphinx_doc_gen.py
@sphinx-build -b html -j $(NPROCS) doc/python_api/sphinx-in doc/python_api/sphinx-out
@echo "docs written into: '$(BLENDER_DIR)/doc/python_api/sphinx-out/index.html'"
@ -609,7 +609,7 @@ doc_doxy: .FORCE
doc_dna: .FORCE
@$(BLENDER_BIN) \
--background -noaudio --factory-startup \
--background --factory-startup \
--python doc/blender_file_format/BlendFileDnaExporter_25.py
@echo "docs written into: '$(BLENDER_DIR)/doc/blender_file_format/dna.html'"

View File

@ -43,6 +43,10 @@ set(OSL_EXTRA_ARGS
-DPython_EXECUTABLE=${PYTHON_BINARY}
)
if(NOT APPLE)
list(APPEND OSL_EXTRA_ARGS -DOSL_USE_OPTIX=ON)
endif()
ExternalProject_Add(external_osl
URL file://${PACKAGE_DIR}/${OSL_FILE}
DOWNLOAD_DIR ${DOWNLOAD_DIR}

View File

@ -26,7 +26,7 @@ exit /b 1
:detect_blender_done
%BLENDER_BIN% ^
--background -noaudio --factory-startup ^
--background --factory-startup ^
--python %BLENDER_DIR%/doc/python_api/sphinx_doc_gen.py
"%SPHINX_BIN%" -b html %SPHINXOPTS% %O% %SOURCEDIR% %BUILDDIR%

View File

@ -363,15 +363,15 @@ class DNACatalogHTML:
def usage():
print("\nUsage: \n\tblender2.5 --background -noaudio --python BlendFileDnaExporter_25.py [-- [options]]")
print("\nUsage: \n\tblender2.5 --background --python BlendFileDnaExporter_25.py [-- [options]]")
print("Options:")
print("\t--dna-keep-blend: doesn't delete the produced blend file DNA export to html")
print("\t--dna-debug: sets the logging level to DEBUG (lots of additional info)")
print("\t--dna-versioned saves version information in the html and blend filenames")
print("\t--dna-overwrite-css overwrite dna.css, useful when modifying css in the script")
print("Examples:")
print("\tdefault: % blender2.5 --background -noaudio --python BlendFileDnaExporter_25.py")
print("\twith options: % blender2.5 --background -noaudio --python BlendFileDnaExporter_25.py -- --dna-keep-blend --dna-debug\n")
print("\tdefault: % blender2.5 --background --python BlendFileDnaExporter_25.py")
print("\twith options: % blender2.5 --background --python BlendFileDnaExporter_25.py -- --dna-keep-blend --dna-debug\n")
######################################################

View File

@ -16,14 +16,14 @@ Below you have the help message with a list of options you can use.
Usage:
blender2.5 --background -noaudio --python BlendFileDnaExporter_25.py [-- [options]]
blender2.5 --background --python BlendFileDnaExporter_25.py [-- [options]]
Options:
--dna-keep-blend: doesn't delete the produced blend file DNA export to html
--dna-debug: sets the logging level to DEBUG (lots of additional info)
--dna-versioned saves version information in the html and blend filenames
--dna-overwrite-css overwrite dna.css, useful when modifying css in the script
Examples:
default: % blender2.5 --background -noaudio --python BlendFileDnaExporter_25.py
with options: % blender2.5 --background -noaudio --python BlendFileDnaExporter_25.py -- --dna-keep-blend --dna-debug
default: % blender2.5 --background --python BlendFileDnaExporter_25.py
with options: % blender2.5 --background --python BlendFileDnaExporter_25.py -- --dna-keep-blend --dna-debug

View File

@ -55,6 +55,7 @@ import pxr.Gf as Gf
import pxr.Sdf as Sdf
import pxr.Usd as Usd
import pxr.UsdShade as UsdShade
import textwrap
class USDHookExample(bpy.types.USDHook):

View File

@ -1,7 +1,7 @@
..
This document is appended to the auto generated BMesh API doc to avoid clogging up the C files with details.
to test this run:
./blender.bin -b -noaudio -P doc/python_api/sphinx_doc_gen.py -- \
./blender.bin -b -P doc/python_api/sphinx_doc_gen.py -- \
--partial bmesh* ; cd doc/python_api ; sphinx-build sphinx-in sphinx-out ; cd ../../

View File

@ -7,7 +7,7 @@ API dump in RST files
---------------------
Run this script from Blender's root path once you have compiled Blender
blender --background --factory-startup -noaudio --python doc/python_api/sphinx_doc_gen.py
blender --background --factory-startup --python doc/python_api/sphinx_doc_gen.py
This will generate python files in doc/python_api/sphinx-in/
providing ./blender is or links to the blender executable
@ -239,12 +239,12 @@ BPY_LOGGER.setLevel(logging.DEBUG)
"""
# for quick rebuilds
rm -rf /b/doc/python_api/sphinx-* && \
./blender -b -noaudio --factory-startup -P doc/python_api/sphinx_doc_gen.py && \
./blender -b --factory-startup -P doc/python_api/sphinx_doc_gen.py && \
sphinx-build doc/python_api/sphinx-in doc/python_api/sphinx-out
or
./blender -b -noaudio --factory-startup -P doc/python_api/sphinx_doc_gen.py -- -f -B
./blender -b --factory-startup -P doc/python_api/sphinx_doc_gen.py -- -f -B
"""
# Switch for quick testing so doc-builds don't take so long.

View File

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

View File

@ -25,7 +25,7 @@
#include "util/log.h"
#include "util/task.h"
#include "BKE_duplilist.h"
#include "BKE_duplilist.hh"
CCL_NAMESPACE_BEGIN

View File

@ -23,7 +23,7 @@
#include "util/string.h"
#include "util/task.h"
#include "BKE_duplilist.h"
#include "BKE_duplilist.hh"
CCL_NAMESPACE_BEGIN

View File

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

View File

@ -13,6 +13,7 @@
#include "util/log.h"
#ifdef WITH_OSL
# include <OSL/oslconfig.h>
# include <OSL/oslversion.h>
#endif
@ -72,7 +73,8 @@ void device_optix_info(const vector<DeviceInfo> &cuda_devices, vector<DeviceInfo
info.type = DEVICE_OPTIX;
info.id += "_OptiX";
# if defined(WITH_OSL) && (OSL_VERSION_MINOR >= 13 || OSL_VERSION_MAJOR > 1)
# if defined(WITH_OSL) && defined(OSL_USE_OPTIX) && \
(OSL_VERSION_MINOR >= 13 || OSL_VERSION_MAJOR > 1)
info.has_osl = true;
# endif
info.denoisers |= DENOISER_OPTIX;

View File

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

View File

@ -102,7 +102,8 @@ GHOST_DropTargetX11::~GHOST_DropTargetX11()
char *GHOST_DropTargetX11::FileUrlDecode(const char *fileUrl)
{
if (strncmp(fileUrl, "file://", 7) == 0) {
return GHOST_URL_decode_alloc(fileUrl + 7);
const char *file = fileUrl + 7;
return GHOST_URL_decode_alloc(file, strlen(file));
}
return nullptr;

View File

@ -12,6 +12,7 @@
#include <cstdlib>
#include <cstring>
#include "GHOST_Debug.hh"
#include "GHOST_PathUtils.hh"
#include "GHOST_Types.h"
@ -24,9 +25,10 @@ using DecodeState_e = enum DecodeState_e {
STATE_CONVERTING
};
void GHOST_URL_decode(char *buf_dst, int buf_dst_size, const char *buf_src)
void GHOST_URL_decode(char *buf_dst, int buf_dst_size, const char *buf_src, const int buf_src_len)
{
const uint buf_src_len = strlen(buf_src);
GHOST_ASSERT(strnlen(buf_src, buf_src_len) == buf_src_len, "Incorrect length");
DecodeState_e state = STATE_SEARCH;
uint ascii_character;
@ -85,12 +87,12 @@ void GHOST_URL_decode(char *buf_dst, int buf_dst_size, const char *buf_src)
}
}
char *GHOST_URL_decode_alloc(const char *buf_src)
char *GHOST_URL_decode_alloc(const char *buf_src, const int buf_src_len)
{
/* Assume one character of encoded URL can be expanded to 4 chars max. */
const size_t decoded_size_max = 4 * strlen(buf_src) + 1;
const size_t decoded_size_max = 4 * buf_src_len + 1;
char *buf_dst = (char *)malloc(decoded_size_max);
GHOST_URL_decode(buf_dst, decoded_size_max, buf_src);
GHOST_URL_decode(buf_dst, decoded_size_max, buf_src, buf_src_len);
const size_t decoded_size = strlen(buf_dst) + 1;
if (decoded_size != decoded_size_max) {
char *buf_dst_trim = (char *)malloc(decoded_size);

View File

@ -14,12 +14,13 @@
* \param buf_dst: Buffer for decoded URL.
* \param buf_dst_maxlen: Size of output buffer.
* \param buf_src: Input encoded buffer to be decoded.
* \param buf_src_len: The length of `buf_src` to use.
*/
void GHOST_URL_decode(char *buf_dst, int buf_dst_size, const char *buf_src);
void GHOST_URL_decode(char *buf_dst, int buf_dst_size, const char *buf_src, int buf_src_len);
/**
* A version of #GHOST_URL_decode that allocates the string & returns it.
*
* \param buf_src: Input encoded buffer to be decoded.
* \return The decoded output buffer.
*/
char *GHOST_URL_decode_alloc(const char *buf_src);
char *GHOST_URL_decode_alloc(const char *buf_src, int buf_src_len);

View File

@ -2926,6 +2926,9 @@ static char *read_buffer_from_data_offer(GWL_DataOffer *data_offer,
}
close(pipefd[0]);
}
else {
*r_len = 0;
}
return buf;
}
@ -3259,20 +3262,19 @@ static void data_device_handle_drop(void *data, wl_data_device * /*wl_data_devic
CLOG_INFO(LOG, 2, "drop mime_recieve=%s", mime_receive);
auto read_uris_fn = [](GWL_Seat *const seat,
GWL_DataOffer *data_offer,
wl_surface *wl_surface_window,
const char *mime_receive) {
auto read_drop_data_fn = [](GWL_Seat *const seat,
GWL_DataOffer *data_offer,
wl_surface *wl_surface_window,
const char *mime_receive) {
const uint64_t event_ms = seat->system->getMilliSeconds();
const wl_fixed_t xy[2] = {UNPACK2(data_offer->dnd.xy)};
const bool nil_terminate = (mime_receive != ghost_wl_mime_text_uri);
size_t data_buf_len = 0;
const char *data_buf = read_buffer_from_data_offer(
data_offer, mime_receive, nullptr, false, &data_buf_len);
std::string data = data_buf ? std::string(data_buf, data_buf_len) : "";
free(const_cast<char *>(data_buf));
data_offer, mime_receive, nullptr, nil_terminate, &data_buf_len);
CLOG_INFO(LOG, 2, "drop_read_uris mime_receive=%s, data=%s", mime_receive, data.c_str());
CLOG_INFO(LOG, 2, "read_drop_data mime_receive=%s, data_len=%zu", mime_receive, data_buf_len);
wl_data_offer_finish(data_offer->wl.id);
wl_data_offer_destroy(data_offer->wl.id);
@ -3283,69 +3285,97 @@ static void data_device_handle_drop(void *data, wl_data_device * /*wl_data_devic
delete data_offer;
data_offer = nullptr;
GHOST_SystemWayland *const system = seat->system;
/* Don't generate a drop event if the data could not be read,
* an error will have been logged. */
if (data_buf != nullptr) {
GHOST_TDragnDropTypes ghost_dnd_type = GHOST_kDragnDropTypeUnknown;
void *ghost_dnd_data = nullptr;
if (mime_receive == ghost_wl_mime_text_uri) {
static constexpr const char *file_proto = "file://";
/* NOTE: some applications CRLF (`\r\n`) GTK3 for e.g. & others don't `pcmanfm-qt`.
* So support both, once `\n` is found, strip the preceding `\r` if found. */
static constexpr const char *lf = "\n";
/* Failure to receive drop data . */
if (mime_receive == ghost_wl_mime_text_uri) {
const char file_proto[] = "file://";
/* NOTE: some applications CRLF (`\r\n`) GTK3 for e.g. & others don't `pcmanfm-qt`.
* So support both, once `\n` is found, strip the preceding `\r` if found. */
const char lf = '\n';
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_window);
std::vector<std::string> uris;
const std::string_view data = std::string_view(data_buf, data_buf_len);
std::vector<std::string_view> uris;
size_t pos = 0;
while (pos != std::string::npos) {
pos = data.find(file_proto, pos);
if (pos == std::string::npos) {
break;
size_t pos = 0;
while (pos != std::string::npos) {
pos = data.find(file_proto, pos);
if (pos == std::string::npos) {
break;
}
const size_t start = pos + sizeof(file_proto) - 1;
pos = data.find(lf, pos);
size_t end = pos;
if (UNLIKELY(end == std::string::npos)) {
/* Note that most well behaved file managers will add a trailing newline,
* Gnome's web browser (44.3) doesn't, so support reading up until the last byte. */
end = data.size();
}
/* Account for 'CRLF' case. */
if (data[end - 1] == '\r') {
end -= 1;
}
std::string_view data_substr = data.substr(start, end - start);
uris.push_back(data_substr);
CLOG_INFO(LOG,
2,
"read_drop_data pos=%zu, text_uri=\"%.*s\"",
start,
int(data_substr.size()),
data_substr.data());
}
const size_t start = pos + sizeof(file_proto) - 1;
pos = data.find(lf, pos);
size_t end = pos;
if (UNLIKELY(end == std::string::npos)) {
/* Note that most well behaved file managers will add a trailing newline,
* Gnome's web browser (44.3) doesn't, so support reading up until the last byte. */
end = data.size();
GHOST_TStringArray *flist = static_cast<GHOST_TStringArray *>(
malloc(sizeof(GHOST_TStringArray)));
flist->count = int(uris.size());
flist->strings = static_cast<uint8_t **>(malloc(uris.size() * sizeof(uint8_t *)));
for (size_t i = 0; i < uris.size(); i++) {
flist->strings[i] = reinterpret_cast<uint8_t *>(
GHOST_URL_decode_alloc(uris[i].data(), uris[i].size()));
}
/* Account for 'CRLF' case. */
if (data[end - 1] == '\r') {
end -= 1;
}
uris.push_back(data.substr(start, end - start));
CLOG_INFO(LOG, 2, "drop_read_uris pos=%zu, text_uri=\"%s\"", start, uris.back().c_str());
CLOG_INFO(LOG, 2, "read_drop_data file_count=%d", flist->count);
ghost_dnd_type = GHOST_kDragnDropTypeFilenames;
ghost_dnd_data = flist;
}
else if (ELEM(mime_receive, ghost_wl_mime_text_plain, ghost_wl_mime_text_utf8)) {
ghost_dnd_type = GHOST_kDragnDropTypeString;
ghost_dnd_data = (void *)data_buf; /* Move ownership to the event. */
data_buf = nullptr;
}
GHOST_TStringArray *flist = static_cast<GHOST_TStringArray *>(
malloc(sizeof(GHOST_TStringArray)));
flist->count = int(uris.size());
flist->strings = static_cast<uint8_t **>(malloc(uris.size() * sizeof(uint8_t *)));
for (size_t i = 0; i < uris.size(); i++) {
flist->strings[i] = reinterpret_cast<uint8_t *>(GHOST_URL_decode_alloc(uris[i].c_str()));
if (ghost_dnd_type != GHOST_kDragnDropTypeUnknown) {
GHOST_SystemWayland *const system = seat->system;
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_window);
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, xy)};
system->pushEvent_maybe_pending(new GHOST_EventDragnDrop(event_ms,
GHOST_kEventDraggingDropDone,
ghost_dnd_type,
win,
UNPACK2(event_xy),
ghost_dnd_data));
wl_display_roundtrip(system->wl_display_get());
}
else {
CLOG_INFO(LOG, 2, "read_drop_data, unhandled!");
}
CLOG_INFO(LOG, 2, "drop_read_uris_fn file_count=%d", flist->count);
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, xy)};
system->pushEvent_maybe_pending(new GHOST_EventDragnDrop(event_ms,
GHOST_kEventDraggingDropDone,
GHOST_kDragnDropTypeFilenames,
win,
UNPACK2(event_xy),
flist));
free(const_cast<char *>(data_buf));
}
else if (ELEM(mime_receive, ghost_wl_mime_text_plain, ghost_wl_mime_text_utf8)) {
/* TODO: enable use of internal functions 'txt_insert_buf' and
* 'text_update_edited' to behave like dropped text was pasted. */
CLOG_INFO(LOG, 2, "drop_read_uris_fn (text_plain, text_utf8), unhandled!");
}
wl_display_roundtrip(system->wl_display_get());
};
/* Pass in `seat->wl_surface_window_focus_dnd` instead of accessing it from `seat` since the
* leave callback (#data_device_handle_leave) will clear the value once this function starts. */
std::thread read_thread(
read_uris_fn, seat, data_offer, seat->wl.surface_window_focus_dnd, mime_receive);
read_drop_data_fn, seat, data_offer, seat->wl.surface_window_focus_dnd, mime_receive);
read_thread.detach();
}

View File

@ -76,7 +76,7 @@ for blend in icons_blend:
output_dir = os.path.join(BASEDIR, "icons")
files_old = set(names_and_time_from_path(output_dir))
cmd = (
blender_bin, "--background", "--factory-startup", "-noaudio",
blender_bin, "--background", "--factory-startup",
blend,
"--python", os.path.join(BASEDIR, "blender_icons_geom.py"),
"--",

View File

@ -71,7 +71,7 @@ datatoc_icon_split_py = os.path.join(BASEDIR, "..", "..", "source", "blender", "
# create .dat pixmaps (which are stored in git)
cmd = (
blender_bin, "--background", "--factory-startup", "-noaudio",
blender_bin, "--background", "--factory-startup",
"--python", datatoc_icon_split_py, "--",
"--image=" + os.path.join(BASEDIR, "blender_icons16.png"),
"--output=" + os.path.join(BASEDIR, "blender_icons16"),
@ -85,7 +85,7 @@ cmd = (
run(cmd, env=env)
cmd = (
blender_bin, "--background", "--factory-startup", "-noaudio",
blender_bin, "--background", "--factory-startup",
"--python", datatoc_icon_split_py, "--",
"--image=" + os.path.join(BASEDIR, "blender_icons32.png"),
"--output=" + os.path.join(BASEDIR, "blender_icons32"),

View File

@ -262,7 +262,6 @@ url_manual_mapping = (
("bpy.types.clothsettings.compression_stiffness_max*", "physics/cloth/settings/property_weights.html#bpy-types-clothsettings-compression-stiffness-max"),
("bpy.types.colormanagedsequencercolorspacesettings*", "render/color_management.html#bpy-types-colormanagedsequencercolorspacesettings"),
("bpy.types.colormanagedviewsettings.view_transform*", "render/color_management.html#bpy-types-colormanagedviewsettings-view-transform"),
("bpy.types.compositornodetree.use_groupnode_buffer*", "compositing/sidebar.html#bpy-types-compositornodetree-use-groupnode-buffer"),
("bpy.types.cyclesmaterialsettings.volume_step_rate*", "render/cycles/material_settings.html#bpy-types-cyclesmaterialsettings-volume-step-rate"),
("bpy.types.cyclesobjectsettings.is_caustics_caster*", "render/cycles/object_settings/object_data.html#bpy-types-cyclesobjectsettings-is-caustics-caster"),
("bpy.types.cyclesrendersettings.adaptive_threshold*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-adaptive-threshold"),
@ -1023,7 +1022,6 @@ url_manual_mapping = (
("bpy.types.compositornodecolorcorrection*", "compositing/types/color/adjust/color_correction.html#bpy-types-compositornodecolorcorrection"),
("bpy.types.compositornodemoviedistortion*", "compositing/types/transform/movie_distortion.html#bpy-types-compositornodemoviedistortion"),
("bpy.types.compositornodetree.chunk_size*", "compositing/sidebar.html#bpy-types-compositornodetree-chunk-size"),
("bpy.types.compositornodetree.use_opencl*", "compositing/sidebar.html#bpy-types-compositornodetree-use-opencl"),
("bpy.types.cyclesrendersettings.caustics*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-caustics"),
("bpy.types.cyclesrendersettings.denoiser*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-denoiser"),
("bpy.types.editbone.use_inherit_rotation*", "animation/armatures/bones/properties/relations.html#bpy-types-editbone-use-inherit-rotation"),

View File

@ -105,7 +105,6 @@ class WM_OT_previews_batch_generate(Operator):
bpy.app.binary_path,
"--background",
"--factory-startup",
"-noaudio",
]
if self.use_trusted:
cmd.append("--enable-autoexec")
@ -215,7 +214,6 @@ class WM_OT_previews_batch_clear(Operator):
bpy.app.binary_path,
"--background",
"--factory-startup",
"-noaudio",
]
if self.use_trusted:
cmd.append("--enable-autoexec")

View File

@ -533,7 +533,7 @@ class NODE_MT_category_GEO_UTILITIES(Menu):
bl_idname = "NODE_MT_category_GEO_UTILITIES"
bl_label = "Utilities"
def draw(self, _context):
def draw(self, context):
layout = self.layout
layout.menu("NODE_MT_geometry_node_GEO_COLOR")
layout.menu("NODE_MT_category_GEO_TEXT")
@ -541,6 +541,8 @@ class NODE_MT_category_GEO_UTILITIES(Menu):
layout.separator()
layout.menu("NODE_MT_category_GEO_UTILITIES_FIELD")
layout.menu("NODE_MT_category_GEO_UTILITIES_MATH")
if context.preferences.experimental.use_new_matrix_socket:
layout.menu("NODE_MT_category_utilities_matrix")
layout.menu("NODE_MT_category_GEO_UTILITIES_ROTATION")
layout.menu("NODE_MT_category_GEO_UTILITIES_DEPRECATED")
layout.separator()
@ -592,6 +594,22 @@ class NODE_MT_category_GEO_UTILITIES_ROTATION(Menu):
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Rotation")
class NODE_MT_category_utilities_matrix(Menu):
bl_idname = "NODE_MT_category_utilities_matrix"
bl_label = "Matrix"
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "FunctionNodeCombineTransform")
node_add_menu.add_node_type(layout, "FunctionNodeInvertMatrix")
node_add_menu.add_node_type(layout, "FunctionNodeMatrixMultiply")
node_add_menu.add_node_type(layout, "FunctionNodeSeparateTransform")
node_add_menu.add_node_type(layout, "FunctionNodeTransformDirection")
node_add_menu.add_node_type(layout, "FunctionNodeTransformPoint")
node_add_menu.add_node_type(layout, "FunctionNodeTransposeMatrix")
node_add_menu.draw_assets_for_catalog(layout, "Utilities/Matrix")
class NODE_MT_category_GEO_UTILITIES_MATH(Menu):
bl_idname = "NODE_MT_category_GEO_UTILITIES_MATH"
bl_label = "Math"
@ -779,6 +797,7 @@ classes = (
NODE_MT_category_GEO_UTILITIES_FIELD,
NODE_MT_category_GEO_UTILITIES_MATH,
NODE_MT_category_GEO_UTILITIES_ROTATION,
NODE_MT_category_utilities_matrix,
NODE_MT_category_GEO_UTILITIES_DEPRECATED,
NODE_MT_category_GEO_GROUP,
)

View File

@ -43,7 +43,7 @@ class MotionPathButtonsPanel:
col.prop(mps, "frame_step", text="Step")
row = col.row()
row.prop(mps, "bake_in_camera_space", text="Bake to Active Camera")
row.prop(mps, "use_camera_space_bake", text="Bake to Active Camera")
if bones:
op_category = "pose"

View File

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

View File

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

View File

@ -159,7 +159,7 @@ class GRAPH_MT_view(Menu):
layout.prop(st, "use_realtime_update")
layout.prop(st, "show_sliders")
layout.prop(st, "use_auto_merge_keyframes")
layout.prop(st, "autolock_translation_axis")
layout.prop(st, "use_auto_lock_translation_axis")
layout.separator()
if st.mode != 'DRIVERS':

View File

@ -818,12 +818,9 @@ class NODE_PT_quality(bpy.types.Panel):
col.active = not use_realtime
col.prop(tree, "render_quality", text="Render")
col.prop(tree, "edit_quality", text="Edit")
col.prop(tree, "chunk_size")
col = layout.column()
col.active = not use_realtime
col.prop(tree, "use_opencl")
col.prop(tree, "use_groupnode_buffer")
col.prop(tree, "use_two_pass")
col.prop(tree, "use_viewer_border")

View File

@ -2661,6 +2661,7 @@ class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
({"property": "use_sculpt_texture_paint"}, ("blender/blender/issues/96225", "#96225")),
({"property": "use_experimental_compositors"}, ("blender/blender/issues/88150", "#88150")),
({"property": "use_grease_pencil_version3"}, ("blender/blender/projects/6", "Grease Pencil 3.0")),
({"property": "use_new_matrix_socket"}, ("blender/blender/issues/116067", "Matrix Socket")),
({"property": "enable_overlay_next"}, ("blender/blender/issues/102179", "#102179")),
({"property": "use_extension_repos"}, ("/blender/blender/issues/106254", "#106254")),
),

View File

@ -827,13 +827,21 @@ class VIEW3D_HT_header(Header):
depress=(tool_settings.gpencil_selectmode_edit == 'STROKE'),
).mode = 'STROKE'
if object_mode == 'PAINT_GREASE_PENCIL':
row = layout.row(align=True)
row.prop(tool_settings, "use_gpencil_draw_additive", text="", icon='FREEZE')
if object_mode in {'PAINT_GREASE_PENCIL', 'EDIT', 'WEIGHT_PAINT'}:
row = layout.row(align=True)
row.prop(tool_settings, "use_grease_pencil_multi_frame_editing", text="")
if object_mode == 'PAINT_GREASE_PENCIL':
row = layout.row()
sub = row.row(align=True)
sub.prop(tool_settings, "use_gpencil_draw_additive", text="", icon='FREEZE')
if object_mode in {'EDIT', 'WEIGHT_PAINT'}:
sub = row.row(align=True)
sub.enabled = tool_settings.use_grease_pencil_multi_frame_editing
sub.popover(
panel="VIEW3D_PT_grease_pencil_multi_frame",
text="Multiframe",
)
# Grease Pencil (legacy)
if obj and obj.type == 'GPENCIL' and context.gpencil_data:
@ -8004,6 +8012,25 @@ class VIEW3D_PT_gpencil_multi_frame(Panel):
layout.template_curve_mapping(settings, "multiframe_falloff_curve", brush=True)
class VIEW3D_PT_grease_pencil_multi_frame(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
bl_label = "Multi Frame"
def draw(self, context):
layout = self.layout
tool_settings = context.tool_settings
settings = tool_settings.gpencil_sculpt
col = layout.column(align=True)
col.prop(settings, "use_multiframe_falloff")
# Falloff curve
if settings.use_multiframe_falloff:
layout.template_curve_mapping(settings, "multiframe_falloff_curve", brush=True)
# Grease Pencil Object - Curve Editing tools
class VIEW3D_PT_gpencil_curve_edit(Panel):
bl_space_type = 'VIEW_3D'
@ -9024,6 +9051,7 @@ classes = (
VIEW3D_PT_grease_pencil,
VIEW3D_PT_annotation_onion,
VIEW3D_PT_gpencil_multi_frame,
VIEW3D_PT_grease_pencil_multi_frame,
VIEW3D_PT_gpencil_curve_edit,
VIEW3D_PT_gpencil_sculpt_automasking,
VIEW3D_PT_quad_view,

View File

@ -12,6 +12,7 @@
#include <string>
#include "BLI_bitmap.h"
#include "BLI_vector.hh"
#include "DNA_anim_types.h"
#include "ED_transform.hh"
@ -192,6 +193,8 @@ bool autokeyframe_property(bContext *C,
* expected to be the size of the property array.
* \param frame: is expected to be in the local time of the action, meaning it has to be NLA mapped
* already.
* \param keying_mask is expected to have the same size as `rna_path`. A false bit means that index
* will be skipped.
* \returns The number of keys inserted.
*/
int insert_key_action(Main *bmain,
@ -202,7 +205,8 @@ int insert_key_action(Main *bmain,
float frame,
Span<float> values,
eInsertKeyFlags insert_key_flag,
eBezTriple_KeyframeType key_type);
eBezTriple_KeyframeType key_type,
const BLI_bitmap *keying_mask);
/**
* Insert keys to the ID of the given PointerRNA for the given RNA paths. Tries to create an
@ -215,6 +219,7 @@ void insert_key_rna(PointerRNA *rna_pointer,
eInsertKeyFlags insert_key_flags,
eBezTriple_KeyframeType key_type,
Main *bmain,
ReportList *reports);
ReportList *reports,
const AnimationEvalContext &anim_eval_context);
} // namespace blender::animrig

View File

@ -6,10 +6,8 @@
* \ingroup animrig
*/
#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BLI_map.hh"
#include "BLI_math_color.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_string_utils.hh"
@ -19,8 +17,6 @@
#include "DNA_armature_types.h"
#include "BLI_math_bits.h"
#include "MEM_guardedalloc.h"
#include "BKE_animsys.h"
@ -440,7 +436,7 @@ void ANIM_armature_bonecoll_active_name_set(bArmature *armature, const char *nam
ANIM_armature_bonecoll_active_set(armature, bcoll);
}
void ANIM_armature_bonecoll_active_runtime_refresh(struct bArmature *armature)
void ANIM_armature_bonecoll_active_runtime_refresh(bArmature *armature)
{
const std::string_view active_name = armature->active_collection_name;
if (active_name.empty()) {
@ -1062,8 +1058,8 @@ static bool bcoll_list_contains(const ListBase /*BoneCollectionRef*/ *collection
return false;
}
bool ANIM_armature_bonecoll_contains_active_bone(const struct bArmature *armature,
const struct BoneCollection *bcoll)
bool ANIM_armature_bonecoll_contains_active_bone(const bArmature *armature,
const BoneCollection *bcoll)
{
if (armature->edbo) {
if (!armature->act_edbone) {

View File

@ -7,7 +7,6 @@
*/
#include "ANIM_driver.hh"
#include "BKE_animsys.h"
#include "BKE_fcurve_driver.h"
#include "DNA_anim_types.h"
#include "RNA_access.hh"

View File

@ -41,7 +41,6 @@
#include "RNA_path.hh"
#include "RNA_prototypes.h"
#include "WM_api.hh"
#include "WM_types.hh"
namespace blender::animrig {
@ -863,7 +862,8 @@ int insert_key_action(Main *bmain,
const float frame,
const Span<float> values,
eInsertKeyFlags insert_key_flag,
eBezTriple_KeyframeType key_type)
eBezTriple_KeyframeType key_type,
const BLI_bitmap *keying_mask)
{
BLI_assert(bmain != nullptr);
BLI_assert(action != nullptr);
@ -880,6 +880,10 @@ int insert_key_action(Main *bmain,
int property_array_index = 0;
int inserted_keys = 0;
for (float value : values) {
if (!BLI_BITMAP_TEST_BOOL(keying_mask, property_array_index)) {
property_array_index++;
continue;
}
const bool inserted_key = insert_keyframe_fcurve_value(bmain,
nullptr,
ptr,
@ -925,7 +929,8 @@ void insert_key_rna(PointerRNA *rna_pointer,
const eInsertKeyFlags insert_key_flags,
const eBezTriple_KeyframeType key_type,
Main *bmain,
ReportList *reports)
ReportList *reports,
const AnimationEvalContext &anim_eval_context)
{
ID *id = rna_pointer->owner_id;
bAction *action = id_action_ensure(bmain, id);
@ -939,6 +944,15 @@ void insert_key_rna(PointerRNA *rna_pointer,
}
AnimData *adt = BKE_animdata_from_id(id);
/* Keyframing functions can deal with the nla_context being a nullptr. */
ListBase nla_cache = {nullptr, nullptr};
NlaKeyframingContext *nla_context = nullptr;
if (adt && adt->action == action) {
nla_context = BKE_animsys_get_nla_keyframing_context(
&nla_cache, rna_pointer, adt, &anim_eval_context);
}
const float nla_frame = BKE_nla_tweakedit_remap(adt, scene_frame, NLATIME_CONVERT_UNMAP);
const bool visual_keyframing = insert_key_flags & INSERTKEY_MATRIX;
@ -961,6 +975,16 @@ void insert_key_rna(PointerRNA *rna_pointer,
prop);
Vector<float> rna_values = get_keyframe_values(&ptr, prop, visual_keyframing);
BLI_bitmap *successful_remaps = BLI_BITMAP_NEW(rna_values.size(), __func__);
BKE_animsys_nla_remap_keyframe_values(nla_context,
rna_pointer,
prop,
rna_values.as_mutable_span(),
-1,
&anim_eval_context,
nullptr,
successful_remaps);
insert_key_count += insert_key_action(bmain,
action,
rna_pointer,
@ -969,7 +993,9 @@ void insert_key_rna(PointerRNA *rna_pointer,
nla_frame,
rna_values.as_span(),
insert_key_flags,
key_type);
key_type,
successful_remaps);
MEM_freeN(successful_remaps);
}
if (insert_key_count == 0) {

View File

@ -9,8 +9,6 @@
#include "BKE_animsys.h"
#include "BKE_context.hh"
#include "BKE_fcurve.h"
#include "BKE_layer.hh"
#include "BKE_object.hh"
#include "BKE_scene.hh"
#include "BLI_listbase.h"
@ -22,11 +20,8 @@
#include "RNA_prototypes.h"
#include "ED_keyframing.hh"
#include "ED_scene.hh"
#include "ED_transform.hh"
#include "ANIM_keyframing.hh"
#include "ANIM_rna.hh"
#include "WM_api.hh"
#include "WM_types.hh"
@ -165,7 +160,8 @@ void autokeyframe_object(bContext *C, Scene *scene, Object *ob, Span<std::string
flag,
eBezTriple_KeyframeType(scene->toolsettings->keyframe_type),
bmain,
reports);
reports,
anim_eval_context);
}
}
@ -290,7 +286,8 @@ void autokeyframe_pose_channel(bContext *C,
flag,
eBezTriple_KeyframeType(scene->toolsettings->keyframe_type),
bmain,
reports);
reports,
anim_eval_context);
}
}

View File

@ -12,12 +12,10 @@
#include "ANIM_rna.hh"
#include "ANIM_visualkey.hh"
#include "BKE_animsys.h"
#include "BKE_armature.hh"
#include "BLI_math_matrix.h"
#include "BLI_math_rotation.h"
#include "BLI_math_vector.h"
#include "DNA_constraint_types.h"
#include "DNA_object_types.h"
@ -25,7 +23,6 @@
#include "RNA_access.hh"
#include "RNA_prototypes.h"
#include "RNA_types.hh"
namespace blender::animrig {
@ -214,11 +211,11 @@ Vector<float> visualkey_get_values(PointerRNA *ptr, PropertyRNA *prop)
Object *ob = static_cast<Object *>(ptr->data);
/* Loc code is specific... */
if (strstr(identifier, "location")) {
values.extend({ob->object_to_world[3], 3});
values.extend({ob->object_to_world().location(), 3});
return values;
}
copy_m4_m4(tmat, ob->object_to_world);
copy_m4_m4(tmat, ob->object_to_world().ptr());
rotmode = ob->rotmode;
}
else if (ptr->type == &RNA_PoseBone) {

View File

@ -21,9 +21,12 @@
#include "BKE_callbacks.hh"
struct IDRemapper;
struct Main;
namespace blender::bke::id {
class IDRemapper;
}
namespace blender::asset_system {
class AssetIdentifier;
@ -140,7 +143,7 @@ class AssetLibrary {
* mapped to null (typically when an ID gets removed), the asset is removed, because we don't
* support such empty/null assets.
*/
void remap_ids_and_remove_invalid(const IDRemapper &mappings);
void remap_ids_and_remove_invalid(const blender::bke::id::IDRemapper &mappings);
/**
* Update `catalog_simple_name` by looking up the asset's catalog by its ID.
@ -230,11 +233,6 @@ std::string AS_asset_library_find_suitable_root_path_from_path(blender::StringRe
*/
std::string AS_asset_library_find_suitable_root_path_from_main(const Main *bmain);
blender::asset_system::AssetCatalogService *AS_asset_library_get_catalog_service(
const blender::asset_system::AssetLibrary *library);
blender::asset_system::AssetCatalogTree *AS_asset_library_get_catalog_tree(
const blender::asset_system::AssetLibrary *library);
/**
* Force clearing of all asset library data. After calling this, new asset libraries can be loaded
* just as usual using #AS_asset_library_load(), no init or other setup is needed.
@ -253,10 +251,6 @@ void AS_asset_libraries_exit();
blender::asset_system::AssetLibrary *AS_asset_library_load(const char *name,
const char *library_dirpath);
/** Look up the asset's catalog and copy its simple name into #asset_data. */
void AS_asset_library_refresh_catalog_simplename(
blender::asset_system::AssetLibrary *asset_library, AssetMetaData *asset_data);
/** Return whether any loaded AssetLibrary has unsaved changes to its catalogs. */
bool AS_asset_library_has_any_unsaved_catalogs(void);
@ -264,7 +258,7 @@ 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).
*/
void AS_asset_library_remap_ids(const IDRemapper *mappings);
void AS_asset_library_remap_ids(const blender::bke::id::IDRemapper &mappings);
/**
* Attempt to resolve a full path to an asset based on the currently available (not necessary

View File

@ -317,7 +317,7 @@ static std::string asset_definition_default_file_path_from_dir(StringRef asset_l
void AssetCatalogService::load_from_disk()
{
load_from_disk(asset_library_root_);
this->load_from_disk(asset_library_root_);
}
void AssetCatalogService::load_from_disk(const CatalogFilePath &file_or_directory_path)
@ -330,10 +330,10 @@ void AssetCatalogService::load_from_disk(const CatalogFilePath &file_or_director
}
if (S_ISREG(status.st_mode)) {
load_single_file(file_or_directory_path);
this->load_single_file(file_or_directory_path);
}
else if (S_ISDIR(status.st_mode)) {
load_directory_recursive(file_or_directory_path);
this->load_directory_recursive(file_or_directory_path);
}
else {
/* TODO(@sybren): throw an appropriate exception. */
@ -341,7 +341,7 @@ void AssetCatalogService::load_from_disk(const CatalogFilePath &file_or_director
/* TODO: Should there be a sanitize step? E.g. to remove catalogs with identical paths? */
rebuild_tree();
this->rebuild_tree();
}
void AssetCatalogService::add_from_existing(const AssetCatalogService &other_service)
@ -423,7 +423,7 @@ void AssetCatalogService::reload_catalogs()
const CatalogID catalog_id = catalog->catalog_id;
cats_in_file.add(catalog_id);
const bool should_skip = is_catalog_known_with_unsaved_changes(catalog_id);
const bool should_skip = this->is_catalog_known_with_unsaved_changes(catalog_id);
if (should_skip) {
/* Do not overwrite unsaved local changes. */
return false;
@ -447,7 +447,7 @@ void AssetCatalogService::purge_catalogs_not_listed(const Set<CatalogID> &catalo
if (catalogs_to_keep.contains(cat_id)) {
continue;
}
if (is_catalog_known_with_unsaved_changes(cat_id)) {
if (this->is_catalog_known_with_unsaved_changes(cat_id)) {
continue;
}
/* This catalog is not on disk, but also not modified, so get rid of it. */
@ -455,7 +455,7 @@ void AssetCatalogService::purge_catalogs_not_listed(const Set<CatalogID> &catalo
}
for (CatalogID cat_id : cats_to_remove) {
delete_catalog_by_id_hard(cat_id);
this->delete_catalog_by_id_hard(cat_id);
}
}
@ -481,12 +481,12 @@ bool AssetCatalogService::write_to_disk(const CatalogFilePath &blend_file_path)
{
BLI_assert(!is_read_only_);
if (!write_to_disk_ex(blend_file_path)) {
if (!this->write_to_disk_ex(blend_file_path)) {
return false;
}
untag_has_unsaved_changes();
rebuild_tree();
this->untag_has_unsaved_changes();
this->rebuild_tree();
return true;
}
@ -496,7 +496,7 @@ bool AssetCatalogService::write_to_disk_ex(const CatalogFilePath &blend_file_pat
/* - Already loaded a CDF from disk? -> Always write to that file. */
if (catalog_collection_->catalog_definition_file_) {
reload_catalogs();
this->reload_catalogs();
return catalog_collection_->catalog_definition_file_->write_to_disk();
}
@ -507,9 +507,10 @@ bool AssetCatalogService::write_to_disk_ex(const CatalogFilePath &blend_file_pat
return true; /* Writing nothing when there is nothing to write is still a success. */
}
const CatalogFilePath cdf_path_to_write = find_suitable_cdf_path_for_writing(blend_file_path);
catalog_collection_->catalog_definition_file_ = construct_cdf_in_memory(cdf_path_to_write);
reload_catalogs();
const CatalogFilePath cdf_path_to_write = this->find_suitable_cdf_path_for_writing(
blend_file_path);
catalog_collection_->catalog_definition_file_ = this->construct_cdf_in_memory(cdf_path_to_write);
this->reload_catalogs();
return catalog_collection_->catalog_definition_file_->write_to_disk();
}
@ -528,7 +529,7 @@ void AssetCatalogService::prepare_to_merge_on_write()
/* Mark all in-memory catalogs as "dirty", to force them to be kept around on
* the next "load-merge-write" cycle. */
tag_all_catalogs_as_unsaved_changes();
this->tag_all_catalogs_as_unsaved_changes();
}
CatalogFilePath AssetCatalogService::find_suitable_cdf_path_for_writing(
@ -590,8 +591,8 @@ std::unique_ptr<AssetCatalogTree> AssetCatalogService::read_into_tree()
void AssetCatalogService::rebuild_tree()
{
create_missing_catalogs();
this->catalog_tree_ = read_into_tree();
this->create_missing_catalogs();
this->catalog_tree_ = this->read_into_tree();
}
void AssetCatalogService::create_missing_catalogs()
@ -661,7 +662,7 @@ void AssetCatalogService::redo()
undo_snapshots_.append(std::move(catalog_collection_));
catalog_collection_ = redo_snapshots_.pop_last();
rebuild_tree();
this->rebuild_tree();
AssetLibraryService::get()->rebuild_all_library();
}

View File

@ -13,6 +13,7 @@
#include "AS_asset_library.hh"
#include "AS_asset_representation.hh"
#include "BKE_lib_remap.hh"
#include "BKE_main.hh"
#include "BKE_preferences.h"
@ -93,36 +94,11 @@ std::string AS_asset_library_find_suitable_root_path_from_main(const Main *bmain
return AS_asset_library_find_suitable_root_path_from_path(bmain->filepath);
}
AssetCatalogService *AS_asset_library_get_catalog_service(const AssetLibrary *library)
{
if (library == nullptr) {
return nullptr;
}
return library->catalog_service.get();
}
AssetCatalogTree *AS_asset_library_get_catalog_tree(const AssetLibrary *library)
{
AssetCatalogService *catalog_service = AS_asset_library_get_catalog_service(library);
if (catalog_service == nullptr) {
return nullptr;
}
return catalog_service->get_catalog_tree();
}
void AS_asset_library_refresh_catalog_simplename(AssetLibrary *asset_library,
AssetMetaData *asset_data)
{
asset_library->refresh_catalog_simplename(asset_data);
}
void AS_asset_library_remap_ids(const IDRemapper *mappings)
void AS_asset_library_remap_ids(const bke::id::IDRemapper &mappings)
{
AssetLibraryService *service = AssetLibraryService::get();
service->foreach_loaded_asset_library(
[mappings](AssetLibrary &library) { library.remap_ids_and_remove_invalid(*mappings); },
true);
[mappings](AssetLibrary &library) { library.remap_ids_and_remove_invalid(mappings); }, true);
}
void AS_asset_full_path_explode_from_weak_ref(const AssetWeakReference *asset_reference,
@ -239,7 +215,7 @@ bool AssetLibrary::remove_asset(AssetRepresentation &asset)
return asset_storage_->remove_asset(asset);
}
void AssetLibrary::remap_ids_and_remove_invalid(const IDRemapper &mappings)
void AssetLibrary::remap_ids_and_remove_invalid(const bke::id::IDRemapper &mappings)
{
asset_storage_->remap_ids_and_remove_invalid(mappings);
}

View File

@ -15,7 +15,7 @@ OnDiskAssetLibrary::OnDiskAssetLibrary(eAssetLibraryType library_type,
StringRef root_path)
: AssetLibrary(library_type, name, root_path)
{
on_blend_save_handler_register();
this->on_blend_save_handler_register();
}
void OnDiskAssetLibrary::refresh_catalogs()

View File

@ -12,7 +12,7 @@ namespace blender::asset_system {
RuntimeAssetLibrary::RuntimeAssetLibrary() : AssetLibrary(ASSET_LIBRARY_LOCAL)
{
on_blend_save_handler_register();
this->on_blend_save_handler_register();
}
} // namespace blender::asset_system

View File

@ -74,7 +74,7 @@ AssetLibrary *AssetLibraryService::get_asset_library(
return nullptr;
}
return get_asset_library_on_disk_builtin(type, root_path);
return this->get_asset_library_on_disk_builtin(type, root_path);
}
case ASSET_LIBRARY_LOCAL: {
/* For the "Current File" library we get the asset library root path based on main. */
@ -83,14 +83,14 @@ AssetLibrary *AssetLibraryService::get_asset_library(
if (root_path.empty()) {
/* File wasn't saved yet. */
return get_asset_library_current_file();
return this->get_asset_library_current_file();
}
return get_asset_library_on_disk_builtin(type, root_path);
return this->get_asset_library_on_disk_builtin(type, root_path);
}
case ASSET_LIBRARY_ALL:
return get_asset_library_all(bmain);
return this->get_asset_library_all(bmain);
case ASSET_LIBRARY_CUSTOM: {
bUserAssetLibrary *custom_library = find_custom_asset_library_from_library_ref(
bUserAssetLibrary *custom_library = this->find_custom_asset_library_from_library_ref(
library_reference);
if (!custom_library) {
return nullptr;
@ -101,7 +101,8 @@ AssetLibrary *AssetLibraryService::get_asset_library(
return nullptr;
}
AssetLibrary *library = get_asset_library_on_disk_custom(custom_library->name, root_path);
AssetLibrary *library = this->get_asset_library_on_disk_custom(custom_library->name,
root_path);
library->import_method_ = eAssetImportMethod(custom_library->import_method);
library->may_override_import_method_ = true;
library->use_relative_path_ = (custom_library->flag & ASSET_LIBRARY_RELATIVE_PATH) != 0;
@ -156,7 +157,7 @@ AssetLibrary *AssetLibraryService::get_asset_library_on_disk(eAssetLibraryType l
AssetLibrary *AssetLibraryService::get_asset_library_on_disk_custom(StringRef name,
StringRefNull root_path)
{
return get_asset_library_on_disk(ASSET_LIBRARY_CUSTOM, name, root_path);
return this->get_asset_library_on_disk(ASSET_LIBRARY_CUSTOM, name, root_path);
}
AssetLibrary *AssetLibraryService::get_asset_library_on_disk_builtin(eAssetLibraryType type,
@ -168,7 +169,7 @@ AssetLibrary *AssetLibraryService::get_asset_library_on_disk_builtin(eAssetLibra
/* Builtin asset libraries don't need a name, the #eAssetLibraryType is enough to identify them
* (and doesn't change, unlike the name). */
return get_asset_library_on_disk(type, {}, root_path);
return this->get_asset_library_on_disk(type, {}, root_path);
}
AssetLibrary *AssetLibraryService::get_asset_library_current_file()
@ -203,7 +204,7 @@ AssetLibrary *AssetLibraryService::get_asset_library_all(const Main *bmain)
}
/* Ensure all asset libraries are loaded. */
get_asset_library(bmain, library_ref);
this->get_asset_library(bmain, library_ref);
}
if (all_library_) {
@ -249,8 +250,8 @@ std::string AssetLibraryService::resolve_asset_weak_reference_to_library_path(
switch (eAssetLibraryType(asset_reference.asset_library_type)) {
case ASSET_LIBRARY_CUSTOM: {
bUserAssetLibrary *custom_lib = find_custom_preferences_asset_library_from_asset_weak_ref(
asset_reference);
bUserAssetLibrary *custom_lib =
this->find_custom_preferences_asset_library_from_asset_weak_ref(asset_reference);
if (custom_lib) {
library_dirpath = custom_lib->dirpath;
break;
@ -258,7 +259,7 @@ std::string AssetLibraryService::resolve_asset_weak_reference_to_library_path(
/* A bit of an odd-ball, the API supports loading custom libraries from arbitrary paths (used
* by unit tests). So check all loaded on-disk libraries too. */
AssetLibrary *loaded_custom_lib = find_loaded_on_disk_asset_library_from_name(
AssetLibrary *loaded_custom_lib = this->find_loaded_on_disk_asset_library_from_name(
asset_reference.asset_library_identifier);
if (!loaded_custom_lib) {
return "";
@ -368,7 +369,7 @@ std::optional<AssetLibraryService::ExplodedPath> AssetLibraryService::
switch (eAssetLibraryType(asset_reference.asset_library_type)) {
case ASSET_LIBRARY_LOCAL: {
std::string path_in_file = normalize_asset_weak_reference_relative_asset_identifier(
std::string path_in_file = this->normalize_asset_weak_reference_relative_asset_identifier(
asset_reference);
const int64_t group_len = int64_t(path_in_file.find(SEP));
@ -381,14 +382,14 @@ std::optional<AssetLibraryService::ExplodedPath> AssetLibraryService::
}
case ASSET_LIBRARY_CUSTOM:
case ASSET_LIBRARY_ESSENTIALS: {
std::string full_path = resolve_asset_weak_reference_to_full_path(asset_reference);
std::string full_path = this->resolve_asset_weak_reference_to_full_path(asset_reference);
/* #full_path uses native slashes, so others don't need to be considered in the following. */
if (full_path.empty()) {
return std::nullopt;
}
int64_t blendfile_extension_pos = rfind_blendfile_extension(full_path);
int64_t blendfile_extension_pos = this->rfind_blendfile_extension(full_path);
BLI_assert(blendfile_extension_pos != StringRef::not_found);
size_t group_pos = full_path.find(SEP, blendfile_extension_pos);

View File

@ -43,7 +43,7 @@ bool AssetStorage::remove_asset(AssetRepresentation &asset)
return external_assets_.remove_as(&asset);
}
void AssetStorage::remap_ids_and_remove_invalid(const IDRemapper &mappings)
void AssetStorage::remap_ids_and_remove_invalid(const blender::bke::id::IDRemapper &mappings)
{
Set<AssetRepresentation *> removed_assets{};
@ -51,8 +51,8 @@ void AssetStorage::remap_ids_and_remove_invalid(const IDRemapper &mappings)
AssetRepresentation &asset = *asset_ptr;
BLI_assert(asset.is_local_id());
const IDRemapperApplyResult result = BKE_id_remapper_apply(
&mappings, &asset.local_asset_id_, ID_REMAP_APPLY_DEFAULT);
const IDRemapperApplyResult result = mappings.apply(&asset.local_asset_id_,
ID_REMAP_APPLY_DEFAULT);
/* Entirely remove assets whose ID is unset. We don't want assets with a null ID pointer. */
if (result == ID_REMAP_RESULT_SOURCE_UNASSIGNED) {

View File

@ -17,7 +17,10 @@
struct AssetMetaData;
struct ID;
struct IDRemapper;
namespace blender::bke::id {
class IDRemapper;
}
namespace blender::asset_system {
@ -49,7 +52,7 @@ class AssetStorage {
bool remove_asset(AssetRepresentation &asset);
/** See #AssetLibrary::remap_ids_and_remove_nulled(). */
void remap_ids_and_remove_invalid(const IDRemapper &mappings);
void remap_ids_and_remove_invalid(const blender::bke::id::IDRemapper &mappings);
};
} // namespace blender::asset_system

View File

@ -46,7 +46,7 @@
#include "blf_internal.hh"
#include "blf_internal_types.hh"
#include "BLI_strict_flags.h"
#include "BLI_strict_flags.h" /* Keep last. */
#ifdef WIN32
# define FT_New_Face FT_New_Face__win32_compat

View File

@ -38,9 +38,10 @@
#include "blf_internal_types.hh"
#include "BLI_math_vector.h"
#include "BLI_strict_flags.h"
#include "BLI_string_utf8.h"
#include "BLI_strict_flags.h" /* Keep last. */
/**
* Convert glyph coverage amounts to lightness values. Uses a LUT that perceptually improves
* anti-aliasing and results in text that looks a bit fuller and slightly brighter. This should

View File

@ -11,13 +11,19 @@
#include "GPU_texture.h"
#include "GPU_vertex_buffer.h"
struct ColorManagedDisplay;
struct FontBLF;
struct GPUBatch;
struct GPUVertBuf;
struct GPUVertBufRaw;
#include FT_MULTIPLE_MASTERS_H /* Variable font support. */
/** Maximum variation axes per font. */
#define BLF_VARIATIONS_MAX 16
#define MAKE_DVAR_TAG(a, b, c, d) \
(((uint32_t)a << 24u) | ((uint32_t)b << 16u) | ((uint32_t)c << 8u) | ((uint32_t)d))
((uint32_t(a) << 24u) | (uint32_t(b) << 16u) | (uint32_t(c) << 8u) | (uint32_t(d)))
#define BLF_VARIATION_AXIS_WEIGHT MAKE_DVAR_TAG('w', 'g', 'h', 't') /* 'wght' weight axis. */
#define BLF_VARIATION_AXIS_SLANT MAKE_DVAR_TAG('s', 'l', 'n', 't') /* 'slnt' slant axis. */
@ -44,27 +50,27 @@ typedef int32_t ft_pix;
#define FT_PIX_ROUND(x) FT_PIX_FLOOR((x) + 32)
#define FT_PIX_CEIL(x) ((x) + 63)
BLI_INLINE int ft_pix_to_int(ft_pix v)
inline int ft_pix_to_int(ft_pix v)
{
return (int)(v >> 6);
return int(v >> 6);
}
BLI_INLINE int ft_pix_to_int_floor(ft_pix v)
inline int ft_pix_to_int_floor(ft_pix v)
{
return (int)(v >> 6); /* No need for explicit floor as the bits are removed when shifting. */
return int(v >> 6); /* No need for explicit floor as the bits are removed when shifting. */
}
BLI_INLINE int ft_pix_to_int_ceil(ft_pix v)
inline int ft_pix_to_int_ceil(ft_pix v)
{
return (int)(FT_PIX_CEIL(v) >> 6);
return int(FT_PIX_CEIL(v) >> 6);
}
BLI_INLINE ft_pix ft_pix_from_int(int v)
inline ft_pix ft_pix_from_int(int v)
{
return v * 64;
}
BLI_INLINE ft_pix ft_pix_from_float(float v)
inline ft_pix ft_pix_from_float(float v)
{
return lroundf(v * 64.0f);
}
@ -79,12 +85,12 @@ BLI_INLINE ft_pix ft_pix_from_float(float v)
/** A value in the kerning cache that indicates it is not yet set. */
#define KERNING_ENTRY_UNSET INT_MAX
typedef struct BatchBLF {
struct BatchBLF {
/** Can only batch glyph from the same font. */
struct FontBLF *font;
struct GPUBatch *batch;
struct GPUVertBuf *verts;
struct GPUVertBufRaw pos_step, col_step, offset_step, glyph_size_step, glyph_comp_len_step,
FontBLF *font;
GPUBatch *batch;
GPUVertBuf *verts;
GPUVertBufRaw pos_step, col_step, offset_step, glyph_size_step, glyph_comp_len_step,
glyph_mode_step;
unsigned int pos_loc, col_loc, offset_loc, glyph_size_loc, glyph_comp_len_loc, glyph_mode_loc;
unsigned int glyph_len;
@ -93,22 +99,22 @@ typedef struct BatchBLF {
/* Previous call `modelmatrix`. */
float mat[4][4];
bool enabled, active, simple_shader;
struct GlyphCacheBLF *glyph_cache;
} BatchBLF;
GlyphCacheBLF *glyph_cache;
};
extern BatchBLF g_batch;
typedef struct KerningCacheBLF {
struct KerningCacheBLF {
/**
* Cache a ascii glyph pairs. Only store the x offset we are interested in,
* instead of the full #FT_Vector since it's not used for drawing at the moment.
*/
int ascii_table[KERNING_CACHE_TABLE_SIZE][KERNING_CACHE_TABLE_SIZE];
} KerningCacheBLF;
};
typedef struct GlyphCacheBLF {
struct GlyphCacheBLF *next;
struct GlyphCacheBLF *prev;
struct GlyphCacheBLF {
GlyphCacheBLF *next;
GlyphCacheBLF *prev;
/** Font size. */
float size;
@ -133,12 +139,11 @@ typedef struct GlyphCacheBLF {
int bitmap_len;
int bitmap_len_landed;
int bitmap_len_alloc;
};
} GlyphCacheBLF;
typedef struct GlyphBLF {
struct GlyphBLF *next;
struct GlyphBLF *prev;
struct GlyphBLF {
GlyphBLF *next;
GlyphBLF *prev;
/** The character, as UTF-32. */
unsigned int c;
@ -183,10 +188,10 @@ typedef struct GlyphBLF {
*/
int pos[2];
struct GlyphCacheBLF *glyph_cache;
} GlyphBLF;
GlyphCacheBLF *glyph_cache;
};
typedef struct FontBufInfoBLF {
struct FontBufInfoBLF {
/** For draw to buffer, always set this to NULL after finish! */
float *fbuf;
@ -200,17 +205,16 @@ typedef struct FontBufInfoBLF {
int ch;
/** Display device used for color management. */
struct ColorManagedDisplay *display;
ColorManagedDisplay *display;
/** The color, the alphas is get from the glyph! (color is sRGB space). */
float col_init[4];
/** Cached conversion from 'col_init'. */
unsigned char col_char[4];
float col_float[4];
};
} FontBufInfoBLF;
typedef struct FontMetrics {
struct FontMetrics {
/** Indicate that these values have been properly loaded. */
bool valid;
/** This font's default weight, 100-900, 400 is normal. */
@ -274,9 +278,9 @@ typedef struct FontMetrics {
short superscript_xoffset;
/** Positive (!) number of font units below baseline for subscript characters. */
short superscript_yoffset;
} FontMetrics;
};
typedef struct FontBLF {
struct FontBLF {
/** Full path to font file or NULL if from memory. */
char *filepath;
@ -382,4 +386,4 @@ typedef struct FontBLF {
/** Mutex lock for glyph cache. */
ThreadMutex glyph_cache_mutex;
} FontBLF;
};

View File

@ -33,7 +33,7 @@
#include "BLF_api.hh"
#include "BLI_strict_flags.h"
#include "BLI_strict_flags.h" /* Keep last. */
/* Maximum length of text sample in char32_t, including nullptr terminator. */
#define BLF_SAMPLE_LEN 5

View File

@ -35,7 +35,8 @@ inline void convert_to_static_type(const CPPType &cpp_type, const Func &func)
int8_t,
ColorGeometry4f,
ColorGeometry4b,
math::Quaternion>([&](auto type_tag) {
math::Quaternion,
float4x4>([&](auto type_tag) {
using T = typename decltype(type_tag)::type;
if constexpr (std::is_same_v<T, void>) {
/* It's expected that the given cpp type is one of the supported ones. */
@ -517,6 +518,26 @@ class ColorGeometry4bMixer {
void finalize(const IndexMask &mask);
};
class float4x4Mixer {
private:
MutableSpan<float4x4> buffer_;
Array<float> total_weights_;
Array<float3> location_buffer_;
Array<float3> expmap_buffer_;
Array<float3> scale_buffer_;
public:
float4x4Mixer(MutableSpan<float4x4> buffer);
/**
* \param mask: Only initialize these indices. Other indices in the buffer will be invalid.
*/
float4x4Mixer(MutableSpan<float4x4> buffer, const IndexMask &mask);
void set(int64_t index, const float4x4 &value, float weight = 1.0f);
void mix_in(int64_t index, const float4x4 &value, float weight = 1.0f);
void finalize();
void finalize(const IndexMask &mask);
};
template<typename T> struct DefaultMixerStruct {
/* Use void by default. This can be checked for in `if constexpr` statements. */
using type = void;
@ -538,6 +559,9 @@ template<> struct DefaultMixerStruct<ColorGeometry4f> {
template<> struct DefaultMixerStruct<ColorGeometry4b> {
using type = ColorGeometry4bMixer;
};
template<> struct DefaultMixerStruct<float4x4> {
using type = float4x4Mixer;
};
template<> struct DefaultMixerStruct<int> {
static double int_to_double(const int &value)
{

View File

@ -29,7 +29,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 2
#define BLENDER_FILE_SUBVERSION 3
/* 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

@ -75,10 +75,10 @@ struct BPathForeachPathData;
* \return `true` if the path has been changed, and in that case,
* result must be written to `path_dst`.
*/
typedef bool (*BPathForeachPathFunctionCallback)(BPathForeachPathData *bpath_data,
char *path_dst,
size_t path_dst_maxncpy,
const char *path_src);
using BPathForeachPathFunctionCallback = bool (*)(BPathForeachPathData *bpath_data,
char *path_dst,
size_t path_dst_maxncpy,
const char *path_src);
/** Storage for common data needed across the BPath 'foreach_path' code. */
struct BPathForeachPathData {

View File

@ -12,6 +12,7 @@
#include <mutex>
#include "BLI_bit_span.hh"
#include "BLI_index_mask_fwd.hh"
#include "BLI_kdopbvh.h"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
@ -114,6 +115,13 @@ BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
BVHCacheType bvh_cache_type,
int tree_type);
/**
* Build a bvh tree from the triangles in the mesh that correspond to the faces in the given mask.
*/
void BKE_bvhtree_from_mesh_tris_init(const Mesh &mesh,
const blender::IndexMask &faces_mask,
BVHTreeFromMesh &r_data);
/**
* Frees data allocated by a call to `bvhtree_from_mesh_*`.
*/

View File

@ -69,7 +69,7 @@ struct PointerRNA;
* All callbacks here must be exposed via the Python module `bpy.app.handlers`,
* see `bpy_app_handlers.cc`.
*/
typedef enum {
enum eCbEvent {
BKE_CB_EVT_FRAME_CHANGE_PRE,
BKE_CB_EVT_FRAME_CHANGE_POST,
BKE_CB_EVT_RENDER_PRE,
@ -111,7 +111,7 @@ typedef enum {
BKE_CB_EVT_EXTENSION_REPOS_SYNC,
BKE_CB_EVT_EXTENSION_REPOS_UPGRADE,
BKE_CB_EVT_TOT,
} eCbEvent;
};
struct bCallbackFuncStore {
bCallbackFuncStore *next, *prev;

View File

@ -312,8 +312,8 @@ void BKE_collection_blend_read_data(BlendDataReader *reader, Collection *collect
/* Iteration callbacks. */
typedef void (*BKE_scene_objects_Cb)(Object *ob, void *data);
typedef void (*BKE_scene_collections_Cb)(Collection *ob, void *data);
using BKE_scene_objects_Cb = void (*)(Object *ob, void *data);
using BKE_scene_collections_Cb = void (*)(Collection *ob, void *data);
/* Iteration over objects in collection. */

View File

@ -32,7 +32,7 @@ struct Object;
struct rctf;
struct TextBox;
typedef int eBezTriple_Flag__Alias;
using eBezTriple_Flag__Alias = int;
struct CurveCache {
ListBase disp;

View File

@ -73,7 +73,7 @@ extern const CustomData_MeshMasks CD_MASK_EVERYTHING;
* CD_NUMTYPES elements, that indicate if a layer can be copied. */
/** Add/copy/merge allocation types. */
typedef enum eCDAllocType {
enum eCDAllocType {
/** Allocate and set to default, which is usually just zeroed memory. */
CD_SET_DEFAULT = 2,
/**
@ -81,18 +81,18 @@ typedef enum eCDAllocType {
* if all layer values will be set by the caller after creating the layer.
*/
CD_CONSTRUCT = 5,
} eCDAllocType;
};
#define CD_TYPE_AS_MASK(_type) (eCustomDataMask)((eCustomDataMask)1 << (eCustomDataMask)(_type))
void customData_mask_layers__print(const CustomData_MeshMasks *mask);
typedef void (*cd_interp)(
using cd_interp = void (*)(
const void **sources, const float *weights, const float *sub_weights, int count, void *dest);
typedef void (*cd_copy)(const void *source, void *dest, int count);
typedef void (*cd_set_default_value)(void *data, int count);
typedef void (*cd_free)(void *data, int count);
typedef bool (*cd_validate)(void *item, uint totitems, bool do_fixes);
using cd_copy = void (*)(const void *source, void *dest, int count);
using cd_set_default_value = void (*)(void *data, int count);
using cd_free = void (*)(void *data, int count);
using cd_validate = bool (*)(void *item, uint totitems, bool do_fixes);
/**
* Update mask_dst with layers defined in mask_src (equivalent to a bit-wise OR).

View File

@ -1,25 +1,13 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bke
*/
#ifdef __cplusplus
namespace blender::bke {
struct GeometrySet;
}
using GeometrySetHandle = blender::bke::GeometrySet;
#else
typedef struct GeometrySetHandle GeometrySetHandle;
#endif
#ifdef __cplusplus
extern "C" {
#endif
struct Depsgraph;
struct ID;
struct ListBase;
@ -28,6 +16,9 @@ struct ParticleSystem;
struct Scene;
struct ViewLayer;
struct ViewerPath;
namespace blender::bke {
struct GeometrySet;
}
/* ---------------------------------------------------- */
/* Dupli-Geometry */
@ -35,31 +26,29 @@ struct ViewerPath;
/**
* \return a #ListBase of #DupliObject.
*/
struct ListBase *object_duplilist(struct Depsgraph *depsgraph,
struct Scene *sce,
struct Object *ob);
ListBase *object_duplilist(Depsgraph *depsgraph, Scene *sce, Object *ob);
/**
* \return a #ListBase of #DupliObject for the preview geometry referenced by the #ViewerPath.
*/
struct ListBase *object_duplilist_preview(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
const struct ViewerPath *viewer_path);
void free_object_duplilist(struct ListBase *lb);
ListBase *object_duplilist_preview(Depsgraph *depsgraph,
Scene *scene,
Object *ob,
const ViewerPath *viewer_path);
void free_object_duplilist(ListBase *lb);
typedef struct DupliObject {
struct DupliObject *next, *prev;
struct DupliObject {
DupliObject *next, *prev;
/* Object whose geometry is instanced. */
struct Object *ob;
Object *ob;
/* Data owned by the object above that is instanced. This might not be the same as `ob->data`. */
struct ID *ob_data;
ID *ob_data;
float mat[4][4];
float orco[3], uv[2];
short type; /* from Object.transflag */
short type; /* From #Object::transflag. */
char no_draw;
/* If this dupli object is belongs to a preview, this is non-null. */
const GeometrySetHandle *preview_base_geometry;
const blender::bke::GeometrySet *preview_base_geometry;
/* Index of the top-level instance this dupli is part of or -1 when unused. */
int preview_instance_index;
@ -68,7 +57,7 @@ typedef struct DupliObject {
int persistent_id[8]; /* MAX_DUPLI_RECUR */
/* Particle this dupli was generated from. */
struct ParticleSystem *particle_system;
ParticleSystem *particle_system;
/* Geometry set stack for instance attributes; for each level lists the
* geometry set and instance index within it.
@ -79,19 +68,19 @@ typedef struct DupliObject {
* size between 1 and MAX_DUPLI_RECUR can be used without issues.
*/
int instance_idx[4];
const GeometrySetHandle *instance_data[4];
const blender::bke::GeometrySet *instance_data[4];
/* Random ID for shading */
unsigned int random_id;
} DupliObject;
};
/**
* Look up the RGBA value of a uniform shader attribute.
* \return true if the attribute was found; if not, r_value is also set to zero.
*/
bool BKE_object_dupli_find_rgba_attribute(const struct Object *ob,
const struct DupliObject *dupli,
const struct Object *dupli_parent,
bool BKE_object_dupli_find_rgba_attribute(const Object *ob,
const DupliObject *dupli,
const Object *dupli_parent,
const char *name,
float r_value[4]);
@ -99,11 +88,7 @@ bool BKE_object_dupli_find_rgba_attribute(const struct Object *ob,
* Look up the RGBA value of a view layer/scene/world shader attribute.
* \return true if the attribute was found; if not, r_value is also set to zero.
*/
bool BKE_view_layer_find_rgba_attribute(const struct Scene *scene,
const struct ViewLayer *layer,
bool BKE_view_layer_find_rgba_attribute(const Scene *scene,
const ViewLayer *layer,
const char *name,
float r_value[4]);
#ifdef __cplusplus
}
#endif

View File

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

View File

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

View File

@ -60,40 +60,40 @@ bool BKE_idtype_cache_key_cmp(const void *key_a_v, const void *key_b_v);
/* ********** Prototypes for #IDTypeInfo callbacks. ********** */
typedef void (*IDTypeInitDataFunction)(ID *id);
using IDTypeInitDataFunction = void (*)(ID *id);
/** \param flag: Copying options (see BKE_lib_id.hh's LIB_ID_COPY_... flags for more). */
typedef void (*IDTypeCopyDataFunction)(Main *bmain, ID *id_dst, const ID *id_src, int flag);
using IDTypeCopyDataFunction = void (*)(Main *bmain, ID *id_dst, const ID *id_src, int flag);
typedef void (*IDTypeFreeDataFunction)(ID *id);
using IDTypeFreeDataFunction = void (*)(ID *id);
/** \param flags: See BKE_lib_id.hh's LIB_ID_MAKELOCAL_... flags. */
typedef void (*IDTypeMakeLocalFunction)(Main *bmain, ID *id, int flags);
using IDTypeMakeLocalFunction = void (*)(Main *bmain, ID *id, int flags);
typedef void (*IDTypeForeachIDFunction)(ID *id, LibraryForeachIDData *data);
using IDTypeForeachIDFunction = void (*)(ID *id, LibraryForeachIDData *data);
typedef enum eIDTypeInfoCacheCallbackFlags {
enum eIDTypeInfoCacheCallbackFlags {
/** Indicates to the callback that cache may be stored in the .blend file,
* so its pointer should not be cleared at read-time. */
IDTYPE_CACHE_CB_FLAGS_PERSISTENT = 1 << 0,
} eIDTypeInfoCacheCallbackFlags;
typedef void (*IDTypeForeachCacheFunctionCallback)(
ID *id, const IDCacheKey *cache_key, void **cache_p, uint flags, void *user_data);
typedef void (*IDTypeForeachCacheFunction)(ID *id,
IDTypeForeachCacheFunctionCallback function_callback,
void *user_data);
};
using IDTypeForeachCacheFunctionCallback =
void (*)(ID *id, const IDCacheKey *cache_key, void **cache_p, uint flags, void *user_data);
using IDTypeForeachCacheFunction = void (*)(ID *id,
IDTypeForeachCacheFunctionCallback function_callback,
void *user_data);
typedef void (*IDTypeForeachPathFunction)(ID *id, BPathForeachPathData *bpath_data);
using IDTypeForeachPathFunction = void (*)(ID *id, BPathForeachPathData *bpath_data);
typedef ID **(*IDTypeEmbeddedOwnerPointerGetFunction)(ID *id);
using IDTypeEmbeddedOwnerPointerGetFunction = ID **(*)(ID *id);
typedef void (*IDTypeBlendWriteFunction)(BlendWriter *writer, ID *id, const void *id_address);
typedef void (*IDTypeBlendReadDataFunction)(BlendDataReader *reader, ID *id);
typedef void (*IDTypeBlendReadAfterLiblinkFunction)(BlendLibReader *reader, ID *id);
using IDTypeBlendWriteFunction = void (*)(BlendWriter *writer, ID *id, const void *id_address);
using IDTypeBlendReadDataFunction = void (*)(BlendDataReader *reader, ID *id);
using IDTypeBlendReadAfterLiblinkFunction = void (*)(BlendLibReader *reader, ID *id);
typedef void (*IDTypeBlendReadUndoPreserve)(BlendLibReader *reader, ID *id_new, ID *id_old);
using IDTypeBlendReadUndoPreserve = void (*)(BlendLibReader *reader, ID *id_new, ID *id_old);
typedef void (*IDTypeLibOverrideApplyPost)(ID *id_dst, ID *id_src);
using IDTypeLibOverrideApplyPost = void (*)(ID *id_dst, ID *id_src);
struct IDTypeInfo {
/* ********** General IDType data. ********** */
@ -109,6 +109,14 @@ struct IDTypeInfo {
*/
uint64_t id_filter;
/**
* Known types of ID dependencies.
*
* Used by #BKE_library_id_can_use_filter_id, together with additional runtime heuristics, to
* generate a filter value containing only ID types that given ID could be using.
*/
uint64_t dependencies_id_types;
/**
* Define the position of this data-block type in the virtual list of all data in a Main that is
* returned by `set_listbasepointers()`.
@ -337,6 +345,24 @@ bool BKE_idtype_idcode_append_is_reusable(short idcode);
*/
short BKE_idtype_idcode_from_name(const char *idtype_name);
/**
* Convert an \a idcode into an \a idtype_index (e.g. #ID_OB -> #INDEX_ID_OB).
*/
int BKE_idtype_idcode_to_index(short idcode);
/**
* Convert an \a idfilter into an \a idtype_index (e.g. #FILTER_ID_OB -> #INDEX_ID_OB).
*/
int BKE_idtype_idfilter_to_index(uint64_t idfilter);
/**
* Convert an \a idtype_index into an \a idcode (e.g. #INDEX_ID_OB -> #ID_OB).
*/
short BKE_idtype_index_to_idcode(int idtype_index);
/**
* Convert an \a idtype_index into an \a idfilter (e.g. #INDEX_ID_OB -> #FILTER_ID_OB).
*/
uint64_t BKE_idtype_index_to_idfilter(int idtype_index);
/**
* Convert an \a idcode into an \a idfilter (e.g. #ID_OB -> #FILTER_ID_OB).
*/
@ -344,16 +370,7 @@ uint64_t BKE_idtype_idcode_to_idfilter(short idcode);
/**
* Convert an \a idfilter into an \a idcode (e.g. #FILTER_ID_OB -> #ID_OB).
*/
short BKE_idtype_idcode_from_idfilter(uint64_t idfilter);
/**
* Convert an \a idcode into an index (e.g. #ID_OB -> #INDEX_ID_OB).
*/
int BKE_idtype_idcode_to_index(short idcode);
/**
* Get an \a idcode from an index (e.g. #INDEX_ID_OB -> #ID_OB).
*/
short BKE_idtype_idcode_from_index(int index);
short BKE_idtype_idfilter_to_idcode(uint64_t idfilter);
/**
* Return an ID code and steps the index forward 1.
@ -361,7 +378,7 @@ short BKE_idtype_idcode_from_index(int index);
* \param index: start as 0.
* \return the code, 0 when all codes have been returned.
*/
short BKE_idtype_idcode_iter_step(int *index);
short BKE_idtype_idcode_iter_step(int *idtype_index);
/* Some helpers/wrappers around callbacks defined in #IDTypeInfo, dealing e.g. with embedded IDs.
* XXX Ideally those would rather belong to #BKE_lib_id, but using callback function pointers makes

View File

@ -33,6 +33,8 @@
#include "BLI_compiler_attrs.h"
#include "BLI_utildefines.h"
#include "BLI_set.hh"
#include "DNA_userdef_enums.h"
struct BlendWriter;
@ -212,7 +214,7 @@ ID *BKE_libblock_find_name_and_library(Main *bmain,
* Duplicate (a.k.a. deep copy) common processing options.
* See also eDupli_ID_Flags for options controlling what kind of IDs to duplicate.
*/
typedef enum eLibIDDuplicateFlags {
enum eLibIDDuplicateFlags {
/** This call to a duplicate function is part of another call for some parent ID.
* Therefore, this sub-process should not clear `newid` pointers, nor handle remapping itself.
* NOTE: In some cases (like Object one), the duplicate function may be called on the root ID
@ -222,7 +224,7 @@ typedef enum eLibIDDuplicateFlags {
/** This call is performed on a 'root' ID, and should therefore perform some decisions regarding
* sub-IDs (dependencies), check for linked vs. locale data, etc. */
LIB_ID_DUPLICATE_IS_ROOT_ID = 1 << 1,
} eLibIDDuplicateFlags;
};
ENUM_OPERATORS(eLibIDDuplicateFlags, LIB_ID_DUPLICATE_IS_ROOT_ID)
@ -319,11 +321,23 @@ void BKE_id_delete_ex(Main *bmain, void *idv, const int extra_remapping_flags) A
* This is more efficient than calling #BKE_id_delete repetitively on a large set of IDs
* (several times faster when deleting most of the IDs at once).
*
* \warning Considered experimental for now, seems to be working OK but this is
* risky code in a complicated area.
* \return Number of deleted data-blocks.
*/
size_t BKE_id_multi_tagged_delete(Main *bmain) ATTR_NONNULL();
/**
* Properly delete all IDs from \a ids_to_delete, from given \a bmain database.
*
* This is more efficient than calling #BKE_id_delete repetitively on a large set of IDs
* (several times faster when deleting most of the IDs at once).
*
* \note The ID pointers are not removed from the Set (which may contain more pointers than
* originally given, when extra users or dependencies also had to be deleted with the original set
* of IDs). They are all freed though, so these pointers are all invalid after calling this
* function.
*
* \return Number of deleted data-blocks.
*/
size_t BKE_id_multi_delete(Main *bmain, blender::Set<ID *> &ids_to_delete);
/**
* Add a 'NO_MAIN' data-block to given main (also sets user-counts of its IDs if needed).

View File

@ -25,6 +25,7 @@
#include <array>
struct IDTypeInfo;
struct LibraryForeachIDData;
struct Main;
@ -141,7 +142,7 @@ struct LibraryIDLinkCallbackData {
*
* \return a set of flags to control further iteration (0 to keep going).
*/
typedef int (*LibraryIDLinkCallback)(LibraryIDLinkCallbackData *cb_data);
using LibraryIDLinkCallback = int (*)(LibraryIDLinkCallbackData *cb_data);
/* Flags for the foreach function itself. */
enum {
@ -299,7 +300,9 @@ bool BKE_library_id_can_use_idtype(ID *owner_id, short id_type_used);
/**
* Given the owner_id return the type of id_types it can use as a filter_id.
*/
uint64_t BKE_library_id_can_use_filter_id(const ID *owner_id, const bool include_ui);
uint64_t BKE_library_id_can_use_filter_id(const ID *owner_id,
const bool include_ui,
const IDTypeInfo *owner_id_type = nullptr);
/**
* Check whether given ID is used locally (i.e. by another non-linked ID).

View File

@ -21,13 +21,18 @@
*/
#include "BLI_compiler_attrs.h"
#include "BLI_map.hh"
#include "BLI_set.hh"
#include "BLI_span.hh"
#include "BLI_utildefines.h"
struct ID;
struct IDRemapper;
struct Main;
namespace blender::bke::id {
class IDRemapper;
}
/* BKE_libblock_free, delete are declared in BKE_lib_id.hh for convenience. */
/* Also IDRemap->flag. */
@ -44,10 +49,11 @@ enum {
*/
ID_REMAP_SKIP_NEVER_NULL_USAGE = 1 << 1,
/**
* This tells the callback func to flag with #LIB_DOIT all IDs
* using target one with a 'never NULL' pointer (like e.g. #Object.data).
* Store in the #IDRemapper all IDs using target one with a 'never NULL' pointer (like e.g.
* #Object.data), when such ID usage has (or should have) been remapped to `nullptr`. See also
* #ID_REMAP_FORCE_NEVER_NULL_USAGE and #ID_REMAP_SKIP_NEVER_NULL_USAGE.
*/
ID_REMAP_FLAG_NEVER_NULL_USAGE = 1 << 2,
ID_REMAP_STORE_NEVER_NULL_USAGE = 1 << 2,
/**
* This tells the callback func to force setting IDs
* using target one with a 'never NULL' pointer to NULL.
@ -124,9 +130,13 @@ enum eIDRemapType {
*
* \note Is preferred over BKE_libblock_remap_locked due to performance.
*/
void BKE_libblock_remap_multiple_locked(Main *bmain, IDRemapper *mappings, const int remap_flags);
void BKE_libblock_remap_multiple_locked(Main *bmain,
blender::bke::id::IDRemapper &mappings,
const int remap_flags);
void BKE_libblock_remap_multiple(Main *bmain, IDRemapper *mappings, const int remap_flags);
void BKE_libblock_remap_multiple(Main *bmain,
blender::bke::id::IDRemapper &mappings,
const int remap_flags);
/**
* Bare raw remapping of IDs, with no other processing than actually updating the ID pointers.
@ -137,7 +147,9 @@ void BKE_libblock_remap_multiple(Main *bmain, IDRemapper *mappings, const int re
* case e.g. in read-file process.
*
* WARNING: This call will likely leave the given BMain in invalid state in many aspects. */
void BKE_libblock_remap_multiple_raw(Main *bmain, IDRemapper *mappings, const int remap_flags);
void BKE_libblock_remap_multiple_raw(Main *bmain,
blender::bke::id::IDRemapper &mappings,
const int remap_flags);
/**
* Replace all references in given Main to \a old_id by \a new_id
* (if \a new_id is NULL, it unlinks \a old_id).
@ -153,12 +165,8 @@ void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, int remap_fla
/**
* Unlink given \a id from given \a bmain
* (does not touch to indirect, i.e. library, usages of the ID).
*
* \param do_flag_never_null: If true, all IDs using \a idv in a 'non-NULL' way are flagged by
* #LIB_TAG_DOIT flag (quite obviously, 'non-NULL' usages can never be unlinked by this function).
*/
void BKE_libblock_unlink(Main *bmain, void *idv, bool do_flag_never_null, bool do_skip_indirect)
ATTR_NONNULL();
void BKE_libblock_unlink(Main *bmain, void *idv, bool do_skip_indirect) ATTR_NONNULL();
/**
* Similar to libblock_remap, but only affects IDs used by given \a idv ID.
@ -178,7 +186,7 @@ void BKE_libblock_relink_ex(Main *bmain, void *idv, void *old_idv, void *new_idv
void BKE_libblock_relink_multiple(Main *bmain,
const blender::Span<ID *> ids,
eIDRemapType remap_type,
IDRemapper *id_remapper,
blender::bke::id::IDRemapper &id_remapper,
int remap_flags);
/**
@ -193,7 +201,8 @@ void BKE_libblock_relink_multiple(Main *bmain,
void BKE_libblock_relink_to_newid(Main *bmain, ID *id, int remap_flag) ATTR_NONNULL();
using BKE_library_free_notifier_reference_cb = void (*)(const void *);
using BKE_library_remap_editor_id_reference_cb = void (*)(const IDRemapper *mappings);
using BKE_library_remap_editor_id_reference_cb =
void (*)(const blender::bke::id::IDRemapper &mappings);
void BKE_library_callback_free_notifier_reference_set(BKE_library_free_notifier_reference_cb func);
void BKE_library_callback_remap_editor_id_reference_set(
@ -220,7 +229,7 @@ enum IDRemapperApplyOptions {
*
* NOTE: Currently unused by main remapping code, since user-count is handled by
* `foreach_libblock_remap_callback_apply` there, depending on whether the remapped pointer does
* use it or not. Need for rare cases in UI handling though (see e.g. `image_id_remap` in
* use it or not. Needed for rare cases in UI handling though (see e.g. `image_id_remap` in
* `space_image.cc`).
*/
ID_REMAP_APPLY_UPDATE_REFCOUNT = (1 << 0),
@ -233,9 +242,9 @@ enum IDRemapperApplyOptions {
ID_REMAP_APPLY_ENSURE_REAL = (1 << 1),
/**
* Unassign in stead of remap when the new ID data-block would become id_self.
* Unassign instead of remap when the new ID pointer would point to itself.
*
* To use this option 'BKE_id_remapper_apply_ex' must be used with a not-null id_self parameter.
* To use this option #IDRemapper::apply must be used with a non-null id_self parameter.
*/
ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF = (1 << 2),
@ -244,58 +253,83 @@ enum IDRemapperApplyOptions {
ENUM_OPERATORS(IDRemapperApplyOptions, ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF)
using IDRemapperIterFunction = void (*)(ID *old_id, ID *new_id, void *user_data);
using IDTypeFilter = uint64_t;
/**
* Create a new ID Remapper.
*
* An ID remapper stores multiple remapping rules.
*/
IDRemapper *BKE_id_remapper_create();
namespace blender::bke::id {
void BKE_id_remapper_clear(IDRemapper *id_remapper);
bool BKE_id_remapper_is_empty(const IDRemapper *id_remapper);
/** Free the given ID Remapper. */
void BKE_id_remapper_free(IDRemapper *id_remapper);
/** Add a new remapping. Does not replace an existing mapping for `old_id`, if any. */
void BKE_id_remapper_add(IDRemapper *id_remapper, ID *old_id, ID *new_id);
/** Add a new remapping, replacing a potential already existing mapping of `old_id`. */
void BKE_id_remapper_add_overwrite(IDRemapper *id_remapper, ID *old_id, ID *new_id);
class IDRemapper {
blender::Map<ID *, ID *> mappings_;
IDTypeFilter source_types_ = 0;
/**
* Apply a remapping.
*
* Update the id pointer stored in the given r_id_ptr if a remapping rule exists.
*/
IDRemapperApplyResult BKE_id_remapper_apply(const IDRemapper *id_remapper,
ID **r_id_ptr,
IDRemapperApplyOptions options);
/**
* Apply a remapping.
*
* Use this function when `ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF`. In this case
* the #id_self parameter is required. Otherwise the #BKE_id_remapper_apply can be used.
*
* \param id_self: required for ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF.
* When remapping to id_self it will then be remapped to NULL.
*/
IDRemapperApplyResult BKE_id_remapper_apply_ex(const IDRemapper *id_remapper,
ID **r_id_ptr,
IDRemapperApplyOptions options,
ID *id_self);
bool BKE_id_remapper_has_mapping_for(const IDRemapper *id_remapper, uint64_t type_filter);
/**
* Store all IDs using another ID with the 'NEVER_NULL' flag, which have (or
* should have been) remapped to `nullptr`.
*/
blender::Set<ID *> never_null_users_;
/**
* Determine the mapping result, without applying the mapping.
*/
IDRemapperApplyResult BKE_id_remapper_get_mapping_result(const IDRemapper *id_remapper,
ID *id,
IDRemapperApplyOptions options,
const ID *id_self);
void BKE_id_remapper_iter(const IDRemapper *id_remapper,
IDRemapperIterFunction func,
void *user_data);
public:
void clear(void)
{
mappings_.clear();
never_null_users_.clear();
source_types_ = 0;
}
/** Returns a readable string for the given result. Can be used for debugging purposes. */
const char *BKE_id_remapper_result_string(const IDRemapperApplyResult result);
/** Prints out the rules inside the given id_remapper. Can be used for debugging purposes. */
void BKE_id_remapper_print(const IDRemapper *id_remapper);
bool is_empty(void) const
{
return mappings_.is_empty();
}
bool contains_mappings_for_any(IDTypeFilter filter) const
{
return (source_types_ & filter) != 0;
}
/** Add a new remapping. Does not replace an existing mapping for `old_id`, if any. */
void add(ID *old_id, ID *new_id);
/** Add a new remapping, replacing a potential already existing mapping of `old_id`. */
void add_overwrite(ID *old_id, ID *new_id);
/** Determine the mapping result, without applying the mapping. */
IDRemapperApplyResult get_mapping_result(ID *id,
IDRemapperApplyOptions options,
const ID *id_self) const;
/**
* Apply a remapping.
*
* Update the id pointer stored in the given r_id_ptr if a remapping rule exists.
*
* \param id_self: Only for ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF.
* When remapping to `id_self` it will then be remapped to `nullptr` instead.
*/
IDRemapperApplyResult apply(ID **r_id_ptr,
IDRemapperApplyOptions options,
ID *id_self = nullptr) const;
void never_null_users_add(ID *id)
{
never_null_users_.add(id);
}
const blender::Set<ID *> &never_null_users(void) const
{
return never_null_users_;
}
/** Iterate over all remapping pairs in the remapper, and call the callback function on them. */
void iter(IDRemapperIterFunction func, void *user_data) const
{
for (auto item : mappings_.items()) {
func(item.key, item.value, user_data);
}
}
/** Return a readable string for the given result. Can be used for debugging purposes. */
static const blender::StringRefNull result_to_string(const IDRemapperApplyResult result);
/** Print out the rules inside the given id_remapper. Can be used for debugging purposes. */
void print(void) const;
};
} // namespace blender::bke::id

View File

@ -290,6 +290,17 @@ inline int face_triangles_num(const int face_size)
return face_size - 2;
}
/**
* Return the range of triangles that belong to the given face.
*/
inline IndexRange face_triangles_range(OffsetIndices<int> faces, int face_i)
{
const IndexRange face = faces[face_i];
/* This is the same as #poly_to_tri_count which is not included here. */
const int start_triangle = face.start() - face_i * 2;
return IndexRange(start_triangle, face_triangles_num(face.size()));
}
/**
* Return the index of the edge's vertex that is not the \a vert.
*/
@ -306,6 +317,9 @@ inline int edge_other_vert(const int2 edge, const int vert)
} // namespace mesh
/** Create a mesh with no built-in attributes. */
Mesh *mesh_new_no_attributes(int verts_num, int edges_num, int faces_num, int corners_num);
/** Calculate edges from faces. */
void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, bool select_new_edges);

View File

@ -1366,6 +1366,13 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define FN_NODE_ROTATE_VECTOR 1229
#define FN_NODE_ROTATE_ROTATION 1230
#define FN_NODE_INVERT_ROTATION 1231
#define FN_NODE_TRANSFORM_POINT 1232
#define FN_NODE_TRANSFORM_DIRECTION 1233
#define FN_NODE_MATRIX_MULTIPLY 1234
#define FN_NODE_COMBINE_TRANSFORM 1235
#define FN_NODE_SEPARATE_TRANSFORM 1236
#define FN_NODE_INVERT_MATRIX 1237
#define FN_NODE_TRANSPOSE_MATRIX 1238
/** \} */

View File

@ -130,6 +130,7 @@ static const bNodeSocketStaticTypeInfo node_socket_subtypes[] = {
{"NodeSocketIntFactor", "NodeTreeInterfaceSocketIntFactor", SOCK_INT, PROP_FACTOR},
{"NodeSocketBool", "NodeTreeInterfaceSocketBool", SOCK_BOOLEAN, PROP_NONE},
{"NodeSocketRotation", "NodeTreeInterfaceSocketRotation", SOCK_ROTATION, PROP_NONE},
{"NodeSocketMatrix", "NodeTreeInterfaceSocketMatrix", SOCK_MATRIX, PROP_NONE},
{"NodeSocketVector", "NodeTreeInterfaceSocketVector", SOCK_VECTOR, PROP_NONE},
{"NodeSocketVectorTranslation",
"NodeTreeInterfaceSocketVectorTranslation",
@ -206,6 +207,7 @@ template<typename Fn> bool socket_data_to_static_type(const eNodeSocketDatatype
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_MATRIX:
case SOCK_GEOMETRY:
return true;
}

View File

@ -319,7 +319,7 @@ blender::Vector<Base *> BKE_object_pose_base_array_get(const Scene *scene,
void BKE_object_get_parent_matrix(Object *ob, Object *par, float r_parentmat[4][4]);
/**
* Compute object world transform and store it in `ob->object_to_world`.
* Compute object world transform and store it in `ob->object_to_world().ptr()`.
*/
void BKE_object_where_is_calc(Depsgraph *depsgraph, Scene *scene, Object *ob);
void BKE_object_where_is_calc_ex(

View File

@ -26,6 +26,9 @@ namespace blender::bke {
struct GeometrySet;
struct ObjectRuntime {
/** Final transformation matrices with constraints & animsys applied. */
float4x4 object_to_world;
float4x4 world_to_object;
/**
* The custom data layer mask that was last used
* to calculate data_eval and mesh_deform_eval.

View File

@ -17,6 +17,10 @@
#include "BKE_context.hh"
namespace blender::bke::id {
class IDRemapper;
}
namespace blender::asset_system {
class AssetRepresentation;
}
@ -28,7 +32,6 @@ struct BlendLibReader;
struct BlendWriter;
struct Header;
struct ID;
struct IDRemapper;
struct LayoutPanelState;
struct LibraryForeachIDData;
struct ListBase;
@ -109,7 +112,7 @@ struct SpaceType {
bContextDataCallback context;
/* Used when we want to replace an ID by another (or NULL). */
void (*id_remap)(ScrArea *area, SpaceLink *sl, const IDRemapper *mappings);
void (*id_remap)(ScrArea *area, SpaceLink *sl, const blender::bke::id::IDRemapper &mappings);
/**
* foreach_id callback to process all ID pointers of the editor. Used indirectly by lib_query's

View File

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

View File

@ -29,7 +29,10 @@ struct BlendDataReader;
struct BlendLibReader;
struct LibraryForeachIDData;
struct Library;
struct IDRemapper;
namespace blender::bke::id {
class IDRemapper;
}
enum ViewerPathEqualFlag {
VIEWER_PATH_EQUAL_FLAG_IGNORE_REPEAT_ITERATION = (1 << 0),
@ -44,7 +47,8 @@ bool BKE_viewer_path_equal(const ViewerPath *a,
void BKE_viewer_path_blend_write(BlendWriter *writer, const ViewerPath *viewer_path);
void BKE_viewer_path_blend_read_data(BlendDataReader *reader, ViewerPath *viewer_path);
void BKE_viewer_path_foreach_id(LibraryForeachIDData *data, ViewerPath *viewer_path);
void BKE_viewer_path_id_remap(ViewerPath *viewer_path, const IDRemapper *mappings);
void BKE_viewer_path_id_remap(ViewerPath *viewer_path,
const blender::bke::id::IDRemapper &mappings);
ViewerPathElem *BKE_viewer_path_elem_new(ViewerPathElemType type);
IDViewerPathElem *BKE_viewer_path_elem_new_id();

View File

@ -0,0 +1,23 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "DNA_windowmanager_types.h"
namespace blender::bke {
class WindowManagerRuntime {
public:
/** Indicates whether interface is locked for user interaction. */
bool is_interface_locked = false;
/** Information and error reports. */
ReportList reports;
WindowManagerRuntime();
~WindowManagerRuntime();
};
} // namespace blender::bke

View File

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

View File

@ -315,6 +315,7 @@ set(SRC
intern/volume_grid_file_cache.cc
intern/volume_render.cc
intern/volume_to_mesh.cc
intern/wm_runtime.cc
intern/workspace.cc
intern/world.cc
intern/writeavi.cc
@ -381,7 +382,7 @@ set(SRC
BKE_data_transfer.h
BKE_deform.hh
BKE_displist.h
BKE_duplilist.h
BKE_duplilist.hh
BKE_dynamicpaint.h
BKE_editlattice.h
BKE_editmesh.hh
@ -522,6 +523,7 @@ set(SRC
BKE_volume_openvdb.hh
BKE_volume_render.hh
BKE_volume_to_mesh.hh
BKE_wm_runtime.hh
BKE_workspace.h
BKE_world.h
BKE_writeavi.h

View File

@ -268,6 +268,7 @@ static AssetTypeInfo AssetType_AC = {
IDTypeInfo IDType_ID_AC = {
/*id_code*/ ID_AC,
/*id_filter*/ FILTER_ID_AC,
/*dependencies_id_types*/ 0,
/*main_listbase_index*/ INDEX_ID_AC,
/*struct_size*/ sizeof(bAction),
/*name*/ "Action",
@ -1711,7 +1712,7 @@ void what_does_obaction(Object *ob,
workob->runtime = &workob_runtime;
/* init workob */
copy_m4_m4(workob->object_to_world, ob->object_to_world);
copy_m4_m4(workob->runtime->object_to_world.ptr(), ob->object_to_world().ptr());
copy_m4_m4(workob->parentinv, ob->parentinv);
copy_m4_m4(workob->constinv, ob->constinv);
workob->parent = ob->parent;

View File

@ -475,6 +475,8 @@ static void armature_undo_preserve(BlendLibReader * /*reader*/, ID *id_new, ID *
IDTypeInfo IDType_ID_AR = {
/*id_code*/ ID_AR,
/*id_filter*/ FILTER_ID_AR,
/* IDProps of armature bones can use any type of ID. */
/*dependencies_id_types*/ FILTER_ID_ALL,
/*main_listbase_index*/ INDEX_ID_AR,
/*struct_size*/ sizeof(bArmature),
/*name*/ "Armature",
@ -1992,7 +1994,7 @@ void BKE_armature_mat_world_to_pose(Object *ob, const float inmat[4][4], float o
}
/* Get inverse of (armature) object's matrix. */
invert_m4_m4(obmat, ob->object_to_world);
invert_m4_m4(obmat, ob->object_to_world().ptr());
/* multiply given matrix by object's-inverse to find pose-space matrix */
mul_m4_m4m4(outmat, inmat, obmat);
@ -2967,7 +2969,7 @@ void BKE_pose_where_is(Depsgraph *depsgraph, Scene *scene, Object *ob)
}
}
else {
invert_m4_m4(ob->world_to_object, ob->object_to_world); /* world_to_object is needed */
invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
/* 1. clear flags */
LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
@ -3068,16 +3070,16 @@ void BKE_pchan_minmax(const Object *ob,
pchan->custom_translation[0],
pchan->custom_translation[1],
pchan->custom_translation[2]);
mul_m4_series(mat, ob->object_to_world, tmp, rmat, smat);
mul_m4_series(mat, ob->object_to_world().ptr(), tmp, rmat, smat);
BoundBox bb;
BKE_boundbox_init_from_minmax(&bb, bb_custom->min, bb_custom->max);
BKE_boundbox_minmax(&bb, mat, r_min, r_max);
}
else {
float vec[3];
mul_v3_m4v3(vec, ob->object_to_world, pchan_tx->pose_head);
mul_v3_m4v3(vec, ob->object_to_world().ptr(), pchan_tx->pose_head);
minmax_v3v3_v3(r_min, r_max, vec);
mul_v3_m4v3(vec, ob->object_to_world, pchan_tx->pose_tail);
mul_v3_m4v3(vec, ob->object_to_world().ptr(), pchan_tx->pose_tail);
minmax_v3v3_v3(r_min, r_max, vec);
}
}

View File

@ -600,9 +600,9 @@ static void armature_deform_coords_impl(const Object *ob_arm,
data.bmesh.cd_dvert_offset = cd_dvert_offset;
float obinv[4][4];
invert_m4_m4(obinv, ob_target->object_to_world);
invert_m4_m4(obinv, ob_target->object_to_world().ptr());
mul_m4_m4m4(data.postmat, obinv, ob_arm->object_to_world);
mul_m4_m4m4(data.postmat, obinv, ob_arm->object_to_world().ptr());
invert_m4_m4(data.premat, data.postmat);
if (em_target != nullptr) {

View File

@ -254,11 +254,11 @@ static void apply_curve_transform(
* unless the option to allow curve to be positioned elsewhere is activated (i.e. no root).
*/
if ((ik_data->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) {
mul_m4_v3(ik_data->tar->object_to_world, r_vec);
mul_m4_v3(ik_data->tar->object_to_world().ptr(), r_vec);
}
/* Convert the position to pose-space. */
mul_m4_v3(ob->world_to_object, r_vec);
mul_m4_v3(ob->world_to_object().ptr(), r_vec);
/* Set the new radius (it should be the average value). */
*r_radius = (radius + *r_radius) / 2;
@ -829,7 +829,7 @@ void BKE_pose_eval_init(Depsgraph *depsgraph, Scene * /*scene*/, Object *object)
BLI_assert((object->pose->flag & POSE_RECALC) == 0);
/* world_to_object is needed for solvers. */
invert_m4_m4(object->world_to_object, object->object_to_world);
invert_m4_m4(object->runtime->world_to_object.ptr(), object->object_to_world().ptr());
/* clear flags */
for (bPoseChannel *pchan = static_cast<bPoseChannel *>(pose->chanbase.first); pchan != nullptr;

View File

@ -52,18 +52,10 @@ AssetMetaData *BKE_asset_metadata_copy(const AssetMetaData *source)
BKE_asset_metadata_catalog_id_set(copy, source->catalog_id, source->catalog_simple_name);
if (source->author) {
copy->author = BLI_strdup(source->author);
}
if (source->description) {
copy->description = BLI_strdup(source->description);
}
if (source->copyright) {
copy->copyright = BLI_strdup(source->copyright);
}
if (source->license) {
copy->license = BLI_strdup(source->license);
}
copy->author = BLI_strdup_null(source->author);
copy->description = BLI_strdup_null(source->description);
copy->copyright = BLI_strdup_null(source->copyright);
copy->license = BLI_strdup_null(source->license);
BLI_duplicatelist(&copy->tags, &source->tags);
copy->active_tag = source->active_tag;

View File

@ -50,6 +50,8 @@ const blender::CPPType *custom_data_type_to_cpp_type(const eCustomDataType type)
return &CPPType::get<ColorGeometry4b>();
case CD_PROP_QUATERNION:
return &CPPType::get<math::Quaternion>();
case CD_PROP_FLOAT4X4:
return &CPPType::get<float4x4>();
case CD_PROP_STRING:
return &CPPType::get<MStringProperty>();
default:
@ -89,6 +91,9 @@ eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
if (type.is<math::Quaternion>()) {
return CD_PROP_QUATERNION;
}
if (type.is<float4x4>()) {
return CD_PROP_FLOAT4X4;
}
if (type.is<MStringProperty>()) {
return CD_PROP_STRING;
}
@ -167,6 +172,8 @@ static int attribute_data_type_complexity(const eCustomDataType data_type)
return 8;
case CD_PROP_COLOR:
return 9;
case CD_PROP_FLOAT4X4:
return 10;
#if 0 /* These attribute types are not supported yet. */
case CD_PROP_STRING:
return 10;

View File

@ -3,6 +3,7 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_array_utils.hh"
#include "BLI_math_matrix.hh"
#include "BLI_math_quaternion.hh"
#include "BKE_attribute_math.hh"
@ -36,6 +37,40 @@ math::Quaternion mix4(const float4 &weights,
return math::Quaternion::expmap(expmap_mixed);
}
template<> float4x4 mix2(const float factor, const float4x4 &a, const float4x4 &b)
{
return math::interpolate(a, b, factor);
}
template<>
float4x4 mix3(const float3 &weights, const float4x4 &v0, const float4x4 &v1, const float4x4 &v2)
{
const float3 location = mix3(weights, v0.location(), v1.location(), v2.location());
const math::Quaternion rotation = mix3(
weights, math::to_quaternion(v0), math::to_quaternion(v1), math::to_quaternion(v2));
const float3 scale = mix3(weights, math::to_scale(v0), math::to_scale(v1), math::to_scale(v2));
return math::from_loc_rot_scale<float4x4>(location, rotation, scale);
}
template<>
float4x4 mix4(const float4 &weights,
const float4x4 &v0,
const float4x4 &v1,
const float4x4 &v2,
const float4x4 &v3)
{
const float3 location = mix4(
weights, v0.location(), v1.location(), v2.location(), v3.location());
const math::Quaternion rotation = mix4(weights,
math::to_quaternion(v0),
math::to_quaternion(v1),
math::to_quaternion(v2),
math::to_quaternion(v3));
const float3 scale = mix4(
weights, math::to_scale(v0), math::to_scale(v1), math::to_scale(v2), math::to_scale(v3));
return math::from_loc_rot_scale<float4x4>(location, rotation, scale);
}
ColorGeometry4fMixer::ColorGeometry4fMixer(MutableSpan<ColorGeometry4f> buffer,
ColorGeometry4f default_color)
: ColorGeometry4fMixer(buffer, buffer.index_range(), default_color)
@ -160,6 +195,58 @@ void ColorGeometry4bMixer::finalize(const IndexMask &mask)
});
}
float4x4Mixer::float4x4Mixer(MutableSpan<float4x4> buffer)
: float4x4Mixer(buffer, buffer.index_range())
{
}
float4x4Mixer::float4x4Mixer(MutableSpan<float4x4> buffer, const IndexMask & /*mask*/)
: buffer_(buffer),
total_weights_(buffer.size(), 0.0f),
location_buffer_(buffer.size(), float3(0)),
expmap_buffer_(buffer.size(), float3(0)),
scale_buffer_(buffer.size(), float3(0))
{
}
void float4x4Mixer::float4x4Mixer::set(int64_t index, const float4x4 &value, const float weight)
{
location_buffer_[index] = value.location() * weight;
expmap_buffer_[index] = math::to_quaternion(value).expmap() * weight;
scale_buffer_[index] = math::to_scale(value) * weight;
total_weights_[index] = weight;
}
void float4x4Mixer::mix_in(int64_t index, const float4x4 &value, float weight)
{
location_buffer_[index] += value.location() * weight;
expmap_buffer_[index] += math::to_quaternion(value).expmap() * weight;
scale_buffer_[index] += math::to_scale(value) * weight;
total_weights_[index] += weight;
}
void float4x4Mixer::finalize()
{
this->finalize(buffer_.index_range());
}
void float4x4Mixer::finalize(const IndexMask &mask)
{
mask.foreach_index([&](const int64_t i) {
const float weight = total_weights_[i];
if (weight > 0.0f) {
const float weight_inv = math::rcp(weight);
buffer_[i] = math::from_loc_rot_scale<float4x4>(
location_buffer_[i] * weight_inv,
math::Quaternion::expmap(expmap_buffer_[i] * weight_inv),
scale_buffer_[i] * weight_inv);
}
else {
buffer_[i] = float4x4::identity();
}
});
}
void gather(const GSpan src, const Span<int> map, GMutableSpan dst)
{
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {

View File

@ -1042,6 +1042,10 @@ static std::shared_ptr<io::serialize::Value> serialize_primitive_value(
const math::Quaternion value = *static_cast<const math::Quaternion *>(value_ptr);
return serialize_float_array({&value.x, 4});
}
case CD_PROP_FLOAT4X4: {
const float4x4 value = *static_cast<const float4x4 *>(value_ptr);
return serialize_float_array({value.base_ptr(), value.col_len * value.row_len});
}
default:
break;
}
@ -1160,6 +1164,9 @@ template<typename T>
case CD_PROP_QUATERNION: {
return deserialize_float_array(io_value, {static_cast<float *>(r_value), 4});
}
case CD_PROP_FLOAT4X4: {
return deserialize_float_array(io_value, {static_cast<float *>(r_value), 4 * 4});
}
default:
break;
}

View File

@ -47,6 +47,7 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
case SOCK_INT:
case SOCK_BOOLEAN:
case SOCK_ROTATION:
case SOCK_MATRIX:
case SOCK_RGBA: {
auto &value_variant = *static_cast<SocketValueVariant *>(socket_value);
if (value_variant.is_context_dependent_field()) {
@ -131,6 +132,7 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
case SOCK_INT:
case SOCK_BOOLEAN:
case SOCK_ROTATION:
case SOCK_MATRIX:
case SOCK_RGBA: {
const CPPType &base_type = *socket_type_to_geo_nodes_base_cpp_type(socket_type);
if (const auto *item = dynamic_cast<const PrimitiveBakeItem *>(&bake_item)) {

View File

@ -35,6 +35,7 @@
#include "BKE_report.hh"
#include "BKE_screen.hh"
#include "BKE_studiolight.h"
#include "BKE_writeffmpeg.hh"
#include "DEG_depsgraph.hh"
@ -74,6 +75,9 @@ void BKE_blender_free()
BKE_callback_global_finalize();
IMB_moviecache_destruct();
#ifdef WITH_FFMPEG
BKE_ffmpeg_exit();
#endif
BKE_node_system_exit();
}
@ -356,6 +360,11 @@ void BKE_blender_userdef_app_template_data_swap(UserDef *userdef_a, UserDef *use
* - various minor settings (add as needed).
*/
#define VALUE_SWAP(id) \
{ \
std::swap(userdef_a->id, userdef_b->id); \
}
#define DATA_SWAP(id) \
{ \
UserDef userdef_tmp; \
@ -376,12 +385,12 @@ void BKE_blender_userdef_app_template_data_swap(UserDef *userdef_a, UserDef *use
} \
((void)0)
std::swap(userdef_a->uistyles, userdef_b->uistyles);
std::swap(userdef_a->uifonts, userdef_b->uifonts);
std::swap(userdef_a->themes, userdef_b->themes);
std::swap(userdef_a->addons, userdef_b->addons);
std::swap(userdef_a->user_keymaps, userdef_b->user_keymaps);
std::swap(userdef_a->user_keyconfig_prefs, userdef_b->user_keyconfig_prefs);
VALUE_SWAP(uistyles);
VALUE_SWAP(uifonts);
VALUE_SWAP(themes);
VALUE_SWAP(addons);
VALUE_SWAP(user_keymaps);
VALUE_SWAP(user_keyconfig_prefs);
DATA_SWAP(font_path_ui);
DATA_SWAP(font_path_ui_mono);
@ -395,9 +404,8 @@ void BKE_blender_userdef_app_template_data_swap(UserDef *userdef_a, UserDef *use
DATA_SWAP(ui_scale);
#undef SWAP_TYPELESS
#undef VALUE_SWAP
#undef DATA_SWAP
#undef LISTBASE_SWAP
#undef FLAG_SWAP
}

View File

@ -64,6 +64,8 @@
# include "BPY_extern.h"
#endif
using namespace blender::bke;
/* -------------------------------------------------------------------- */
/** \name Blend/Library Paths
* \{ */
@ -228,7 +230,7 @@ struct ReuseOldBMainData {
/** Storage for all remapping rules (old_id -> new_id) required by the preservation of old IDs
* into the new Main. */
IDRemapper *remapper;
id::IDRemapper *remapper;
bool is_libraries_remapped;
/** Used to find matching IDs by name/lib in new main, to remap ID usages of data ported over
@ -246,25 +248,25 @@ struct ReuseOldBMainData {
* double of a linked data as a local one, without any known relationships between them. In
* practice, this latter case is not expected to commonly happen.
*/
static IDRemapper *reuse_bmain_data_remapper_ensure(ReuseOldBMainData *reuse_data)
static id::IDRemapper &reuse_bmain_data_remapper_ensure(ReuseOldBMainData *reuse_data)
{
if (reuse_data->is_libraries_remapped) {
return reuse_data->remapper;
return *reuse_data->remapper;
}
if (reuse_data->remapper == nullptr) {
reuse_data->remapper = BKE_id_remapper_create();
reuse_data->remapper = MEM_new<id::IDRemapper>(__func__);
}
Main *new_bmain = reuse_data->new_bmain;
Main *old_bmain = reuse_data->old_bmain;
IDRemapper *remapper = reuse_data->remapper;
id::IDRemapper &remapper = *reuse_data->remapper;
LISTBASE_FOREACH (Library *, old_lib_iter, &old_bmain->libraries) {
/* In case newly opened `new_bmain` is a library of the `old_bmain`, remap it to null, since a
* file should never ever have linked data from itself. */
if (STREQ(old_lib_iter->filepath_abs, new_bmain->filepath)) {
BKE_id_remapper_add(remapper, &old_lib_iter->id, nullptr);
remapper.add(&old_lib_iter->id, nullptr);
continue;
}
@ -277,19 +279,18 @@ static IDRemapper *reuse_bmain_data_remapper_ensure(ReuseOldBMainData *reuse_dat
continue;
}
BKE_id_remapper_add(remapper, &old_lib_iter->id, &new_lib_iter->id);
remapper.add(&old_lib_iter->id, &new_lib_iter->id);
break;
}
}
reuse_data->is_libraries_remapped = true;
return reuse_data->remapper;
return *reuse_data->remapper;
}
static bool reuse_bmain_data_remapper_is_id_remapped(IDRemapper *remapper, ID *id)
static bool reuse_bmain_data_remapper_is_id_remapped(id::IDRemapper &remapper, ID *id)
{
IDRemapperApplyResult result = BKE_id_remapper_get_mapping_result(
remapper, id, ID_REMAP_APPLY_DEFAULT, nullptr);
IDRemapperApplyResult result = remapper.get_mapping_result(id, ID_REMAP_APPLY_DEFAULT, nullptr);
if (ELEM(result, ID_REMAP_RESULT_SOURCE_REMAPPED, ID_REMAP_RESULT_SOURCE_UNASSIGNED)) {
/* ID is already remapped to its matching ID in the new main, or explicitly remapped to null,
* nothing else to do here. */
@ -319,7 +320,7 @@ static void swap_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, con
ListBase *new_lb = which_libbase(new_bmain, id_code);
ListBase *old_lb = which_libbase(old_bmain, id_code);
IDRemapper *remapper = reuse_bmain_data_remapper_ensure(reuse_data);
id::IDRemapper &remapper = reuse_bmain_data_remapper_ensure(reuse_data);
/* NOTE: Full swapping is only supported for ID types that are assumed to be only local
* data-blocks (like UI-like ones). Otherwise, the swapping could fail in many funny ways. */
@ -346,14 +347,14 @@ static void swap_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, con
const int strcmp_result = strcmp(discarded_id_iter->name + 2, reused_id_iter->name + 2);
if (strcmp_result == 0) {
/* Matching IDs, we can remap the discarded 'new' one to the re-used 'old' one. */
BKE_id_remapper_add(remapper, discarded_id_iter, reused_id_iter);
remapper.add(discarded_id_iter, reused_id_iter);
discarded_id_iter = static_cast<ID *>(discarded_id_iter->next);
reused_id_iter = static_cast<ID *>(reused_id_iter->next);
}
else if (strcmp_result < 0) {
/* No matching reused 'old' ID for this discarded 'new' one. */
BKE_id_remapper_add(remapper, discarded_id_iter, nullptr);
remapper.add(discarded_id_iter, nullptr);
discarded_id_iter = static_cast<ID *>(discarded_id_iter->next);
}
@ -365,7 +366,7 @@ static void swap_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, con
for (; discarded_id_iter != nullptr;
discarded_id_iter = static_cast<ID *>(discarded_id_iter->next))
{
BKE_id_remapper_add(remapper, discarded_id_iter, nullptr);
remapper.add(discarded_id_iter, nullptr);
}
FOREACH_MAIN_LISTBASE_ID_BEGIN (new_lb, reused_id_iter) {
@ -374,7 +375,7 @@ static void swap_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, con
/* Ensure that the reused ID is remapped to itself, since it is known to be in the `new_bmain`.
*/
BKE_id_remapper_add_overwrite(remapper, reused_id_iter, reused_id_iter);
remapper.add_overwrite(reused_id_iter, reused_id_iter);
}
FOREACH_MAIN_LISTBASE_ID_END;
}
@ -428,8 +429,8 @@ static void swap_wm_data_for_blendfile(ReuseOldBMainData *reuse_data, const bool
* new WM, and is responsible to free it properly. */
reuse_data->wm_setup_data->old_wm = old_wm;
IDRemapper *remapper = reuse_bmain_data_remapper_ensure(reuse_data);
BKE_id_remapper_add(remapper, &old_wm->id, &new_wm->id);
id::IDRemapper &remapper = reuse_bmain_data_remapper_ensure(reuse_data);
remapper.add(&old_wm->id, &new_wm->id);
}
/* Current (old) WM, but no (new) one in file (should only happen when reading pre 2.5 files, no
* WM back then), or not loading UI: Keep current WM. */
@ -452,7 +453,7 @@ static int swap_old_bmain_data_for_blendfile_dependencies_process_cb(
ReuseOldBMainData *reuse_data = static_cast<ReuseOldBMainData *>(cb_data->user_data);
/* First check if it has already been remapped. */
IDRemapper *remapper = reuse_bmain_data_remapper_ensure(reuse_data);
id::IDRemapper &remapper = reuse_bmain_data_remapper_ensure(reuse_data);
if (reuse_bmain_data_remapper_is_id_remapped(remapper, id)) {
return IDWALK_RET_NOP;
}
@ -461,7 +462,7 @@ static int swap_old_bmain_data_for_blendfile_dependencies_process_cb(
BLI_assert(id_map != nullptr);
ID *id_new = BKE_main_idmap_lookup_id(id_map, id);
BKE_id_remapper_add(remapper, id, id_new);
remapper.add(id, id_new);
return IDWALK_RET_NOP;
}
@ -784,7 +785,7 @@ static void setup_app_data(bContext *C,
/* Handle all pending remapping from swapping old and new IDs around. */
BKE_libblock_remap_multiple_raw(bfd->main,
reuse_data.remapper,
*reuse_data.remapper,
(ID_REMAP_FORCE_UI_POINTERS | ID_REMAP_SKIP_USER_REFCOUNT |
ID_REMAP_SKIP_UPDATE_TAGGING | ID_REMAP_SKIP_USER_CLEAR));
@ -793,7 +794,7 @@ static void setup_app_data(bContext *C,
* library of the previous opened blendfile'. */
reuse_bmain_data_invalid_local_usages_fix(&reuse_data);
BKE_id_remapper_free(reuse_data.remapper);
MEM_delete(reuse_data.remapper);
reuse_data.remapper = nullptr;
wm_data_consistency_ensure(CTX_wm_manager(C), curscene, cur_view_layer);
@ -938,7 +939,7 @@ static void setup_app_data(bContext *C,
BLI_assert(BKE_main_namemap_validate(bmain));
if (mode != LOAD_UNDO && !USER_EXPERIMENTAL_TEST(&U, no_override_auto_resync)) {
reports->duration.lib_overrides_resync = BLI_check_seconds_timer();
reports->duration.lib_overrides_resync = BLI_time_now_seconds();
BKE_lib_override_library_main_resync(
bmain,
@ -946,7 +947,7 @@ static void setup_app_data(bContext *C,
bfd->cur_view_layer ? bfd->cur_view_layer : BKE_view_layer_default_view(curscene),
reports);
reports->duration.lib_overrides_resync = BLI_check_seconds_timer() -
reports->duration.lib_overrides_resync = BLI_time_now_seconds() -
reports->duration.lib_overrides_resync;
/* We need to rebuild some of the deleted override rules (for UI feedback purpose). */

View File

@ -962,7 +962,7 @@ void boids_precalc_rules(ParticleSettings *part, float cfra)
if (flbr->ob && flbr->cfra != cfra) {
/* save object locations for velocity calculations */
copy_v3_v3(flbr->oloc, flbr->loc);
copy_v3_v3(flbr->loc, flbr->ob->object_to_world[3]);
copy_v3_v3(flbr->loc, flbr->ob->object_to_world().location());
flbr->cfra = cfra;
}
}

View File

@ -72,7 +72,7 @@
#include "SEQ_iterator.hh"
#ifndef _MSC_VER
# include "BLI_strict_flags.h"
# include "BLI_strict_flags.h" /* Keep last. */
#endif
static CLG_LogRef LOG = {"bke.bpath"};

View File

@ -409,6 +409,8 @@ static void brush_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old)
IDTypeInfo IDType_ID_BR = {
/*id_code*/ ID_BR,
/*id_filter*/ FILTER_ID_BR,
/*dependencies_id_types*/
(FILTER_ID_BR | FILTER_ID_IM | FILTER_ID_PC | FILTER_ID_TE | FILTER_ID_MA),
/*main_listbase_index*/ INDEX_ID_BR,
/*struct_size*/ sizeof(Brush),
/*name*/ "Brush",

View File

@ -932,6 +932,53 @@ BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
return data->tree;
}
void BKE_bvhtree_from_mesh_tris_init(const Mesh &mesh,
const blender::IndexMask &faces_mask,
BVHTreeFromMesh &r_data)
{
using namespace blender;
using namespace blender::bke;
const Span<float3> positions = mesh.vert_positions();
const Span<int2> edges = mesh.edges();
const Span<int> corner_verts = mesh.corner_verts();
const OffsetIndices faces = mesh.faces();
const Span<int3> corner_tris = mesh.corner_tris();
bvhtree_from_mesh_setup_data(nullptr,
BVHTREE_FROM_CORNER_TRIS,
positions,
edges,
corner_verts,
corner_tris,
nullptr,
&r_data);
int tris_num = 0;
faces_mask.foreach_index(
[&](const int i) { tris_num += mesh::face_triangles_num(faces[i].size()); });
int active_num = -1;
BVHTree *tree = bvhtree_new_common(0.0f, 2, 6, tris_num, active_num);
r_data.tree = tree;
if (tree == nullptr) {
return;
}
faces_mask.foreach_index([&](const int face_i) {
const IndexRange triangles_range = mesh::face_triangles_range(faces, face_i);
for (const int tri_i : triangles_range) {
float co[3][3];
copy_v3_v3(co[0], positions[corner_verts[corner_tris[tri_i][0]]]);
copy_v3_v3(co[1], positions[corner_verts[corner_tris[tri_i][1]]]);
copy_v3_v3(co[2], positions[corner_verts[corner_tris[tri_i][2]]]);
BLI_bvhtree_insert(tree, tri_i, co[0], 3);
}
});
BLI_bvhtree_balance(tree);
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@ -121,6 +121,7 @@ static void cache_file_blend_read_data(BlendDataReader *reader, ID *id)
IDTypeInfo IDType_ID_CF = {
/*id_code*/ ID_CF,
/*id_filter*/ FILTER_ID_CF,
/*dependencies_id_types*/ 0,
/*main_listbase_index*/ INDEX_ID_CF,
/*struct_size*/ sizeof(CacheFile),
/*name*/ "CacheFile",

View File

@ -229,6 +229,7 @@ static void camera_blend_read_data(BlendDataReader *reader, ID *id)
IDTypeInfo IDType_ID_CA = {
/*id_code*/ ID_CA,
/*id_filter*/ FILTER_ID_CA,
/*dependencies_id_types*/ FILTER_ID_OB | FILTER_ID_IM,
/*main_listbase_index*/ INDEX_ID_CA,
/*struct_size*/ sizeof(Camera),
/*name*/ "Camera",
@ -278,16 +279,18 @@ float BKE_camera_object_dof_distance(const Object *ob)
}
if (cam->dof.focus_object) {
float view_dir[3], dof_dir[3];
normalize_v3_v3(view_dir, ob->object_to_world[2]);
normalize_v3_v3(view_dir, ob->object_to_world().ptr()[2]);
bPoseChannel *pchan = BKE_pose_channel_find_name(cam->dof.focus_object->pose,
cam->dof.focus_subtarget);
if (pchan) {
float posemat[4][4];
mul_m4_m4m4(posemat, cam->dof.focus_object->object_to_world, pchan->pose_mat);
sub_v3_v3v3(dof_dir, ob->object_to_world[3], posemat[3]);
mul_m4_m4m4(posemat, cam->dof.focus_object->object_to_world().ptr(), pchan->pose_mat);
sub_v3_v3v3(dof_dir, ob->object_to_world().location(), posemat[3]);
}
else {
sub_v3_v3v3(dof_dir, ob->object_to_world[3], cam->dof.focus_object->object_to_world[3]);
sub_v3_v3v3(dof_dir,
ob->object_to_world().location(),
cam->dof.focus_object->object_to_world().location());
}
return fabsf(dot_v3v3(view_dir, dof_dir));
}
@ -682,7 +685,7 @@ static void camera_frame_fit_data_init(const Scene *scene,
BKE_camera_params_compute_matrix(params);
/* initialize callback data */
copy_m3_m4(data->camera_rotmat, (float(*)[4])ob->object_to_world);
copy_m3_m4(data->camera_rotmat, (float(*)[4])ob->object_to_world().ptr());
normalize_m3(data->camera_rotmat);
/* To transform a plane which is in its homogeneous representation (4d vector),
* we need the inverse of the transpose of the transform matrix... */
@ -884,7 +887,7 @@ bool BKE_camera_view_frame_fit_to_coords(const Depsgraph *depsgraph,
static void camera_model_matrix(const Object *camera, float r_modelmat[4][4])
{
copy_m4_m4(r_modelmat, camera->object_to_world);
copy_m4_m4(r_modelmat, camera->object_to_world().ptr());
}
static void camera_stereo3d_model_matrix(const Object *camera,
@ -910,7 +913,7 @@ static void camera_stereo3d_model_matrix(const Object *camera,
}
float size[3];
mat4_to_size(size, camera->object_to_world);
mat4_to_size(size, camera->object_to_world().ptr());
size_to_mat4(sizemat, size);
if (pivot == CAM_S3D_PIVOT_CENTER) {
@ -950,7 +953,7 @@ static void camera_stereo3d_model_matrix(const Object *camera,
toeinmat[3][0] = interocular_distance * fac_signed;
/* transform */
normalize_m4_m4(r_modelmat, camera->object_to_world);
normalize_m4_m4(r_modelmat, camera->object_to_world().ptr());
mul_m4_m4m4(r_modelmat, r_modelmat, toeinmat);
/* scale back to the original size */
@ -958,7 +961,7 @@ static void camera_stereo3d_model_matrix(const Object *camera,
}
else { /* CAM_S3D_PIVOT_LEFT, CAM_S3D_PIVOT_RIGHT */
/* rotate perpendicular to the interocular line */
normalize_m4_m4(r_modelmat, camera->object_to_world);
normalize_m4_m4(r_modelmat, camera->object_to_world().ptr());
mul_m4_m4m4(r_modelmat, r_modelmat, rotmat);
/* translate along the interocular line */
@ -974,7 +977,7 @@ static void camera_stereo3d_model_matrix(const Object *camera,
}
}
else {
normalize_m4_m4(r_modelmat, camera->object_to_world);
normalize_m4_m4(r_modelmat, camera->object_to_world().ptr());
/* translate - no rotation in CAM_S3D_OFFAXIS, CAM_S3D_PARALLEL */
translate_m4(r_modelmat, -interocular_distance * fac_signed, 0.0f, 0.0f);

View File

@ -272,7 +272,7 @@ static int do_step_cloth(
/* Get the current position. */
copy_v3_v3(verts->xconst, positions[i]);
mul_m4_v3(ob->object_to_world, verts->xconst);
mul_m4_v3(ob->object_to_world().ptr(), verts->xconst);
if (vert_mass_changed) {
verts->mass = clmd->sim_parms->mass;
@ -575,11 +575,11 @@ static void cloth_to_object(Object *ob, ClothModifierData *clmd, float (*vertexC
if (clmd->clothObject) {
/* Inverse matrix is not up to date. */
invert_m4_m4(ob->world_to_object, ob->object_to_world);
invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
for (i = 0; i < cloth->mvert_num; i++) {
copy_v3_v3(vertexCos[i], cloth->verts[i].x);
mul_m4_v3(ob->world_to_object, vertexCos[i]); /* cloth is in global coords */
mul_m4_v3(ob->world_to_object().ptr(), vertexCos[i]); /* cloth is in global coords */
}
}
}
@ -759,11 +759,11 @@ static bool cloth_from_object(
if (first) {
copy_v3_v3(verts->x, positions[i]);
mul_m4_v3(ob->object_to_world, verts->x);
mul_m4_v3(ob->object_to_world().ptr(), verts->x);
if (shapekey_rest) {
copy_v3_v3(verts->xrest, shapekey_rest[i]);
mul_m4_v3(ob->object_to_world, verts->xrest);
mul_m4_v3(ob->object_to_world().ptr(), verts->xrest);
}
else {
copy_v3_v3(verts->xrest, verts->x);
@ -1153,7 +1153,7 @@ static void cloth_update_verts(Object *ob, ClothModifierData *clmd, Mesh *mesh)
/* vertex count is already ensured to match */
for (i = 0; i < mesh->verts_num; i++, verts++) {
copy_v3_v3(verts->xrest, positions[i]);
mul_m4_v3(ob->object_to_world, verts->xrest);
mul_m4_v3(ob->object_to_world().ptr(), verts->xrest);
}
}

View File

@ -376,6 +376,7 @@ static void collection_blend_read_after_liblink(BlendLibReader * /*reader*/, ID
IDTypeInfo IDType_ID_GR = {
/*id_code*/ ID_GR,
/*id_filter*/ FILTER_ID_GR,
/*dependencies_id_types*/ FILTER_ID_OB | FILTER_ID_GR,
/*main_listbase_index*/ INDEX_ID_GR,
/*struct_size*/ sizeof(Collection),
/*name*/ "Collection",

View File

@ -155,7 +155,7 @@ bConstraintOb *BKE_constraints_make_evalob(
/* Quaternion/Axis-Angle, so Eulers should just use default order. */
cob->rotOrder = EULER_ORDER_DEFAULT;
}
copy_m4_m4(cob->matrix, ob->object_to_world);
copy_m4_m4(cob->matrix, ob->object_to_world().ptr());
}
else {
unit_m4(cob->matrix);
@ -181,7 +181,7 @@ bConstraintOb *BKE_constraints_make_evalob(
}
/* matrix in world-space */
mul_m4_m4m4(cob->matrix, ob->object_to_world, cob->pchan->pose_mat);
mul_m4_m4m4(cob->matrix, ob->object_to_world().ptr(), cob->pchan->pose_mat);
}
else {
unit_m4(cob->matrix);
@ -222,7 +222,7 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob)
/* cob->ob might not exist! */
if (cob->ob) {
/* copy new ob-matrix back to owner */
copy_m4_m4(cob->ob->object_to_world, cob->matrix);
copy_m4_m4(cob->ob->runtime->object_to_world.ptr(), cob->matrix);
/* copy inverse of delta back to owner */
invert_m4_m4(cob->ob->constinv, delta);
@ -233,7 +233,7 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob)
/* cob->ob or cob->pchan might not exist */
if (cob->ob && cob->pchan) {
/* copy new pose-matrix back to owner */
mul_m4_m4m4(cob->pchan->pose_mat, cob->ob->world_to_object, cob->matrix);
mul_m4_m4m4(cob->pchan->pose_mat, cob->ob->world_to_object().ptr(), cob->matrix);
/* copy inverse of delta back to owner */
invert_m4_m4(cob->pchan->constinv, delta);
@ -282,7 +282,7 @@ void BKE_constraint_mat_convertspace(Object *ob,
}
else {
/* World to pose. */
invert_m4_m4(imat, ob->object_to_world);
invert_m4_m4(imat, ob->object_to_world().ptr());
mul_m4_m4m4(mat, imat, mat);
/* Use pose-space as stepping stone for other spaces. */
@ -326,7 +326,7 @@ void BKE_constraint_mat_convertspace(Object *ob,
}
else {
/* Pose to world. */
mul_m4_m4m4(mat, ob->object_to_world, mat);
mul_m4_m4m4(mat, ob->object_to_world().ptr(), mat);
/* Use world-space as stepping stone for other spaces. */
if (to != CONSTRAINT_SPACE_WORLD) {
/* Call self with slightly different values. */
@ -436,7 +436,7 @@ void BKE_constraint_mat_convertspace(Object *ob,
/* Check if object has a parent. */
if (ob->parent) {
/* 'subtract' parent's effects from owner. */
mul_m4_m4m4(diff_mat, ob->parent->object_to_world, ob->parentinv);
mul_m4_m4m4(diff_mat, ob->parent->object_to_world().ptr(), ob->parentinv);
invert_m4_m4_safe(imat, diff_mat);
mul_m4_m4m4(mat, imat, mat);
}
@ -472,7 +472,7 @@ void BKE_constraint_mat_convertspace(Object *ob,
/* check that object has a parent - otherwise this won't work */
if (ob->parent) {
/* 'add' parent's effect back to owner */
mul_m4_m4m4(diff_mat, ob->parent->object_to_world, ob->parentinv);
mul_m4_m4m4(diff_mat, ob->parent->object_to_world().ptr(), ob->parentinv);
mul_m4_m4m4(mat, diff_mat, mat);
}
else {
@ -525,7 +525,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
const int defgroup = BKE_object_defgroup_name_index(ob, substring);
/* initialize target matrix using target matrix */
copy_m4_m4(mat, ob->object_to_world);
copy_m4_m4(mat, ob->object_to_world().ptr());
/* get index of vertex group */
if (defgroup == -1) {
@ -591,7 +591,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
* calc_gizmo_stats, V3D_ORIENT_NORMAL case */
/* We need the transpose of the inverse for a normal. */
copy_m3_m4(imat, ob->object_to_world);
copy_m3_m4(imat, ob->object_to_world().ptr());
invert_m3_m3(tmat, imat);
transpose_m3(tmat);
@ -612,7 +612,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
normalize_m4(mat);
/* apply the average coordinate as the new location */
mul_v3_m4v3(mat[3], ob->object_to_world, vec);
mul_v3_m4v3(mat[3], ob->object_to_world().ptr(), vec);
}
/* function that sets the given matrix based on given vertex group in lattice */
@ -634,7 +634,7 @@ static void contarget_get_lattice_mat(Object *ob, const char *substring, float m
const int defgroup = BKE_object_defgroup_name_index(ob, substring);
/* initialize target matrix using target matrix */
copy_m4_m4(mat, ob->object_to_world);
copy_m4_m4(mat, ob->object_to_world().ptr());
/* get index of vertex group */
if (defgroup == -1) {
@ -668,11 +668,12 @@ static void contarget_get_lattice_mat(Object *ob, const char *substring, float m
}
}
/* find average location, then multiply by ob->object_to_world to find world-space location */
/* find average location, then multiply by ob->object_to_world().ptr() to find world-space
* location */
if (grouped) {
mul_v3_fl(vec, 1.0f / grouped);
}
mul_v3_m4v3(tvec, ob->object_to_world, vec);
mul_v3_m4v3(tvec, ob->object_to_world().ptr(), vec);
/* copy new location to matrix */
copy_v3_v3(mat[3], tvec);
@ -691,7 +692,7 @@ static void constraint_target_to_mat4(Object *ob,
{
/* Case OBJECT */
if (substring[0] == '\0') {
copy_m4_m4(mat, ob->object_to_world);
copy_m4_m4(mat, ob->object_to_world().ptr());
BKE_constraint_mat_convertspace(ob, nullptr, cob, mat, from, to, false);
}
/* Case VERTEXGROUP */
@ -726,7 +727,7 @@ static void constraint_target_to_mat4(Object *ob,
if (headtail < 0.000001f && !(is_bbone && full_bbone)) {
/* skip length interpolation if set to head */
mul_m4_m4m4(mat, ob->object_to_world, pchan->pose_mat);
mul_m4_m4m4(mat, ob->object_to_world().ptr(), pchan->pose_mat);
}
else if (is_bbone && pchan->bone->segments == pchan->runtime.bbone_segments) {
/* use point along bbone */
@ -752,7 +753,7 @@ static void constraint_target_to_mat4(Object *ob,
mul_v3_m4v3(tempmat[3], pchan->pose_mat, loc);
}
mul_m4_m4m4(mat, ob->object_to_world, tempmat);
mul_m4_m4m4(mat, ob->object_to_world().ptr(), tempmat);
}
else {
float tempmat[4][4], loc[3];
@ -764,11 +765,11 @@ static void constraint_target_to_mat4(Object *ob,
copy_m4_m4(tempmat, pchan->pose_mat);
copy_v3_v3(tempmat[3], loc);
mul_m4_m4m4(mat, ob->object_to_world, tempmat);
mul_m4_m4m4(mat, ob->object_to_world().ptr(), tempmat);
}
}
else {
copy_m4_m4(mat, ob->object_to_world);
copy_m4_m4(mat, ob->object_to_world().ptr());
}
/* convert matrix space as required */
@ -1078,7 +1079,7 @@ static void childof_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
if (data->flag & CHILDOF_SET_INVERSE) {
invert_m4_m4(data->invmat, parmat);
if (cob->pchan != nullptr) {
mul_m4_series(data->invmat, data->invmat, cob->ob->object_to_world);
mul_m4_series(data->invmat, data->invmat, cob->ob->object_to_world().ptr());
}
copy_m4_m4(inverse_matrix, data->invmat);
@ -1398,8 +1399,8 @@ static void kinematic_get_tarmat(Depsgraph * /*depsgraph*/,
else {
float vec[3];
/* move grabtarget into world space */
mul_v3_m4v3(vec, ob->object_to_world, data->grabtarget);
copy_m4_m4(ct->matrix, ob->object_to_world);
mul_v3_m4v3(vec, ob->object_to_world().ptr(), data->grabtarget);
copy_m4_m4(ct->matrix, ob->object_to_world().ptr());
copy_v3_v3(ct->matrix[3], vec);
}
}
@ -1539,7 +1540,7 @@ static void followpath_get_tarmat(Depsgraph * /*depsgraph*/,
copy_v3_v3(totmat[3], vec);
mul_m4_m4m4(ct->matrix, ct->tar->object_to_world, totmat);
mul_m4_m4m4(ct->matrix, ct->tar->object_to_world().ptr(), totmat);
}
}
}
@ -2569,7 +2570,7 @@ static void armdef_get_tarmat(Depsgraph * /*depsgraph*/,
bPoseChannel *pchan = BKE_pose_channel_find_name(ct->tar->pose, ct->subtarget);
if (pchan != nullptr) {
mul_m4_m4m4(ct->matrix, ct->tar->object_to_world, pchan->pose_mat);
mul_m4_m4m4(ct->matrix, ct->tar->object_to_world().ptr(), pchan->pose_mat);
return;
}
}
@ -2626,7 +2627,7 @@ static void armdef_accumulate_bone(const bConstraintTarget *ct,
float weight = ct->weight;
/* Our object's location in target pose space. */
invert_m4_m4(iobmat, ct->tar->object_to_world);
invert_m4_m4(iobmat, ct->tar->object_to_world().ptr());
mul_v3_m4v3(co, iobmat, wco);
/* Multiply by the envelope weight when appropriate. */
@ -2651,7 +2652,7 @@ static void armdef_accumulate_bone(const bConstraintTarget *ct,
mul_m4_m4m4(basemat, bone->arm_mat, b_bone_rest_mats[index].mat);
}
armdef_accumulate_matrix(ct->tar->object_to_world,
armdef_accumulate_matrix(ct->tar->object_to_world().ptr(),
iobmat,
basemat,
b_bone_mats[index + 1].mat,
@ -2665,7 +2666,7 @@ static void armdef_accumulate_bone(const bConstraintTarget *ct,
mul_m4_m4m4(basemat, bone->arm_mat, b_bone_rest_mats[index + 1].mat);
}
armdef_accumulate_matrix(ct->tar->object_to_world,
armdef_accumulate_matrix(ct->tar->object_to_world().ptr(),
iobmat,
basemat,
b_bone_mats[index + 2].mat,
@ -2676,7 +2677,7 @@ static void armdef_accumulate_bone(const bConstraintTarget *ct,
}
else {
/* Simple bone. This requires DEG_OPCODE_BONE_DONE dependency due to chan_mat. */
armdef_accumulate_matrix(ct->tar->object_to_world,
armdef_accumulate_matrix(ct->tar->object_to_world().ptr(),
iobmat,
bone->arm_mat,
pchan->chan_mat,
@ -2709,7 +2710,7 @@ static void armdef_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ
/* For constraints on bones, use the rest position to bind b-bone segments
* and envelopes, to allow safely changing the bone location as if parented. */
copy_v3_v3(input_co, cob->pchan->bone->arm_head);
mul_m4_v3(cob->ob->object_to_world, input_co);
mul_m4_v3(cob->ob->object_to_world().ptr(), input_co);
}
else {
copy_v3_v3(input_co, cob->matrix[3]);
@ -3941,7 +3942,7 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
unit_m4(totmat);
copy_v3_v3(totmat[3], vec);
mul_m4_m4m4(targetMatrix, ct->tar->object_to_world, totmat);
mul_m4_m4m4(targetMatrix, ct->tar->object_to_world().ptr(), totmat);
}
}
@ -4242,7 +4243,7 @@ static void shrinkwrap_get_tarmat(Depsgraph * /*depsgraph*/,
if (BKE_shrinkwrap_init_tree(
&tree, target_eval, scon->shrinkType, scon->shrinkMode, do_track_normal))
{
BLI_space_transform_from_matrices(&transform, cob->matrix, ct->tar->object_to_world);
BLI_space_transform_from_matrices(&transform, cob->matrix, ct->tar->object_to_world().ptr());
switch (scon->shrinkType) {
case MOD_SHRINKWRAP_NEAREST_SURFACE:
@ -4916,7 +4917,7 @@ static void followtrack_evaluate_using_3d_position_object(FollowTrackContext *co
/* Object matrix of the camera. */
float camera_obmat[4][4];
copy_m4_m4(camera_obmat, camera_object->object_to_world);
copy_m4_m4(camera_obmat, camera_object->object_to_world().ptr());
/* Calculate inverted matrix of the solved camera at the current time. */
float reconstructed_camera_mat[4][4];
@ -5068,10 +5069,11 @@ static void followtrack_project_to_depth_object_if_needed(FollowTrackContext *co
}
float depth_object_mat_inv[4][4];
invert_m4_m4(depth_object_mat_inv, depth_object->object_to_world);
invert_m4_m4(depth_object_mat_inv, depth_object->object_to_world().ptr());
float ray_start[3], ray_end[3];
mul_v3_m4v3(ray_start, depth_object_mat_inv, context->camera_object->object_to_world[3]);
mul_v3_m4v3(
ray_start, depth_object_mat_inv, context->camera_object->object_to_world().location());
mul_v3_m4v3(ray_end, depth_object_mat_inv, cob->matrix[3]);
float ray_direction[3];
@ -5094,7 +5096,7 @@ static void followtrack_project_to_depth_object_if_needed(FollowTrackContext *co
&tree_data);
if (result != -1) {
mul_v3_m4v3(cob->matrix[3], depth_object->object_to_world, hit.co);
mul_v3_m4v3(cob->matrix[3], depth_object->object_to_world().ptr(), hit.co);
}
free_bvhtree_from_mesh(&tree_data);
@ -5142,9 +5144,9 @@ static void followtrack_evaluate_using_2d_position(FollowTrackContext *context,
}
float disp[3];
mul_v3_m4v3(disp, camera_object->object_to_world, vec);
mul_v3_m4v3(disp, camera_object->object_to_world().ptr(), vec);
copy_m4_m4(rmat, camera_object->object_to_world);
copy_m4_m4(rmat, camera_object->object_to_world().ptr());
zero_v3(rmat[3]);
mul_m4_m4m4(cob->matrix, cob->matrix, rmat);
@ -5166,10 +5168,10 @@ static void followtrack_evaluate_using_2d_position(FollowTrackContext *context,
}
float disp[3];
mul_v3_m4v3(disp, camera_object->object_to_world, vec);
mul_v3_m4v3(disp, camera_object->object_to_world().ptr(), vec);
/* apply camera rotation so Z-axis would be co-linear */
copy_m4_m4(rmat, camera_object->object_to_world);
copy_m4_m4(rmat, camera_object->object_to_world().ptr());
zero_v3(rmat[3]);
mul_m4_m4m4(cob->matrix, cob->matrix, rmat);
@ -5315,7 +5317,7 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, mat);
invert_m4_m4(imat, mat);
mul_m4_m4m4(parmat, camob->object_to_world, imat);
mul_m4_m4m4(parmat, camob->object_to_world().ptr(), imat);
copy_m4_m4(obmat, cob->matrix);
@ -5668,7 +5670,7 @@ bool BKE_constraint_apply_for_object(Depsgraph *depsgraph,
BLI_freelinkN(&single_con, new_con);
/* Apply transform from matrix. */
BKE_object_apply_mat4(ob, ob_eval->object_to_world, true, true);
BKE_object_apply_mat4(ob, ob_eval->object_to_world().ptr(), true, true);
return true;
}
@ -6261,7 +6263,7 @@ void BKE_constraint_target_matrix_get(Depsgraph *depsgraph,
cob->ob = (Object *)ownerdata;
cob->pchan = nullptr;
if (cob->ob) {
copy_m4_m4(cob->matrix, cob->ob->object_to_world);
copy_m4_m4(cob->matrix, cob->ob->object_to_world().ptr());
copy_m4_m4(cob->startmat, cob->matrix);
}
else {

View File

@ -38,6 +38,7 @@
#include "BKE_scene.hh"
#include "BKE_screen.hh"
#include "BKE_sound.h"
#include "BKE_wm_runtime.hh"
#include "BKE_workspace.h"
#include "RE_engine.h"
@ -706,7 +707,7 @@ wmWindowManager *CTX_wm_manager(const bContext *C)
bool CTX_wm_interface_locked(const bContext *C)
{
return bool(C->wm.manager->is_interface_locked);
return C->wm.manager->runtime->is_interface_locked;
}
wmWindow *CTX_wm_window(const bContext *C)
@ -766,7 +767,7 @@ wmMsgBus *CTX_wm_message_bus(const bContext *C)
ReportList *CTX_wm_reports(const bContext *C)
{
if (C->wm.manager) {
return &(C->wm.manager->reports);
return &(C->wm.manager->runtime->reports);
}
return nullptr;

View File

@ -271,6 +271,7 @@ static void curve_blend_read_data(BlendDataReader *reader, ID *id)
IDTypeInfo IDType_ID_CU_LEGACY = {
/*id_code*/ ID_CU_LEGACY,
/*id_filter*/ FILTER_ID_CU_LEGACY,
/*dependencies_id_types*/ FILTER_ID_OB | FILTER_ID_MA | FILTER_ID_VF | FILTER_ID_KE,
/*main_listbase_index*/ INDEX_ID_CU_LEGACY,
/*struct_size*/ sizeof(Curve),
/*name*/ "Curve",

View File

@ -12,8 +12,7 @@
#include <cstring>
#include "BLI_listbase.h"
/* Needed with MSVC for M_PI & M_PI_2 */
#include "BLI_math_base.h"
#include "BLI_math_base.h" /* Needed with MSVC for M_PI & M_PI_2. */
#include "MEM_guardedalloc.h"

View File

@ -18,10 +18,10 @@ extern "C" {
#include "curve_fit_nd.h"
}
#include "BLI_strict_flags.h"
#include <cstring>
#include "BLI_strict_flags.h" /* Keep last. */
struct Knot {
Knot *next, *prev;
uint point_index; /* Index in point array. */

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