Files
test2/source/blender/makesdna/DNA_print.hh
Jacques Lucke 9fd7a093c9 DNA: support getting sdna id for static DNA type
This adds a new `DNA_sdna_type_ids.hh` header:
```cpp
namespace blender::dna {

/**
 * Each DNA struct has an integer identifier which is unique within a specific
 * Blender build, but not necessarily across different builds. The identifier
 * can be used to index into `SDNA.structs`.
 */
template<typename T> int sdna_struct_id_get();

/**
 * The maximum identifier that will be returned by #sdna_struct_id_get in this
 * Blender build.
 */
int sdna_struct_id_get_max();

}  // namespace blender::dna
```

The `sdna_struct_id_get` function is used as replacement of
`SDNA_TYPE_FROM_STRUCT` in all places except the DNA defaults system. The
defaults system is C code and therefore can't use the template. There is ongoing
work to replace the defaults system as well though: #134531.

Using this templated function has some benefits over the old approach:
* No need to rely on macros.
* Can use type inferencing in functions like `BLO_write_struct` which avoids
  redundancy on the call site. E.g. `BLO_write_struct(writer, ActionStrip,
  strip);` can become `BLO_write_struct(writer, strip);` which could even become
  `writer.write_struct(strip);`. None of that is implemented as part of this
  patch though.
* No need to include the generated `dna_type_offsets.h` file which contains a
  huge enum.

Implementation wise, this is done using explicit template instantiations in a
new file generated by `makesdna.cc`: `dna_struct_ids.cc`. The generated file
looks like so:
```cpp
namespace blender::dna {

template<typename T> int sdna_struct_id_get();

int sdna_struct_id_get_max();
int sdna_struct_id_get_max() { return 951; }

}
struct IDPropertyUIData;
template<> int blender:🧬:sdna_struct_id_get<IDPropertyUIData>() { return 1; }
struct IDPropertyUIDataEnumItem;
template<> int blender:🧬:sdna_struct_id_get<IDPropertyUIDataEnumItem>() { return 2; }
```

I tried using static variables instead of separate functions, but I didn't
manage to link it properly. Not quite sure yet if that's an actual limitation or
if I was just missing something.

Pull Request: https://projects.blender.org/blender/blender/pulls/138706
2025-05-12 11:16:26 +02:00

50 lines
1.5 KiB
C++

/* SPDX-FileCopyrightText: 2025 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include <cstdint>
#include <iosfwd>
#include "DNA_sdna_type_ids.hh"
struct SDNA;
struct SDNA_Struct;
namespace blender::dna {
/**
* Print all members of the struct assuming that the data has the given address. This is mainly
* useful for observing what data is written to a .blend file.
*
* \param sdna: Contains reflection information about DNA structs.
* \param struct_id: The type the data points to. Used to index into `sdna.structs`.
* \param data: Where the data is stored.
* \param address: The address that should be printed. Often it's the same as `data`.
* \param element_num: The number of elements in the array, or 1 if there is only one struct.
* \param stream: Where to print the output.
*/
void print_structs_at_address(const SDNA &sdna,
int struct_id,
const void *data,
const void *address,
int64_t element_num,
std::ostream &stream);
/**
* Prints all members of the struct to stdout.
*/
void print_struct_by_id(int struct_id, const void *data);
} // namespace blender::dna
/**
* Prints all members of the struct to stdout.
*
* Usage:
* DNA_print_struct(bNode, node);
*/
#define DNA_print_struct(struct_name, data_ptr) \
blender::dna::print_struct_by_id(blender::dna::sdna_struct_id_get<struct_name>(), data_ptr)