Changeset View
Changeset View
Standalone View
Standalone View
source/blender/makesdna/intern/dna_genfile.c
| Show First 20 Lines • Show All 974 Lines • ▼ Show 20 Lines | if (elem_streq(name, oname)) { /* name equal */ | ||||
| } | } | ||||
| break; /* Fail below. */ | break; /* Fail below. */ | ||||
| } | } | ||||
| offset += DNA_elem_size_nr(sdna, member->type, member->name); | offset += DNA_elem_size_nr(sdna, member->type, member->name); | ||||
| } | } | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| /* Each struct member belongs to one of the categories below. */ | |||||
| typedef enum eStructMemberCategory { | |||||
| STRUCT_MEMBER_CATEGORY_STRUCT, | |||||
| STRUCT_MEMBER_CATEGORY_PRIMITIVE, | |||||
| STRUCT_MEMBER_CATEGORY_POINTER, | |||||
| } eStructMemberCategory; | |||||
| static eStructMemberCategory get_struct_member_category(const SDNA *sdna, | |||||
| const SDNA_StructMember *member) | |||||
| { | |||||
| const char *member_name = sdna->names[member->name]; | |||||
| if (ispointer(member_name)) { | |||||
| return STRUCT_MEMBER_CATEGORY_POINTER; | |||||
| } | |||||
| const char *member_type_name = sdna->types[member->type]; | |||||
| if (DNA_struct_find(sdna, member_type_name)) { | |||||
| return STRUCT_MEMBER_CATEGORY_STRUCT; | |||||
| } | |||||
| return STRUCT_MEMBER_CATEGORY_PRIMITIVE; | |||||
| } | |||||
| static int get_member_size_in_bytes(const SDNA *sdna, const SDNA_StructMember *member) | |||||
| { | |||||
| const char *name = sdna->names[member->name]; | |||||
| const int array_length = sdna->names_array_len[member->name]; | |||||
| if (ispointer(name)) { | |||||
| return sdna->pointer_size * array_length; | |||||
| } | |||||
| const int type_size = sdna->types_size[member->type]; | |||||
| return type_size * array_length; | |||||
| } | |||||
| /** | /** | ||||
| * Does endian swapping on the fields of a struct value. | * Does endian swapping on the fields of a struct value. | ||||
| * | * | ||||
| * \param oldsdna: SDNA of Blender that saved file | * \param sdna: SDNA of the struct_nr belongs to | ||||
| * \param oldSDNAnr: Index of struct info within oldsdna | * \param struct_nr: Index of struct info within sdna | ||||
| * \param data: Struct data | * \param data: Struct data that is to be converted | ||||
| */ | */ | ||||
| void DNA_struct_switch_endian(const SDNA *oldsdna, int oldSDNAnr, char *data) | void DNA_struct_switch_endian(const SDNA *sdna, int struct_nr, char *data) | ||||
| { | { | ||||
| /* Recursive! | if (struct_nr == -1) { | ||||
| * If element is a struct, call recursive. | |||||
| */ | |||||
| if (oldSDNAnr == -1) { | |||||
| return; | return; | ||||
| } | } | ||||
| const int firststructtypenr = oldsdna->structs[0]->type; | |||||
| const SDNA_Struct *struct_info = oldsdna->structs[oldSDNAnr]; | const SDNA_Struct *struct_info = sdna->structs[struct_nr]; | ||||
| char *cur = data; | |||||
| for (int a = 0; a < struct_info->members_len; a++) { | int offset_in_bytes = 0; | ||||
| const SDNA_StructMember *member = &struct_info->members[a]; | for (int member_index = 0; member_index < struct_info->members_len; member_index++) { | ||||
| const char *type = oldsdna->types[member->type]; | const SDNA_StructMember *member = &struct_info->members[member_index]; | ||||
| const char *name = oldsdna->names[member->name]; | const eStructMemberCategory member_category = get_struct_member_category(sdna, member); | ||||
| const int old_name_array_len = oldsdna->names_array_len[member->name]; | char *member_data = data + offset_in_bytes; | ||||
| const char *member_type_name = sdna->types[member->type]; | |||||
| /* DNA_elem_size_nr = including arraysize */ | const int member_array_length = sdna->names_array_len[member->name]; | ||||
| const int elen = DNA_elem_size_nr(oldsdna, member->type, member->name); | |||||
| switch (member_category) { | |||||
| /* test: is type a struct? */ | case STRUCT_MEMBER_CATEGORY_STRUCT: { | ||||
| if (member->type >= firststructtypenr && !ispointer(name)) { | const int substruct_size = sdna->types_size[member->type]; | ||||
| /* struct field type */ | const int substruct_nr = DNA_struct_find_nr(sdna, member_type_name); | ||||
| /* where does the old data start (is there one?) */ | BLI_assert(substruct_nr != -1); | ||||
| for (int a = 0; a < member_array_length; a++) { | |||||
| const int data_offset = elem_offset(oldsdna, type, name, struct_info); | DNA_struct_switch_endian(sdna, substruct_nr, member_data + a * substruct_size); | ||||
| if (data_offset != -1) { | |||||
| char *cpo = data + data_offset; | |||||
| unsigned int oldsdna_index_last = UINT_MAX; | |||||
| oldSDNAnr = DNA_struct_find_nr_ex(oldsdna, type, &oldsdna_index_last); | |||||
| int mul = old_name_array_len; | |||||
| const int elena = elen / mul; | |||||
| while (mul--) { | |||||
| DNA_struct_switch_endian(oldsdna, oldSDNAnr, cpo); | |||||
| cpo += elena; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| else { | break; | ||||
| /* non-struct field type */ | |||||
| if (ispointer(name)) { | |||||
| /* See readfile.c (#bh4_from_bh8 swap endian argument), | |||||
| * this is only done when reducing the size of a pointer from 4 to 8. */ | |||||
| if (sizeof(void *) < 8) { | |||||
| if (oldsdna->pointer_size == 8) { | |||||
| BLI_endian_switch_int64_array((int64_t *)cur, old_name_array_len); | |||||
| } | } | ||||
JacquesLucke: Here we were switching 8 byte pointers only, which I found confusing. | |||||
| case STRUCT_MEMBER_CATEGORY_PRIMITIVE: { | |||||
| switch (member->type) { | |||||
| case SDNA_TYPE_SHORT: | |||||
| case SDNA_TYPE_USHORT: { | |||||
| BLI_endian_switch_int16_array((int16_t *)member_data, member_array_length); | |||||
| break; | |||||
| } | } | ||||
| case SDNA_TYPE_INT: | |||||
| case SDNA_TYPE_FLOAT: { | |||||
| /* Note, intentionally ignore long/ulong, because these could be 4 or 8 bytes. | |||||
| * Fortunately, we only use these types for runtime variables and only once for a | |||||
| * struct type that is no longer used. */ | |||||
| BLI_endian_switch_int32_array((int32_t *)member_data, member_array_length); | |||||
| break; | |||||
| } | } | ||||
| else { | case SDNA_TYPE_INT64: | ||||
| if (ELEM(member->type, SDNA_TYPE_SHORT, SDNA_TYPE_USHORT)) { | case SDNA_TYPE_UINT64: | ||||
| case SDNA_TYPE_DOUBLE: { | |||||
| /* exception: variable called blocktype: derived from ID_ */ | BLI_endian_switch_int64_array((int64_t *)member_data, member_array_length); | ||||
Done Inline ActionsThis special case has been moved to direct_link_ipo. JacquesLucke: This special case has been moved to `direct_link_ipo`. | |||||
| bool skip = false; | break; | ||||
| if (name[0] == 'b' && name[1] == 'l') { | |||||
| if (STREQ(name, "blocktype")) { | |||||
| skip = true; | |||||
| } | } | ||||
| default: { | |||||
| break; | |||||
| } | } | ||||
| if (skip == false) { | |||||
| BLI_endian_switch_int16_array((int16_t *)cur, old_name_array_len); | |||||
| } | } | ||||
| break; | |||||
| } | } | ||||
| else if (ELEM(member->type, SDNA_TYPE_INT, SDNA_TYPE_FLOAT)) { | case STRUCT_MEMBER_CATEGORY_POINTER: { | ||||
| /* note, intentionally ignore long/ulong here these could be 4 or 8 bits, | if (sdna->pointer_size == 4) { | ||||
| * but turns out we only used for runtime vars and | BLI_endian_switch_uint32_array((uint32_t *)member_data, member_array_length); | ||||
| * only once for a struct type that's no longer used. */ | |||||
| BLI_endian_switch_int32_array((int32_t *)cur, old_name_array_len); | |||||
| } | } | ||||
| else if (ELEM(member->type, SDNA_TYPE_INT64, SDNA_TYPE_UINT64, SDNA_TYPE_DOUBLE)) { | else { | ||||
| BLI_endian_switch_int64_array((int64_t *)cur, old_name_array_len); | BLI_endian_switch_uint64_array((uint64_t *)member_data, member_array_length); | ||||
| } | } | ||||
| break; | |||||
| } | } | ||||
| } | } | ||||
| cur += elen; | offset_in_bytes += get_member_size_in_bytes(sdna, member); | ||||
| } | } | ||||
| } | } | ||||
| typedef enum eReconstructStepType { | typedef enum eReconstructStepType { | ||||
| RECONSTRUCT_STEP_MEMCPY, | RECONSTRUCT_STEP_MEMCPY, | ||||
| RECONSTRUCT_STEP_CAST_PRIMITIVE, | RECONSTRUCT_STEP_CAST_PRIMITIVE, | ||||
| RECONSTRUCT_STEP_CAST_POINTER_TO_32, | RECONSTRUCT_STEP_CAST_POINTER_TO_32, | ||||
| RECONSTRUCT_STEP_CAST_POINTER_TO_64, | RECONSTRUCT_STEP_CAST_POINTER_TO_64, | ||||
| ▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | void *DNA_struct_reconstruct(const DNA_ReconstructInfo *reconstruct_info, | ||||
| const int new_block_size = newsdna->types_size[new_struct->type]; | const int new_block_size = newsdna->types_size[new_struct->type]; | ||||
| char *new_blocks = MEM_callocN(blocks * new_block_size, "reconstruct"); | char *new_blocks = MEM_callocN(blocks * new_block_size, "reconstruct"); | ||||
| reconstruct_structs( | reconstruct_structs( | ||||
| reconstruct_info, blocks, old_struct_nr, new_struct_nr, old_blocks, new_blocks); | reconstruct_info, blocks, old_struct_nr, new_struct_nr, old_blocks, new_blocks); | ||||
| return new_blocks; | return new_blocks; | ||||
| } | } | ||||
| /* Each struct member belongs to one of the categories below. */ | |||||
| typedef enum eStructMemberCategory { | |||||
| STRUCT_MEMBER_CATEGORY_STRUCT, | |||||
| STRUCT_MEMBER_CATEGORY_PRIMITIVE, | |||||
| STRUCT_MEMBER_CATEGORY_POINTER, | |||||
| } eStructMemberCategory; | |||||
| static eStructMemberCategory get_struct_member_category(const SDNA *sdna, | |||||
| const SDNA_StructMember *member) | |||||
| { | |||||
| const char *member_name = sdna->names[member->name]; | |||||
| if (ispointer(member_name)) { | |||||
| return STRUCT_MEMBER_CATEGORY_POINTER; | |||||
| } | |||||
| const char *member_type_name = sdna->types[member->type]; | |||||
| if (DNA_struct_find(sdna, member_type_name)) { | |||||
| return STRUCT_MEMBER_CATEGORY_STRUCT; | |||||
| } | |||||
| return STRUCT_MEMBER_CATEGORY_PRIMITIVE; | |||||
| } | |||||
| static int get_member_size_in_bytes(const SDNA *sdna, const SDNA_StructMember *member) | |||||
| { | |||||
| const char *name = sdna->names[member->name]; | |||||
| const int array_length = sdna->names_array_len[member->name]; | |||||
| if (ispointer(name)) { | |||||
| return sdna->pointer_size * array_length; | |||||
| } | |||||
| const int type_size = sdna->types_size[member->type]; | |||||
| return type_size * array_length; | |||||
| } | |||||
| /** Finds a member in the given struct with the given name. */ | /** Finds a member in the given struct with the given name. */ | ||||
| static const SDNA_StructMember *find_member_with_matching_name(const SDNA *sdna, | static const SDNA_StructMember *find_member_with_matching_name(const SDNA *sdna, | ||||
| const SDNA_Struct *struct_info, | const SDNA_Struct *struct_info, | ||||
| const char *name, | const char *name, | ||||
| int *r_offset) | int *r_offset) | ||||
| { | { | ||||
| int offset = 0; | int offset = 0; | ||||
| for (int a = 0; a < struct_info->members_len; a++) { | for (int a = 0; a < struct_info->members_len; a++) { | ||||
| ▲ Show 20 Lines • Show All 661 Lines • Show Last 20 Lines | |||||
Here we were switching 8 byte pointers only, which I found confusing.