2011-02-17 05:57:18 +00:00
|
|
|
/*
|
2002-10-12 11:37:38 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
2008-04-16 22:40:48 +00:00
|
|
|
* of the License, or (at your option) any later version.
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
2011-02-17 05:57:18 +00:00
|
|
|
*/
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
* \ingroup DNA
|
2019-02-06 15:52:04 +11:00
|
|
|
*
|
|
|
|
* \brief Struct muncher for making SDNA.
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
2011-02-17 16:17:40 +00:00
|
|
|
* \section aboutmakesdnac About makesdna tool
|
2002-10-12 11:37:38 +00:00
|
|
|
* Originally by Ton, some mods by Frank, and some cleaning and
|
|
|
|
* extension by Nzc.
|
|
|
|
*
|
|
|
|
* Makesdna creates a .c file with a long string of numbers that
|
|
|
|
* encode the Blender file format. It is fast, because it is basically
|
|
|
|
* a binary dump. There are some details to mind when reconstructing
|
|
|
|
* the file (endianness and byte-alignment).
|
|
|
|
*
|
|
|
|
* This little program scans all structs that need to be serialized,
|
|
|
|
* and determined the names and types of all members. It calculates
|
|
|
|
* how much memory (on disk or in ram) is needed to store that struct,
|
|
|
|
* and the offsets for reaching a particular one.
|
|
|
|
*
|
|
|
|
* There is a facility to get verbose output from sdna. Search for
|
2011-02-17 16:17:40 +00:00
|
|
|
* \ref debugSDNA. This int can be set to 0 (no output) to some int. Higher
|
2002-10-12 11:37:38 +00:00
|
|
|
* numbers give more output.
|
2012-03-07 18:27:12 +00:00
|
|
|
*/
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-05-17 16:57:31 +02:00
|
|
|
#define DNA_DEPRECATED_ALLOW
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
2019-02-12 11:43:33 +11:00
|
|
|
#include <assert.h>
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
2019-02-12 11:43:33 +11:00
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
#include "BLI_alloca.h"
|
|
|
|
#include "BLI_ghash.h"
|
2019-02-12 16:47:39 +11:00
|
|
|
#include "BLI_memarena.h"
|
2019-04-17 06:17:24 +02:00
|
|
|
#include "BLI_sys_types.h" /* for intptr_t support */
|
2008-08-17 17:08:00 +00:00
|
|
|
|
2019-02-12 17:03:16 +11:00
|
|
|
#include "dna_utils.h"
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
#define SDNA_MAX_FILENAME_LENGTH 255
|
|
|
|
|
|
|
|
/* Included the path relative from /source/blender/ here, so we can move */
|
|
|
|
/* headers around with more freedom. */
|
2011-11-14 16:05:44 +00:00
|
|
|
static const char *includefiles[] = {
|
2019-04-17 06:17:24 +02:00
|
|
|
/* if you add files here, please add them at the end
|
2019-04-18 07:21:26 +02:00
|
|
|
* of makesdna.c (this file) as well */
|
2019-04-17 06:17:24 +02:00
|
|
|
"DNA_listBase.h",
|
|
|
|
"DNA_vec_types.h",
|
|
|
|
"DNA_ID.h",
|
|
|
|
"DNA_ipo_types.h",
|
|
|
|
"DNA_key_types.h",
|
|
|
|
"DNA_text_types.h",
|
|
|
|
"DNA_packedFile_types.h",
|
|
|
|
"DNA_gpu_types.h",
|
|
|
|
"DNA_camera_types.h",
|
|
|
|
"DNA_image_types.h",
|
|
|
|
"DNA_texture_types.h",
|
|
|
|
"DNA_light_types.h",
|
|
|
|
"DNA_material_types.h",
|
|
|
|
"DNA_vfont_types.h",
|
|
|
|
"DNA_meta_types.h",
|
|
|
|
"DNA_curve_types.h",
|
|
|
|
"DNA_mesh_types.h",
|
|
|
|
"DNA_meshdata_types.h",
|
|
|
|
"DNA_modifier_types.h",
|
|
|
|
"DNA_lattice_types.h",
|
|
|
|
"DNA_object_types.h",
|
|
|
|
"DNA_object_force_types.h",
|
|
|
|
"DNA_object_fluidsim_types.h",
|
|
|
|
"DNA_world_types.h",
|
|
|
|
"DNA_scene_types.h",
|
|
|
|
"DNA_view3d_types.h",
|
|
|
|
"DNA_view2d_types.h",
|
|
|
|
"DNA_space_types.h",
|
|
|
|
"DNA_userdef_types.h",
|
|
|
|
"DNA_screen_types.h",
|
|
|
|
"DNA_sdna_types.h",
|
|
|
|
"DNA_fileglobal_types.h",
|
|
|
|
"DNA_sequence_types.h",
|
|
|
|
"DNA_effect_types.h",
|
|
|
|
"DNA_outliner_types.h",
|
|
|
|
"DNA_sound_types.h",
|
|
|
|
"DNA_collection_types.h",
|
|
|
|
"DNA_armature_types.h",
|
|
|
|
"DNA_action_types.h",
|
|
|
|
"DNA_constraint_types.h",
|
|
|
|
"DNA_nla_types.h",
|
|
|
|
"DNA_node_types.h",
|
|
|
|
"DNA_color_types.h",
|
|
|
|
"DNA_brush_types.h",
|
|
|
|
"DNA_customdata_types.h",
|
|
|
|
"DNA_particle_types.h",
|
|
|
|
"DNA_cloth_types.h",
|
|
|
|
"DNA_gpencil_types.h",
|
|
|
|
"DNA_gpencil_modifier_types.h",
|
|
|
|
"DNA_shader_fx_types.h",
|
|
|
|
"DNA_windowmanager_types.h",
|
|
|
|
"DNA_anim_types.h",
|
|
|
|
"DNA_boid_types.h",
|
|
|
|
"DNA_smoke_types.h",
|
|
|
|
"DNA_speaker_types.h",
|
|
|
|
"DNA_movieclip_types.h",
|
|
|
|
"DNA_tracking_types.h",
|
|
|
|
"DNA_dynamicpaint_types.h",
|
|
|
|
"DNA_mask_types.h",
|
|
|
|
"DNA_rigidbody_types.h",
|
|
|
|
"DNA_freestyle_types.h",
|
|
|
|
"DNA_linestyle_types.h",
|
|
|
|
"DNA_cachefile_types.h",
|
|
|
|
"DNA_layer_types.h",
|
|
|
|
"DNA_workspace_types.h",
|
|
|
|
"DNA_lightprobe_types.h",
|
|
|
|
|
|
|
|
/* see comment above before editing! */
|
|
|
|
|
|
|
|
/* empty string to indicate end of includefiles */
|
|
|
|
"",
|
2002-10-12 11:37:38 +00:00
|
|
|
};
|
|
|
|
|
2019-02-15 10:31:51 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Variables
|
|
|
|
* \{ */
|
|
|
|
|
2019-02-23 19:16:28 +11:00
|
|
|
static MemArena *mem_arena = NULL;
|
2019-02-12 16:47:39 +11:00
|
|
|
|
2019-05-21 17:53:22 +10:00
|
|
|
static int max_data_size = 500000, max_array_len = 50000;
|
|
|
|
static int names_len = 0;
|
|
|
|
static int types_len = 0;
|
|
|
|
static int structs_len = 0;
|
2019-03-03 01:05:58 +11:00
|
|
|
/** At address `names[a]` is string `a`. */
|
2019-02-12 16:47:39 +11:00
|
|
|
static char **names;
|
2019-03-03 01:05:58 +11:00
|
|
|
/** At address `types[a]` is string `a`. */
|
2019-02-12 16:47:39 +11:00
|
|
|
static char **types;
|
2019-03-03 01:05:58 +11:00
|
|
|
/** At `types_size[a]` is the size of type `a` on this systems bitness (32 or 64). */
|
|
|
|
static short *types_size_native;
|
|
|
|
/** Contains sizes as they are calculated on 32 bit systems. */
|
|
|
|
static short *types_size_32;
|
|
|
|
/** Contains sizes as they are calculated on 64 bit systems. */
|
|
|
|
static short *types_size_64;
|
|
|
|
/** At `sp = structs[a]` is the first address of a struct definition:
|
|
|
|
* - `sp[0]` is type number.
|
|
|
|
* - `sp[1]` is the length of the element array (next).
|
2019-05-21 17:53:22 +10:00
|
|
|
* - `sp[2]` sp[3] is [(type_index, name_index), ..] (number of pairs is defined by `sp[1]`),
|
2019-03-03 01:05:58 +11:00
|
|
|
*/
|
2019-01-15 23:14:35 +11:00
|
|
|
static short **structs, *structdata;
|
2019-02-12 11:43:33 +11:00
|
|
|
|
|
|
|
/** Versioning data */
|
|
|
|
static struct {
|
2019-04-17 06:17:24 +02:00
|
|
|
GHash *struct_map_alias_from_static;
|
|
|
|
GHash *struct_map_static_from_alias;
|
|
|
|
GHash *elem_map_alias_from_static;
|
|
|
|
GHash *elem_map_static_from_alias;
|
2019-02-12 11:43:33 +11:00
|
|
|
} g_version_data = {NULL};
|
|
|
|
|
2011-02-17 16:17:40 +00:00
|
|
|
/**
|
|
|
|
* Variable to control debug output of makesdna.
|
2002-10-12 11:37:38 +00:00
|
|
|
* debugSDNA:
|
2018-11-14 12:53:15 +11:00
|
|
|
* - 0 = no output, except errors
|
|
|
|
* - 1 = detail actions
|
|
|
|
* - 2 = full trace, tell which names and types were found
|
|
|
|
* - 4 = full trace, plus all gritty details
|
2002-10-12 11:37:38 +00:00
|
|
|
*/
|
2011-08-28 05:06:30 +00:00
|
|
|
static int debugSDNA = 0;
|
|
|
|
static int additional_slen_offset;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-12 10:10:04 +11:00
|
|
|
#define DEBUG_PRINTF(debug_level, ...) \
|
2019-04-17 06:17:24 +02:00
|
|
|
{ \
|
|
|
|
if (debugSDNA > debug_level) { \
|
|
|
|
printf(__VA_ARGS__); \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
((void)0)
|
2019-02-12 16:47:39 +11:00
|
|
|
|
|
|
|
/* stub for BLI_abort() */
|
|
|
|
#ifndef NDEBUG
|
|
|
|
void BLI_system_backtrace(FILE *fp)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
(void)fp;
|
2019-02-12 16:47:39 +11:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-02-15 10:31:51 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Function Declarations
|
|
|
|
* \{ */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/**
|
2019-02-15 10:31:51 +11:00
|
|
|
* Ensure type \c str to is in the #types array.
|
|
|
|
* \param str: Struct name without any qualifiers.
|
|
|
|
* \param len: The struct size in bytes.
|
|
|
|
* \return Index in the #types array.
|
2002-10-12 11:37:38 +00:00
|
|
|
*/
|
2019-03-03 01:05:58 +11:00
|
|
|
static int add_type(const char *str, int size);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/**
|
2019-02-15 10:31:51 +11:00
|
|
|
* Ensure \c str is int the #names array.
|
|
|
|
* \param str: Struct member name which may include pointer prefix & array size.
|
|
|
|
* \return Index in the #names array.
|
2002-10-12 11:37:38 +00:00
|
|
|
*/
|
2011-10-27 14:41:26 +00:00
|
|
|
static int add_name(const char *str);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Search whether this structure type was already found, and if not,
|
|
|
|
* add it.
|
|
|
|
*/
|
2011-10-27 14:41:26 +00:00
|
|
|
static short *add_struct(int namecode);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove comments from this buffer. Assumes that the buffer refers to
|
|
|
|
* ascii-code text.
|
|
|
|
*/
|
2019-03-03 01:05:58 +11:00
|
|
|
static int preprocess_include(char *maindata, const int maindata_len);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Scan this file for serializable types.
|
2018-06-01 18:19:39 +02:00
|
|
|
*/
|
2016-01-14 13:00:49 +11:00
|
|
|
static int convert_include(const char *filename);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine how many bytes are needed for each struct.
|
2018-06-01 18:19:39 +02:00
|
|
|
*/
|
2019-04-02 12:32:21 +02:00
|
|
|
static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char *base_directory);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Construct the DNA.c file
|
2018-06-01 18:19:39 +02:00
|
|
|
*/
|
2012-12-17 02:46:30 +00:00
|
|
|
static void dna_write(FILE *file, const void *pntr, const int size);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
/**
|
2010-07-25 01:45:53 +00:00
|
|
|
* Report all structures found so far, and print their lengths.
|
2002-10-12 11:37:38 +00:00
|
|
|
*/
|
2019-03-03 01:05:58 +11:00
|
|
|
void print_struct_sizes(void);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-15 10:31:51 +11:00
|
|
|
/** \} */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-15 10:31:51 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Implementation
|
|
|
|
*
|
|
|
|
* Make DNA string (write to file).
|
|
|
|
* \{ */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-12 11:43:33 +11:00
|
|
|
static const char *version_struct_static_from_alias(const char *str)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
const char *str_test = BLI_ghash_lookup(g_version_data.struct_map_static_from_alias, str);
|
|
|
|
if (str_test != NULL) {
|
|
|
|
return str_test;
|
|
|
|
}
|
|
|
|
return str;
|
2019-02-12 11:43:33 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
static const char *version_struct_alias_from_static(const char *str)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
const char *str_test = BLI_ghash_lookup(g_version_data.struct_map_alias_from_static, str);
|
|
|
|
if (str_test != NULL) {
|
|
|
|
return str_test;
|
|
|
|
}
|
|
|
|
return str;
|
2019-02-12 11:43:33 +11:00
|
|
|
}
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
static const char *version_elem_static_from_alias(const int strct, const char *elem_alias_full)
|
2019-02-12 11:43:33 +11:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
const uint elem_alias_full_len = strlen(elem_alias_full);
|
|
|
|
char *elem_alias = alloca(elem_alias_full_len + 1);
|
|
|
|
const int elem_alias_len = DNA_elem_id_strip_copy(elem_alias, elem_alias_full);
|
|
|
|
const char *str_pair[2] = {types[strct], elem_alias};
|
|
|
|
const char *elem_static = BLI_ghash_lookup(g_version_data.elem_map_static_from_alias, str_pair);
|
|
|
|
if (elem_static != NULL) {
|
|
|
|
return DNA_elem_id_rename(mem_arena,
|
|
|
|
elem_alias,
|
|
|
|
elem_alias_len,
|
|
|
|
elem_static,
|
|
|
|
strlen(elem_static),
|
|
|
|
elem_alias_full,
|
|
|
|
elem_alias_full_len,
|
|
|
|
DNA_elem_id_offset_start(elem_alias_full));
|
|
|
|
}
|
|
|
|
return elem_alias_full;
|
2019-02-12 11:43:33 +11:00
|
|
|
}
|
|
|
|
|
2019-02-27 15:07:56 +11:00
|
|
|
/**
|
|
|
|
* Enforce '_pad123' naming convention, disallow 'pad123' or 'pad_123',
|
|
|
|
* special exception for [a-z] after since there is a 'pad_rot_angle' preference.
|
|
|
|
*/
|
|
|
|
static bool is_name_legal(const char *name)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
const int name_size = strlen(name) + 1;
|
|
|
|
char *name_strip = alloca(name_size);
|
|
|
|
DNA_elem_id_strip_copy(name_strip, name);
|
|
|
|
|
|
|
|
const char prefix[] = {'p', 'a', 'd'};
|
|
|
|
|
|
|
|
if (name[0] == '_') {
|
|
|
|
if (strncmp(&name_strip[1], prefix, sizeof(prefix)) != 0) {
|
|
|
|
fprintf(
|
|
|
|
stderr, "Error: only '_pad' variables can start with an underscore, found '%s'\n", name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strncmp(name_strip, prefix, sizeof(prefix)) == 0) {
|
|
|
|
int i = sizeof(prefix);
|
|
|
|
if (name_strip[i] >= 'a' && name_strip[i] <= 'z') {
|
|
|
|
/* may be part of a word, allow that. */
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool has_only_digit_or_none = true;
|
|
|
|
for (; name_strip[i]; i++) {
|
|
|
|
const char c = name_strip[i];
|
|
|
|
if (!((c >= '0' && c <= '9') || c == '_')) {
|
|
|
|
has_only_digit_or_none = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (has_only_digit_or_none) {
|
|
|
|
/* found 'pad' or 'pad123'. */
|
|
|
|
fprintf(
|
|
|
|
stderr, "Error: padding variables must be formatted '_pad[number]', found '%s'\n", name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2019-02-27 15:07:56 +11:00
|
|
|
}
|
|
|
|
|
2019-03-03 01:05:58 +11:00
|
|
|
static int add_type(const char *str, int size)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
char *cp;
|
|
|
|
|
|
|
|
/* first do validity check */
|
|
|
|
if (str[0] == 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else if (strchr(str, '*')) {
|
|
|
|
/* note: this is valid C syntax but we can't parse, complain!
|
|
|
|
* 'struct SomeStruct* somevar;' <-- correct but we cant handle right now. */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
str = version_struct_static_from_alias(str);
|
|
|
|
|
|
|
|
/* search through type array */
|
2019-05-21 17:53:22 +10:00
|
|
|
for (int index = 0; index < types_len; index++) {
|
|
|
|
if (strcmp(str, types[index]) == 0) {
|
2019-04-17 06:17:24 +02:00
|
|
|
if (size) {
|
2019-05-21 17:53:22 +10:00
|
|
|
types_size_native[index] = size;
|
|
|
|
types_size_32[index] = size;
|
|
|
|
types_size_64[index] = size;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-05-21 17:53:22 +10:00
|
|
|
return index;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* append new type */
|
|
|
|
const int str_size = strlen(str) + 1;
|
|
|
|
cp = BLI_memarena_alloc(mem_arena, str_size);
|
|
|
|
memcpy(cp, str, str_size);
|
2019-05-21 17:53:22 +10:00
|
|
|
types[types_len] = cp;
|
|
|
|
types_size_native[types_len] = size;
|
|
|
|
types_size_32[types_len] = size;
|
|
|
|
types_size_64[types_len] = size;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-21 17:53:22 +10:00
|
|
|
if (types_len >= max_array_len) {
|
2019-04-17 06:17:24 +02:00
|
|
|
printf("too many types\n");
|
2019-05-21 17:53:22 +10:00
|
|
|
return types_len - 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-05-21 17:53:22 +10:00
|
|
|
types_len++;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-21 17:53:22 +10:00
|
|
|
return types_len - 1;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Because of the weird way of tokenizing, we have to 'cast' function
|
|
|
|
* pointers to ... (*f)(), whatever the original signature. In fact,
|
|
|
|
* we add name and type at the same time... There are two special
|
|
|
|
* cases, unfortunately. These are explicitly checked.
|
|
|
|
*
|
|
|
|
* */
|
2011-10-27 14:41:26 +00:00
|
|
|
static int add_name(const char *str)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
int nr, i, j, k;
|
|
|
|
char *cp;
|
|
|
|
char buf[255]; /* stupid limit, change it :) */
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
additional_slen_offset = 0;
|
|
|
|
|
|
|
|
if (str[0] == 0 /* || (str[1] == 0) */) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (str[0] == '(' && str[1] == '*') {
|
|
|
|
/* we handle function pointer and special array cases here, e.g.
|
|
|
|
* void (*function)(...) and float (*array)[..]. the array case
|
|
|
|
* name is still converted to (array *)() though because it is that
|
|
|
|
* way in old dna too, and works correct with elementsize() */
|
|
|
|
int isfuncptr = (strchr(str + 1, '(')) != NULL;
|
|
|
|
|
|
|
|
DEBUG_PRINTF(3, "\t\t\t\t*** Function pointer or multidim array pointer found\n");
|
|
|
|
/* functionpointer: transform the type (sometimes) */
|
|
|
|
i = 0;
|
|
|
|
|
|
|
|
while (str[i] != ')') {
|
|
|
|
buf[i] = str[i];
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Another number we need is the extra slen offset. This extra
|
|
|
|
* offset is the overshoot after a space. If there is no
|
|
|
|
* space, no overshoot should be calculated. */
|
|
|
|
j = i; /* j at first closing brace */
|
|
|
|
|
|
|
|
DEBUG_PRINTF(3, "first brace after offset %d\n", i);
|
|
|
|
|
|
|
|
j++; /* j beyond closing brace ? */
|
|
|
|
while ((str[j] != 0) && (str[j] != ')')) {
|
|
|
|
DEBUG_PRINTF(3, "seen %c (%d)\n", str[j], str[j]);
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
DEBUG_PRINTF(3,
|
|
|
|
"seen %c (%d)\n"
|
|
|
|
"special after offset%d\n",
|
|
|
|
str[j],
|
|
|
|
str[j],
|
|
|
|
j);
|
|
|
|
|
|
|
|
if (!isfuncptr) {
|
|
|
|
/* multidimensional array pointer case */
|
|
|
|
if (str[j] == 0) {
|
|
|
|
DEBUG_PRINTF(3, "offsetting for multidim array pointer\n");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf("Error during tokening multidim array pointer\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (str[j] == 0) {
|
|
|
|
DEBUG_PRINTF(3, "offsetting for space\n");
|
|
|
|
/* get additional offset */
|
|
|
|
k = 0;
|
|
|
|
while (str[j] != ')') {
|
|
|
|
j++;
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
DEBUG_PRINTF(3, "extra offset %d\n", k);
|
|
|
|
additional_slen_offset = k;
|
|
|
|
}
|
|
|
|
else if (str[j] == ')') {
|
|
|
|
DEBUG_PRINTF(3, "offsetting for brace\n");
|
2019-04-20 11:28:21 +02:00
|
|
|
/* don't get extra offset */
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf("Error during tokening function pointer argument list\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Put )(void) at the end? Maybe )(). Should check this with
|
|
|
|
* old sdna. Actually, sometimes )(), sometimes )(void...)
|
|
|
|
* Alas.. such is the nature of brain-damage :(
|
|
|
|
*
|
|
|
|
* Sorted it out: always do )(), except for headdraw and
|
|
|
|
* windraw, part of ScrArea. This is important, because some
|
|
|
|
* linkers will treat different fp's differently when called
|
|
|
|
* !!! This has to do with interference in byte-alignment and
|
|
|
|
* the way args are pushed on the stack.
|
|
|
|
*
|
|
|
|
* */
|
|
|
|
buf[i] = 0;
|
|
|
|
DEBUG_PRINTF(3, "Name before chomping: %s\n", buf);
|
|
|
|
if ((strncmp(buf, "(*headdraw", 10) == 0) || (strncmp(buf, "(*windraw", 9) == 0)) {
|
|
|
|
buf[i] = ')';
|
|
|
|
buf[i + 1] = '(';
|
|
|
|
buf[i + 2] = 'v';
|
|
|
|
buf[i + 3] = 'o';
|
|
|
|
buf[i + 4] = 'i';
|
|
|
|
buf[i + 5] = 'd';
|
|
|
|
buf[i + 6] = ')';
|
|
|
|
buf[i + 7] = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
buf[i] = ')';
|
|
|
|
buf[i + 1] = '(';
|
|
|
|
buf[i + 2] = ')';
|
|
|
|
buf[i + 3] = 0;
|
|
|
|
}
|
|
|
|
/* now precede with buf*/
|
|
|
|
DEBUG_PRINTF(3, "\t\t\t\t\tProposing fp name %s\n", buf);
|
|
|
|
name = buf;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* normal field: old code */
|
|
|
|
name = str;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* search name array */
|
2019-05-21 17:53:22 +10:00
|
|
|
for (nr = 0; nr < names_len; nr++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
if (strcmp(name, names[nr]) == 0) {
|
|
|
|
return nr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Sanity check the name. */
|
|
|
|
if (!is_name_legal(name)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Append new name. */
|
|
|
|
const int name_size = strlen(name) + 1;
|
|
|
|
cp = BLI_memarena_alloc(mem_arena, name_size);
|
|
|
|
memcpy(cp, name, name_size);
|
2019-05-21 17:53:22 +10:00
|
|
|
names[names_len] = cp;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-21 17:53:22 +10:00
|
|
|
if (names_len >= max_array_len) {
|
2019-04-17 06:17:24 +02:00
|
|
|
printf("too many names\n");
|
2019-05-21 17:53:22 +10:00
|
|
|
return names_len - 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-05-21 17:53:22 +10:00
|
|
|
names_len++;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-21 17:53:22 +10:00
|
|
|
return names_len - 1;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2011-11-14 16:05:44 +00:00
|
|
|
static short *add_struct(int namecode)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
int len;
|
|
|
|
short *sp;
|
|
|
|
|
2019-05-21 17:53:22 +10:00
|
|
|
if (structs_len == 0) {
|
2019-04-17 06:17:24 +02:00
|
|
|
structs[0] = structdata;
|
|
|
|
}
|
|
|
|
else {
|
2019-05-21 17:53:22 +10:00
|
|
|
sp = structs[structs_len - 1];
|
2019-04-17 06:17:24 +02:00
|
|
|
len = sp[1];
|
2019-05-21 17:53:22 +10:00
|
|
|
structs[structs_len] = sp + 2 * len + 2;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2019-05-21 17:53:22 +10:00
|
|
|
sp = structs[structs_len];
|
2019-04-17 06:17:24 +02:00
|
|
|
sp[0] = namecode;
|
|
|
|
|
2019-05-21 17:53:22 +10:00
|
|
|
if (structs_len >= max_array_len) {
|
2019-04-17 06:17:24 +02:00
|
|
|
printf("too many structs\n");
|
|
|
|
return sp;
|
|
|
|
}
|
2019-05-21 17:53:22 +10:00
|
|
|
structs_len++;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
|
|
|
return sp;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2019-03-03 01:05:58 +11:00
|
|
|
static int preprocess_include(char *maindata, const int maindata_len)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
int a, newlen, comment = 0;
|
|
|
|
char *cp, *temp, *md;
|
|
|
|
|
|
|
|
/* note: len + 1, last character is a dummy to prevent
|
|
|
|
* comparisons using uninitialized memory */
|
|
|
|
temp = MEM_mallocN(maindata_len + 1, "preprocess_include");
|
|
|
|
temp[maindata_len] = ' ';
|
|
|
|
|
|
|
|
memcpy(temp, maindata, maindata_len);
|
|
|
|
|
|
|
|
/* remove all c++ comments */
|
|
|
|
/* replace all enters/tabs/etc with spaces */
|
|
|
|
cp = temp;
|
|
|
|
a = maindata_len;
|
|
|
|
comment = 0;
|
|
|
|
while (a--) {
|
|
|
|
if (cp[0] == '/' && cp[1] == '/') {
|
|
|
|
comment = 1;
|
|
|
|
}
|
|
|
|
else if (*cp == '\n') {
|
|
|
|
comment = 0;
|
|
|
|
}
|
2019-04-22 09:16:18 +10:00
|
|
|
if (comment || *cp < 32 || *cp > 128) {
|
2019-04-17 06:17:24 +02:00
|
|
|
*cp = 32;
|
2019-04-22 09:16:18 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
cp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* data from temp copy to maindata, remove comments and double spaces */
|
|
|
|
cp = temp;
|
|
|
|
md = maindata;
|
|
|
|
newlen = 0;
|
|
|
|
comment = 0;
|
|
|
|
a = maindata_len;
|
|
|
|
while (a--) {
|
|
|
|
|
|
|
|
if (cp[0] == '/' && cp[1] == '*') {
|
|
|
|
comment = 1;
|
|
|
|
cp[0] = cp[1] = 32;
|
|
|
|
}
|
|
|
|
if (cp[0] == '*' && cp[1] == '/') {
|
|
|
|
comment = 0;
|
|
|
|
cp[0] = cp[1] = 32;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do not copy when: */
|
|
|
|
if (comment) {
|
|
|
|
/* pass */
|
|
|
|
}
|
|
|
|
else if (cp[0] == ' ' && cp[1] == ' ') {
|
|
|
|
/* pass */
|
|
|
|
}
|
|
|
|
else if (cp[-1] == '*' && cp[0] == ' ') {
|
|
|
|
/* pointers with a space */
|
|
|
|
} /* skip special keywords */
|
|
|
|
else if (strncmp("DNA_DEPRECATED", cp, 14) == 0) {
|
|
|
|
/* single values are skipped already, so decrement 1 less */
|
|
|
|
a -= 13;
|
|
|
|
cp += 13;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
md[0] = cp[0];
|
|
|
|
md++;
|
|
|
|
newlen++;
|
|
|
|
}
|
|
|
|
cp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(temp);
|
|
|
|
return newlen;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2016-01-14 13:00:49 +11:00
|
|
|
static void *read_file_data(const char *filename, int *r_len)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
#ifdef WIN32
|
2019-04-17 06:17:24 +02:00
|
|
|
FILE *fp = fopen(filename, "rb");
|
2002-10-12 11:37:38 +00:00
|
|
|
#else
|
2019-04-17 06:17:24 +02:00
|
|
|
FILE *fp = fopen(filename, "r");
|
2002-10-12 11:37:38 +00:00
|
|
|
#endif
|
2019-04-17 06:17:24 +02:00
|
|
|
void *data;
|
|
|
|
|
|
|
|
if (!fp) {
|
|
|
|
*r_len = -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
fseek(fp, 0L, SEEK_END);
|
|
|
|
*r_len = ftell(fp);
|
|
|
|
fseek(fp, 0L, SEEK_SET);
|
|
|
|
|
|
|
|
if (*r_len == -1) {
|
|
|
|
fclose(fp);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = MEM_mallocN(*r_len, "read_file_data");
|
|
|
|
if (!data) {
|
|
|
|
*r_len = -1;
|
|
|
|
fclose(fp);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fread(data, *r_len, 1, fp) != 1) {
|
|
|
|
*r_len = -1;
|
|
|
|
MEM_freeN(data);
|
|
|
|
fclose(fp);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
return data;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2016-01-14 13:00:49 +11:00
|
|
|
static int convert_include(const char *filename)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
/* read include file, skip structs with a '#' before it.
|
|
|
|
* store all data in temporal arrays.
|
|
|
|
*/
|
|
|
|
int maindata_len, count, slen, type, name, strct;
|
|
|
|
short *structpoin, *sp;
|
|
|
|
char *maindata, *mainend, *md, *md1;
|
|
|
|
bool skip_struct;
|
|
|
|
|
|
|
|
md = maindata = read_file_data(filename, &maindata_len);
|
|
|
|
if (maindata_len == -1) {
|
|
|
|
fprintf(stderr, "Can't read file %s\n", filename);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
maindata_len = preprocess_include(maindata, maindata_len);
|
|
|
|
mainend = maindata + maindata_len - 1;
|
|
|
|
|
|
|
|
/* we look for '{' and then back to 'struct' */
|
|
|
|
count = 0;
|
|
|
|
skip_struct = false;
|
|
|
|
while (count < maindata_len) {
|
|
|
|
|
|
|
|
/* code for skipping a struct: two hashes on 2 lines. (preprocess added a space) */
|
|
|
|
if (md[0] == '#' && md[1] == ' ' && md[2] == '#') {
|
|
|
|
skip_struct = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (md[0] == '{') {
|
|
|
|
md[0] = 0;
|
|
|
|
if (skip_struct) {
|
|
|
|
skip_struct = false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (md[-1] == ' ') {
|
|
|
|
md[-1] = 0;
|
|
|
|
}
|
|
|
|
md1 = md - 2;
|
|
|
|
while (*md1 != 32) {
|
|
|
|
/* to beginning of word */
|
|
|
|
md1--;
|
|
|
|
}
|
|
|
|
md1++;
|
|
|
|
|
|
|
|
/* we've got a struct name when... */
|
|
|
|
if (strncmp(md1 - 7, "struct", 6) == 0) {
|
|
|
|
|
|
|
|
strct = add_type(md1, 0);
|
|
|
|
if (strct == -1) {
|
|
|
|
fprintf(stderr, "File '%s' contains struct we cant parse \"%s\"\n", filename, md1);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
structpoin = add_struct(strct);
|
|
|
|
sp = structpoin + 2;
|
|
|
|
|
|
|
|
DEBUG_PRINTF(1, "\t|\t|-- detected struct %s\n", types[strct]);
|
|
|
|
|
|
|
|
/* first lets make it all nice strings */
|
|
|
|
md1 = md + 1;
|
|
|
|
while (*md1 != '}') {
|
|
|
|
if (md1 > mainend) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*md1 == ',' || *md1 == ' ') {
|
|
|
|
*md1 = 0;
|
|
|
|
}
|
|
|
|
md1++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* read types and names until first character that is not '}' */
|
|
|
|
md1 = md + 1;
|
|
|
|
while (*md1 != '}') {
|
|
|
|
if (md1 > mainend) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* skip when it says 'struct' or 'unsigned' or 'const' */
|
|
|
|
if (*md1) {
|
|
|
|
if (strncmp(md1, "struct", 6) == 0) {
|
|
|
|
md1 += 7;
|
|
|
|
}
|
|
|
|
if (strncmp(md1, "unsigned", 8) == 0) {
|
|
|
|
md1 += 9;
|
|
|
|
}
|
|
|
|
if (strncmp(md1, "const", 5) == 0) {
|
|
|
|
md1 += 6;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we've got a type! */
|
|
|
|
type = add_type(md1, 0);
|
|
|
|
if (type == -1) {
|
|
|
|
fprintf(
|
|
|
|
stderr, "File '%s' contains struct we can't parse \"%s\"\n", filename, md1);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG_PRINTF(1, "\t|\t|\tfound type %s (", md1);
|
|
|
|
|
|
|
|
md1 += strlen(md1);
|
|
|
|
|
|
|
|
/* read until ';' */
|
|
|
|
while (*md1 != ';') {
|
|
|
|
if (md1 > mainend) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*md1) {
|
|
|
|
/* We've got a name. slen needs
|
|
|
|
* correction for function
|
|
|
|
* pointers! */
|
|
|
|
slen = (int)strlen(md1);
|
|
|
|
if (md1[slen - 1] == ';') {
|
|
|
|
md1[slen - 1] = 0;
|
|
|
|
|
|
|
|
name = add_name(version_elem_static_from_alias(strct, md1));
|
|
|
|
if (name == -1) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"File '%s' contains struct with name that can't be added \"%s\"\n",
|
|
|
|
filename,
|
|
|
|
md1);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
slen += additional_slen_offset;
|
|
|
|
sp[0] = type;
|
|
|
|
sp[1] = name;
|
|
|
|
|
|
|
|
if (names[name] != NULL) {
|
|
|
|
DEBUG_PRINTF(1, "%s |", names[name]);
|
|
|
|
}
|
|
|
|
|
|
|
|
structpoin[1]++;
|
|
|
|
sp += 2;
|
|
|
|
|
|
|
|
md1 += slen;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
name = add_name(version_elem_static_from_alias(strct, md1));
|
|
|
|
if (name == -1) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"File '%s' contains struct with name that can't be added \"%s\"\n",
|
|
|
|
filename,
|
|
|
|
md1);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
slen += additional_slen_offset;
|
|
|
|
|
|
|
|
sp[0] = type;
|
|
|
|
sp[1] = name;
|
|
|
|
if (names[name] != NULL) {
|
|
|
|
DEBUG_PRINTF(1, "%s ||", names[name]);
|
|
|
|
}
|
|
|
|
|
|
|
|
structpoin[1]++;
|
|
|
|
sp += 2;
|
|
|
|
|
|
|
|
md1 += slen;
|
|
|
|
}
|
|
|
|
md1++;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG_PRINTF(1, ")\n");
|
|
|
|
}
|
|
|
|
md1++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
count++;
|
|
|
|
md++;
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(maindata);
|
|
|
|
|
|
|
|
return 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
static bool check_field_alignment(
|
|
|
|
int firststruct, int structtype, int type, int len, const char *name, const char *detail)
|
2016-05-09 09:53:50 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
bool result = true;
|
|
|
|
if (type < firststruct && types_size_native[type] > 4 && (len % 8)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Align 8 error (%s) in struct: %s %s (add %d padding bytes)\n",
|
|
|
|
detail,
|
|
|
|
types[structtype],
|
|
|
|
name,
|
|
|
|
len % 8);
|
|
|
|
result = false;
|
|
|
|
}
|
|
|
|
if (types_size_native[type] > 3 && (len % 4)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Align 4 error (%s) in struct: %s %s (add %d padding bytes)\n",
|
|
|
|
detail,
|
|
|
|
types[structtype],
|
|
|
|
name,
|
|
|
|
len % 4);
|
|
|
|
result = false;
|
|
|
|
}
|
|
|
|
if (types_size_native[type] == 2 && (len % 2)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Align 2 error (%s) in struct: %s %s (add %d padding bytes)\n",
|
|
|
|
detail,
|
|
|
|
types[structtype],
|
|
|
|
name,
|
|
|
|
len % 2);
|
|
|
|
result = false;
|
|
|
|
}
|
|
|
|
return result;
|
2016-05-09 09:53:50 +02:00
|
|
|
}
|
|
|
|
|
2019-04-02 12:32:21 +02:00
|
|
|
static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char *base_directory)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-05-21 17:53:22 +10:00
|
|
|
int unknown = structs_len, lastunknown;
|
2019-04-17 06:17:24 +02:00
|
|
|
bool dna_error = false;
|
|
|
|
|
|
|
|
/* Write test to verify sizes are accurate. */
|
|
|
|
fprintf(file_verify, "/* Verify struct sizes and member offsets are as expected by DNA. */\n");
|
|
|
|
fprintf(file_verify, "#include \"BLI_assert.h\"\n\n");
|
|
|
|
fprintf(file_verify, "#define DNA_DEPRECATED\n");
|
|
|
|
for (int i = 0; *(includefiles[i]) != '\0'; i++) {
|
|
|
|
fprintf(file_verify, "#include \"%s%s\"\n", base_directory, includefiles[i]);
|
|
|
|
}
|
|
|
|
fprintf(file_verify, "\n");
|
|
|
|
|
|
|
|
/* Multiple iterations to handle nested structs. */
|
|
|
|
while (unknown) {
|
|
|
|
lastunknown = unknown;
|
|
|
|
unknown = 0;
|
|
|
|
|
|
|
|
/* check all structs... */
|
2019-05-21 17:53:22 +10:00
|
|
|
for (int a = 0; a < structs_len; a++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
const short *structpoin = structs[a];
|
|
|
|
const int structtype = structpoin[0];
|
|
|
|
const char *structname = version_struct_alias_from_static(types[structtype]);
|
|
|
|
|
|
|
|
/* when length is not known... */
|
|
|
|
if (types_size_native[structtype] == 0) {
|
|
|
|
|
|
|
|
const short *sp = structpoin + 2;
|
|
|
|
int size_native = 0;
|
|
|
|
int size_32 = 0;
|
|
|
|
int size_64 = 0;
|
|
|
|
bool has_pointer = false;
|
|
|
|
|
|
|
|
/* check all elements in struct */
|
|
|
|
for (int b = 0; b < structpoin[1]; b++, sp += 2) {
|
|
|
|
int type = sp[0];
|
|
|
|
const char *cp = names[sp[1]];
|
|
|
|
int namelen = (int)strlen(cp);
|
|
|
|
|
|
|
|
/* Write size verification to file. */
|
|
|
|
{
|
|
|
|
char *name_static = alloca(namelen + 1);
|
|
|
|
DNA_elem_id_strip_copy(name_static, cp);
|
|
|
|
const char *str_pair[2] = {types[structtype], name_static};
|
|
|
|
const char *name_alias = BLI_ghash_lookup(g_version_data.elem_map_alias_from_static,
|
|
|
|
str_pair);
|
|
|
|
fprintf(file_verify,
|
|
|
|
"BLI_STATIC_ASSERT(offsetof(struct %s, %s) == %d, \"DNA member offset "
|
|
|
|
"verify\");\n",
|
|
|
|
structname,
|
|
|
|
name_alias ? name_alias : name_static,
|
|
|
|
size_native);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* is it a pointer or function pointer? */
|
|
|
|
if (cp[0] == '*' || cp[1] == '*') {
|
|
|
|
has_pointer = 1;
|
|
|
|
/* has the name an extra length? (array) */
|
|
|
|
int mul = 1;
|
|
|
|
if (cp[namelen - 1] == ']') {
|
|
|
|
mul = DNA_elem_array_size(cp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mul == 0) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Zero array size found or could not parse %s: '%.*s'\n",
|
|
|
|
types[structtype],
|
|
|
|
namelen + 1,
|
|
|
|
cp);
|
|
|
|
dna_error = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 4-8 aligned/ */
|
|
|
|
if (sizeof(void *) == 4) {
|
|
|
|
if (size_native % 4) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Align pointer error in struct (size_native 4): %s %s\n",
|
|
|
|
types[structtype],
|
|
|
|
cp);
|
|
|
|
dna_error = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (size_native % 8) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Align pointer error in struct (size_native 8): %s %s\n",
|
|
|
|
types[structtype],
|
|
|
|
cp);
|
|
|
|
dna_error = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (size_64 % 8) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Align pointer error in struct (size_64 8): %s %s\n",
|
|
|
|
types[structtype],
|
|
|
|
cp);
|
|
|
|
dna_error = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_native += sizeof(void *) * mul;
|
|
|
|
size_32 += 4 * mul;
|
|
|
|
size_64 += 8 * mul;
|
|
|
|
}
|
|
|
|
else if (cp[0] == '[') {
|
|
|
|
/* parsing can cause names "var" and "[3]"
|
|
|
|
* to be found for "float var [3]" */
|
|
|
|
fprintf(stderr,
|
|
|
|
"Parse error in struct, invalid member name: %s %s\n",
|
|
|
|
types[structtype],
|
|
|
|
cp);
|
|
|
|
dna_error = 1;
|
|
|
|
}
|
|
|
|
else if (types_size_native[type]) {
|
|
|
|
/* has the name an extra length? (array) */
|
|
|
|
int mul = 1;
|
|
|
|
if (cp[namelen - 1] == ']') {
|
|
|
|
mul = DNA_elem_array_size(cp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mul == 0) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Zero array size found or could not parse %s: '%.*s'\n",
|
|
|
|
types[structtype],
|
|
|
|
namelen + 1,
|
|
|
|
cp);
|
|
|
|
dna_error = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* struct alignment */
|
|
|
|
if (type >= firststruct) {
|
|
|
|
if (sizeof(void *) == 8 && (size_native % 8)) {
|
|
|
|
fprintf(stderr, "Align struct error: %s %s\n", types[structtype], cp);
|
|
|
|
dna_error = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check 2-4-8 aligned. */
|
|
|
|
if (!check_field_alignment(firststruct, structtype, type, size_32, cp, "32 bit")) {
|
|
|
|
dna_error = 1;
|
|
|
|
}
|
|
|
|
if (!check_field_alignment(firststruct, structtype, type, size_64, cp, "64 bit")) {
|
|
|
|
dna_error = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_native += mul * types_size_native[type];
|
|
|
|
size_32 += mul * types_size_32[type];
|
|
|
|
size_64 += mul * types_size_64[type];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
size_native = 0;
|
|
|
|
size_32 = 0;
|
|
|
|
size_64 = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (size_native == 0) {
|
|
|
|
unknown++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
types_size_native[structtype] = size_native;
|
|
|
|
types_size_32[structtype] = size_32;
|
|
|
|
types_size_64[structtype] = size_64;
|
|
|
|
/* two ways to detect if a struct contains a pointer:
|
|
|
|
* has_pointer is set or size_native doesn't match any of 32/64bit lengths*/
|
|
|
|
if (has_pointer || size_64 != size_native || size_32 != size_native) {
|
|
|
|
if (size_64 % 8) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Sizeerror 8 in struct: %s (add %d bytes)\n",
|
|
|
|
types[structtype],
|
|
|
|
size_64 % 8);
|
|
|
|
dna_error = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (size_native % 4) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Sizeerror 4 in struct: %s (add %d bytes)\n",
|
|
|
|
types[structtype],
|
|
|
|
size_native % 4);
|
|
|
|
dna_error = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write size verification to file. */
|
|
|
|
fprintf(file_verify,
|
|
|
|
"BLI_STATIC_ASSERT(sizeof(struct %s) == %d, \"DNA struct size verify\");\n\n",
|
|
|
|
structname,
|
|
|
|
size_native);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unknown == lastunknown) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unknown) {
|
|
|
|
fprintf(stderr, "ERROR: still %d structs unknown\n", unknown);
|
|
|
|
|
|
|
|
if (debugSDNA) {
|
|
|
|
fprintf(stderr, "*** Known structs :\n");
|
|
|
|
|
2019-05-21 17:53:22 +10:00
|
|
|
for (int a = 0; a < structs_len; a++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
const short *structpoin = structs[a];
|
|
|
|
const int structtype = structpoin[0];
|
|
|
|
|
|
|
|
/* length unknown */
|
|
|
|
if (types_size_native[structtype] != 0) {
|
|
|
|
fprintf(stderr, " %s\n", types[structtype]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr, "*** Unknown structs :\n");
|
|
|
|
|
2019-05-21 17:53:22 +10:00
|
|
|
for (int a = 0; a < structs_len; a++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
const short *structpoin = structs[a];
|
|
|
|
const int structtype = structpoin[0];
|
|
|
|
|
|
|
|
/* length unknown yet */
|
|
|
|
if (types_size_native[structtype] == 0) {
|
|
|
|
fprintf(stderr, " %s\n", types[structtype]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dna_error = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return dna_error;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define MAX_DNA_LINE_LENGTH 20
|
|
|
|
|
2012-12-17 02:46:30 +00:00
|
|
|
static void dna_write(FILE *file, const void *pntr, const int size)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
static int linelength = 0;
|
|
|
|
int i;
|
|
|
|
const char *data;
|
|
|
|
|
|
|
|
data = (const char *)pntr;
|
|
|
|
|
|
|
|
for (i = 0; i < size; i++) {
|
|
|
|
fprintf(file, "%d, ", data[i]);
|
|
|
|
linelength++;
|
|
|
|
if (linelength >= MAX_DNA_LINE_LENGTH) {
|
|
|
|
fprintf(file, "\n");
|
|
|
|
linelength = 0;
|
|
|
|
}
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2019-03-03 01:05:58 +11:00
|
|
|
void print_struct_sizes(void)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-05-21 17:53:22 +10:00
|
|
|
int a, unknown = structs_len, structtype;
|
2019-04-17 06:17:24 +02:00
|
|
|
/*int lastunknown;*/ /*UNUSED*/
|
|
|
|
const short *structpoin;
|
|
|
|
printf("\n\n*** All detected structs:\n");
|
|
|
|
|
|
|
|
while (unknown) {
|
|
|
|
/*lastunknown = unknown;*/ /*UNUSED*/
|
|
|
|
unknown = 0;
|
|
|
|
|
|
|
|
/* check all structs... */
|
2019-05-21 17:53:22 +10:00
|
|
|
for (a = 0; a < structs_len; a++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
structpoin = structs[a];
|
|
|
|
structtype = structpoin[0];
|
|
|
|
printf("\t%s\t:%d\n", types[structtype], types_size_native[structtype]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("*** End of list\n");
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
static int make_structDNA(const char *base_directory,
|
|
|
|
FILE *file,
|
|
|
|
FILE *file_offsets,
|
|
|
|
FILE *file_verify)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
int i;
|
|
|
|
const short *sp;
|
|
|
|
/* str contains filenames. Since we now include paths, I stretched */
|
|
|
|
/* it a bit. Hope this is enough :) -nzc- */
|
|
|
|
char str[SDNA_MAX_FILENAME_LENGTH];
|
|
|
|
int firststruct;
|
|
|
|
|
|
|
|
if (debugSDNA > 0) {
|
|
|
|
fflush(stdout);
|
|
|
|
printf("Running makesdna at debug level %d\n", debugSDNA);
|
|
|
|
}
|
|
|
|
|
|
|
|
mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
|
|
|
|
|
|
|
|
/* the longest known struct is 50k, so we assume 100k is sufficient! */
|
2019-05-21 17:53:22 +10:00
|
|
|
structdata = MEM_callocN(max_data_size, "structdata");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
|
|
|
/* a maximum of 5000 variables, must be sufficient? */
|
2019-05-21 17:53:22 +10:00
|
|
|
names = MEM_callocN(sizeof(char *) * max_array_len, "names");
|
|
|
|
types = MEM_callocN(sizeof(char *) * max_array_len, "types");
|
|
|
|
types_size_native = MEM_callocN(sizeof(short) * max_array_len, "types_size_native");
|
|
|
|
types_size_32 = MEM_callocN(sizeof(short) * max_array_len, "types_size_32");
|
|
|
|
types_size_64 = MEM_callocN(sizeof(short) * max_array_len, "types_size_64");
|
|
|
|
structs = MEM_callocN(sizeof(short *) * max_array_len, "structs");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
|
|
|
/* Build versioning data */
|
|
|
|
DNA_alias_maps(DNA_RENAME_ALIAS_FROM_STATIC,
|
|
|
|
&g_version_data.struct_map_alias_from_static,
|
|
|
|
&g_version_data.elem_map_alias_from_static);
|
|
|
|
DNA_alias_maps(DNA_RENAME_STATIC_FROM_ALIAS,
|
|
|
|
&g_version_data.struct_map_static_from_alias,
|
|
|
|
&g_version_data.elem_map_static_from_alias);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Insertion of all known types.
|
|
|
|
*
|
|
|
|
* \warning Order of function calls here must be aligned with #eSDNA_Type.
|
|
|
|
* \warning uint is not allowed! use in structs an unsigned int.
|
|
|
|
* \warning sizes must match #DNA_elem_type_size().
|
|
|
|
*/
|
|
|
|
add_type("char", 1); /* SDNA_TYPE_CHAR */
|
|
|
|
add_type("uchar", 1); /* SDNA_TYPE_UCHAR */
|
|
|
|
add_type("short", 2); /* SDNA_TYPE_SHORT */
|
|
|
|
add_type("ushort", 2); /* SDNA_TYPE_USHORT */
|
|
|
|
add_type("int", 4); /* SDNA_TYPE_INT */
|
|
|
|
|
|
|
|
/* note, long isn't supported,
|
|
|
|
* these are place-holders to maintain alignment with eSDNA_Type*/
|
|
|
|
add_type("long", 4); /* SDNA_TYPE_LONG */
|
|
|
|
add_type("ulong", 4); /* SDNA_TYPE_ULONG */
|
|
|
|
|
|
|
|
add_type("float", 4); /* SDNA_TYPE_FLOAT */
|
|
|
|
add_type("double", 8); /* SDNA_TYPE_DOUBLE */
|
|
|
|
add_type("int64_t", 8); /* SDNA_TYPE_INT64 */
|
|
|
|
add_type("uint64_t", 8); /* SDNA_TYPE_UINT64 */
|
|
|
|
add_type("void", 0); /* SDNA_TYPE_VOID */
|
|
|
|
|
|
|
|
/* the defines above shouldn't be output in the padding file... */
|
2019-05-21 17:53:22 +10:00
|
|
|
firststruct = types_len;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
|
|
|
/* add all include files defined in the global array */
|
|
|
|
/* Since the internal file+path name buffer has limited length, I do a */
|
|
|
|
/* little test first... */
|
|
|
|
/* Mind the breaking condition here! */
|
|
|
|
DEBUG_PRINTF(0, "\tStart of header scan:\n");
|
|
|
|
for (i = 0; *(includefiles[i]) != '\0'; i++) {
|
|
|
|
sprintf(str, "%s%s", base_directory, includefiles[i]);
|
|
|
|
DEBUG_PRINTF(0, "\t|-- Converting %s\n", str);
|
|
|
|
if (convert_include(str)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DEBUG_PRINTF(0, "\tFinished scanning %d headers.\n", i);
|
|
|
|
|
|
|
|
if (calculate_struct_sizes(firststruct, file_verify, base_directory)) {
|
|
|
|
/* error */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FOR DEBUG */
|
|
|
|
if (debugSDNA > 1) {
|
|
|
|
int a, b;
|
|
|
|
/* short *elem; */
|
|
|
|
short num_types;
|
|
|
|
|
2019-05-21 17:53:22 +10:00
|
|
|
printf("names_len %d types_len %d structs_len %d\n", names_len, types_len, structs_len);
|
|
|
|
for (a = 0; a < names_len; a++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
printf(" %s\n", names[a]);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
sp = types_size_native;
|
2019-05-21 17:53:22 +10:00
|
|
|
for (a = 0; a < types_len; a++, sp++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
printf(" %s %d\n", types[a], *sp);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
|
2019-05-21 17:53:22 +10:00
|
|
|
for (a = 0; a < structs_len; a++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
sp = structs[a];
|
|
|
|
printf(" struct %s elems: %d size: %d\n", types[sp[0]], sp[1], types_size_native[sp[0]]);
|
|
|
|
num_types = sp[1];
|
|
|
|
sp += 2;
|
|
|
|
/* ? num_types was elem? */
|
|
|
|
for (b = 0; b < num_types; b++, sp += 2) {
|
|
|
|
printf(" %s %s\n", types[sp[0]], names[sp[1]]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* file writing */
|
|
|
|
|
|
|
|
DEBUG_PRINTF(0, "Writing file ... ");
|
|
|
|
|
2019-05-21 17:53:22 +10:00
|
|
|
if (names_len == 0 || structs_len == 0) {
|
2019-04-17 06:17:24 +02:00
|
|
|
/* pass */
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const char nil_bytes[4] = {0};
|
|
|
|
int len, len_align;
|
|
|
|
|
|
|
|
dna_write(file, "SDNA", 4);
|
|
|
|
|
|
|
|
/* write names */
|
|
|
|
dna_write(file, "NAME", 4);
|
2019-05-21 17:53:22 +10:00
|
|
|
len = names_len;
|
2019-04-17 06:17:24 +02:00
|
|
|
dna_write(file, &len, 4);
|
|
|
|
/* write array */
|
|
|
|
len = 0;
|
2019-05-21 17:53:22 +10:00
|
|
|
for (int nr = 0; nr < names_len; nr++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
int name_size = strlen(names[nr]) + 1;
|
|
|
|
dna_write(file, names[nr], name_size);
|
|
|
|
len += name_size;
|
|
|
|
}
|
|
|
|
len_align = (len + 3) & ~3;
|
|
|
|
if (len != len_align) {
|
|
|
|
dna_write(file, nil_bytes, len_align - len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* write TYPES */
|
|
|
|
dna_write(file, "TYPE", 4);
|
2019-05-21 17:53:22 +10:00
|
|
|
len = types_len;
|
2019-04-17 06:17:24 +02:00
|
|
|
dna_write(file, &len, 4);
|
|
|
|
/* write array */
|
|
|
|
len = 0;
|
2019-05-21 17:53:22 +10:00
|
|
|
for (int nr = 0; nr < types_len; nr++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
int type_size = strlen(types[nr]) + 1;
|
|
|
|
dna_write(file, types[nr], type_size);
|
|
|
|
len += type_size;
|
|
|
|
}
|
|
|
|
len_align = (len + 3) & ~3;
|
|
|
|
if (len != len_align) {
|
|
|
|
dna_write(file, nil_bytes, len_align - len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* WRITE TYPELENGTHS */
|
|
|
|
dna_write(file, "TLEN", 4);
|
|
|
|
|
2019-05-21 17:53:22 +10:00
|
|
|
len = 2 * types_len;
|
|
|
|
if (types_len & 1) {
|
2019-04-17 06:17:24 +02:00
|
|
|
len += 2;
|
|
|
|
}
|
|
|
|
dna_write(file, types_size_native, len);
|
|
|
|
|
|
|
|
/* WRITE STRUCTS */
|
|
|
|
dna_write(file, "STRC", 4);
|
2019-05-21 17:53:22 +10:00
|
|
|
len = structs_len;
|
2019-04-17 06:17:24 +02:00
|
|
|
dna_write(file, &len, 4);
|
|
|
|
|
|
|
|
/* calc datablock size */
|
2019-05-21 17:53:22 +10:00
|
|
|
sp = structs[structs_len - 1];
|
2019-04-17 06:17:24 +02:00
|
|
|
sp += 2 + 2 * (sp[1]);
|
|
|
|
len = (intptr_t)((char *)sp - (char *)structs[0]);
|
|
|
|
len = (len + 3) & ~3;
|
|
|
|
|
|
|
|
dna_write(file, structs[0], len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* write a simple enum with all structs offsets,
|
|
|
|
* should only be accessed via SDNA_TYPE_FROM_STRUCT macro */
|
|
|
|
{
|
|
|
|
fprintf(file_offsets, "#define SDNA_TYPE_FROM_STRUCT(id) _SDNA_TYPE_##id\n");
|
|
|
|
fprintf(file_offsets, "enum {\n");
|
2019-05-21 17:53:22 +10:00
|
|
|
for (i = 0; i < structs_len; i++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
const short *structpoin = structs[i];
|
|
|
|
const int structtype = structpoin[0];
|
|
|
|
fprintf(file_offsets,
|
|
|
|
"\t_SDNA_TYPE_%s = %d,\n",
|
|
|
|
version_struct_alias_from_static(types[structtype]),
|
|
|
|
i);
|
|
|
|
}
|
2019-05-21 17:53:22 +10:00
|
|
|
fprintf(file_offsets, "\tSDNA_TYPE_MAX = %d,\n", structs_len);
|
2019-04-17 06:17:24 +02:00
|
|
|
fprintf(file_offsets, "};\n\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check versioning errors which could cause duplicate names,
|
|
|
|
* do last because names are stripped. */
|
|
|
|
{
|
|
|
|
GSet *names_unique = BLI_gset_str_new_ex(__func__, 512);
|
2019-05-21 17:53:22 +10:00
|
|
|
for (int struct_nr = 0; struct_nr < structs_len; struct_nr++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
sp = structs[struct_nr];
|
|
|
|
const char *struct_name = types[sp[0]];
|
|
|
|
const int len = sp[1];
|
|
|
|
sp += 2;
|
|
|
|
for (int a = 0; a < len; a++, sp += 2) {
|
|
|
|
char *name = names[sp[1]];
|
|
|
|
DNA_elem_id_strip(name);
|
|
|
|
if (!BLI_gset_add(names_unique, name)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Error: duplicate name found '%s.%s', "
|
|
|
|
"likely cause is 'dna_rename_defs.h'\n",
|
|
|
|
struct_name,
|
|
|
|
name);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BLI_gset_clear(names_unique, NULL);
|
|
|
|
}
|
|
|
|
BLI_gset_free(names_unique, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(structdata);
|
|
|
|
MEM_freeN(names);
|
|
|
|
MEM_freeN(types);
|
|
|
|
MEM_freeN(types_size_native);
|
|
|
|
MEM_freeN(types_size_32);
|
|
|
|
MEM_freeN(types_size_64);
|
|
|
|
MEM_freeN(structs);
|
|
|
|
|
|
|
|
BLI_memarena_free(mem_arena);
|
|
|
|
|
|
|
|
BLI_ghash_free(g_version_data.struct_map_alias_from_static, NULL, NULL);
|
|
|
|
BLI_ghash_free(g_version_data.struct_map_static_from_alias, NULL, NULL);
|
|
|
|
BLI_ghash_free(g_version_data.elem_map_static_from_alias, MEM_freeN, NULL);
|
|
|
|
BLI_ghash_free(g_version_data.elem_map_alias_from_static, MEM_freeN, NULL);
|
|
|
|
|
|
|
|
DEBUG_PRINTF(0, "done.\n");
|
|
|
|
|
|
|
|
return 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2019-02-15 10:31:51 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* end make DNA. */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Main Function
|
|
|
|
* \{ */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2011-10-27 14:41:26 +00:00
|
|
|
static void make_bad_file(const char *file, int line)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
FILE *fp = fopen(file, "w");
|
|
|
|
fprintf(fp,
|
|
|
|
"#error \"Error! can't make correct DNA.c file from %s:%d, check alignment.\"\n",
|
|
|
|
__FILE__,
|
|
|
|
line);
|
|
|
|
fclose(fp);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2005-07-20 20:46:01 +00:00
|
|
|
#ifndef BASE_HEADER
|
2019-04-17 06:17:24 +02:00
|
|
|
# define BASE_HEADER "../"
|
2005-07-20 20:46:01 +00:00
|
|
|
#endif
|
|
|
|
|
2012-05-12 15:02:10 +00:00
|
|
|
int main(int argc, char **argv)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
int return_status = 0;
|
|
|
|
|
|
|
|
if (argc != 4 && argc != 5) {
|
|
|
|
printf("Usage: %s dna.c dna_struct_offsets.h [base directory]\n", argv[0]);
|
|
|
|
return_status = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
FILE *file_dna = fopen(argv[1], "w");
|
|
|
|
FILE *file_dna_offsets = fopen(argv[2], "w");
|
|
|
|
FILE *file_dna_verify = fopen(argv[3], "w");
|
|
|
|
if (!file_dna) {
|
|
|
|
printf("Unable to open file: %s\n", argv[1]);
|
|
|
|
return_status = 1;
|
|
|
|
}
|
|
|
|
else if (!file_dna_offsets) {
|
|
|
|
printf("Unable to open file: %s\n", argv[2]);
|
|
|
|
return_status = 1;
|
|
|
|
}
|
|
|
|
else if (!file_dna_verify) {
|
|
|
|
printf("Unable to open file: %s\n", argv[3]);
|
|
|
|
return_status = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const char *base_directory;
|
|
|
|
|
|
|
|
if (argc == 5) {
|
|
|
|
base_directory = argv[4];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
base_directory = BASE_HEADER;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(file_dna, "extern const unsigned char DNAstr[];\n");
|
|
|
|
fprintf(file_dna, "const unsigned char DNAstr[] = {\n");
|
|
|
|
if (make_structDNA(base_directory, file_dna, file_dna_offsets, file_dna_verify)) {
|
|
|
|
/* error */
|
|
|
|
fclose(file_dna);
|
|
|
|
file_dna = NULL;
|
|
|
|
make_bad_file(argv[1], __LINE__);
|
|
|
|
return_status = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fprintf(file_dna, "};\n");
|
|
|
|
fprintf(file_dna, "extern const int DNAlen;\n");
|
|
|
|
fprintf(file_dna, "const int DNAlen = sizeof(DNAstr);\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (file_dna) {
|
|
|
|
fclose(file_dna);
|
|
|
|
}
|
|
|
|
if (file_dna_offsets) {
|
|
|
|
fclose(file_dna_offsets);
|
|
|
|
}
|
|
|
|
if (file_dna_verify) {
|
|
|
|
fclose(file_dna_verify);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return return_status;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2018-09-24 17:27:41 +02:00
|
|
|
/* handy but fails on struct bounds which makesdna doesn't care about
|
2012-10-23 04:26:39 +00:00
|
|
|
* with quite the same strictness as GCC does */
|
2012-10-06 00:42:30 +00:00
|
|
|
#if 0
|
2012-04-12 07:40:47 +00:00
|
|
|
/* include files for automatic dependencies */
|
2012-10-04 09:20:58 +00:00
|
|
|
|
|
|
|
/* extra safety check that we are aligned,
|
|
|
|
* warnings here are easier to fix the makesdna's */
|
2019-04-17 06:17:24 +02:00
|
|
|
# ifdef __GNUC__
|
|
|
|
# pragma GCC diagnostic error "-Wpadded"
|
|
|
|
# endif
|
2012-10-04 09:20:58 +00:00
|
|
|
|
2012-10-06 00:42:30 +00:00
|
|
|
#endif /* if 0 */
|
|
|
|
|
2013-12-04 13:51:41 +11:00
|
|
|
/* even though DNA supports, 'long' shouldn't be used since it can be either 32 or 64bit,
|
|
|
|
* use int or int64_t instead.
|
|
|
|
* Only valid use would be as a runtime variable if an API expected a long,
|
|
|
|
* but so far we dont have this happening. */
|
|
|
|
#ifdef __GNUC__
|
|
|
|
# pragma GCC poison long
|
|
|
|
#endif
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_listBase.h"
|
|
|
|
#include "DNA_vec_types.h"
|
|
|
|
#include "DNA_ID.h"
|
|
|
|
#include "DNA_ipo_types.h"
|
|
|
|
#include "DNA_key_types.h"
|
|
|
|
#include "DNA_text_types.h"
|
|
|
|
#include "DNA_packedFile_types.h"
|
|
|
|
#include "DNA_camera_types.h"
|
|
|
|
#include "DNA_image_types.h"
|
|
|
|
#include "DNA_texture_types.h"
|
2019-02-27 12:34:56 +11:00
|
|
|
#include "DNA_light_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_material_types.h"
|
|
|
|
#include "DNA_vfont_types.h"
|
|
|
|
#include "DNA_meta_types.h"
|
|
|
|
#include "DNA_curve_types.h"
|
|
|
|
#include "DNA_mesh_types.h"
|
2004-03-20 22:55:42 +00:00
|
|
|
#include "DNA_meshdata_types.h"
|
2005-07-19 20:14:17 +00:00
|
|
|
#include "DNA_modifier_types.h"
|
2018-06-17 17:04:09 +02:00
|
|
|
#include "DNA_lattice_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_object_types.h"
|
2018-02-07 11:14:08 +11:00
|
|
|
#include "DNA_object_force_types.h"
|
|
|
|
#include "DNA_object_fluidsim_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_world_types.h"
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "DNA_view3d_types.h"
|
2018-06-17 17:04:09 +02:00
|
|
|
#include "DNA_view2d_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_space_types.h"
|
|
|
|
#include "DNA_userdef_types.h"
|
|
|
|
#include "DNA_screen_types.h"
|
|
|
|
#include "DNA_sdna_types.h"
|
|
|
|
#include "DNA_fileglobal_types.h"
|
|
|
|
#include "DNA_sequence_types.h"
|
|
|
|
#include "DNA_effect_types.h"
|
2009-09-18 22:25:49 +00:00
|
|
|
#include "DNA_outliner_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_sound_types.h"
|
2018-08-29 15:32:50 +02:00
|
|
|
#include "DNA_collection_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_armature_types.h"
|
|
|
|
#include "DNA_action_types.h"
|
|
|
|
#include "DNA_constraint_types.h"
|
|
|
|
#include "DNA_nla_types.h"
|
2005-12-18 13:46:01 +00:00
|
|
|
#include "DNA_node_types.h"
|
Orange:
- New UI element: the "Curve Button".
For mapping ranges (like 0 - 1) to another range, the curve button can be
used for proportional falloff, bone influences, painting density, etc.
Most evident use is of course to map RGB color with curves.
To be able to use it, you have to allocate a CurveMapping struct and pass
this on to the button. The CurveMapping API is in the new C file
blenkernel/intern/colortools.c
It's as simple as calling:
curvemap= curvemapping_add(3, 0, 0, 1, 1)
Which will create 3 curves, and sets a default 0-1 range. The current code
only supports up to 4 curves maximum per mapping struct.
The CurveMap button in Blender than handles allmost all editing.
Evaluating a single channel:
float newvalue= curvemapping_evaluateF(curvemap, 0, oldval);
Where the second argument is the channel index, here 0-1-2 are possible.
Or mapping a vector:
curvemapping_evaluate3F(curvemap, newvec, oldvec);
Optimized versions for byte or short mapping is possible too, not done yet.
In butspace.c I've added a template wrapper for buttons around the curve, to
reveil settings or show tools; check this screenie:
http://www.blender.org/bf/curves.jpg
- Buttons R, G, B: select channel
- icons + and -: zoom in, out
- icon 'wrench': menu with tools, like clear curve, set handle type
- icon 'clipping': menu with clip values, and to dis/enable clipping
- icon 'x': delete selection
In the curve button itself, only LMB clicks are handled (like all UI elements
in Blender).
- click on point: select
- shift+click on point: swap select
- click on point + drag: select point (if not selected) and move it
- click outside point + drag: translate view
- CTRL+click: add new point
- hold SHIFT while dragging to snap to grid
(Yes I know... either one of these can be Blender compliant, not both!)
- if you drag a point exactly on top of another, it merges them
Other fixes:
- Icons now draw using "Safe RasterPos", so they align with pixel boundary.
the old code made ints from the raster pos coordinate, which doesn't work
well for zoom in/out situations
- bug in Node editing: buttons could not get freed, causing in memory error
prints at end of a Blender session. That one was a very simple, but nasty
error causing me all evening last night to find!
(Hint; check diff of editnode.c, where uiDoButtons is called)
Last note: this adds 3 new files in our tree, I did scons, but not MSVC!
2006-01-08 11:41:06 +00:00
|
|
|
#include "DNA_color_types.h"
|
Brush Datablock:
- Added a new Brush datablock, only used by image paint, but intended
to be used in texture paint, vertex paint, weight paint and sculpt
mode also.
- Being a datablock, these brushes can be saved, appended and linked.
They have a fake user by default, to make sure they are saved even if
not selected.
Image Painting:
- Replaced the img module with C code in imagepaint.c
- Airbrush is no longer a separate tool, but rather an option that can
be used for soften, smear and clone also.
- Blend modes mix, add, subtract, multiply, darken and lighten have been
added, code taken directly from vertex paint.
Note to project files maintainers:
- The img module was removed from SCons and Makefiles, and this should
be done in other build systems also. I'll wait to remove the module
from cvs, to not break compilation.
2006-07-26 22:29:23 +00:00
|
|
|
#include "DNA_brush_types.h"
|
Added custom vertex/edge/face data for meshes:
All data layers, including MVert/MEdge/MFace, are now managed as custom
data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are
still used of course, but allocating, copying or freeing these arrays
should be done through the CustomData API.
Work in progress documentation on this is here:
http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData
Replaced TFace by MTFace:
This is the same struct, except that it does not contain color, that now
always stays separated in MCol. This was not a good design decision to
begin with, and it is needed for adding multiple color layers later. Note
that this does mean older Blender versions will not be able to read UV
coordinates from the next release, due to an SDNA limitation.
Removed DispListMesh:
This now fully replaced by DerivedMesh. To provide access to arrays of
vertices, edges and faces, like DispListMesh does. The semantics of the
DerivedMesh.getVertArray() and similar functions were changed to return
a pointer to an array if one exists, or otherwise allocate a temporary
one. On releasing the DerivedMesh, this temporary array will be removed
automatically.
Removed ssDM and meshDM DerivedMesh backends:
The ssDM backend was for DispListMesh, so that became obsolete automatically.
The meshDM backend was replaced by the custom data backend, that now figures
out which layers need to be modified, and only duplicates those.
This changes code in many places, and overall removes 2514 lines of code.
So, there's a good chance this might break some stuff, although I've been
testing it for a few days now. The good news is, adding multiple color and
uv layers should now become easy.
2006-11-20 04:28:02 +00:00
|
|
|
#include "DNA_customdata_types.h"
|
2016-12-28 17:30:58 +01:00
|
|
|
#include "DNA_particle_types.h"
|
2008-01-29 21:01:12 +00:00
|
|
|
#include "DNA_cloth_types.h"
|
2008-07-22 09:53:25 +00:00
|
|
|
#include "DNA_gpencil_types.h"
|
2018-07-31 10:22:19 +02:00
|
|
|
#include "DNA_gpencil_modifier_types.h"
|
|
|
|
#include "DNA_shader_fx_types.h"
|
2009-09-18 22:25:49 +00:00
|
|
|
#include "DNA_windowmanager_types.h"
|
|
|
|
#include "DNA_anim_types.h"
|
2016-12-28 17:30:58 +01:00
|
|
|
#include "DNA_boid_types.h"
|
2009-09-18 22:25:49 +00:00
|
|
|
#include "DNA_smoke_types.h"
|
2011-08-01 11:44:20 +00:00
|
|
|
#include "DNA_speaker_types.h"
|
2011-11-07 12:55:18 +00:00
|
|
|
#include "DNA_movieclip_types.h"
|
|
|
|
#include "DNA_tracking_types.h"
|
2011-05-24 07:08:58 +00:00
|
|
|
#include "DNA_dynamicpaint_types.h"
|
2012-06-04 16:42:58 +00:00
|
|
|
#include "DNA_mask_types.h"
|
2013-01-23 05:56:22 +00:00
|
|
|
#include "DNA_rigidbody_types.h"
|
2009-09-28 03:56:31 +00:00
|
|
|
#include "DNA_freestyle_types.h"
|
2010-07-20 17:57:33 +00:00
|
|
|
#include "DNA_linestyle_types.h"
|
Basic Alembic support
All in all, this patch adds an Alembic importer, an Alembic exporter,
and a new CacheFile data block which, for now, wraps around an Alembic
archive. This data block is made available through a new modifier ("Mesh
Sequence Cache") as well as a new constraint ("Transform Cache") to
somewhat properly support respectively geometric and transformation data
streaming from alembic caches.
A more in-depth documentation is to be found on the wiki, as well as a
guide to compile alembic: https://wiki.blender.org/index.php/
User:Kevindietrich/AlembicBasicIo.
Many thanks to everyone involved in this little project, and huge shout
out to "cgstrive" for the thorough testings with Maya, 3ds Max, Houdini
and Realflow as well as @fjuhec, @jensverwiebe and @jasperge for the
custom builds and compile fixes.
Reviewers: sergey, campbellbarton, mont29
Reviewed By: sergey, campbellbarton, mont29
Differential Revision: https://developer.blender.org/D2060
2016-08-06 06:20:37 +02:00
|
|
|
#include "DNA_cachefile_types.h"
|
Render Layers and Collections (merge from render-layers)
Design Documents
----------------
* https://wiki.blender.org/index.php/Dev:2.8/Source/Layers
* https://wiki.blender.org/index.php/Dev:2.8/Source/DataDesignRevised
User Commit Log
---------------
* New Layer and Collection system to replace render layers and viewport layers.
* A layer is a set of collections of objects (and their drawing options) required for specific tasks.
* A collection is a set of objects, equivalent of the old layers in Blender. A collection can be shared across multiple layers.
* All Scenes have a master collection that all other collections are children of.
* New collection "context" tab (in Properties Editor)
* New temporary viewport "collections" panel to control per-collection
visibility
Missing User Features
---------------------
* Collection "Filter"
Option to add objects based on their names
* Collection Manager operators
The existing buttons are placeholders
* Collection Manager drawing
The editor main region is empty
* Collection Override
* Per-Collection engine settings
This will come as a separate commit, as part of the clay-engine branch
Dev Commit Log
--------------
* New DNA file (DNA_layer_types.h) with the new structs
We are replacing Base by a new extended Base while keeping it backward
compatible with some legacy settings (i.e., lay, flag_legacy).
Renamed all Base to BaseLegacy to make it clear the areas of code that
still need to be converted
Note: manual changes were required on - deg_builder_nodes.h, rna_object.c, KX_Light.cpp
* Unittesting for main syncronization requirements
- read, write, add/copy/remove objects, copy scene, collection
link/unlinking, context)
* New Editor: Collection Manager
Based on patch by Julian Eisel
This is extracted from the layer-manager branch. With the following changes:
- Renamed references of layer manager to collections manager
- I doesn't include the editors/space_collections/ draw and util files
- The drawing code itself will be implemented separately by Julian
* Base / Object:
A little note about them. Original Blender code would try to keep them
in sync through the code, juggling flags back and forth. This will now
be handled by Depsgraph, keeping Object and Bases more separated
throughout the non-rendering code.
Scene.base is being cleared in doversion, and the old viewport drawing
code was poorly converted to use the new bases while the new viewport
code doesn't get merged and replace the old one.
Python API Changes
------------------
```
- scene.layers
+ # no longer exists
- scene.objects
+ scene.scene_layers.active.objects
- scene.objects.active
+ scene.render_layers.active.objects.active
- bpy.context.scene.objects.link()
+ bpy.context.scene_collection.objects.link()
- bpy_extras.object_utils.object_data_add(context, obdata, operator=None, use_active_layer=True, name=None)
+ bpy_extras.object_utils.object_data_add(context, obdata, operator=None, name=None)
- bpy.context.object.select
+ bpy.context.object.select = True
+ bpy.context.object.select = False
+ bpy.context.object.select_get()
+ bpy.context.object.select_set(action='SELECT')
+ bpy.context.object.select_set(action='DESELECT')
-AddObjectHelper.layers
+ # no longer exists
```
2017-02-07 10:18:38 +01:00
|
|
|
#include "DNA_layer_types.h"
|
Main Workspace Integration
This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup)
Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know!
(Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.)
== Main Changes/Features
* Introduces the new Workspaces as data-blocks.
* Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces.
* Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces).
* Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead.
* Store screen-layouts (`bScreen`) per workspace.
* Store an active screen-layout per workspace. Changing the workspace will enable this layout.
* Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.)
* Store an active render layer per workspace.
* Moved mode switch from 3D View header to Info Editor header.
* Store active scene in window (not directly workspace related, but overlaps quite a bit).
* Removed 'Use Global Scene' User Preference option.
* Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well.
* Default .blend only contains one workspace ("General").
* Support appending workspaces.
Opening files without UI and commandline rendering should work fine.
Note that the UI is temporary! We plan to introduce a new global topbar
that contains the workspace options and tabs for switching workspaces.
== Technical Notes
* Workspaces are data-blocks.
* Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now.
* A workspace can be active in multiple windows at the same time.
* The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned).
* The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that).
* Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs.
* `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those.
* Added scene operators `SCENE_OT_`. Was previously done through screen operators.
== BPY API Changes
* Removed `Screen.scene`, added `Window.scene`
* Removed `UserPreferencesView.use_global_scene`
* Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces`
* Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer`
* Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name)
== What's left?
* There are a few open design questions (T50521). We should find the needed answers and implement them.
* Allow adding and removing individual workspaces from workspace configuration (needs UI design).
* Get the override system ready and support overrides per workspace.
* Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc).
* Allow enabling add-ons per workspace.
* Support custom workspace keymaps.
* Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later.
* Get the topbar done.
* Workspaces need a proper icon, current one is just a placeholder :)
Reviewed By: campbellbarton, mont29
Tags: #user_interface, #bf_blender_2.8
Maniphest Tasks: T50521
Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
|
|
|
#include "DNA_workspace_types.h"
|
2017-06-12 20:59:54 +10:00
|
|
|
#include "DNA_lightprobe_types.h"
|
Main Workspace Integration
This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup)
Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know!
(Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.)
== Main Changes/Features
* Introduces the new Workspaces as data-blocks.
* Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces.
* Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces).
* Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead.
* Store screen-layouts (`bScreen`) per workspace.
* Store an active screen-layout per workspace. Changing the workspace will enable this layout.
* Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.)
* Store an active render layer per workspace.
* Moved mode switch from 3D View header to Info Editor header.
* Store active scene in window (not directly workspace related, but overlaps quite a bit).
* Removed 'Use Global Scene' User Preference option.
* Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well.
* Default .blend only contains one workspace ("General").
* Support appending workspaces.
Opening files without UI and commandline rendering should work fine.
Note that the UI is temporary! We plan to introduce a new global topbar
that contains the workspace options and tabs for switching workspaces.
== Technical Notes
* Workspaces are data-blocks.
* Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now.
* A workspace can be active in multiple windows at the same time.
* The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned).
* The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that).
* Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs.
* `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those.
* Added scene operators `SCENE_OT_`. Was previously done through screen operators.
== BPY API Changes
* Removed `Screen.scene`, added `Window.scene`
* Removed `UserPreferencesView.use_global_scene`
* Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces`
* Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer`
* Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name)
== What's left?
* There are a few open design questions (T50521). We should find the needed answers and implement them.
* Allow adding and removing individual workspaces from workspace configuration (needs UI design).
* Get the override system ready and support overrides per workspace.
* Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc).
* Allow enabling add-ons per workspace.
* Support custom workspace keymaps.
* Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later.
* Get the topbar done.
* Workspaces need a proper icon, current one is just a placeholder :)
Reviewed By: campbellbarton, mont29
Tags: #user_interface, #bf_blender_2.8
Maniphest Tasks: T50521
Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
/* end of list */
|
2019-02-15 10:31:51 +11:00
|
|
|
|
|
|
|
/** \} */
|
2019-02-16 12:54:33 +11:00
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name DNA Renaming Sanity Check
|
|
|
|
*
|
|
|
|
* Without this it's possible to reference struct members that don't exist,
|
|
|
|
* breaking backward & forward compatibility.
|
|
|
|
*
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
static void UNUSED_FUNCTION(dna_rename_defs_ensure)(void)
|
|
|
|
{
|
|
|
|
#define DNA_STRUCT_RENAME(old, new) (void)sizeof(new);
|
|
|
|
#define DNA_STRUCT_RENAME_ELEM(struct_name, old, new) (void)offsetof(struct_name, new);
|
|
|
|
#include "dna_rename_defs.h"
|
|
|
|
#undef DNA_STRUCT_RENAME
|
|
|
|
#undef DNA_STRUCT_RENAME_ELEM
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \} */
|