Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View File

@@ -0,0 +1,204 @@
# SPDX-FileCopyrightText: 2006 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
set(INC
PUBLIC ..
PUBLIC ${CMAKE_CURRENT_BINARY_DIR}
../../blenlib
../../imbuf
../../imbuf/movie
)
set(INC_SYS
)
set(LIB
PRIVATE bf::intern::atomic
PRIVATE bf::intern::guardedalloc
PRIVATE bf::dependencies::optional::tbb
PUBLIC bf::dependencies::openimageio
bf::dependencies::fmt
)
add_definitions(-DWITH_DNA_GHASH)
# Needed for `mallocn.cc`.
if(HAVE_MALLOC_STATS_H)
add_definitions(-DHAVE_MALLOC_STATS_H)
endif()
set(dna_header_include_file "${CMAKE_CURRENT_BINARY_DIR}/dna_includes_all.h")
set(dna_header_string_file "${CMAKE_CURRENT_BINARY_DIR}/dna_includes_as_strings.h")
set(DNA_INCLUDE_TEXT "/* Do not edit manually, changes will be overwritten. */\n")
set(DNA_FILE_LIST "/* Do not edit manually, changes will be overwritten. */\n")
foreach(header ${SRC_DNA_INC})
get_filename_component(dna_header_file ${header} NAME)
string(APPEND DNA_INCLUDE_TEXT "#include \"${header}\"\n")
string(APPEND DNA_FILE_LIST "\t\"${dna_header_file}\",\n")
endforeach()
file(GENERATE OUTPUT ${dna_header_include_file} CONTENT "${DNA_INCLUDE_TEXT}")
file(GENERATE OUTPUT ${dna_header_string_file} CONTENT "${DNA_FILE_LIST}")
# -----------------------------------------------------------------------------
# Build `makesdna` executable.
# Subset of `blenlib` used by `makesdna`.
set(BLENLIB_SRC
../../blenlib/intern/BLI_assert.cc
../../blenlib/intern/BLI_ghash.cc
../../blenlib/intern/BLI_ghash_utils.cc
../../blenlib/intern/BLI_linklist.cc
../../blenlib/intern/BLI_memarena.cc
../../blenlib/intern/BLI_mempool.cc
../../blenlib/intern/listbase.cc
../../blenlib/intern/string.cc
# Dependency of BLI_ghash.cc
../../blenlib/intern/hash_mm2a.cc
# Dependencies of BLI_mempool.cc when ASAN is enabled.
../../blenlib/intern/gsqueue.cc
../../blenlib/intern/threads.cc
../../blenlib/intern/time.cc
)
set(SRC
dna_parse.cc
dna_utils.cc
makesdna.cc
${BLENLIB_SRC}
${dna_header_include_file}
${dna_header_string_file}
dna_parse.h
dna_utils.h
)
# BLI_mempool.cc needs these files for ThreadMutex when
# compiling in address sanitizer mode.
if(WITH_COMPILER_ASAN)
list(APPEND SRC
)
endif()
# `SRC_DNA_INC` is defined in the parent directory.
add_c_and_cxx_flags_custom_test(makesdna)
add_executable(makesdna ${SRC} ${SRC_DNA_INC})
if(EMSCRIPTEN)
target_link_options(makesdna PRIVATE
"-sMODULARIZE=0" "-sEXPORT_ES6=0" "-sENVIRONMENT=node" "-sEXIT_RUNTIME=1"
"-sNODERAWFS=1")
add_custom_command(TARGET makesdna POST_BUILD
COMMAND chmod +x "$<TARGET_FILE:makesdna>")
endif()
setup_platform_linker_flags(makesdna)
setup_platform_linker_libs(makesdna)
blender_target_include_dirs(makesdna ${INC})
blender_target_include_dirs_sys(makesdna ${INC_SYS})
target_link_libraries(makesdna ${LIB})
target_link_libraries(makesdna PRIVATE bf::dependencies::pthreads)
# Output dna.cc
if(EMSCRIPTEN)
set(MAKESDNA_EXECUTABLE /usr/bin/node "$<TARGET_FILE:makesdna>")
else()
set(MAKESDNA_EXECUTABLE "$<TARGET_FILE:makesdna>")
endif()
add_custom_command(
OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/dna.cc
${CMAKE_CURRENT_BINARY_DIR}/dna_defaults.cc
${CMAKE_CURRENT_BINARY_DIR}/dna_struct_ids.cc
${CMAKE_CURRENT_BINARY_DIR}/dna_type_offsets.h
${CMAKE_CURRENT_BINARY_DIR}/dna_verify.cc
COMMAND
${CMAKE_COMMAND} -E env ${PLATFORM_ENV_BUILD}
${MAKESDNA_EXECUTABLE}
${CMAKE_CURRENT_BINARY_DIR}/dna.cc
${CMAKE_CURRENT_BINARY_DIR}/dna_type_offsets.h
${CMAKE_CURRENT_BINARY_DIR}/dna_verify.cc
${CMAKE_CURRENT_BINARY_DIR}/dna_struct_ids.cc
${CMAKE_CURRENT_BINARY_DIR}/dna_defaults.cc
${CMAKE_SOURCE_DIR}/source/blender/makesdna/
DEPENDS makesdna
)
# -----------------------------------------------------------------------------
# Build bf_dna library
set(SRC
dna_genfile.cc
dna_utils.cc
${CMAKE_CURRENT_BINARY_DIR}/dna.cc
${CMAKE_CURRENT_BINARY_DIR}/dna_struct_ids.cc
${SRC_DNA_INC}
${CMAKE_CURRENT_BINARY_DIR}/dna_type_offsets.h
dna_rename_defs.h
dna_utils.h
)
# The generated verification file encodes the native host pointer layout.
# WebAssembly is a 32-bit target, so those native-size assertions are not
# applicable even though the runtime DNA tables remain required.
if(NOT EMSCRIPTEN)
list(APPEND SRC ${CMAKE_CURRENT_BINARY_DIR}/dna_verify.cc)
endif()
set_source_files_properties(
${CMAKE_CURRENT_BINARY_DIR}/dna.cc
${CMAKE_CURRENT_BINARY_DIR}/dna_struct_ids.cc
${CMAKE_CURRENT_BINARY_DIR}/dna_type_offsets.h
${CMAKE_CURRENT_BINARY_DIR}/dna_verify.cc
PROPERTIES GENERATED TRUE
)
blender_add_lib(bf_dna "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
add_library(bf::dna ALIAS bf_dna)
# -----------------------------------------------------------------------------
# Build bf_dna_defaults library
set(SRC
${CMAKE_CURRENT_BINARY_DIR}/dna_defaults.cc
${CMAKE_SOURCE_DIR}/release/datafiles/userdef/userdef_default_theme.c
${SRC_DNA_INC}
)
set_source_files_properties(
${CMAKE_CURRENT_BINARY_DIR}/dna_defaults.cc
PROPERTIES GENERATED TRUE
)
blender_add_lib(bf_dna_defaults "${SRC}" "${INC}" "${INC_SYS}" "${LIB};bf_dna")
# -----------------------------------------------------------------------------
# Build bf_dna_blenlib library
set(INC
..
../../blenlib
)
set(INC_SYS
)
set(SRC
${BLENLIB_SRC}
${SRC_DNA_OTHER_INC}
)
set(LIB
PRIVATE bf::intern::atomic
PRIVATE bf::intern::guardedalloc
PRIVATE bf::dependencies::optional::tbb
)
blender_add_lib(bf_dna_blenlib "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,857 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
* SPDX-FileCopyrightText: 2002-2026 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup DNA
*
* \brief Parser for DNA header files used by `makesdna`.
*
* The parser understands a basic subset of C/C++ needed for parsing structs
* and their members. Code surrounded by `#ifdef __cplusplus` is skipped to
* avoid having to parse more advanced C++.
*/
#include "dna_parse.h"
#include <cctype>
#include <cstdio>
#include <cstring>
#include <fstream>
#include "BLI_map.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_string_ref.hh"
#include "BLI_utildefines.h"
#include "dna_utils.h"
namespace blender {
int debugSDNA = 0;
namespace dna {
#define DEBUG_PRINTF(debug_level, ...) \
{ \
if (debugSDNA > debug_level) { \
printf(__VA_ARGS__); \
} \
} \
((void)0)
/* -------------------------------------------------------------------- */
/** \name File I/O
* \{ */
Span<const char *> default_dna_header_filenames()
{
static const char *files[] = {
#include "dna_includes_as_strings.h"
};
return Span<const char *>(files, sizeof(files) / sizeof(files[0]));
}
[[nodiscard]] static bool read_file_data(const StringRefNull filepath, Vector<char> &data)
{
std::ifstream file(filepath, std::ios::binary | std::ios::ate);
if (!file) {
return false;
}
const std::streamsize size = file.tellg();
if (size < 0) {
return false;
}
file.seekg(0, std::ios::beg);
data.resize(size);
return file.read(data.data(), size) ? true : false;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Token Stream
* \{ */
/* Token kind is either an identifier or number, or an ascii character. */
using TokenKind = int;
constexpr TokenKind TOKEN_IDENTIFIER = 256;
constexpr TokenKind TOKEN_NUMBER = 257;
constexpr TokenKind TOKEN_END = 258;
struct Token {
TokenKind kind;
StringRef text;
};
class TokenStream {
Vector<Token> tokens_;
int64_t pos_ = 0;
public:
void append(Token &&token)
{
tokens_.append(std::move(token));
}
bool at_end() const
{
return pos_ >= tokens_.size();
}
TokenKind kind(int64_t offset = 0) const
{
return (pos_ + offset < tokens_.size()) ? tokens_[pos_ + offset].kind : TOKEN_END;
}
const Token &peek(int64_t offset = 0) const
{
return tokens_[pos_ + offset];
}
const Token &consume()
{
return tokens_[pos_++];
}
void advance()
{
pos_++;
}
bool consume(TokenKind k)
{
if (this->kind() == k) {
pos_++;
return true;
}
return false;
}
bool consume_keyword(StringRef kw)
{
if (this->kind() == TOKEN_IDENTIFIER && this->peek().text == kw) {
pos_++;
return true;
}
return false;
}
bool consume_expression(StringRef expr)
{
int64_t n = 0;
while (!expr.is_empty()) {
if (this->kind(n) == TOKEN_END) {
return false;
}
if (expr[0] == ' ') {
expr = expr.drop_prefix(1);
continue;
}
const StringRef text = this->peek(n).text;
if (!expr.startswith(text)) {
return false;
}
expr = expr.drop_prefix(text.size());
n++;
}
pos_ += n;
return true;
}
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Tokenizer
* \{ */
static bool is_identifier_start(char c)
{
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
}
static bool is_identifier_continuation(char c)
{
return is_identifier_start(c) || (c >= '0' && c <= '9');
}
/** Turn a DNA header into a token stream for parsing. Tokens will reference the
* source string data so it must be kept alive. */
static TokenStream tokenize_dna_header(StringRef source)
{
TokenStream stream;
const char *cur = source.begin();
const char *end = source.end();
while (cur < end) {
const char c = *cur;
/* White-space. */
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
cur++;
continue;
}
/* Discard C++ style comment. */
if (c == '/' && cur + 1 < end && cur[1] == '/') {
cur += 2;
while (cur < end && *cur != '\n') {
cur++;
}
continue;
}
/* Discard C style comment. */
if (c == '/' && cur + 1 < end && cur[1] == '*') {
cur += 2;
while (cur + 1 < end && !(cur[0] == '*' && cur[1] == '/')) {
cur++;
}
if (cur + 1 < end) {
cur += 2;
}
continue;
}
/* Discard string literal. */
if (c == '"') {
cur++;
while (cur < end && *cur != '"') {
if (*cur == '\\' && cur + 1 < end) {
cur++;
}
cur++;
}
if (cur < end) {
cur++;
}
continue;
}
/* Add identifier, :: scope separators are considered part of it. */
if (is_identifier_start(c)) {
const char *begin = cur;
while (cur < end && is_identifier_continuation(*cur)) {
cur++;
}
while (cur + 1 < end && cur[0] == ':' && cur[1] == ':') {
cur += 2;
while (cur < end && is_identifier_continuation(*cur)) {
cur++;
}
}
StringRef text(begin, cur - begin);
stream.append({TOKEN_IDENTIFIER, text});
continue;
}
/* Number. */
if (c >= '0' && c <= '9') {
const char *begin = cur;
while (cur < end && *cur >= '0' && *cur <= '9') {
cur++;
}
stream.append({TOKEN_NUMBER, StringRef(begin, cur - begin)});
continue;
}
/* Add anything else as a single character token. */
stream.append({c, StringRef(cur, 1)});
cur++;
}
return stream;
}
/** Strip tokens that we want to ignore for parsing. */
static TokenStream strip_ignored_tokens(TokenStream stream)
{
TokenStream stripped_stream;
while (!stream.at_end()) {
/* Skip blocks with C++ code that we can't parse. */
if (stream.consume_expression("#ifdef __cplusplus") ||
stream.consume_expression("#if defined(__cplusplus)"))
{
while (!stream.at_end() && !stream.consume_expression("#endif")) {
stream.advance();
}
continue;
}
/* Skip DNA macros that we don't need to parse. */
if (stream.consume_keyword("DNA_DEPRECATED")) {
continue;
}
if (stream.consume_keyword("DNA_DEFINE_CXX_METHODS")) {
while (!stream.at_end() && stream.kind() != ')') {
stream.advance();
}
if (!stream.at_end()) {
stream.advance();
}
continue;
}
stripped_stream.append(Token{stream.consume()});
}
return stripped_stream;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Name Validation
* \{ */
/** Validate a struct type name. */
static bool is_valid_type_name(const StringRefNull type_name, const StringRefNull filepath)
{
if (type_name.is_empty()) {
fprintf(stderr,
"File '%s' contains struct we can't parse \"%s\"\n",
filepath.c_str(),
type_name.c_str());
return false;
}
if (ELEM(type_name, "long", "ulong")) {
fprintf(stderr,
"File '%s' contains use of \"%s\" in DNA struct which is not allowed\n",
filepath.c_str(),
type_name.c_str());
return false;
}
return true;
}
/** Validate a member name. */
static bool is_valid_member_name(const StringRefNull name, const StringRefNull filepath)
{
/* Strip pointer/array decorators: e.g. `*var[3]` -> `var`. */
const StringRef name_strip = DNA_member_id_string_ref(name);
/* Enforce '_pad123' naming convention, disallow 'pad123' or 'pad_123',
* special exception for [a-z] after since there is a 'pad_rot_angle' preference. */
if (!name_strip.is_empty() && name_strip[0] == '_' && !name_strip.startswith("_pad")) {
fprintf(stderr,
"File '%s': only '_pad' variables can start with an underscore, found '%s'\n",
filepath.c_str(),
name.c_str());
return false;
}
if (name_strip.startswith("pad")) {
const StringRef rest = name_strip.drop_prefix(3);
if (!rest.is_empty() && rest[0] >= 'a' && rest[0] <= 'z') {
/* May be part of a word, allow that. */
return true;
}
bool has_only_digit_or_none = true;
for (char c : rest) {
if (!((c >= '0' && c <= '9') || c == '_')) {
has_only_digit_or_none = false;
break;
}
}
if (has_only_digit_or_none) {
fprintf(stderr,
"File '%s': padding variables must be formatted '_pad[number]', found '%s'\n",
filepath.c_str(),
name.c_str());
return false;
}
}
return true;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Parser
* \{ */
/** Consume a balanced `open ... close` group. The current token must be #open. */
static void skip_balanced(TokenStream &stream, TokenKind open, TokenKind close)
{
stream.advance();
int depth = 1;
while (!stream.at_end() && depth > 0) {
const TokenKind k = stream.consume().kind;
if (k == open) {
depth++;
}
else if (k == close) {
depth--;
}
}
}
/** Skip member default initializer from `=` until `;`. */
static void skip_initializer(TokenStream &stream)
{
int depth = 0;
while (!stream.at_end()) {
const TokenKind k = stream.kind();
if (depth == 0 && (k == ',' || k == ';')) {
return;
}
if (k == '{' || k == '(') {
depth++;
}
else if (k == '}' || k == ')') {
depth--;
}
stream.advance();
}
}
/** Append array `[size]` suffixes to the name. */
static void append_array_suffix(TokenStream &stream, std::string &out)
{
while (!stream.at_end() && stream.kind() == '[') {
out += '[';
stream.advance();
int depth = 1;
while (!stream.at_end() && depth > 0) {
const Token &t = stream.consume();
out += t.text;
if (t.kind == '[') {
depth++;
}
else if (t.kind == ']') {
depth--;
}
}
}
}
/** Append template `<...>` arguments to the name. */
static void append_template_suffix(TokenStream &stream, std::string &out)
{
if (!stream.consume('<')) {
return;
}
out += '<';
int depth = 1;
while (!stream.at_end() && depth > 0) {
const Token &t = stream.consume();
out += t.text;
if (t.kind == '<') {
depth++;
}
else if (t.kind == '>') {
depth--;
}
}
}
/**
* Parse a parenthesized declaration: `(*name)(args)` (function pointer) or
* `(*name)[N][M]` (multi-dimensional array pointer). Both are stored in SDNA
* as `(*name)()`.
*/
[[nodiscard]] static bool parse_paren_declaration(TokenStream &stream, std::string &out)
{
stream.advance();
out += '(';
while (stream.consume('*')) {
out += '*';
}
if (stream.at_end() || stream.kind() != TOKEN_IDENTIFIER) {
return false;
}
out += stream.consume().text;
if (!stream.consume(')')) {
return false;
}
out += ')';
if (!stream.at_end() && stream.kind() == '(') {
skip_balanced(stream, '(', ')');
}
else {
while (!stream.at_end() && stream.kind() == '[') {
skip_balanced(stream, '[', ']');
}
}
out += "()";
return true;
}
/** Parse one member declaration. */
[[nodiscard]] static bool parse_member_declaration(TokenStream &stream, std::string &out)
{
out.clear();
/* Pointer prefixes. */
while (stream.consume('*')) {
out += '*';
}
/* Function pointer or multi-dimensional array pointer: `(*name)...` */
if (!stream.at_end() && stream.kind() == '(') {
return parse_paren_declaration(stream, out);
}
/* Plain identifier with potential array suffixes. */
if (stream.at_end() || stream.kind() != TOKEN_IDENTIFIER) {
return false;
}
out += stream.consume().text;
append_array_suffix(stream, out);
return true;
}
/** Parse the body of a struct. */
[[nodiscard]] static bool parse_struct_body(TokenStream &stream,
const StringRefNull filepath,
ParsedStruct &r_struct)
{
while (!stream.at_end() && stream.kind() != '}') {
/* Skip qualifiers. */
while (stream.consume_keyword("struct") || stream.consume_keyword("unsigned") ||
stream.consume_keyword("const"))
{
}
if (stream.at_end() || stream.kind() != TOKEN_IDENTIFIER) {
fprintf(stderr,
"File '%s' contains a member declaration that can't be parsed\n",
filepath.c_str());
return false;
}
/* Consume the identifier and any template arguments (e.g. `ListBaseT<Foo>`)
* into the type name. `substitute_cpp_types` later rewrites templated type
* names into their canonical SDNA form. */
std::string type_name(stream.consume().text);
append_template_suffix(stream, type_name);
if (!is_valid_type_name(type_name, filepath)) {
return false;
}
DEBUG_PRINTF(1, "\t|\t|\tfound type %s (", type_name.c_str());
/* Comma-separated declarations terminated by `;`. */
while (true) {
std::string member_name;
if (!parse_member_declaration(stream, member_name)) {
fprintf(stderr,
"File '%s' contains a member declaration that can't be parsed\n",
filepath.c_str());
return false;
}
if (!is_valid_member_name(member_name, filepath)) {
return false;
}
DEBUG_PRINTF(1, "%s ||", member_name.c_str());
r_struct.members.append({.type_name = type_name, .member_name = member_name});
if (stream.consume('=')) {
skip_initializer(stream);
}
if (stream.consume(';')) {
break;
}
if (!stream.consume(',')) {
fprintf(stderr,
"File '%s' contains a member declaration that can't be parsed\n",
filepath.c_str());
return false;
}
}
DEBUG_PRINTF(1, ")\n");
}
if (!stream.consume('}')) {
fprintf(stderr, "File '%s' contains a struct without a closing brace\n", filepath.c_str());
return false;
}
return true;
}
/** Skip the body of a struct by consuming tokens up to the matching `}`. */
static void skip_struct_body(TokenStream &stream)
{
int depth = 1;
while (!stream.at_end() && depth > 0) {
const TokenKind k = stream.consume().kind;
if (k == '{') {
depth++;
}
else if (k == '}') {
depth--;
}
}
}
/** Parse an enum declaration with its underlying type. */
[[nodiscard]] static bool parse_enum_declaration(TokenStream &stream,
const StringRefNull filepath,
Vector<ParsedEnum> &r_enums)
{
stream.consume_keyword("class");
stream.consume_keyword("struct");
std::string name;
if (!stream.at_end() && stream.kind() == TOKEN_IDENTIFIER) {
name = stream.consume().text;
}
std::string underlying_type;
if (stream.consume(':')) {
if (stream.at_end() || stream.kind() != TOKEN_IDENTIFIER) {
fprintf(stderr,
"File '%s' contains enum '%s' with unparseable underlying type\n",
filepath.c_str(),
name.c_str());
return false;
}
underlying_type = stream.consume().text;
}
if (!stream.consume(';')) {
if (stream.at_end() || stream.kind() != '{') {
return true;
}
skip_balanced(stream, '{', '}');
}
if (!name.empty()) {
r_enums.append({.type_name = std::move(name), .underlying_type = std::move(underlying_type)});
}
return true;
}
static bool parse_dna_header(const StringRefNull filepath,
Vector<ParsedStruct> &r_structs,
Vector<ParsedEnum> &r_enums)
{
Vector<char> buffer;
if (!read_file_data(filepath, buffer)) {
fprintf(stderr, "Can't read file %s\n", filepath.c_str());
return false;
}
TokenStream stream = tokenize_dna_header(StringRef(buffer.data(), buffer.size()));
stream = strip_ignored_tokens(stream);
bool skip_next_struct = false;
while (!stream.at_end()) {
/* `# #` markers in the source flag the next struct definition to be skipped. */
if (stream.kind() == '#' && stream.kind(1) == '#') {
stream.advance();
stream.advance();
skip_next_struct = true;
continue;
}
if (stream.consume_keyword("enum")) {
if (!parse_enum_declaration(stream, filepath, r_enums)) {
return false;
}
continue;
}
if (!stream.consume_keyword("struct")) {
stream.advance();
continue;
}
if (stream.kind() != TOKEN_IDENTIFIER) {
continue;
}
const StringRef name = stream.consume().text;
if (!stream.consume('{')) {
continue;
}
if (skip_next_struct) {
skip_next_struct = false;
skip_struct_body(stream);
continue;
}
const std::string struct_name(name);
if (!is_valid_type_name(struct_name, filepath)) {
return false;
}
ParsedStruct parsed_struct;
parsed_struct.type_name = struct_name;
DEBUG_PRINTF(1, "\t|\t|-- detected struct %s\n", parsed_struct.type_name.c_str());
if (!parse_struct_body(stream, filepath, parsed_struct)) {
return false;
}
r_structs.append(std::move(parsed_struct));
}
return true;
}
bool parse_dna_headers(const StringRefNull base_directory,
Vector<ParsedStruct> &r_structs,
Vector<ParsedEnum> &r_enums,
Span<const char *> include_files)
{
for (const char *filename : include_files) {
const std::string path = std::string(base_directory) + filename;
if (!parse_dna_header(path, r_structs, r_enums)) {
return false;
}
}
return true;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Type Substitution
* \{ */
/** `ListBaseT<...>` -> `ListBase`. */
static void substitute_listbase_t(ParsedMember &member)
{
if (member.type_name.starts_with("ListBaseT<") && member.type_name.ends_with(">")) {
member.type_name = "ListBase";
}
}
/** Replace vector and matrix types with C arrays. */
struct CppVectorMatrixTypeMap {
StringRef cpp_type;
StringRef scalar;
int dimensions[2];
int alignment;
};
static const CppVectorMatrixTypeMap cpp_array_type_mappings[] = {
{"int2", "int", {2, 0}, alignof(blender::int2)},
{"int3", "int", {3, 0}, alignof(blender::int3)},
{"int4", "int", {4, 0}, alignof(blender::int4)},
{"float2", "float", {2, 0}, alignof(blender::float2)},
{"float3", "float", {3, 0}, alignof(blender::float3)},
{"float4", "float", {4, 0}, alignof(blender::float4)},
{"float2x2", "float", {2, 2}, alignof(blender::float2x2)},
{"float3x3", "float", {3, 3}, alignof(blender::float3x3)},
{"float4x4", "float", {4, 4}, alignof(blender::float4x4)},
};
static_assert(sizeof(blender::int2) == sizeof(int[2]));
static_assert(sizeof(blender::int3) == sizeof(int[3]));
static_assert(sizeof(blender::int4) == sizeof(int[4]));
static_assert(sizeof(blender::float2) == sizeof(float[2]));
static_assert(sizeof(blender::float3) == sizeof(float[3]));
static_assert(sizeof(blender::float4) == sizeof(float[4]));
static_assert(sizeof(blender::float2x2) == sizeof(float[2][2]));
static_assert(sizeof(blender::float3x3) == sizeof(float[3][3]));
static_assert(sizeof(blender::float4x4) == sizeof(float[4][4]));
static void substitute_vector_or_matrix(ParsedMember &member)
{
const CppVectorMatrixTypeMap *mapping = nullptr;
for (const CppVectorMatrixTypeMap &m : cpp_array_type_mappings) {
if (member.type_name == m.cpp_type) {
mapping = &m;
break;
}
}
if (mapping == nullptr || member.member_name.empty()) {
return;
}
member.type_name = mapping->scalar;
member.alignment = mapping->alignment;
/* Members like `float (*var)[3][3]` have the `[3][3]` stripped in
* #parse_paren_declaration. So also don't add it for `float3x3 *var` either,
* rather keep it as `float` `*var`. */
if (member.member_name[0] != '*' && member.member_name[0] != '(') {
member.member_name += '[';
member.member_name += char('0' + mapping->dimensions[0]);
member.member_name += ']';
if (mapping->dimensions[1] != 0) {
member.member_name += '[';
member.member_name += char('0' + mapping->dimensions[1]);
member.member_name += ']';
}
}
}
/** Replace member types matching an enum with the enum's underlying type. */
[[nodiscard]] static bool substitute_enum(const ParsedStruct &parsed_struct,
ParsedMember &member,
const Map<StringRef, const ParsedEnum *> &enum_map)
{
const ParsedEnum *const *found = enum_map.lookup_ptr(member.type_name);
if (found == nullptr) {
return true;
}
const ParsedEnum &parsed_enum = **found;
if (parsed_enum.underlying_type.empty()) {
fprintf(stderr,
"Struct '%s' member '%s' uses enum '%s' without an explicit underlying type\n",
parsed_struct.type_name.c_str(),
member.member_name.c_str(),
parsed_enum.type_name.c_str());
return false;
}
member.type_name = parsed_enum.underlying_type;
return true;
}
/** Map modern C integer type names to old SDNA names. */
static void substitute_sdna_integer_type(ParsedMember &member)
{
static const std::pair<const char *, const char *> integer_type_aliases[] = {
{"uint8_t", "uchar"},
{"int16_t", "short"},
{"uint16_t", "ushort"},
{"int32_t", "int"},
{"uint32_t", "int"},
};
for (const auto &[alias, sdna_name] : integer_type_aliases) {
if (member.type_name == alias) {
member.type_name = sdna_name;
break;
}
}
}
bool substitute_cpp_types(Vector<ParsedStruct> &structs,
const Span<ParsedEnum> enums,
bool /*for_rna*/)
{
Map<StringRef, const ParsedEnum *> enum_map;
enum_map.reserve(enums.size());
for (const ParsedEnum &parsed_enum : enums) {
enum_map.add(parsed_enum.type_name, &parsed_enum);
}
for (ParsedStruct &parsed_struct : structs) {
for (ParsedMember &member : parsed_struct.members) {
substitute_listbase_t(member);
substitute_vector_or_matrix(member);
if (!substitute_enum(parsed_struct, member, enum_map)) {
return false;
}
substitute_sdna_integer_type(member);
}
}
return true;
}
/** \} */
} // namespace dna
} // namespace blender

View File

@@ -0,0 +1,53 @@
/* SPDX-FileCopyrightText: 2026 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include <string>
#include "BLI_span.hh"
#include "BLI_string_ref.hh"
#include "BLI_vector.hh"
namespace blender::dna {
struct ParsedMember {
/** Single-identifier type name, e.g. `int`, `float`, `Material`. */
std::string type_name;
/** Canonical full member name, e.g. `*var`, `arr[4]`, `(*func)()`. */
std::string member_name;
/** Original C++ code full member name, before renames. */
std::string alias_member_name;
/** Required alignment in bytes. */
int alignment = 0;
};
struct ParsedStruct {
std::string type_name;
/** Original C++ code full member name, before renames. */
std::string alias_type_name;
Vector<ParsedMember> members;
};
struct ParsedEnum {
std::string type_name;
/** Underlying integer type, e.g. `int8_t`. */
std::string underlying_type;
};
/** List of all DNA header filenames. */
Span<const char *> default_dna_header_filenames();
/** Extract structs, their members, and enums from DNA headers. */
[[nodiscard]] bool parse_dna_headers(StringRefNull base_directory,
Vector<ParsedStruct> &r_structs,
Vector<ParsedEnum> &r_enums,
Span<const char *> include_files);
/** Convert C++ types to plain C types understood by DNA. */
[[nodiscard]] bool substitute_cpp_types(Vector<ParsedStruct> &structs,
Span<ParsedEnum> enums,
bool for_rna);
} // namespace blender::dna

View File

@@ -0,0 +1,311 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup DNA
*
* Defines in this header are only used to define blend file storage.
* This allows us to rename variables & structs without breaking compatibility.
*
* - When renaming the member of a struct which has itself been renamed
* refer to the newer name, not the original.
*
* - Changes here only change generated code for `makesdna.cc` and `makesrna.cc`
* without impacting Blender's run-time, besides allowing us to use the new names.
*
* - Renaming something that has already been renamed can be done
* by editing the existing rename macro.
* All references to the previous destination name can be removed since they're
* never written to disk.
*
* - Old names aren't sanity checked (since this file is the only place that knows about them)
* typos in the old names will break both backwards & forwards compatibility **TAKE CARE**.
*
* - Old names may be referenced as strings in versioning code which uses:
* #DNA_struct_exists & #DNA_struct_member_exists.
* The names used for versioning checks must be updated too.
*
* - Before editing rename defines run:
*
* `sha256sum $BUILD_DIR/source/blender/makesdna/intern/dna.cc`
*
* Compare the results before & after to ensure all changes are reversed by renaming
* and the DNA remains unchanged.
*
* \see `versioning_dna.cc` for actual version patching.
*/
/* No include guard (intentional). */
/* Match RNA names where possible. */
/* NOTE: Keep sorted! */
DNA_STRUCT_RENAME(ActionChannelBag, ActionChannelbag)
DNA_STRUCT_RENAME(Lamp, Light)
DNA_STRUCT_RENAME(NodeImageMultiFile, NodeCompositorFileOutput)
DNA_STRUCT_RENAME(SeqConnection, StripConnection)
DNA_STRUCT_RENAME(SeqRetimingHandle, SeqRetimingKey)
DNA_STRUCT_RENAME(Sequence, Strip)
DNA_STRUCT_RENAME(SequenceModifierData, StripModifierData)
DNA_STRUCT_RENAME(SpaceButs, SpaceProperties)
DNA_STRUCT_RENAME(SpaceIpo, SpaceGraph)
DNA_STRUCT_RENAME(SpaceOops, SpaceOutliner)
DNA_STRUCT_RENAME(Strip, StripData)
DNA_STRUCT_RENAME(TransformVars, TransformVarsLegacy)
DNA_STRUCT_RENAME_MEMBER(ActionSlot, name, identifier)
DNA_STRUCT_RENAME_MEMBER(AnimData, slot_name, last_slot_identifier)
DNA_STRUCT_RENAME_MEMBER(AnimData, tmp_slot_name, tmp_last_slot_identifier)
DNA_STRUCT_RENAME_MEMBER(BPoint, alfa, tilt)
DNA_STRUCT_RENAME_MEMBER(BezTriple, alfa, tilt)
DNA_STRUCT_RENAME_MEMBER(Bone, curveInX, curve_in_x)
DNA_STRUCT_RENAME_MEMBER(Bone, curveInY, curve_in_z)
DNA_STRUCT_RENAME_MEMBER(Bone, curveOutX, curve_out_x)
DNA_STRUCT_RENAME_MEMBER(Bone, curveOutY, curve_out_z)
DNA_STRUCT_RENAME_MEMBER(Bone, scaleIn, scale_in_x)
DNA_STRUCT_RENAME_MEMBER(Bone, scaleOut, scale_out_x)
DNA_STRUCT_RENAME_MEMBER(Bone, scale_in_y, scale_in_z)
DNA_STRUCT_RENAME_MEMBER(Bone, scale_out_y, scale_out_z)
DNA_STRUCT_RENAME_MEMBER(Brush, curve, curve_distance_falloff)
DNA_STRUCT_RENAME_MEMBER(Brush, curve_preset, curve_distance_falloff_preset)
DNA_STRUCT_RENAME_MEMBER(Brush, curves_sculpt_tool, curves_sculpt_brush_type)
DNA_STRUCT_RENAME_MEMBER(Brush, gpencil_sculpt_tool, gpencil_sculpt_brush_type)
DNA_STRUCT_RENAME_MEMBER(Brush, gpencil_tool, gpencil_brush_type)
DNA_STRUCT_RENAME_MEMBER(Brush, gpencil_vertex_tool, gpencil_vertex_brush_type)
DNA_STRUCT_RENAME_MEMBER(Brush, gpencil_weight_tool, gpencil_weight_brush_type)
DNA_STRUCT_RENAME_MEMBER(Brush, imagepaint_tool, image_brush_type)
DNA_STRUCT_RENAME_MEMBER(Brush, sculpt_tool, sculpt_brush_type)
DNA_STRUCT_RENAME_MEMBER(Brush, unprojected_radius, unprojected_size)
DNA_STRUCT_RENAME_MEMBER(Brush, vertexpaint_tool, vertex_brush_type)
DNA_STRUCT_RENAME_MEMBER(Brush, weightpaint_tool, weight_brush_type)
DNA_STRUCT_RENAME_MEMBER(BrushGpencilSettings, gradient_f, hardness)
DNA_STRUCT_RENAME_MEMBER(BrushGpencilSettings, gradient_s, aspect_ratio)
DNA_STRUCT_RENAME_MEMBER(Camera, YF_dofdist, dof_distance)
DNA_STRUCT_RENAME_MEMBER(Camera, clipend, clip_end)
DNA_STRUCT_RENAME_MEMBER(Camera, clipsta, clip_start)
DNA_STRUCT_RENAME_MEMBER(Camera, dtx, composition_guide_flags)
DNA_STRUCT_RENAME_MEMBER(Collection, dupli_ofs, instance_offset)
DNA_STRUCT_RENAME_MEMBER(Curve, ext1, extrude)
DNA_STRUCT_RENAME_MEMBER(Curve, ext2, bevel_radius)
DNA_STRUCT_RENAME_MEMBER(Curve, len_wchar, len_char32)
DNA_STRUCT_RENAME_MEMBER(Curve, loc, texspace_location)
DNA_STRUCT_RENAME_MEMBER(Curve, size, texspace_size)
DNA_STRUCT_RENAME_MEMBER(Curve, texflag, texspace_flag)
DNA_STRUCT_RENAME_MEMBER(Curve, type, ob_type)
DNA_STRUCT_RENAME_MEMBER(Curve, width, offset)
DNA_STRUCT_RENAME_MEMBER(Curves, attributes_active_index, attributes_active_index_legacy)
DNA_STRUCT_RENAME_MEMBER(CurvesGeometry, curve_data, curve_data_legacy)
DNA_STRUCT_RENAME_MEMBER(CurvesGeometry, curve_size, curve_num)
DNA_STRUCT_RENAME_MEMBER(CurvesGeometry, point_size, point_num)
DNA_STRUCT_RENAME_MEMBER(CustomDataExternal, filename, filepath)
DNA_STRUCT_RENAME_MEMBER(Editing, act_seq, act_strip)
DNA_STRUCT_RENAME_MEMBER(Editing, over_border, overlay_frame_rect)
DNA_STRUCT_RENAME_MEMBER(Editing, over_cfra, overlay_frame_abs)
DNA_STRUCT_RENAME_MEMBER(Editing, over_flag, overlay_frame_flag)
DNA_STRUCT_RENAME_MEMBER(Editing, over_ofs, overlay_frame_ofs)
DNA_STRUCT_RENAME_MEMBER(FileAssetSelectParams, import_type, import_method)
DNA_STRUCT_RENAME_MEMBER(FileGlobal, filename, filepath)
DNA_STRUCT_RENAME_MEMBER(FluidDomainSettings, cache_frame_pause_guiding, cache_frame_pause_guide)
DNA_STRUCT_RENAME_MEMBER(FluidDomainSettings, guiding_alpha, guide_alpha)
DNA_STRUCT_RENAME_MEMBER(FluidDomainSettings, guiding_beta, guide_beta)
DNA_STRUCT_RENAME_MEMBER(FluidDomainSettings, guiding_parent, guide_parent)
DNA_STRUCT_RENAME_MEMBER(FluidDomainSettings, guiding_source, guide_source)
DNA_STRUCT_RENAME_MEMBER(FluidDomainSettings, guiding_vel_factor, guide_vel_factor)
DNA_STRUCT_RENAME_MEMBER(FluidEffectorSettings, guiding_mode, guide_mode)
DNA_STRUCT_RENAME_MEMBER(GreasePencil, drawing_array_size, drawing_array_num)
DNA_STRUCT_RENAME_MEMBER(GreasePencil, layers_data, layers_data_legacy)
DNA_STRUCT_RENAME_MEMBER(GreasePencil, material_array_size, material_array_num)
DNA_STRUCT_RENAME_MEMBER(GreasePencilLayerFramesMapStorage, size, num)
DNA_STRUCT_RENAME_MEMBER(GreasePencilLineartModifierData, thickness, thickness_legacy)
DNA_STRUCT_RENAME_MEMBER(HookModifierData, totindex, indexar_num)
DNA_STRUCT_RENAME_MEMBER(Image, name, filepath)
DNA_STRUCT_RENAME_MEMBER(ImageFormatData, planes, color_mode)
DNA_STRUCT_RENAME_MEMBER(LaplacianDeformModifierData, total_verts, verts_num)
DNA_STRUCT_RENAME_MEMBER(Library, name, filepath)
DNA_STRUCT_RENAME_MEMBER(Light, clipend, clipend_deprecated)
DNA_STRUCT_RENAME_MEMBER(Light, energy, energy_deprecated)
DNA_STRUCT_RENAME_MEMBER(Light, energy_new, energy)
DNA_STRUCT_RENAME_MEMBER(LineartGpencilModifierData, line_types, edge_types)
DNA_STRUCT_RENAME_MEMBER(LineartGpencilModifierData, transparency_flags, mask_switches)
DNA_STRUCT_RENAME_MEMBER(LineartGpencilModifierData, transparency_mask, material_mask_bits)
DNA_STRUCT_RENAME_MEMBER(MDefCell, totinfluence, influences_num)
DNA_STRUCT_RENAME_MEMBER(MEdge, bweight, bweight_legacy)
DNA_STRUCT_RENAME_MEMBER(MEdge, crease, crease_legacy)
DNA_STRUCT_RENAME_MEMBER(MEdge, flag, flag_legacy)
DNA_STRUCT_RENAME_MEMBER(MPoly, flag, flag_legacy)
DNA_STRUCT_RENAME_MEMBER(MPoly, mat_nr, mat_nr_legacy)
DNA_STRUCT_RENAME_MEMBER(MVert, bweight, bweight_legacy)
DNA_STRUCT_RENAME_MEMBER(MVert, co, co_legacy)
DNA_STRUCT_RENAME_MEMBER(MVert, flag, flag_legacy)
DNA_STRUCT_RENAME_MEMBER(MaskLayer, restrictflag, visibility_flag)
DNA_STRUCT_RENAME_MEMBER(MaterialLineArt, transparency_mask, material_mask_bits)
DNA_STRUCT_RENAME_MEMBER(Mesh, edata, edge_data)
DNA_STRUCT_RENAME_MEMBER(Mesh, fdata, fdata_legacy)
DNA_STRUCT_RENAME_MEMBER(Mesh, ldata, corner_data)
DNA_STRUCT_RENAME_MEMBER(Mesh, loc, texspace_location)
DNA_STRUCT_RENAME_MEMBER(Mesh, pdata, face_data)
DNA_STRUCT_RENAME_MEMBER(Mesh, poly_offset_indices, face_offset_indices)
DNA_STRUCT_RENAME_MEMBER(Mesh, size, texspace_size)
DNA_STRUCT_RENAME_MEMBER(Mesh, smoothresh, smoothresh_legacy)
DNA_STRUCT_RENAME_MEMBER(Mesh, texflag, texspace_flag)
DNA_STRUCT_RENAME_MEMBER(Mesh, totedge, edges_num)
DNA_STRUCT_RENAME_MEMBER(Mesh, totface, totface_legacy)
DNA_STRUCT_RENAME_MEMBER(Mesh, totloop, corners_num)
DNA_STRUCT_RENAME_MEMBER(Mesh, totpoly, faces_num)
DNA_STRUCT_RENAME_MEMBER(Mesh, totvert, verts_num)
DNA_STRUCT_RENAME_MEMBER(Mesh, vdata, vert_data)
DNA_STRUCT_RENAME_MEMBER(MeshDeformModifierData, totcagevert, cage_verts_num)
DNA_STRUCT_RENAME_MEMBER(MeshDeformModifierData, totinfluence, influences_num)
DNA_STRUCT_RENAME_MEMBER(MeshDeformModifierData, totvert, verts_num)
DNA_STRUCT_RENAME_MEMBER(MetaBall, loc, texspace_location)
DNA_STRUCT_RENAME_MEMBER(MetaBall, size, texspace_size)
DNA_STRUCT_RENAME_MEMBER(MetaBall, texflag, texspace_flag)
DNA_STRUCT_RENAME_MEMBER(MetaStack, parseq, parent_strip)
DNA_STRUCT_RENAME_MEMBER(MovieClip, name, filepath)
DNA_STRUCT_RENAME_MEMBER(MovieTracking, act_plane_track, act_plane_track_legacy)
DNA_STRUCT_RENAME_MEMBER(MovieTracking, act_track, act_track_legacy)
DNA_STRUCT_RENAME_MEMBER(MovieTracking, plane_tracks, plane_tracks_legacy)
DNA_STRUCT_RENAME_MEMBER(MovieTracking, reconstruction, reconstruction_legacy)
DNA_STRUCT_RENAME_MEMBER(MovieTracking, tracks, tracks_legacy)
DNA_STRUCT_RENAME_MEMBER(MovieTrackingCamera, principal, principal_legacy)
DNA_STRUCT_RENAME_MEMBER(MovieTrackingSettings, keyframe1, keyframe1_legacy)
DNA_STRUCT_RENAME_MEMBER(MovieTrackingSettings, keyframe2, keyframe2_legacy)
DNA_STRUCT_RENAME_MEMBER(MovieTrackingStabilization, rot_track, rot_track_legacy)
DNA_STRUCT_RENAME_MEMBER(MovieTrackingTrack, pat_max, pat_max_legacy)
DNA_STRUCT_RENAME_MEMBER(MovieTrackingTrack, pat_min, pat_min_legacy)
DNA_STRUCT_RENAME_MEMBER(MovieTrackingTrack, search_max, search_max_legacy)
DNA_STRUCT_RENAME_MEMBER(MovieTrackingTrack, search_min, search_min_legacy)
DNA_STRUCT_RENAME_MEMBER(NlaStrip, action_slot_name, last_slot_identifier)
DNA_STRUCT_RENAME_MEMBER(NodeCompositorFileOutput, active_input, active_item_index)
DNA_STRUCT_RENAME_MEMBER(NodeCompositorFileOutput, base_path, directory)
DNA_STRUCT_RENAME_MEMBER(NodeCryptomatte, num_inputs, inputs_num)
DNA_STRUCT_RENAME_MEMBER(NodeGeometryAttributeCapture, data_type, data_type_legacy)
DNA_STRUCT_RENAME_MEMBER(NodeGeometryViewer, data_type, data_type_legacy)
DNA_STRUCT_RENAME_MEMBER(NodeTexSky, dust_density, aerosol_density)
DNA_STRUCT_RENAME_MEMBER(NodesModifierData, settings, settings_legacy)
DNA_STRUCT_RENAME_MEMBER(NodesModifierData, simulation_bake_directory, bake_directory)
DNA_STRUCT_RENAME_MEMBER(Object, col, color)
DNA_STRUCT_RENAME_MEMBER(Object, dup_group, instance_collection)
DNA_STRUCT_RENAME_MEMBER(Object, dupfacesca, instance_faces_scale)
DNA_STRUCT_RENAME_MEMBER(Object, restrictflag, visibility_flag)
DNA_STRUCT_RENAME_MEMBER(Object, size, scale)
DNA_STRUCT_RENAME_MEMBER(OpacityGpencilModifierData, hardeness, hardness)
DNA_STRUCT_RENAME_MEMBER(Paint, num_input_samples, num_input_samples_deprecated)
DNA_STRUCT_RENAME_MEMBER(ParticleSettings, child_nbr, child_percent)
DNA_STRUCT_RENAME_MEMBER(ParticleSettings, dup_group, instance_collection)
DNA_STRUCT_RENAME_MEMBER(ParticleSettings, dup_ob, instance_object)
DNA_STRUCT_RENAME_MEMBER(ParticleSettings, dupliweights, instance_weights)
DNA_STRUCT_RENAME_MEMBER(ParticleSettings, ren_child_nbr, child_render_percent)
DNA_STRUCT_RENAME_MEMBER(PointCloud, pdata, pdata_legacy)
DNA_STRUCT_RENAME_MEMBER(RenderData, bake_filter, bake_margin)
DNA_STRUCT_RENAME_MEMBER(RenderData, blurfac, motion_blur_shutter)
DNA_STRUCT_RENAME_MEMBER(RenderData, planes, color_mode)
DNA_STRUCT_RENAME_MEMBER(RigidBodyWorld, steps_per_second, substeps_per_frame)
DNA_STRUCT_RENAME_MEMBER(SDefBind, numverts, verts_num)
DNA_STRUCT_RENAME_MEMBER(SDefVert, numbinds, binds_num)
DNA_STRUCT_RENAME_MEMBER(SceneEEVEE, gtao_focus, fast_gi_bias)
DNA_STRUCT_RENAME_MEMBER(SceneEEVEE, gtao_quality, fast_gi_quality)
DNA_STRUCT_RENAME_MEMBER(SceneEEVEE, gtao_resolution, fast_gi_resolution)
DNA_STRUCT_RENAME_MEMBER(SceneEEVEE, motion_blur_position, motion_blur_position_deprecated)
DNA_STRUCT_RENAME_MEMBER(SceneEEVEE, motion_blur_shutter, motion_blur_shutter_deprecated)
DNA_STRUCT_RENAME_MEMBER(SceneEEVEE, shadow_cube_size, shadow_cube_size_deprecated)
DNA_STRUCT_RENAME_MEMBER(Sculpt, radial_symm, radial_symm_legacy)
DNA_STRUCT_RENAME_MEMBER(SpaceImage, pixel_snap_mode, pixel_round_mode)
DNA_STRUCT_RENAME_MEMBER(SpaceNode, geometry_nodes_tool_tree, selected_node_group)
DNA_STRUCT_RENAME_MEMBER(SpaceNode, geometry_nodes_type, node_tree_sub_type)
DNA_STRUCT_RENAME_MEMBER(SpaceSeq, overlay_type, overlay_frame_type)
DNA_STRUCT_RENAME_MEMBER(SpeedControlVars, globalSpeed, globalSpeed_legacy)
DNA_STRUCT_RENAME_MEMBER(Strip, endstill, endstill_legacy)
DNA_STRUCT_RENAME_MEMBER(Strip, machine, channel)
DNA_STRUCT_RENAME_MEMBER(Strip, pitch, pitch_legacy)
DNA_STRUCT_RENAME_MEMBER(Strip, retiming_handle_num, retiming_keys_num)
DNA_STRUCT_RENAME_MEMBER(Strip, retiming_handles, retiming_keys)
DNA_STRUCT_RENAME_MEMBER(Strip, seq1, input1)
DNA_STRUCT_RENAME_MEMBER(Strip, seq2, input2)
DNA_STRUCT_RENAME_MEMBER(Strip, speed_fader, speed_fader_legacy)
DNA_STRUCT_RENAME_MEMBER(Strip, startstill, startstill_legacy)
DNA_STRUCT_RENAME_MEMBER(Strip, strip, data)
DNA_STRUCT_RENAME_MEMBER(StripConnection, seq_ref, strip_ref)
DNA_STRUCT_RENAME_MEMBER(StripData, color_balance, color_balance_legacy)
DNA_STRUCT_RENAME_MEMBER(StripData, dir, dirpath)
DNA_STRUCT_RENAME_MEMBER(StripElem, name, filename)
DNA_STRUCT_RENAME_MEMBER(StripModifierData, mask_sequence, mask_strip)
DNA_STRUCT_RENAME_MEMBER(StripProxy, dir, dirpath)
DNA_STRUCT_RENAME_MEMBER(StripProxy, file, filename)
DNA_STRUCT_RENAME_MEMBER(SurfaceDeformModifierData, num_mesh_verts, mesh_verts_num)
DNA_STRUCT_RENAME_MEMBER(SurfaceDeformModifierData, numpoly, target_polys_num)
DNA_STRUCT_RENAME_MEMBER(SurfaceDeformModifierData, numverts, bind_verts_num)
DNA_STRUCT_RENAME_MEMBER(Text, name, filepath)
DNA_STRUCT_RENAME_MEMBER(TextVars, align_y, align_y_legacy)
DNA_STRUCT_RENAME_MEMBER(TextVars, text, text_legacy)
DNA_STRUCT_RENAME_MEMBER(ThemeSpace, show_back_grad, background_type)
DNA_STRUCT_RENAME_MEMBER(UVProjectModifierData, num_projectors, projectors_num)
DNA_STRUCT_RENAME_MEMBER(UnifiedPaintSettings, unprojected_radius, unprojected_size)
DNA_STRUCT_RENAME_MEMBER(UserDef, autokey_flag, keying_flag)
DNA_STRUCT_RENAME_MEMBER(UserDef, gp_manhattendist, gp_manhattandist)
DNA_STRUCT_RENAME_MEMBER(UserDef, max_shader_compilation_subprocesses, gpu_shader_workers)
DNA_STRUCT_RENAME_MEMBER(UserDef, ndof_orbit_sensitivity, ndof_rotation_sensitivity)
DNA_STRUCT_RENAME_MEMBER(UserDef, ndof_sensitivity, ndof_translation_sensitivity)
DNA_STRUCT_RENAME_MEMBER(UserDef, pythondir, pythondir_legacy)
DNA_STRUCT_RENAME_MEMBER(UvSculpt, curve_preset, curve_distance_falloff_preset)
DNA_STRUCT_RENAME_MEMBER(UvSculpt, strength_curve, curve_distance_falloff)
DNA_STRUCT_RENAME_MEMBER(VFont, name, filepath)
DNA_STRUCT_RENAME_MEMBER(View3D, far, clip_end)
DNA_STRUCT_RENAME_MEMBER(View3D, local_collections_uuid, local_collections_uid)
DNA_STRUCT_RENAME_MEMBER(View3D, local_view_uuid, local_view_uid)
DNA_STRUCT_RENAME_MEMBER(View3D, near, clip_start)
DNA_STRUCT_RENAME_MEMBER(View3D, ob_centre, ob_center)
DNA_STRUCT_RENAME_MEMBER(View3D, ob_centre_bone, ob_center_bone)
DNA_STRUCT_RENAME_MEMBER(View3D, ob_centre_cursor, ob_center_cursor)
DNA_STRUCT_RENAME_MEMBER(View3D, vignette_aperture, xr_vignette_aperture)
DNA_STRUCT_RENAME_MEMBER(bActionConstraint, action_slot_name, last_slot_identifier)
DNA_STRUCT_RENAME_MEMBER(bActionGroup, channel_bag, channelbag)
DNA_STRUCT_RENAME_MEMBER(bArmature, collections, collections_legacy)
DNA_STRUCT_RENAME_MEMBER(bGPDstroke, gradient_f, hardness)
DNA_STRUCT_RENAME_MEMBER(bGPDstroke, gradient_s, aspect_ratio)
DNA_STRUCT_RENAME_MEMBER(bNode, locx, locx_legacy)
DNA_STRUCT_RENAME_MEMBER(bNode, locy, locy_legacy)
DNA_STRUCT_RENAME_MEMBER(bNode, offsetx, offsetx_legacy)
DNA_STRUCT_RENAME_MEMBER(bNode, offsety, offsety_legacy)
DNA_STRUCT_RENAME_MEMBER(bNode, type, type_legacy)
DNA_STRUCT_RENAME_MEMBER(bNodeLink, multi_input_socket_index, multi_input_sort_id)
DNA_STRUCT_RENAME_MEMBER(bNodeTree, inputs, inputs_legacy)
DNA_STRUCT_RENAME_MEMBER(bNodeTree, outputs, outputs_legacy)
DNA_STRUCT_RENAME_MEMBER(bPoseChannel, curveInX, curve_in_x)
DNA_STRUCT_RENAME_MEMBER(bPoseChannel, curveInY, curve_in_z)
DNA_STRUCT_RENAME_MEMBER(bPoseChannel, curveOutX, curve_out_x)
DNA_STRUCT_RENAME_MEMBER(bPoseChannel, curveOutY, curve_out_z)
DNA_STRUCT_RENAME_MEMBER(bPoseChannel, scaleIn, scale_in_x)
DNA_STRUCT_RENAME_MEMBER(bPoseChannel, scaleOut, scale_out_x)
DNA_STRUCT_RENAME_MEMBER(bPoseChannel, scale_in_y, scale_in_z)
DNA_STRUCT_RENAME_MEMBER(bPoseChannel, scale_out_y, scale_out_z)
DNA_STRUCT_RENAME_MEMBER(bPoseChannel, size, scale)
DNA_STRUCT_RENAME_MEMBER(bSameVolumeConstraint, flag, free_axis)
DNA_STRUCT_RENAME_MEMBER(bSound, name, filepath)
DNA_STRUCT_RENAME_MEMBER(bTheme, tact, space_action)
DNA_STRUCT_RENAME_MEMBER(bTheme, tbuts, space_properties)
DNA_STRUCT_RENAME_MEMBER(bTheme, tclip, space_clip)
DNA_STRUCT_RENAME_MEMBER(bTheme, tconsole, space_console)
DNA_STRUCT_RENAME_MEMBER(bTheme, text, space_text)
DNA_STRUCT_RENAME_MEMBER(bTheme, tfile, space_file)
DNA_STRUCT_RENAME_MEMBER(bTheme, tima, space_image)
DNA_STRUCT_RENAME_MEMBER(bTheme, tinfo, space_info)
DNA_STRUCT_RENAME_MEMBER(bTheme, tipo, space_graph)
DNA_STRUCT_RENAME_MEMBER(bTheme, tnla, space_nla)
DNA_STRUCT_RENAME_MEMBER(bTheme, tnode, space_node)
DNA_STRUCT_RENAME_MEMBER(bTheme, toops, space_outliner)
DNA_STRUCT_RENAME_MEMBER(bTheme, tseq, space_sequencer)
DNA_STRUCT_RENAME_MEMBER(bTheme, tstatusbar, space_statusbar)
DNA_STRUCT_RENAME_MEMBER(bTheme, ttopbar, space_topbar)
DNA_STRUCT_RENAME_MEMBER(bTheme, tuserpref, space_preferences)
DNA_STRUCT_RENAME_MEMBER(bTheme, tv3d, space_view3d)
DNA_STRUCT_RENAME_MEMBER(bUserAssetLibrary, path, dirpath)
/* NOTE: Keep sorted! */
/* Write with a different name, old Blender versions crash loading files with non-NULL
* global_areas. See D9442. */
DNA_STRUCT_RENAME_MEMBER(wmWindow, global_area_map, global_areas)
/* NOTE: Keep sorted! */

View File

@@ -0,0 +1,312 @@
/* SPDX-FileCopyrightText: 2018 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup DNA
*
* Utilities for stand-alone `makesdna.cc` and Blender to share.
*/
#include <cstring>
#include "DNA_defs.h"
#include "BLI_alloca.h"
#include "BLI_assert.h"
#include "BLI_sys_types.h"
#include "BLI_utildefines.h"
#include "BLI_memarena.h"
#include "dna_utils.h"
namespace blender {
/* -------------------------------------------------------------------- */
/** \name Struct Member Evaluation
* \{ */
int DNA_member_array_num(const char *str)
{
int result = 1;
int current = 0;
while (true) {
char c = *str++;
switch (c) {
case '\0':
return result;
case '[':
current = 0;
break;
case ']':
result *= current;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
current = current * 10 + (c - '0');
break;
default:
break;
}
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Struct Member Manipulation
* \{ */
static bool is_identifier(const char c)
{
return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') ||
(c == '_'));
}
uint DNA_member_id_offset_start(const char *member_full)
{
uint elem_full_offset = 0;
/* NOTE(@ideasman42): checking nil is needed for invalid names such as `*`,
* these were written by older versions of Blender (v2.66).
* In this case the "name" part will be an empty string.
* The member cannot be used, this just prevents a crash. */
while (!is_identifier(member_full[elem_full_offset]) && member_full[elem_full_offset]) {
elem_full_offset++;
}
return elem_full_offset;
}
static uint dna_member_id_length(const char *member_full_trimmed)
{
uint elem_full_offset = 0;
while (is_identifier(member_full_trimmed[elem_full_offset])) {
elem_full_offset++;
}
return elem_full_offset;
}
StringRef DNA_member_id_string_ref(const StringRefNull member_full)
{
const uint id_start = DNA_member_id_offset_start(member_full.c_str());
const uint id_len = dna_member_id_length(member_full.c_str() + id_start);
return StringRef(member_full.c_str() + id_start, id_len);
}
uint DNA_member_id_strip_copy(char *member_id_dst, const char *member_full_src)
{
const StringRef stripped = DNA_member_id_string_ref(member_full_src);
memcpy(member_id_dst, stripped.data(), stripped.size());
member_id_dst[stripped.size()] = '\0';
return stripped.size();
}
uint DNA_member_id_strip(char *member)
{
const StringRef stripped = DNA_member_id_string_ref(member);
memmove(member, stripped.data(), stripped.size());
member[stripped.size()] = '\0';
return stripped.size();
}
bool DNA_member_id_match(const char *member_id,
const int member_id_len,
const char *member_full,
uint *r_member_full_offset)
{
BLI_assert(strlen(member_id) == member_id_len);
const uint elem_full_offset = DNA_member_id_offset_start(member_full);
const char *elem_full_trim = member_full + elem_full_offset;
if (strncmp(member_id, elem_full_trim, member_id_len) == 0) {
const char c = elem_full_trim[member_id_len];
if (c == '\0' || !is_identifier(c)) {
*r_member_full_offset = elem_full_offset;
return true;
}
}
return false;
}
char *DNA_member_id_rename(MemArena *mem_arena,
const char *member_id_src,
const int member_id_src_len,
const char *member_id_dst,
const int member_id_dst_len,
const char *member_full_src,
const int member_full_src_len,
const uint member_full_src_offset_len)
{
BLI_assert(strlen(member_id_src) == member_id_src_len);
BLI_assert(strlen(member_id_dst) == member_id_dst_len);
BLI_assert(strlen(member_full_src) == member_full_src_len);
BLI_assert(DNA_member_id_offset_start(member_full_src) == member_full_src_offset_len);
UNUSED_VARS_NDEBUG(member_id_src);
const int member_full_dst_len = (member_full_src_len - member_id_src_len) + member_id_dst_len;
char *member_full_dst = static_cast<char *>(
BLI_memarena_alloc(mem_arena, member_full_dst_len + 1));
uint i = 0;
if (member_full_src_offset_len != 0) {
memcpy(member_full_dst, member_full_src, member_full_src_offset_len);
i = member_full_src_offset_len;
}
memcpy(&member_full_dst[i], member_id_dst, member_id_dst_len + 1);
i += member_id_dst_len;
const uint member_full_src_offset_end = member_full_src_offset_len + member_id_src_len;
BLI_assert(dna_member_id_length(member_full_src + member_full_src_offset_len) ==
(member_full_src_offset_end - member_full_src_offset_len));
if (member_full_src[member_full_src_offset_end] != '\0') {
const int member_full_tail_len = (member_full_src_len - member_full_src_offset_end);
memcpy(&member_full_dst[i],
&member_full_src[member_full_src_offset_end],
member_full_tail_len + 1);
i += member_full_tail_len;
}
BLI_assert((strlen(member_full_dst) == member_full_dst_len) && (i == member_full_dst_len));
UNUSED_VARS_NDEBUG(i);
return member_full_dst;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Rename Maps
* \{ */
struct StructRename {
const char *old_name;
const char *new_name;
};
static const StructRename struct_renames[] = {
#define DNA_STRUCT_RENAME(old, new) {#old, #new},
#define DNA_STRUCT_RENAME_MEMBER(new_struct_name, old, new)
#include "dna_rename_defs.h"
#undef DNA_STRUCT_RENAME
#undef DNA_STRUCT_RENAME_MEMBER
};
struct MemberRename {
const char *new_struct_name;
const char *old_name;
const char *new_name;
};
static const MemberRename member_renames[] = {
#define DNA_STRUCT_RENAME(old, new)
#define DNA_STRUCT_RENAME_MEMBER(new_struct_name, old, new) {#new_struct_name, #old, #new},
#include "dna_rename_defs.h"
#undef DNA_STRUCT_RENAME
#undef DNA_STRUCT_RENAME_MEMBER
};
DnaRenameMaps DNA_rename_maps_alias_to_static()
{
DnaRenameMaps data;
for (const StructRename &r : struct_renames) {
data.types.add_new(r.new_name, r.old_name);
}
for (const MemberRename &r : member_renames) {
const StringRefNull struct_static = data.types.lookup_default(r.new_struct_name,
r.new_struct_name);
data.members.add_new({struct_static, r.new_name}, r.old_name);
}
return data;
}
DnaRenameMaps DNA_rename_maps_static_to_alias()
{
DnaRenameMaps data;
Map<StringRefNull, StringRefNull> struct_alias_to_static;
for (const StructRename &r : struct_renames) {
data.types.add_new(r.old_name, r.new_name);
struct_alias_to_static.add_new(r.new_name, r.old_name);
}
for (const MemberRename &r : member_renames) {
const StringRefNull struct_static = struct_alias_to_static.lookup_default(r.new_struct_name,
r.new_struct_name);
data.members.add_new({struct_static, r.old_name}, r.new_name);
}
return data;
}
#undef DNA_MAKESDNA
/** \} */
/* -------------------------------------------------------------------- */
/** \name Struct Name Legacy Hack
* \{ */
/* WARNING: Only keep this for compatibility: *NEVER ADD NEW STRINGS HERE*.
*
* The renaming here isn't complete, references to the old struct names
* are still included in DNA, now fixing these struct names properly
* breaks forward compatibility. Leave these as-is, but don't add to them!
* See D4342#98780. */
const char *DNA_struct_rename_legacy_hack_static_from_alias(const char *name)
{
/* 'bScreen' replaces the old IrisGL 'Screen' struct */
if (STREQ("bScreen", name)) {
return "Screen";
}
/* Groups renamed to collections in 2.8 */
if (STREQ("Collection", name)) {
return "Group";
}
if (STREQ("CollectionObject", name)) {
return "GroupObject";
}
return name;
}
const char *DNA_struct_rename_legacy_hack_alias_from_static(const char *name)
{
/* 'bScreen' replaces the old IrisGL 'Screen' struct */
if (STREQ("Screen", name)) {
return "bScreen";
}
/* Groups renamed to collections in 2.8 */
if (STREQ("Group", name)) {
return "Collection";
}
if (STREQ("GroupObject", name)) {
return "CollectionObject";
}
return name;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Internal helpers for C++
* \{ */
void _DNA_internal_memcpy(void *dst, const void *src, const size_t size)
{
memcpy(dst, src, size);
}
void _DNA_internal_memzero(void *dst, const size_t size)
{
memset(dst, 0, size);
}
void _DNA_internal_swap(void *a, void *b, const size_t size)
{
void *tmp = alloca(size);
memcpy(tmp, a, size);
memcpy(a, b, size);
memcpy(b, tmp, size);
}
/** \} */
} // namespace blender

View File

@@ -0,0 +1,103 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup DNA
*/
#pragma once
#include <utility>
#include "BLI_map.hh"
#include "BLI_string_ref.hh"
#include "BLI_sys_types.h"
namespace blender {
struct MemArena;
/**
* Naming convention in this header:
* - `member_full` refers to the full definition of a struct member, including its prefixes (like
* the pointer `*` ones) and suffixes (like the `[]` array ones).
* - `member_id` (for member identifier) refers to the bare name of the struct member (e.g. `var`
* is the member identifier of the `*var[n1][n2]` full member).
*/
/**
* Parse the `[n1][n2]...` at the end of an array struct member.
*
* \return the total number of array elements `n1 * n2 ...`, or `1` if the member is not an array.
*/
int DNA_member_array_num(const char *str);
/** Find the start offset of the member id (the name) within the full member definition. */
uint DNA_member_id_offset_start(const char *member_full);
/**
* Copy the member id part (the bare name) of the full source member into \a member_id_dst.
*
* \param member_id_dst: destination char buffer, must be at least the size of \a member_src_full.
*/
uint DNA_member_id_strip_copy(char *member_id_dst, const char *member_full_src);
/**
* Same as #DNA_member_id_strip_copy, but modifies the given \a member string in place.
*/
uint DNA_member_id_strip(char *member);
/**
* Return the stripped member identifier portion of #member_full. This references
* the original string and does not make a copy.
*/
StringRef DNA_member_id_string_ref(StringRefNull member_full);
/**
* Check if the member identifier given in \a member_id matches the full name given in \a
* member_full. E.g. `var` matches full names like `var` or `*var[3]`, but not `variable`.
*
* \return true if it does, with the start offset of the match in \a r_member_full_offset.
*/
bool DNA_member_id_match(const char *member_id,
int member_id_len,
const char *member_full,
uint *r_member_full_offset);
/**
* Rename a struct member to a different name.
*
* Replace the source member identifier (\a member_id_src) by the destination one
* (\a member_id_dst), while preserving the potential prefixes and suffixes.
*
* \return a renamed DNA full member, allocated from \a mem_arena.
*/
char *DNA_member_id_rename(struct MemArena *mem_arena,
const char *member_id_src,
int member_id_src_len,
const char *member_id_dst,
int member_id_dst_len,
const char *member_full_src,
int member_full_src_len,
uint member_full_src_offset_len);
/**
* Rename maps built from `dna_rename_defs.h` and other versioning.
*
* - 'Static' is the original name of the data, the one that is still stored in blend-files
* DNA info (to avoid breaking forward compatibility).
* - 'Alias' is the current name of the data, the one used in current DNA definition code.
*/
struct DnaRenameMaps {
/* Type name mapping. */
Map<StringRefNull, StringRefNull> types;
/** Member name mapping (first in pair is always the static struct name). */
Map<std::pair<StringRefNull, StringRefNull>, StringRefNull> members;
};
DnaRenameMaps DNA_rename_maps_alias_to_static();
DnaRenameMaps DNA_rename_maps_static_to_alias();
/**
* DNA Compatibility Hack.
*/
const char *DNA_struct_rename_legacy_hack_alias_from_static(const char *name);
const char *DNA_struct_rename_legacy_hack_static_from_alias(const char *name);
} // namespace blender

File diff suppressed because it is too large Load Diff