Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenloader/intern/readfile.c
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
| Show First 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | |||||
| #include "BLT_translation.h" | #include "BLT_translation.h" | ||||
| #include "BKE_action.h" | #include "BKE_action.h" | ||||
| #include "BKE_armature.h" | #include "BKE_armature.h" | ||||
| #include "BKE_brush.h" | #include "BKE_brush.h" | ||||
| #include "BKE_cachefile.h" | #include "BKE_cachefile.h" | ||||
| #include "BKE_cloth.h" | #include "BKE_cloth.h" | ||||
| #include "BKE_collection.h" | |||||
| #include "BKE_constraint.h" | #include "BKE_constraint.h" | ||||
| #include "BKE_context.h" | #include "BKE_context.h" | ||||
| #include "BKE_curve.h" | #include "BKE_curve.h" | ||||
| #include "BKE_effect.h" | #include "BKE_effect.h" | ||||
| #include "BKE_fcurve.h" | #include "BKE_fcurve.h" | ||||
| #include "BKE_global.h" // for G | #include "BKE_global.h" // for G | ||||
| #include "BKE_group.h" | |||||
| #include "BKE_layer.h" | #include "BKE_layer.h" | ||||
| #include "BKE_library.h" // for which_libbase | #include "BKE_library.h" // for which_libbase | ||||
| #include "BKE_library_idmap.h" | #include "BKE_library_idmap.h" | ||||
| #include "BKE_library_override.h" | #include "BKE_library_override.h" | ||||
| #include "BKE_library_query.h" | #include "BKE_library_query.h" | ||||
| #include "BKE_idcode.h" | #include "BKE_idcode.h" | ||||
| #include "BKE_idprop.h" | #include "BKE_idprop.h" | ||||
| #include "BKE_material.h" | #include "BKE_material.h" | ||||
| ▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | |||||
| } OldNewMap; | } OldNewMap; | ||||
| /* local prototypes */ | /* local prototypes */ | ||||
| static void *read_struct(FileData *fd, BHead *bh, const char *blockname); | static void *read_struct(FileData *fd, BHead *bh, const char *blockname); | ||||
| static void direct_link_modifiers(FileData *fd, ListBase *lb); | static void direct_link_modifiers(FileData *fd, ListBase *lb); | ||||
| static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name); | static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name); | ||||
| static BHead *find_bhead_from_idname(FileData *fd, const char *idname); | static BHead *find_bhead_from_idname(FileData *fd, const char *idname); | ||||
| #ifdef USE_COLLECTION_COMPAT_28 | |||||
| static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection *sc); | static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection *sc); | ||||
| static SceneCollection *get_scene_collection_active_or_create( | #endif | ||||
| struct Scene *scene, struct ViewLayer *view_layer, const int flag); | |||||
| /* this function ensures that reports are printed, | /* this function ensures that reports are printed, | ||||
| * in the case of libraray linking errors this is important! | * in the case of libraray linking errors this is important! | ||||
| * | * | ||||
| * bit kludge but better then doubling up on prints, | * bit kludge but better then doubling up on prints, | ||||
| * we could alternatively have a versions of a report function which forces printing - campbell | * we could alternatively have a versions of a report function which forces printing - campbell | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 5,061 Lines • ▼ Show 20 Lines | #endif | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void direct_link_object(FileData *fd, Object *ob) | static void direct_link_object(FileData *fd, Object *ob) | ||||
| { | { | ||||
| PartEff *paf; | PartEff *paf; | ||||
| /* weak weak... this was only meant as draw flag, now is used in give_base_to_objects too */ | |||||
| ob->flag &= ~OB_FROMGROUP; | |||||
| /* XXX This should not be needed - but seems like it can happen in some cases, so for now play safe... */ | /* XXX This should not be needed - but seems like it can happen in some cases, so for now play safe... */ | ||||
| ob->proxy_from = NULL; | ob->proxy_from = NULL; | ||||
| /* loading saved files with editmode enabled works, but for undo we like | /* loading saved files with editmode enabled works, but for undo we like | ||||
| * to stay in object mode during undo presses so keep editmode disabled. | * to stay in object mode during undo presses so keep editmode disabled. | ||||
| * | * | ||||
| * Also when linking in a file don't allow edit and pose modes. | * Also when linking in a file don't allow edit and pose modes. | ||||
| * See [#34776, #42780] for more information. | * See [#34776, #42780] for more information. | ||||
| ▲ Show 20 Lines • Show All 181 Lines • ▼ Show 20 Lines | // >>> XXX deprecated - old animation system | ||||
| } | } | ||||
| link_list(fd, &ob->lodlevels); | link_list(fd, &ob->lodlevels); | ||||
| ob->currentlod = ob->lodlevels.first; | ob->currentlod = ob->lodlevels.first; | ||||
| ob->preview = direct_link_preview_image(fd, ob->preview); | ob->preview = direct_link_preview_image(fd, ob->preview); | ||||
| } | } | ||||
| static void direct_link_view_settings(FileData *fd, ColorManagedViewSettings *view_settings) | |||||
| { | |||||
| view_settings->curve_mapping = newdataadr(fd, view_settings->curve_mapping); | |||||
| if (view_settings->curve_mapping) | |||||
| direct_link_curvemapping(fd, view_settings->curve_mapping); | |||||
| } | |||||
| /* ***************** READ VIEW LAYER *************** */ | |||||
| static void direct_link_layer_collections(FileData *fd, ListBase *lb, bool master) | |||||
| { | |||||
| link_list(fd, lb); | |||||
| for (LayerCollection *lc = lb->first; lc; lc = lc->next) { | |||||
| #ifdef USE_COLLECTION_COMPAT_28 | |||||
| lc->scene_collection = newdataadr(fd, lc->scene_collection); | |||||
| #endif | |||||
| /* Master collection is not a real datablock. */ | |||||
| if (master) { | |||||
| lc->collection = newdataadr(fd, lc->collection); | |||||
| } | |||||
| direct_link_layer_collections(fd, &lc->layer_collections, false); | |||||
| } | |||||
| } | |||||
| static void direct_link_view_layer(FileData *fd, ViewLayer *view_layer) | |||||
| { | |||||
| view_layer->stats = NULL; | |||||
| link_list(fd, &view_layer->object_bases); | |||||
| view_layer->basact = newdataadr(fd, view_layer->basact); | |||||
| direct_link_layer_collections(fd, &view_layer->layer_collections, true); | |||||
| view_layer->active_collection = newdataadr(fd, view_layer->active_collection); | |||||
| view_layer->id_properties = newdataadr(fd, view_layer->id_properties); | |||||
| IDP_DirectLinkGroup_OrFree(&view_layer->id_properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); | |||||
| link_list(fd, &(view_layer->freestyle_config.modules)); | |||||
| link_list(fd, &(view_layer->freestyle_config.linesets)); | |||||
| view_layer->properties_evaluated = NULL; | |||||
| BLI_listbase_clear(&view_layer->drawdata); | |||||
| view_layer->object_bases_array = NULL; | |||||
| view_layer->object_bases_hash = NULL; | |||||
| } | |||||
| static void lib_link_layer_collection(FileData *fd, Library *lib, LayerCollection *layer_collection, bool master) | |||||
| { | |||||
| /* Master collection is not a real datablock. */ | |||||
| if (!master) { | |||||
| layer_collection->collection = newlibadr(fd, lib, layer_collection->collection); | |||||
| } | |||||
| for (LayerCollection *layer_collection_nested = layer_collection->layer_collections.first; | |||||
| layer_collection_nested != NULL; | |||||
| layer_collection_nested = layer_collection_nested->next) | |||||
| { | |||||
| lib_link_layer_collection(fd, lib, layer_collection_nested, false); | |||||
| } | |||||
| } | |||||
| static void lib_link_view_layer(FileData *fd, Library *lib, ViewLayer *view_layer) | |||||
| { | |||||
| /* tag scene layer to update for collection tree evaluation */ | |||||
| view_layer->flag |= VIEW_LAYER_ENGINE_DIRTY; | |||||
| for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) { | |||||
| fmc->script = newlibadr(fd, lib, fmc->script); | |||||
| } | |||||
| for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) { | |||||
| fls->linestyle = newlibadr_us(fd, lib, fls->linestyle); | |||||
| fls->group = newlibadr_us(fd, lib, fls->group); | |||||
| } | |||||
| for (Base *base = view_layer->object_bases.first, *base_next = NULL; base; base = base_next) { | |||||
| base_next = base->next; | |||||
| /* we only bump the use count for the collection objects */ | |||||
| base->object = newlibadr(fd, lib, base->object); | |||||
| base->flag |= BASE_DIRTY_ENGINE_SETTINGS; | |||||
| if (base->object == NULL) { | |||||
| /* Free in case linked object got lost. */ | |||||
| BLI_freelinkN(&view_layer->object_bases, base); | |||||
| } | |||||
| } | |||||
| for (LayerCollection *layer_collection = view_layer->layer_collections.first; | |||||
| layer_collection != NULL; | |||||
| layer_collection = layer_collection->next) | |||||
| { | |||||
| lib_link_layer_collection(fd, lib, layer_collection, true); | |||||
| } | |||||
| IDP_LibLinkProperty(view_layer->id_properties, fd); | |||||
| } | |||||
| /* ***************** READ COLLECTION *************** */ | |||||
| #ifdef USE_COLLECTION_COMPAT_28 | |||||
| static void direct_link_scene_collection(FileData *fd, SceneCollection *sc) | |||||
| { | |||||
| link_list(fd, &sc->objects); | |||||
| link_list(fd, &sc->scene_collections); | |||||
| for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { | |||||
| direct_link_scene_collection(fd, nsc); | |||||
| } | |||||
| } | |||||
| static void lib_link_scene_collection(FileData *fd, Library *lib, SceneCollection *sc) | |||||
| { | |||||
| for (LinkData *link = sc->objects.first; link; link = link->next) { | |||||
| link->data = newlibadr_us(fd, lib, link->data); | |||||
| BLI_assert(link->data); | |||||
| } | |||||
| for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { | |||||
| lib_link_scene_collection(fd, lib, nsc); | |||||
| } | |||||
| } | |||||
| #endif | |||||
| static void direct_link_collection(FileData *fd, Collection *collection) | |||||
| { | |||||
| link_list(fd, &collection->gobject); | |||||
| link_list(fd, &collection->children); | |||||
| collection->preview = direct_link_preview_image(fd, collection->preview); | |||||
| collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE; | |||||
| BLI_listbase_clear(&collection->object_cache); | |||||
| BLI_listbase_clear(&collection->parents); | |||||
| #ifdef USE_COLLECTION_COMPAT_28 | |||||
| /* This runs before the very first doversion. */ | |||||
| if (collection->collection != NULL) { | |||||
| collection->collection = newdataadr(fd, collection->collection); | |||||
| direct_link_scene_collection(fd, collection->collection); | |||||
| } | |||||
| if (collection->view_layer != NULL) { | |||||
| collection->view_layer = newdataadr(fd, collection->view_layer); | |||||
| direct_link_view_layer(fd, collection->view_layer); | |||||
| } | |||||
| #endif | |||||
| } | |||||
| static void lib_link_collection_data(FileData *fd, Library *lib, Collection *collection) | |||||
| { | |||||
| for (CollectionObject *cob = collection->gobject.first, *cob_next = NULL; cob; cob = cob_next) { | |||||
| cob_next = cob->next; | |||||
| cob->ob = newlibadr_us(fd, lib, cob->ob); | |||||
| if (cob->ob == NULL) { | |||||
| BLI_assert(!"Collection linked object got lost"); // TODO: remove, only for testing now | |||||
| BLI_freelinkN(&collection->gobject, cob); | |||||
| } | |||||
| } | |||||
| for (CollectionChild *child = collection->children.first, *child_next = NULL; child; child = child_next) { | |||||
| child_next = child->next; | |||||
| child->collection = newlibadr_us(fd, lib, child->collection); | |||||
| if (child->collection == NULL || | |||||
| BKE_collection_find_cycle(collection, child->collection)) | |||||
| { | |||||
| BLI_assert(!"Collection child got lost"); // TODO: remove, only for testing now | |||||
| BLI_freelinkN(&collection->children, child); | |||||
| } | |||||
| else { | |||||
| CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), "CollectionParent"); | |||||
| cparent->collection = collection; | |||||
| BLI_addtail(&child->collection->parents, cparent); | |||||
| } | |||||
| } | |||||
| } | |||||
| static void lib_link_collection(FileData *fd, Main *main) | |||||
| { | |||||
| for (Collection *collection = main->collection.first; collection; collection = collection->id.next) { | |||||
| if (collection->id.tag & LIB_TAG_NEED_LINK) { | |||||
| collection->id.tag &= ~LIB_TAG_NEED_LINK; | |||||
| IDP_LibLinkProperty(collection->id.properties, fd); | |||||
| #ifdef USE_COLLECTION_COMPAT_28 | |||||
| if (collection->collection) { | |||||
| lib_link_scene_collection(fd, collection->id.lib, collection->collection); | |||||
| } | |||||
| if (collection->view_layer) { | |||||
| lib_link_view_layer(fd, collection->id.lib, collection->view_layer); | |||||
| } | |||||
| #endif | |||||
| lib_link_collection_data(fd, collection->id.lib, collection); | |||||
| } | |||||
| } | |||||
| } | |||||
| /* ************ READ SCENE ***************** */ | /* ************ READ SCENE ***************** */ | ||||
| /* patch for missing scene IDs, can't be in do-versions */ | /* patch for missing scene IDs, can't be in do-versions */ | ||||
| static void composite_patch(bNodeTree *ntree, Scene *scene) | static void composite_patch(bNodeTree *ntree, Scene *scene) | ||||
| { | { | ||||
| bNode *node; | bNode *node; | ||||
| for (node = ntree->nodes.first; node; node = node->next) { | for (node = ntree->nodes.first; node; node = node->next) { | ||||
| ▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | if (a > totscene) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| #endif | #endif | ||||
| static void lib_link_scene_collection(FileData *fd, Library *lib, SceneCollection *sc) | |||||
| { | |||||
| for (LinkData *link = sc->objects.first; link; link = link->next) { | |||||
| link->data = newlibadr_us(fd, lib, link->data); | |||||
| BLI_assert(link->data); | |||||
| } | |||||
| for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { | |||||
| lib_link_scene_collection(fd, lib, nsc); | |||||
| } | |||||
| } | |||||
| static void lib_link_view_layer(FileData *fd, Library *lib, ViewLayer *view_layer) | |||||
| { | |||||
| /* tag scene layer to update for collection tree evaluation */ | |||||
| view_layer->flag |= VIEW_LAYER_ENGINE_DIRTY; | |||||
| for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) { | |||||
| fmc->script = newlibadr(fd, lib, fmc->script); | |||||
| } | |||||
| for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) { | |||||
| fls->linestyle = newlibadr_us(fd, lib, fls->linestyle); | |||||
| fls->group = newlibadr_us(fd, lib, fls->group); | |||||
| } | |||||
| for (Base *base = view_layer->object_bases.first; base; base = base->next) { | |||||
| /* we only bump the use count for the collection objects */ | |||||
| base->object = newlibadr(fd, lib, base->object); | |||||
| base->flag |= BASE_DIRTY_ENGINE_SETTINGS; | |||||
| } | |||||
| IDP_LibLinkProperty(view_layer->id_properties, fd); | |||||
| } | |||||
| static void lib_link_scene(FileData *fd, Main *main) | static void lib_link_scene(FileData *fd, Main *main) | ||||
| { | { | ||||
| #ifdef USE_SETSCENE_CHECK | #ifdef USE_SETSCENE_CHECK | ||||
| bool need_check_set = false; | bool need_check_set = false; | ||||
| int totscene = 0; | int totscene = 0; | ||||
| #endif | #endif | ||||
| for (Scene *sce = main->scene.first; sce; sce = sce->id.next) { | for (Scene *sce = main->scene.first; sce; sce = sce->id.next) { | ||||
| ▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | if (sce->id.tag & LIB_TAG_NEED_LINK) { | ||||
| marker->camera = newlibadr(fd, sce->id.lib, marker->camera); | marker->camera = newlibadr(fd, sce->id.lib, marker->camera); | ||||
| } | } | ||||
| } | } | ||||
| BKE_sequencer_update_muting(sce->ed); | BKE_sequencer_update_muting(sce->ed); | ||||
| BKE_sequencer_update_sound_bounds_all(sce); | BKE_sequencer_update_sound_bounds_all(sce); | ||||
| /* rigidbody world relies on it's linked groups */ | /* rigidbody world relies on it's linked collections */ | ||||
| if (sce->rigidbody_world) { | if (sce->rigidbody_world) { | ||||
| RigidBodyWorld *rbw = sce->rigidbody_world; | RigidBodyWorld *rbw = sce->rigidbody_world; | ||||
| if (rbw->group) | if (rbw->group) | ||||
| rbw->group = newlibadr(fd, sce->id.lib, rbw->group); | rbw->group = newlibadr(fd, sce->id.lib, rbw->group); | ||||
| if (rbw->constraints) | if (rbw->constraints) | ||||
| rbw->constraints = newlibadr(fd, sce->id.lib, rbw->constraints); | rbw->constraints = newlibadr(fd, sce->id.lib, rbw->constraints); | ||||
| if (rbw->effector_weights) | if (rbw->effector_weights) | ||||
| rbw->effector_weights->group = newlibadr(fd, sce->id.lib, rbw->effector_weights->group); | rbw->effector_weights->group = newlibadr(fd, sce->id.lib, rbw->effector_weights->group); | ||||
| Show All 13 Lines | if (sce->id.tag & LIB_TAG_NEED_LINK) { | ||||
| for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { | for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { | ||||
| fls->linestyle = newlibadr_us(fd, sce->id.lib, fls->linestyle); | fls->linestyle = newlibadr_us(fd, sce->id.lib, fls->linestyle); | ||||
| fls->group = newlibadr_us(fd, sce->id.lib, fls->group); | fls->group = newlibadr_us(fd, sce->id.lib, fls->group); | ||||
| } | } | ||||
| } | } | ||||
| /* Motion Tracking */ | /* Motion Tracking */ | ||||
| sce->clip = newlibadr_us(fd, sce->id.lib, sce->clip); | sce->clip = newlibadr_us(fd, sce->id.lib, sce->clip); | ||||
| #ifdef USE_COLLECTION_COMPAT_28 | |||||
| if (sce->collection) { | |||||
| lib_link_scene_collection(fd, sce->id.lib, sce->collection); | lib_link_scene_collection(fd, sce->id.lib, sce->collection); | ||||
| } | |||||
| #endif | |||||
| if (sce->master_collection) { | |||||
| lib_link_collection_data(fd, sce->id.lib, sce->master_collection); | |||||
| } | |||||
| for (ViewLayer *view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) { | for (ViewLayer *view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) { | ||||
| lib_link_view_layer(fd, sce->id.lib, view_layer); | lib_link_view_layer(fd, sce->id.lib, view_layer); | ||||
| } | } | ||||
| #ifdef USE_SETSCENE_CHECK | #ifdef USE_SETSCENE_CHECK | ||||
| if (sce->set != NULL) { | if (sce->set != NULL) { | ||||
| /* link flag for scenes with set would be reset later, | /* link flag for scenes with set would be reset later, | ||||
| ▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | for (smd = lb->first; smd; smd = smd->next) { | ||||
| else if (smd->type == seqModifierType_HueCorrect) { | else if (smd->type == seqModifierType_HueCorrect) { | ||||
| HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd; | HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd; | ||||
| direct_link_curvemapping(fd, &hcmd->curve_mapping); | direct_link_curvemapping(fd, &hcmd->curve_mapping); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void direct_link_view_settings(FileData *fd, ColorManagedViewSettings *view_settings) | |||||
| { | |||||
| view_settings->curve_mapping = newdataadr(fd, view_settings->curve_mapping); | |||||
| if (view_settings->curve_mapping) | |||||
| direct_link_curvemapping(fd, view_settings->curve_mapping); | |||||
| } | |||||
| static void direct_link_scene_collection(FileData *fd, SceneCollection *sc) | |||||
| { | |||||
| link_list(fd, &sc->objects); | |||||
| link_list(fd, &sc->scene_collections); | |||||
| for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { | |||||
| direct_link_scene_collection(fd, nsc); | |||||
| } | |||||
| } | |||||
| static void direct_link_layer_collections(FileData *fd, ListBase *lb) | |||||
| { | |||||
| link_list(fd, lb); | |||||
| for (LayerCollection *lc = lb->first; lc; lc = lc->next) { | |||||
| lc->scene_collection = newdataadr(fd, lc->scene_collection); | |||||
| link_list(fd, &lc->object_bases); | |||||
| for (LinkData *link = lc->object_bases.first; link; link = link->next) { | |||||
| link->data = newdataadr(fd, link->data); | |||||
| } | |||||
| direct_link_layer_collections(fd, &lc->layer_collections); | |||||
| } | |||||
| } | |||||
| static void direct_link_view_layer(FileData *fd, ViewLayer *view_layer) | |||||
| { | |||||
| view_layer->stats = NULL; | |||||
| link_list(fd, &view_layer->object_bases); | |||||
| view_layer->basact = newdataadr(fd, view_layer->basact); | |||||
| direct_link_layer_collections(fd, &view_layer->layer_collections); | |||||
| view_layer->id_properties = newdataadr(fd, view_layer->id_properties); | |||||
| IDP_DirectLinkGroup_OrFree(&view_layer->id_properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); | |||||
| link_list(fd, &(view_layer->freestyle_config.modules)); | |||||
| link_list(fd, &(view_layer->freestyle_config.linesets)); | |||||
| view_layer->properties_evaluated = NULL; | |||||
| BLI_listbase_clear(&view_layer->drawdata); | |||||
| view_layer->object_bases_array = NULL; | |||||
| } | |||||
| /** | /** | ||||
| * Workspaces store a render layer pointer which can only be read after scene is read. | * Workspaces store a render layer pointer which can only be read after scene is read. | ||||
| */ | */ | ||||
| static void direct_link_workspace_link_scene_data( | static void direct_link_workspace_link_scene_data( | ||||
| FileData *fd, Scene *scene, const ListBase *workspaces) | FileData *fd, Scene *scene, const ListBase *workspaces) | ||||
| { | { | ||||
| for (WorkSpace *workspace = workspaces->first; workspace; workspace = workspace->id.next) { | for (WorkSpace *workspace = workspaces->first; workspace; workspace = workspace->id.next) { | ||||
| for (WorkSpaceDataRelation *relation = workspace->scene_viewlayer_relations.first; | for (WorkSpaceDataRelation *relation = workspace->scene_viewlayer_relations.first; | ||||
| ▲ Show 20 Lines • Show All 258 Lines • ▼ Show 20 Lines | if (rbw->pointcache) { | ||||
| rbw->ltime = (float)rbw->pointcache->startframe; | rbw->ltime = (float)rbw->pointcache->startframe; | ||||
| } | } | ||||
| } | } | ||||
| sce->preview = direct_link_preview_image(fd, sce->preview); | sce->preview = direct_link_preview_image(fd, sce->preview); | ||||
| direct_link_curvemapping(fd, &sce->r.mblur_shutter_curve); | direct_link_curvemapping(fd, &sce->r.mblur_shutter_curve); | ||||
| #ifdef USE_COLLECTION_COMPAT_28 | |||||
| /* this runs before the very first doversion */ | /* this runs before the very first doversion */ | ||||
| if (sce->collection) { | if (sce->collection) { | ||||
| sce->collection = newdataadr(fd, sce->collection); | sce->collection = newdataadr(fd, sce->collection); | ||||
| direct_link_scene_collection(fd, sce->collection); | direct_link_scene_collection(fd, sce->collection); | ||||
| } | } | ||||
| #endif | |||||
| if (sce->master_collection) { | |||||
| sce->master_collection = newdataadr(fd, sce->master_collection); | |||||
| direct_link_collection(fd, sce->master_collection); | |||||
| } | |||||
| /* insert into global old-new map for reading without UI (link_global accesses it again) */ | /* insert into global old-new map for reading without UI (link_global accesses it again) */ | ||||
| link_glob_list(fd, &sce->view_layers); | link_glob_list(fd, &sce->view_layers); | ||||
| for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) { | for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) { | ||||
| direct_link_view_layer(fd, view_layer); | direct_link_view_layer(fd, view_layer); | ||||
| } | } | ||||
| sce->collection_properties = newdataadr(fd, sce->collection_properties); | sce->collection_properties = newdataadr(fd, sce->collection_properties); | ||||
| ▲ Show 20 Lines • Show All 1,330 Lines • ▼ Show 20 Lines | if (sound->id.tag & LIB_TAG_NEED_LINK) { | ||||
| sound->ipo = newlibadr_us(fd, sound->id.lib, sound->ipo); // XXX deprecated - old animation system | sound->ipo = newlibadr_us(fd, sound->id.lib, sound->ipo); // XXX deprecated - old animation system | ||||
| BKE_sound_load(main, sound); | BKE_sound_load(main, sound); | ||||
| sound->id.tag &= ~LIB_TAG_NEED_LINK; | sound->id.tag &= ~LIB_TAG_NEED_LINK; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* ***************** READ GROUP *************** */ | |||||
| static void direct_link_group(FileData *fd, Group *group) | |||||
| { | |||||
| link_list(fd, &group->gobject); | |||||
| group->preview = direct_link_preview_image(fd, group->preview); | |||||
| /* This runs before the very first doversion. */ | |||||
| if (group->collection != NULL) { | |||||
| group->collection = newdataadr(fd, group->collection); | |||||
| direct_link_scene_collection(fd, group->collection); | |||||
| } | |||||
| if (group->view_layer != NULL) { | |||||
| group->view_layer = newdataadr(fd, group->view_layer); | |||||
| direct_link_view_layer(fd, group->view_layer); | |||||
| } | |||||
| } | |||||
| static void lib_link_group(FileData *fd, Main *main) | |||||
| { | |||||
| for (Group *group = main->group.first; group; group = group->id.next) { | |||||
| if (group->id.tag & LIB_TAG_NEED_LINK) { | |||||
| group->id.tag &= ~LIB_TAG_NEED_LINK; | |||||
| IDP_LibLinkProperty(group->id.properties, fd); | |||||
| if (group->view_layer == NULL) { | |||||
| /* Old file, this is required for doversion. */ | |||||
| bool add_us = false; | |||||
| GroupObject *go, *gon; | |||||
| go = group->gobject.first; | |||||
| while (go) { | |||||
| gon = go->next; | |||||
| go->ob = newlibadr_real_us(fd, group->id.lib, go->ob); | |||||
| if (go->ob != NULL) { | |||||
| go->ob->flag |= OB_FROMGROUP; | |||||
| /* If group has an object, it increments user... */ | |||||
| add_us = true; | |||||
| } | |||||
| else { | |||||
| /* Remove NULL objects. */ | |||||
| BLI_remlink(&group->gobject, go); | |||||
| MEM_freeN(go); | |||||
| } | |||||
| go = gon; | |||||
| } | |||||
| if (add_us) { | |||||
| id_us_ensure_real(&group->id); | |||||
| } | |||||
| /* The rest of the read code is only for new files, skip it. */ | |||||
| continue; | |||||
| } | |||||
| lib_link_scene_collection(fd, group->id.lib, group->collection); | |||||
| lib_link_view_layer(fd, group->id.lib, group->view_layer); | |||||
| if (!BLI_listbase_is_empty(&group->view_layer->object_bases)) { | |||||
| id_us_ensure_real(&group->id); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /* ***************** READ MOVIECLIP *************** */ | /* ***************** READ MOVIECLIP *************** */ | ||||
| static void direct_link_movieReconstruction(FileData *fd, MovieTrackingReconstruction *reconstruction) | static void direct_link_movieReconstruction(FileData *fd, MovieTrackingReconstruction *reconstruction) | ||||
| { | { | ||||
| reconstruction->cameras = newdataadr(fd, reconstruction->cameras); | reconstruction->cameras = newdataadr(fd, reconstruction->cameras); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 721 Lines • ▼ Show 20 Lines | case ID_SPK: | ||||
| break; | break; | ||||
| case ID_SO: | case ID_SO: | ||||
| direct_link_sound(fd, (bSound *)id); | direct_link_sound(fd, (bSound *)id); | ||||
| break; | break; | ||||
| case ID_LP: | case ID_LP: | ||||
| direct_link_lightprobe(fd, (LightProbe *)id); | direct_link_lightprobe(fd, (LightProbe *)id); | ||||
| break; | break; | ||||
| case ID_GR: | case ID_GR: | ||||
| direct_link_group(fd, (Group *)id); | direct_link_collection(fd, (Collection *)id); | ||||
| break; | break; | ||||
| case ID_AR: | case ID_AR: | ||||
| direct_link_armature(fd, (bArmature*)id); | direct_link_armature(fd, (bArmature*)id); | ||||
| break; | break; | ||||
| case ID_AC: | case ID_AC: | ||||
| direct_link_action(fd, (bAction*)id); | direct_link_action(fd, (bAction*)id); | ||||
| break; | break; | ||||
| case ID_NT: | case ID_NT: | ||||
| ▲ Show 20 Lines • Show All 191 Lines • ▼ Show 20 Lines | static void lib_link_all(FileData *fd, Main *main) | ||||
| lib_link_world(fd, main); | lib_link_world(fd, main); | ||||
| lib_link_lamp(fd, main); | lib_link_lamp(fd, main); | ||||
| lib_link_latt(fd, main); | lib_link_latt(fd, main); | ||||
| lib_link_text(fd, main); | lib_link_text(fd, main); | ||||
| lib_link_camera(fd, main); | lib_link_camera(fd, main); | ||||
| lib_link_speaker(fd, main); | lib_link_speaker(fd, main); | ||||
| lib_link_lightprobe(fd, main); | lib_link_lightprobe(fd, main); | ||||
| lib_link_sound(fd, main); | lib_link_sound(fd, main); | ||||
| lib_link_group(fd, main); | lib_link_collection(fd, main); | ||||
| lib_link_armature(fd, main); | lib_link_armature(fd, main); | ||||
| lib_link_action(fd, main); | lib_link_action(fd, main); | ||||
| lib_link_vfont(fd, main); | lib_link_vfont(fd, main); | ||||
| lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */ | lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */ | ||||
| lib_link_brush(fd, main); | lib_link_brush(fd, main); | ||||
| lib_link_palette(fd, main); | lib_link_palette(fd, main); | ||||
| lib_link_paint_curve(fd, main); | lib_link_paint_curve(fd, main); | ||||
| lib_link_particlesettings(fd, main); | lib_link_particlesettings(fd, main); | ||||
| ▲ Show 20 Lines • Show All 194 Lines • ▼ Show 20 Lines | BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) | ||||
| } | } | ||||
| BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false); | BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false); | ||||
| /* Now that all our data-blocks are loaded, we can re-generate overrides from their references. */ | /* Now that all our data-blocks are loaded, we can re-generate overrides from their references. */ | ||||
| if (fd->memfile == NULL) { | if (fd->memfile == NULL) { | ||||
| /* Do not apply in undo case! */ | /* Do not apply in undo case! */ | ||||
| BKE_main_override_static_update(bfd->main); | BKE_main_override_static_update(bfd->main); | ||||
| BKE_collections_after_lib_link(bfd->main); | |||||
| } | } | ||||
| lib_verify_nodetree(bfd->main, true); | lib_verify_nodetree(bfd->main, true); | ||||
| fix_relpaths_library(fd->relabase, bfd->main); /* make all relative paths, relative to the open blend file */ | fix_relpaths_library(fd->relabase, bfd->main); /* make all relative paths, relative to the open blend file */ | ||||
| link_global(fd, bfd); /* as last */ | link_global(fd, bfd); /* as last */ | ||||
| fd->mainlist = NULL; /* Safety, this is local variable, shall not be used afterward. */ | fd->mainlist = NULL; /* Safety, this is local variable, shall not be used afterward. */ | ||||
| ▲ Show 20 Lines • Show All 417 Lines • ▼ Show 20 Lines | for (state = part->boids->states.first; state; state = state->next) { | ||||
| BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule; | BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule; | ||||
| expand_doit(fd, mainvar, flbr->ob); | expand_doit(fd, mainvar, flbr->ob); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void expand_group(FileData *fd, Main *mainvar, Group *group) | static void expand_collection(FileData *fd, Main *mainvar, Collection *collection) | ||||
| { | { | ||||
| GroupObject *go; | for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) { | ||||
| expand_doit(fd, mainvar, cob->ob); | |||||
| for (go = group->gobject.first; go; go = go->next) { | |||||
| expand_doit(fd, mainvar, go->ob); | |||||
| } | } | ||||
| if (group->collection != NULL) { | for (CollectionChild *child = collection->children.first; child; child = child->next) { | ||||
| expand_scene_collection(fd, mainvar, group->collection); | expand_doit(fd, mainvar, child->collection); | ||||
| } | } | ||||
| #ifdef USE_COLLECTION_COMPAT_28 | |||||
| if (collection->collection != NULL) { | |||||
| expand_scene_collection(fd, mainvar, collection->collection); | |||||
| } | |||||
| #endif | |||||
| } | } | ||||
| static void expand_key(FileData *fd, Main *mainvar, Key *key) | static void expand_key(FileData *fd, Main *mainvar, Key *key) | ||||
| { | { | ||||
| expand_doit(fd, mainvar, key->ipo); // XXX deprecated - old animation system | expand_doit(fd, mainvar, key->ipo); // XXX deprecated - old animation system | ||||
| if (key->adt) | if (key->adt) | ||||
| expand_animdata(fd, mainvar, key->adt); | expand_animdata(fd, mainvar, key->adt); | ||||
| ▲ Show 20 Lines • Show All 296 Lines • ▼ Show 20 Lines | // XXX deprecated - old animation system (for version patching only) | ||||
| if (ob->currentlod) { | if (ob->currentlod) { | ||||
| LodLevel *level; | LodLevel *level; | ||||
| for (level = ob->lodlevels.first; level; level = level->next) { | for (level = ob->lodlevels.first; level; level = level->next) { | ||||
| expand_doit(fd, mainvar, level->source); | expand_doit(fd, mainvar, level->source); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #ifdef USE_COLLECTION_COMPAT_28 | |||||
| static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection *sc) | static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection *sc) | ||||
| { | { | ||||
| for (LinkData *link = sc->objects.first; link; link = link->next) { | for (LinkData *link = sc->objects.first; link; link = link->next) { | ||||
| expand_doit(fd, mainvar, link->data); | expand_doit(fd, mainvar, link->data); | ||||
| } | } | ||||
| for (SceneCollection *nsc= sc->scene_collections.first; nsc; nsc = nsc->next) { | for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { | ||||
| expand_scene_collection(fd, mainvar, nsc); | expand_scene_collection(fd, mainvar, nsc); | ||||
| } | } | ||||
| } | } | ||||
| #endif | |||||
| static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) | static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) | ||||
| { | { | ||||
| SceneRenderLayer *srl; | SceneRenderLayer *srl; | ||||
| FreestyleModuleConfig *module; | FreestyleModuleConfig *module; | ||||
| FreestyleLineSet *lineset; | FreestyleLineSet *lineset; | ||||
| for (Base *base_legacy = sce->base.first; base_legacy; base_legacy = base_legacy->next) { | for (Base *base_legacy = sce->base.first; base_legacy; base_legacy = base_legacy->next) { | ||||
| ▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) | ||||
| for (TimeMarker *marker = sce->markers.first; marker; marker = marker->next) { | for (TimeMarker *marker = sce->markers.first; marker; marker = marker->next) { | ||||
| if (marker->camera) { | if (marker->camera) { | ||||
| expand_doit(fd, mainvar, marker->camera); | expand_doit(fd, mainvar, marker->camera); | ||||
| } | } | ||||
| } | } | ||||
| expand_doit(fd, mainvar, sce->clip); | expand_doit(fd, mainvar, sce->clip); | ||||
| #ifdef USE_COLLECTION_COMPAT_28 | |||||
| if (sce->collection) { | |||||
| expand_scene_collection(fd, mainvar, sce->collection); | expand_scene_collection(fd, mainvar, sce->collection); | ||||
| } | } | ||||
| #endif | |||||
| if (sce->master_collection) { | |||||
| expand_collection(fd, mainvar, sce->master_collection); | |||||
| } | |||||
| } | |||||
| static void expand_camera(FileData *fd, Main *mainvar, Camera *ca) | static void expand_camera(FileData *fd, Main *mainvar, Camera *ca) | ||||
| { | { | ||||
| expand_doit(fd, mainvar, ca->ipo); // XXX deprecated - old animation system | expand_doit(fd, mainvar, ca->ipo); // XXX deprecated - old animation system | ||||
| if (ca->adt) | if (ca->adt) | ||||
| expand_animdata(fd, mainvar, ca->adt); | expand_animdata(fd, mainvar, ca->adt); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 189 Lines • ▼ Show 20 Lines | while (a--) { | ||||
| break; | break; | ||||
| case ID_AR: | case ID_AR: | ||||
| expand_armature(fd, mainvar, (bArmature *)id); | expand_armature(fd, mainvar, (bArmature *)id); | ||||
| break; | break; | ||||
| case ID_AC: | case ID_AC: | ||||
| expand_action(fd, mainvar, (bAction *)id); // XXX deprecated - old animation system | expand_action(fd, mainvar, (bAction *)id); // XXX deprecated - old animation system | ||||
| break; | break; | ||||
| case ID_GR: | case ID_GR: | ||||
| expand_group(fd, mainvar, (Group *)id); | expand_collection(fd, mainvar, (Collection *)id); | ||||
| break; | break; | ||||
| case ID_NT: | case ID_NT: | ||||
| expand_nodetree(fd, mainvar, (bNodeTree *)id); | expand_nodetree(fd, mainvar, (bNodeTree *)id); | ||||
| break; | break; | ||||
| case ID_BR: | case ID_BR: | ||||
| expand_brush(fd, mainvar, (Brush *)id); | expand_brush(fd, mainvar, (Brush *)id); | ||||
| break; | break; | ||||
| case ID_IP: | case ID_IP: | ||||
| Show All 31 Lines | while (a--) { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* ***************************** */ | /* ***************************** */ | ||||
| static bool object_in_any_scene(Main *mainvar, Object *ob) | static bool object_in_any_scene(Main *bmain, Object *ob) | ||||
| { | { | ||||
| Scene *sce; | Scene *sce; | ||||
| for (sce = mainvar->scene.first; sce; sce = sce->id.next) { | for (sce = bmain->scene.first; sce; sce = sce->id.next) { | ||||
| if (BKE_scene_object_find(sce, ob)) { | if (BKE_scene_object_find(sce, ob)) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| static void give_base_to_objects( | static Collection *get_collection_active( | ||||
| Main *mainvar, Scene *scene, ViewLayer *view_layer, Library *lib, const short flag) | Main *bmain, Scene *scene, ViewLayer *view_layer, const int flag) | ||||
| { | |||||
| if (flag & FILE_ACTIVE_COLLECTION) { | |||||
| LayerCollection *lc = BKE_layer_collection_get_active(view_layer); | |||||
| return lc->collection; | |||||
| } | |||||
| else { | |||||
| return BKE_collection_add(bmain, scene->master_collection, NULL); | |||||
| } | |||||
| } | |||||
| static void add_loose_objects_to_scene( | |||||
| Main *mainvar, Main *bmain, Scene *scene, ViewLayer *view_layer, Library *lib, const short flag) | |||||
| { | { | ||||
| Object *ob; | |||||
| Base *base; | |||||
| SceneCollection *scene_collection = NULL; | |||||
| const bool is_link = (flag & FILE_LINK) != 0; | const bool is_link = (flag & FILE_LINK) != 0; | ||||
| BLI_assert(scene); | BLI_assert(scene); | ||||
| /* Give all objects which are LIB_TAG_INDIRECT a base, or for a group when *lib has been set. */ | /* Give all objects which are LIB_TAG_INDIRECT a base, or for a collection when *lib has been set. */ | ||||
| for (ob = mainvar->object.first; ob; ob = ob->id.next) { | for (Object *ob = mainvar->object.first; ob; ob = ob->id.next) { | ||||
| if ((ob->id.tag & LIB_TAG_INDIRECT) && (ob->id.tag & LIB_TAG_PRE_EXISTING) == 0) { | if ((ob->id.tag & LIB_TAG_INDIRECT) && (ob->id.tag & LIB_TAG_PRE_EXISTING) == 0) { | ||||
| bool do_it = false; | bool do_it = false; | ||||
| if (ob->id.us == 0) { | if (ob->id.us == 0) { | ||||
| do_it = true; | do_it = true; | ||||
| } | } | ||||
| else if (!is_link && (ob->id.lib == lib) && (object_in_any_scene(mainvar, ob) == 0)) { | else if (!is_link && (ob->id.lib == lib) && (object_in_any_scene(bmain, ob) == 0)) { | ||||
| /* When appending, make sure any indirectly loaded objects get a base, else they cant be accessed at all | /* When appending, make sure any indirectly loaded objects get a base, else they cant be accessed at all | ||||
| * (see T27437). */ | * (see T27437). */ | ||||
| do_it = true; | do_it = true; | ||||
| } | } | ||||
| if (do_it) { | if (do_it) { | ||||
| CLAMP_MIN(ob->id.us, 0); | CLAMP_MIN(ob->id.us, 0); | ||||
| if (scene_collection == NULL) { | Collection *active_collection = get_collection_active(bmain, scene, view_layer, FILE_ACTIVE_COLLECTION); | ||||
| scene_collection = get_scene_collection_active_or_create(scene, view_layer, FILE_ACTIVE_COLLECTION); | BKE_collection_object_add(bmain, active_collection, ob); | ||||
| } | Base *base = BKE_view_layer_base_find(view_layer, ob); | ||||
| BKE_collection_object_add(&scene->id, scene_collection, ob); | |||||
| base = BKE_view_layer_base_find(view_layer, ob); | |||||
| BKE_scene_object_base_flag_sync_from_base(base); | BKE_scene_object_base_flag_sync_from_base(base); | ||||
| if (flag & FILE_AUTOSELECT) { | if (flag & FILE_AUTOSELECT) { | ||||
| /* Note that link_object_postprocess() already checks for FILE_AUTOSELECT flag, | /* Note that link_object_postprocess() already checks for FILE_AUTOSELECT flag, | ||||
| * but it will miss objects from non-instantiated groups... */ | * but it will miss objects from non-instantiated collections... */ | ||||
| if (base->flag & BASE_SELECTABLED) { | if (base->flag & BASE_SELECTABLED) { | ||||
| base->flag |= BASE_SELECTED; | base->flag |= BASE_SELECTED; | ||||
| BKE_scene_object_base_flag_sync_from_base(base); | BKE_scene_object_base_flag_sync_from_base(base); | ||||
| } | } | ||||
| /* Do NOT make base active here! screws up GUI stuff, if you want it do it on src/ level. */ | /* Do NOT make base active here! screws up GUI stuff, if you want it do it on src/ level. */ | ||||
| } | } | ||||
| ob->id.tag &= ~LIB_TAG_INDIRECT; | ob->id.tag &= ~LIB_TAG_INDIRECT; | ||||
| ob->id.tag |= LIB_TAG_EXTERN; | ob->id.tag |= LIB_TAG_EXTERN; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void give_base_to_groups( | static void add_collections_to_scene( | ||||
| Main *mainvar, Scene *scene, ViewLayer *view_layer, Library *UNUSED(lib), const short UNUSED(flag)) | Main *mainvar, Main *bmain, Scene *scene, ViewLayer *view_layer, Library *UNUSED(lib), const short flag) | ||||
| { | { | ||||
| Group *group; | Collection *active_collection = get_collection_active(bmain, scene, view_layer, FILE_ACTIVE_COLLECTION); | ||||
| Base *base; | |||||
| Object *ob; | |||||
| SceneCollection *scene_collection; | |||||
| /* If the group is empty this function is not even called, so it's safe to ensure a collection at this point. */ | |||||
| scene_collection = get_scene_collection_active_or_create(scene, view_layer, FILE_ACTIVE_COLLECTION); | |||||
| /* Give all objects which are tagged a base. */ | /* Give all objects which are tagged a base. */ | ||||
| for (group = mainvar->group.first; group; group = group->id.next) { | for (Collection *collection = mainvar->collection.first; collection; collection = collection->id.next) { | ||||
| if (group->id.tag & LIB_TAG_DOIT) { | if (collection->id.tag & LIB_TAG_DOIT) { | ||||
| /* Any indirect group should not have been tagged. */ | if (flag & FILE_GROUP_INSTANCE) { | ||||
| BLI_assert((group->id.tag & LIB_TAG_INDIRECT) == 0); | /* Any indirect collection should not have been tagged. */ | ||||
| BLI_assert((collection->id.tag & LIB_TAG_INDIRECT) == 0); | |||||
| /* BKE_object_add(...) messes with the selection. */ | /* BKE_object_add(...) messes with the selection. */ | ||||
| ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name + 2); | Object *ob = BKE_object_add_only_object(bmain, OB_EMPTY, collection->id.name + 2); | ||||
| ob->type = OB_EMPTY; | ob->type = OB_EMPTY; | ||||
| BKE_collection_object_add(&scene->id, scene_collection, ob); | BKE_collection_object_add(bmain, active_collection, ob); | ||||
| base = BKE_view_layer_base_find(view_layer, ob); | Base *base = BKE_view_layer_base_find(view_layer, ob); | ||||
| if (base->flag & BASE_SELECTABLED) { | if (base->flag & BASE_SELECTABLED) { | ||||
| base->flag |= BASE_SELECTED; | base->flag |= BASE_SELECTED; | ||||
| } | } | ||||
| BKE_scene_object_base_flag_sync_from_base(base); | BKE_scene_object_base_flag_sync_from_base(base); | ||||
| DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); | DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); | ||||
| view_layer->basact = base; | view_layer->basact = base; | ||||
| /* Assign the group. */ | /* Assign the collection. */ | ||||
| ob->dup_group = group; | ob->dup_group = collection; | ||||
| ob->transflag |= OB_DUPLIGROUP; | ob->transflag |= OB_DUPLIGROUP; | ||||
| copy_v3_v3(ob->loc, scene->cursor.location); | copy_v3_v3(ob->loc, scene->cursor.location); | ||||
| } | } | ||||
| else { | |||||
| /* Add collection as child of active collection. */ | |||||
| BKE_collection_child_add(bmain, active_collection, collection); | |||||
| collection->id.tag &= ~LIB_TAG_INDIRECT; | |||||
| collection->id.tag |= LIB_TAG_EXTERN; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| static ID *create_placeholder(Main *mainvar, const short idcode, const char *idname, const short tag) | static ID *create_placeholder(Main *mainvar, const short idcode, const char *idname, const short tag) | ||||
| { | { | ||||
| ListBase *lb = which_libbase(mainvar, idcode); | ListBase *lb = which_libbase(mainvar, idcode); | ||||
| ID *ph_id = BKE_libblock_alloc_notest(idcode); | ID *ph_id = BKE_libblock_alloc_notest(idcode); | ||||
| ▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | static ID *link_named_part( | ||||
| } | } | ||||
| /* if we found the id but the id is NULL, this is really bad */ | /* if we found the id but the id is NULL, this is really bad */ | ||||
| BLI_assert(!((bhead != NULL) && (id == NULL))); | BLI_assert(!((bhead != NULL) && (id == NULL))); | ||||
| return id; | return id; | ||||
| } | } | ||||
| static SceneCollection *get_scene_collection_active_or_create( | static void link_object_postprocess(ID *id, Main *bmain, Scene *scene, ViewLayer *view_layer, const int flag) | ||||
| struct Scene *scene, struct ViewLayer *view_layer, const int flag) | |||||
| { | |||||
| LayerCollection *lc = NULL; | |||||
| if (flag & FILE_ACTIVE_COLLECTION) { | |||||
| lc = BKE_layer_collection_get_active_ensure(scene, view_layer); | |||||
| } | |||||
| else { | |||||
| SceneCollection *sc = BKE_collection_add(&scene->id, NULL, COLLECTION_TYPE_NONE, NULL); | |||||
| lc = BKE_collection_link(view_layer, sc); | |||||
| } | |||||
| return lc->scene_collection; | |||||
| } | |||||
| static void link_object_postprocess(ID *id, Scene *scene, ViewLayer *view_layer, const int flag) | |||||
| { | { | ||||
| if (scene) { | if (scene) { | ||||
| /* link to scene */ | /* link to scene */ | ||||
| Base *base; | Base *base; | ||||
| Object *ob; | Object *ob; | ||||
| SceneCollection *sc; | Collection *collection; | ||||
| ob = (Object *)id; | ob = (Object *)id; | ||||
| ob->mode = OB_MODE_OBJECT; | ob->mode = OB_MODE_OBJECT; | ||||
| sc = get_scene_collection_active_or_create(scene, view_layer, flag); | collection = get_collection_active(bmain, scene, view_layer, flag); | ||||
| BKE_collection_object_add(&scene->id, sc, ob); | BKE_collection_object_add(bmain, collection, ob); | ||||
| base = BKE_view_layer_base_find(view_layer, ob); | base = BKE_view_layer_base_find(view_layer, ob); | ||||
| BKE_scene_object_base_flag_sync_from_base(base); | BKE_scene_object_base_flag_sync_from_base(base); | ||||
| if (flag & FILE_AUTOSELECT) { | if (flag & FILE_AUTOSELECT) { | ||||
| if (base->flag & BASE_SELECTABLED) { | if (base->flag & BASE_SELECTABLED) { | ||||
| base->flag |= BASE_SELECTED; | base->flag |= BASE_SELECTED; | ||||
| BKE_scene_object_base_flag_sync_from_base(base); | BKE_scene_object_base_flag_sync_from_base(base); | ||||
| } | } | ||||
| Show All 21 Lines | for (bhead = blo_firstbhead(fd); bhead; bhead = blo_nextbhead(fd, bhead)) { | ||||
| if (id) { | if (id) { | ||||
| /* sort by name in list */ | /* sort by name in list */ | ||||
| ListBase *lb = which_libbase(mainl, GS(id->name)); | ListBase *lb = which_libbase(mainl, GS(id->name)); | ||||
| id_sort_by_name(lb, id); | id_sort_by_name(lb, id); | ||||
| if (bhead->code == ID_OB) { | if (bhead->code == ID_OB) { | ||||
| /* Instead of instancing Base's directly, postpone until after groups are loaded | /* Instead of instancing Base's directly, postpone until after collections are loaded | ||||
| * otherwise the base's flag is set incorrectly when groups are used */ | * otherwise the base's flag is set incorrectly when collections are used */ | ||||
| Object *ob = (Object *)id; | Object *ob = (Object *)id; | ||||
| ob->mode = OB_MODE_OBJECT; | ob->mode = OB_MODE_OBJECT; | ||||
| /* ensure give_base_to_objects runs on this object */ | /* ensure add_loose_objects_to_scene runs on this object */ | ||||
| BLI_assert(id->us == 0); | BLI_assert(id->us == 0); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static ID *link_named_part_ex( | static ID *link_named_part_ex( | ||||
| Main *mainl, FileData *fd, const short idcode, const char *name, const int flag, | Main *mainl, FileData *fd, const short idcode, const char *name, const int flag, | ||||
| Scene *scene, ViewLayer *view_layer) | Main *bmain, Scene *scene, ViewLayer *view_layer) | ||||
| { | { | ||||
| ID *id = link_named_part(mainl, fd, idcode, name, flag); | ID *id = link_named_part(mainl, fd, idcode, name, flag); | ||||
| if (id && (GS(id->name) == ID_OB)) { /* loose object: give a base */ | if (id && (GS(id->name) == ID_OB)) { /* loose object: give a base */ | ||||
| link_object_postprocess(id, scene, view_layer, flag); | link_object_postprocess(id, bmain, scene, view_layer, flag); | ||||
| } | } | ||||
| else if (id && (GS(id->name) == ID_GR)) { | else if (id && (GS(id->name) == ID_GR)) { | ||||
| /* tag as needing to be instantiated */ | /* tag as needing to be instantiated or linked */ | ||||
| if (flag & FILE_GROUP_INSTANCE) | |||||
| id->tag |= LIB_TAG_DOIT; | id->tag |= LIB_TAG_DOIT; | ||||
| } | } | ||||
| return id; | return id; | ||||
| } | } | ||||
| /** | /** | ||||
| * Link a named datablock from an external blend file. | * Link a named datablock from an external blend file. | ||||
| * | * | ||||
| * \param mainl The main database to link from (not the active one). | * \param mainl The main database to link from (not the active one). | ||||
| * \param bh The blender file handle. | * \param bh The blender file handle. | ||||
| * \param idcode The kind of datablock to link. | * \param idcode The kind of datablock to link. | ||||
| * \param name The name of the datablock (without the 2 char ID prefix). | * \param name The name of the datablock (without the 2 char ID prefix). | ||||
| * \return the linked ID when found. | * \return the linked ID when found. | ||||
| */ | */ | ||||
| ID *BLO_library_link_named_part(Main *mainl, BlendHandle **bh, const short idcode, const char *name) | ID *BLO_library_link_named_part(Main *mainl, BlendHandle **bh, const short idcode, const char *name) | ||||
| { | { | ||||
| FileData *fd = (FileData*)(*bh); | FileData *fd = (FileData*)(*bh); | ||||
| return link_named_part(mainl, fd, idcode, name, 0); | return link_named_part(mainl, fd, idcode, name, 0); | ||||
| } | } | ||||
| /** | /** | ||||
| * Link a named datablock from an external blend file. | * Link a named datablock from an external blend file. | ||||
| * Optionally instantiate the object/group in the scene when the flags are set. | * Optionally instantiate the object/collection in the scene when the flags are set. | ||||
| * | * | ||||
| * \param mainl The main database to link from (not the active one). | * \param mainl The main database to link from (not the active one). | ||||
| * \param bh The blender file handle. | * \param bh The blender file handle. | ||||
| * \param idcode The kind of datablock to link. | * \param idcode The kind of datablock to link. | ||||
| * \param name The name of the datablock (without the 2 char ID prefix). | * \param name The name of the datablock (without the 2 char ID prefix). | ||||
| * \param flag Options for linking, used for instantiating. | * \param flag Options for linking, used for instantiating. | ||||
| * \param scene The scene in which to instantiate objects/groups (if NULL, no instantiation is done). | * \param scene The scene in which to instantiate objects/collections (if NULL, no instantiation is done). | ||||
| * \param v3d The active View3D (only to define active layers for instantiated objects & groups, can be NULL). | * \param v3d The active View3D (only to define active layers for instantiated objects & collections, can be NULL). | ||||
| * \return the linked ID when found. | * \return the linked ID when found. | ||||
| */ | */ | ||||
| ID *BLO_library_link_named_part_ex( | ID *BLO_library_link_named_part_ex( | ||||
| Main *mainl, BlendHandle **bh, | Main *mainl, BlendHandle **bh, | ||||
| const short idcode, const char *name, const int flag, | const short idcode, const char *name, const int flag, | ||||
| Scene *scene, ViewLayer *view_layer) | Main *bmain, Scene *scene, ViewLayer *view_layer) | ||||
| { | { | ||||
| FileData *fd = (FileData*)(*bh); | FileData *fd = (FileData*)(*bh); | ||||
| return link_named_part_ex(mainl, fd, idcode, name, flag, scene, view_layer); | return link_named_part_ex(mainl, fd, idcode, name, flag, bmain, scene, view_layer); | ||||
| } | } | ||||
| static void link_id_part(ReportList *reports, FileData *fd, Main *mainvar, ID *id, ID **r_id) | static void link_id_part(ReportList *reports, FileData *fd, Main *mainvar, ID *id, ID **r_id) | ||||
| { | { | ||||
| BHead *bhead = NULL; | BHead *bhead = NULL; | ||||
| const bool is_valid = BKE_idcode_is_linkable(GS(id->name)) || ((id->tag & LIB_TAG_EXTERN) == 0); | const bool is_valid = BKE_idcode_is_linkable(GS(id->name)) || ((id->tag & LIB_TAG_EXTERN) == 0); | ||||
| if (fd) { | if (fd) { | ||||
| Show All 36 Lines | |||||
| /* common routine to append/link something from a library */ | /* common routine to append/link something from a library */ | ||||
| static Main *library_link_begin(Main *mainvar, FileData **fd, const char *filepath) | static Main *library_link_begin(Main *mainvar, FileData **fd, const char *filepath) | ||||
| { | { | ||||
| Main *mainl; | Main *mainl; | ||||
| (*fd)->mainlist = MEM_callocN(sizeof(ListBase), "FileData.mainlist"); | (*fd)->mainlist = MEM_callocN(sizeof(ListBase), "FileData.mainlist"); | ||||
| /* clear for group instantiating tag */ | /* clear for collection instantiating tag */ | ||||
| BKE_main_id_tag_listbase(&(mainvar->group), LIB_TAG_DOIT, false); | BKE_main_id_tag_listbase(&(mainvar->collection), LIB_TAG_DOIT, false); | ||||
| /* make mains */ | /* make mains */ | ||||
| blo_split_main((*fd)->mainlist, mainvar); | blo_split_main((*fd)->mainlist, mainvar); | ||||
| /* which one do we need? */ | /* which one do we need? */ | ||||
| mainl = blo_find_main(*fd, filepath, G.main->name); | mainl = blo_find_main(*fd, filepath, G.main->name); | ||||
| /* needed for do_version */ | /* needed for do_version */ | ||||
| ▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | for (ID *id = lbarray[i]->first, *idnext; id; id = idnext) { | ||||
| BLI_remlink(lbarray[i], id); | BLI_remlink(lbarray[i], id); | ||||
| BLI_addtail(lbarray_newid[i], id); | BLI_addtail(lbarray_newid[i], id); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* scene and v3d may be NULL. */ | /* scene and v3d may be NULL. */ | ||||
| static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene *scene, ViewLayer *view_layer) | static void library_link_end(Main *mainl, FileData **fd, const short flag, Main *bmain, Scene *scene, ViewLayer *view_layer) | ||||
| { | { | ||||
| Main *mainvar; | Main *mainvar; | ||||
| Library *curlib; | Library *curlib; | ||||
| /* expander now is callback function */ | /* expander now is callback function */ | ||||
| BLO_main_expander(expand_doit_library); | BLO_main_expander(expand_doit_library); | ||||
| /* make main consistent */ | /* make main consistent */ | ||||
| Show All 13 Lines | if (flag & FILE_RELPATH) { | ||||
| BLI_path_rel(curlib->name, G.main->name); | BLI_path_rel(curlib->name, G.main->name); | ||||
| } | } | ||||
| blo_join_main((*fd)->mainlist); | blo_join_main((*fd)->mainlist); | ||||
| mainvar = (*fd)->mainlist->first; | mainvar = (*fd)->mainlist->first; | ||||
| mainl = NULL; /* blo_join_main free's mainl, cant use anymore */ | mainl = NULL; /* blo_join_main free's mainl, cant use anymore */ | ||||
| lib_link_all(*fd, mainvar); | lib_link_all(*fd, mainvar); | ||||
| BKE_collections_after_lib_link(mainvar); | |||||
| /* Yep, second splitting... but this is a very cheap operation, so no big deal. */ | /* Yep, second splitting... but this is a very cheap operation, so no big deal. */ | ||||
| blo_split_main((*fd)->mainlist, mainvar); | blo_split_main((*fd)->mainlist, mainvar); | ||||
| Main *main_newid = BKE_main_new(); | Main *main_newid = BKE_main_new(); | ||||
| for (mainvar = ((Main *)(*fd)->mainlist->first)->next; mainvar; mainvar = mainvar->next) { | for (mainvar = ((Main *)(*fd)->mainlist->first)->next; mainvar; mainvar = mainvar->next) { | ||||
| BLI_assert(mainvar->versionfile != 0); | BLI_assert(mainvar->versionfile != 0); | ||||
| /* We need to split out IDs already existing, or they will go again through do_versions - bad, very bad! */ | /* We need to split out IDs already existing, or they will go again through do_versions - bad, very bad! */ | ||||
| split_main_newid(mainvar, main_newid); | split_main_newid(mainvar, main_newid); | ||||
| do_versions_after_linking(main_newid); | do_versions_after_linking(main_newid); | ||||
| add_main_to_main(mainvar, main_newid); | add_main_to_main(mainvar, main_newid); | ||||
| } | } | ||||
| BKE_main_free(main_newid); | BKE_main_free(main_newid); | ||||
| blo_join_main((*fd)->mainlist); | blo_join_main((*fd)->mainlist); | ||||
| mainvar = (*fd)->mainlist->first; | mainvar = (*fd)->mainlist->first; | ||||
| MEM_freeN((*fd)->mainlist); | MEM_freeN((*fd)->mainlist); | ||||
| BKE_main_id_tag_all(mainvar, LIB_TAG_NEW, false); | BKE_main_id_tag_all(mainvar, LIB_TAG_NEW, false); | ||||
| lib_verify_nodetree(mainvar, false); | lib_verify_nodetree(mainvar, false); | ||||
| fix_relpaths_library(G.main->name, mainvar); /* make all relative paths, relative to the open blend file */ | fix_relpaths_library(G.main->name, mainvar); /* make all relative paths, relative to the open blend file */ | ||||
| /* Give a base to loose objects. If group append, do it for objects too. | /* Give a base to loose objects and collections. | ||||
| * Only directly linked objects & groups are instantiated by `BLO_library_link_named_part_ex()` & co, | * Only directly linked objects & collections are instantiated by `BLO_library_link_named_part_ex()` & co, | ||||
| * here we handle indirect ones and other possible edge-cases. */ | * here we handle indirect ones and other possible edge-cases. */ | ||||
| if (scene) { | if (scene) { | ||||
| give_base_to_objects(mainvar, scene, view_layer, curlib, flag); | add_collections_to_scene(mainvar, bmain, scene, view_layer, curlib, flag); | ||||
| add_loose_objects_to_scene(mainvar, bmain, scene, view_layer, curlib, flag); | |||||
| if (flag & FILE_GROUP_INSTANCE) { | |||||
| give_base_to_groups(mainvar, scene, view_layer, curlib, flag); | |||||
| } | |||||
| } | } | ||||
| else { | else { | ||||
| /* printf("library_append_end, scene is NULL (objects wont get bases)\n"); */ | /* printf("library_append_end, scene is NULL (objects wont get bases)\n"); */ | ||||
| } | } | ||||
| /* clear group instantiating tag */ | /* clear collection instantiating tag */ | ||||
| BKE_main_id_tag_listbase(&(mainvar->group), LIB_TAG_DOIT, false); | BKE_main_id_tag_listbase(&(mainvar->collection), LIB_TAG_DOIT, false); | ||||
| /* patch to prevent switch_endian happens twice */ | /* patch to prevent switch_endian happens twice */ | ||||
| if ((*fd)->flags & FD_FLAGS_SWITCH_ENDIAN) { | if ((*fd)->flags & FD_FLAGS_SWITCH_ENDIAN) { | ||||
| blo_freefiledata(*fd); | blo_freefiledata(*fd); | ||||
| *fd = NULL; | *fd = NULL; | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Finalize linking from a given .blend file (library). | * Finalize linking from a given .blend file (library). | ||||
| * Optionally instance the indirect object/group in the scene when the flags are set. | * Optionally instance the indirect object/collection in the scene when the flags are set. | ||||
| * \note Do not use \a bh after calling this function, it may frees it. | * \note Do not use \a bh after calling this function, it may frees it. | ||||
| * | * | ||||
| * \param mainl The main database to link from (not the active one). | * \param mainl The main database to link from (not the active one). | ||||
| * \param bh The blender file handle (WARNING! may be freed by this function!). | * \param bh The blender file handle (WARNING! may be freed by this function!). | ||||
| * \param flag Options for linking, used for instantiating. | * \param flag Options for linking, used for instantiating. | ||||
| * \param scene The scene in which to instantiate objects/groups (if NULL, no instantiation is done). | * \param bmain The main database in which to instantiate objects/collections | ||||
| * \param view_layer The scene layer in which to instantiate objects/groups (if NULL, no instantiation is done). | * \param scene The scene in which to instantiate objects/collections (if NULL, no instantiation is done). | ||||
| * \param view_layer The scene layer in which to instantiate objects/collections (if NULL, no instantiation is done). | |||||
| */ | */ | ||||
| void BLO_library_link_end(Main *mainl, BlendHandle **bh, int flag, Scene *scene, ViewLayer *view_layer) | void BLO_library_link_end(Main *mainl, BlendHandle **bh, int flag, Main *bmain, Scene *scene, ViewLayer *view_layer) | ||||
| { | { | ||||
| FileData *fd = (FileData*)(*bh); | FileData *fd = (FileData*)(*bh); | ||||
| library_link_end(mainl, &fd, flag, scene, view_layer); | library_link_end(mainl, &fd, flag, bmain, scene, view_layer); | ||||
| *bh = (BlendHandle*)fd; | *bh = (BlendHandle*)fd; | ||||
| } | } | ||||
| void *BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname) | void *BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname) | ||||
| { | { | ||||
| return read_struct(fd, bh, blockname); | return read_struct(fd, bh, blockname); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 257 Lines • Show Last 20 Lines | |||||