diff options
Diffstat (limited to 'source/blender/blenkernel/intern/scene.c')
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 240 |
1 files changed, 185 insertions, 55 deletions
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index b12402d74fc..aa2a1b14841 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -33,6 +33,7 @@ #include "DNA_defaults.h" #include "DNA_gpencil_types.h" #include "DNA_linestyle_types.h" +#include "DNA_mask_types.h" #include "DNA_mesh_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" @@ -42,6 +43,7 @@ #include "DNA_sequence_types.h" #include "DNA_sound_types.h" #include "DNA_space_types.h" +#include "DNA_text_types.h" #include "DNA_view3d_types.h" #include "DNA_windowmanager_types.h" #include "DNA_workspace_types.h" @@ -59,13 +61,14 @@ #include "BLT_translation.h" #include "BKE_action.h" -#include "BKE_anim.h" +#include "BKE_anim_data.h" #include "BKE_animsys.h" #include "BKE_armature.h" #include "BKE_cachefile.h" #include "BKE_collection.h" #include "BKE_colortools.h" #include "BKE_curveprofile.h" +#include "BKE_duplilist.h" #include "BKE_editmesh.h" #include "BKE_fcurve.h" #include "BKE_freestyle.h" @@ -76,6 +79,7 @@ #include "BKE_image.h" #include "BKE_layer.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_linestyle.h" #include "BKE_main.h" @@ -154,6 +158,9 @@ static void scene_init_data(ID *id) scene->unit.mass_unit = (uchar)bUnit_GetBaseUnitOfType(USER_UNIT_METRIC, B_UNIT_MASS); scene->unit.time_unit = (uchar)bUnit_GetBaseUnitOfType(USER_UNIT_METRIC, B_UNIT_TIME); + /* Anti-Aliasing threshold. */ + scene->grease_pencil_settings.smaa_threshold = 1.0f; + { ParticleEditSettings *pset; pset = &scene->toolsettings->particle; @@ -339,12 +346,17 @@ static void scene_free_data(ID *id) /* is no lib link block, but scene extension */ if (scene->nodetree) { - ntreeFreeNestedTree(scene->nodetree); + ntreeFreeEmbeddedTree(scene->nodetree); MEM_freeN(scene->nodetree); scene->nodetree = NULL; } if (scene->rigidbody_world) { + /* Prevent rigidbody freeing code to follow other IDs pointers, this should never be allowed + * nor necessary from here, and with new undo code, those pointers may be fully invalid or + * worse, pointing to data actually belonging to new BMain! */ + scene->rigidbody_world->constraints = NULL; + scene->rigidbody_world->group = NULL; BKE_rigidbody_free_world(scene); } @@ -409,6 +421,155 @@ static void scene_free_data(ID *id) BLI_assert(scene->layer_properties == NULL); } +static void library_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSED(rbw), + ID **id_pointer, + void *user_data, + int cb_flag) +{ + LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; + BKE_lib_query_foreachid_process(data, id_pointer, cb_flag); +} + +static void library_foreach_paint(LibraryForeachIDData *data, Paint *paint) +{ + BKE_LIB_FOREACHID_PROCESS(data, paint->brush, IDWALK_CB_USER); + for (int i = 0; i < paint->tool_slots_len; i++) { + BKE_LIB_FOREACHID_PROCESS(data, paint->tool_slots[i].brush, IDWALK_CB_USER); + } + BKE_LIB_FOREACHID_PROCESS(data, paint->palette, IDWALK_CB_USER); +} + +static void library_foreach_layer_collection(LibraryForeachIDData *data, ListBase *lb) +{ + LISTBASE_FOREACH (LayerCollection *, lc, lb) { + /* XXX This is very weak. The whole idea of keeping pointers to private IDs is very bad + * anyway... */ + const int cb_flag = (lc->collection != NULL && + (lc->collection->id.flag & LIB_EMBEDDED_DATA) != 0) ? + IDWALK_CB_EMBEDDED : + IDWALK_CB_NOP; + BKE_LIB_FOREACHID_PROCESS(data, lc->collection, cb_flag); + library_foreach_layer_collection(data, &lc->layer_collections); + } +} + +static void scene_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Scene *scene = (Scene *)id; + + BKE_LIB_FOREACHID_PROCESS(data, scene->camera, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, scene->world, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, scene->set, IDWALK_CB_NEVER_SELF); + BKE_LIB_FOREACHID_PROCESS(data, scene->clip, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, scene->gpd, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, scene->r.bake.cage_object, IDWALK_CB_NOP); + if (scene->nodetree) { + /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ + BKE_library_foreach_ID_embedded(data, (ID **)&scene->nodetree); + } + if (scene->ed) { + Sequence *seq; + SEQP_BEGIN (scene->ed, seq) { + BKE_LIB_FOREACHID_PROCESS(data, seq->scene, IDWALK_CB_NEVER_SELF); + BKE_LIB_FOREACHID_PROCESS(data, seq->scene_camera, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, seq->clip, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, seq->mask, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, seq->sound, IDWALK_CB_USER); + IDP_foreach_property( + seq->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data); + LISTBASE_FOREACH (SequenceModifierData *, smd, &seq->modifiers) { + BKE_LIB_FOREACHID_PROCESS(data, smd->mask_id, IDWALK_CB_USER); + } + + if (seq->type == SEQ_TYPE_TEXT && seq->effectdata) { + TextVars *text_data = seq->effectdata; + BKE_LIB_FOREACHID_PROCESS(data, text_data->text_font, IDWALK_CB_USER); + } + } + SEQ_END; + } + + /* This pointer can be NULL during old files reading, better be safe than sorry. */ + if (scene->master_collection != NULL) { + BKE_library_foreach_ID_embedded(data, (ID **)&scene->master_collection); + } + + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + BKE_LIB_FOREACHID_PROCESS(data, view_layer->mat_override, IDWALK_CB_USER); + + LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_LIB_FOREACHID_PROCESS(data, base->object, IDWALK_CB_NOP); + } + + library_foreach_layer_collection(data, &view_layer->layer_collections); + + LISTBASE_FOREACH (FreestyleModuleConfig *, fmc, &view_layer->freestyle_config.modules) { + if (fmc->script) { + BKE_LIB_FOREACHID_PROCESS(data, fmc->script, IDWALK_CB_NOP); + } + } + + LISTBASE_FOREACH (FreestyleLineSet *, fls, &view_layer->freestyle_config.linesets) { + if (fls->group) { + BKE_LIB_FOREACHID_PROCESS(data, fls->group, IDWALK_CB_USER); + } + + if (fls->linestyle) { + BKE_LIB_FOREACHID_PROCESS(data, fls->linestyle, IDWALK_CB_USER); + } + } + } + + LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) { + BKE_LIB_FOREACHID_PROCESS(data, marker->camera, IDWALK_CB_NOP); + } + + ToolSettings *toolsett = scene->toolsettings; + if (toolsett) { + BKE_LIB_FOREACHID_PROCESS(data, toolsett->particle.scene, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, toolsett->particle.object, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, toolsett->particle.shape_object, IDWALK_CB_NOP); + + library_foreach_paint(data, &toolsett->imapaint.paint); + BKE_LIB_FOREACHID_PROCESS(data, toolsett->imapaint.stencil, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, toolsett->imapaint.clone, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, toolsett->imapaint.canvas, IDWALK_CB_USER); + + if (toolsett->vpaint) { + library_foreach_paint(data, &toolsett->vpaint->paint); + } + if (toolsett->wpaint) { + library_foreach_paint(data, &toolsett->wpaint->paint); + } + if (toolsett->sculpt) { + library_foreach_paint(data, &toolsett->sculpt->paint); + BKE_LIB_FOREACHID_PROCESS(data, toolsett->sculpt->gravity_object, IDWALK_CB_NOP); + } + if (toolsett->uvsculpt) { + library_foreach_paint(data, &toolsett->uvsculpt->paint); + } + if (toolsett->gp_paint) { + library_foreach_paint(data, &toolsett->gp_paint->paint); + } + if (toolsett->gp_vertexpaint) { + library_foreach_paint(data, &toolsett->gp_vertexpaint->paint); + } + if (toolsett->gp_sculptpaint) { + library_foreach_paint(data, &toolsett->gp_sculptpaint->paint); + } + if (toolsett->gp_weightpaint) { + library_foreach_paint(data, &toolsett->gp_weightpaint->paint); + } + + BKE_LIB_FOREACHID_PROCESS(data, toolsett->gp_sculpt.guide.reference_object, IDWALK_CB_NOP); + } + + if (scene->rigidbody_world) { + BKE_rigidbody_world_id_loop( + scene->rigidbody_world, library_foreach_rigidbodyworldSceneLooper, data); + } +} + IDTypeInfo IDType_ID_SCE = { .id_code = ID_SCE, .id_filter = FILTER_ID_SCE, @@ -425,6 +586,7 @@ IDTypeInfo IDType_ID_SCE = { /* For now default `BKE_lib_id_make_local_generic()` should work, may need more work though to * support all possible corner cases. */ .make_local = NULL, + .foreach_id = scene_foreach_id, }; const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE"; @@ -459,7 +621,7 @@ static void remove_sequencer_fcurves(Scene *sce) if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) { action_groups_remove_channel(adt->action, fcu); - free_fcurve(fcu); + BKE_fcurve_free(fcu); } } } @@ -506,7 +668,6 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag) } BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag); - ts->imapaint.paintcursor = NULL; ts->particle.paintcursor = NULL; ts->particle.scene = NULL; ts->particle.object = NULL; @@ -668,10 +829,9 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) if (type == SCE_COPY_FULL) { /* Copy Freestyle LineStyle datablocks. */ - for (ViewLayer *view_layer_dst = sce_copy->view_layers.first; view_layer_dst; - view_layer_dst = view_layer_dst->next) { - for (FreestyleLineSet *lineset = view_layer_dst->freestyle_config.linesets.first; lineset; - lineset = lineset->next) { + LISTBASE_FOREACH (ViewLayer *, view_layer_dst, &sce_copy->view_layers) { + LISTBASE_FOREACH ( + FreestyleLineSet *, lineset, &view_layer_dst->freestyle_config.linesets) { if (lineset->linestyle) { id_us_min(&lineset->linestyle->id); BKE_id_copy_ex( @@ -731,8 +891,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name) */ bool BKE_scene_object_find(Scene *scene, Object *ob) { - for (ViewLayer *view_layer = scene->view_layers.first; view_layer; - view_layer = view_layer->next) { + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { if (BLI_findptr(&view_layer->object_bases, ob, offsetof(Base, object))) { return true; } @@ -742,9 +901,8 @@ bool BKE_scene_object_find(Scene *scene, Object *ob) Object *BKE_scene_object_find_by_name(const Scene *scene, const char *name) { - for (ViewLayer *view_layer = scene->view_layers.first; view_layer; - view_layer = view_layer->next) { - for (Base *base = view_layer->object_bases.first; base; base = base->next) { + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { if (STREQ(base->object->id.name + 2, name)) { return base->object; } @@ -772,9 +930,8 @@ void BKE_scene_set_background(Main *bmain, Scene *scene) } /* copy layers and flags from bases to objects */ - for (ViewLayer *view_layer = scene->view_layers.first; view_layer; - view_layer = view_layer->next) { - for (Base *base = view_layer->object_bases.first; base; base = base->next) { + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { ob = base->object; /* collection patch... */ BKE_scene_object_base_flag_sync_from_base(base); @@ -928,7 +1085,7 @@ int BKE_scene_base_iter_next( Scene *BKE_scene_find_from_collection(const Main *bmain, const Collection *collection) { for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { - for (ViewLayer *layer = scene->view_layers.first; layer; layer = layer->next) { + LISTBASE_FOREACH (ViewLayer *, layer, &scene->view_layers) { if (BKE_view_layer_has_collection(layer, collection)) { return scene; } @@ -954,7 +1111,7 @@ Object *BKE_scene_camera_switch_find(Scene *scene) Object *camera = NULL; Object *first_camera = NULL; - for (TimeMarker *m = scene->markers.first; m; m = m->next) { + LISTBASE_FOREACH (TimeMarker *, m, &scene->markers) { if (m->camera && (m->camera->restrictflag & OB_RESTRICT_RENDER) == 0) { if ((m->frame <= cfra) && (m->frame > frame)) { camera = m->camera; @@ -1091,9 +1248,7 @@ bool BKE_scene_validate_setscene(Main *bmain, Scene *sce) } /** - * This function is needed to cope with fractional frames - including two Blender rendering - * features mblur (motion blur that renders 'subframes' and blurs them together), - * and fields rendering. + * This function is needed to cope with fractional frames, needed for motion blur & physics. */ float BKE_scene_frame_get(const Scene *scene) { @@ -1170,34 +1325,6 @@ int BKE_scene_orientation_slot_get_index(const TransformOrientationSlot *orient_ /** \} */ -/* That's like really a bummer, because currently animation data for armatures - * might want to use pose, and pose might be missing on the object. - * This happens when changing visible layers, which leads to situations when - * pose is missing or marked for recalc, animation will change it and then - * object update will restore the pose. - * - * This could be solved by the new dependency graph, but for until then we'll - * do an extra pass on the objects to ensure it's all fine. - */ -#define POSE_ANIMATION_WORKAROUND - -#ifdef POSE_ANIMATION_WORKAROUND -static void scene_armature_depsgraph_workaround(Main *bmain, Depsgraph *depsgraph) -{ - Object *ob; - if (BLI_listbase_is_empty(&bmain->armatures) || !DEG_id_type_updated(depsgraph, ID_OB)) { - return; - } - for (ob = bmain->objects.first; ob; ob = ob->id.next) { - if (ob->type == OB_ARMATURE && ob->adt) { - if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) { - BKE_pose_rebuild(bmain, ob, ob->data, true); - } - } - } -} -#endif - static bool check_rendered_viewport_visible(Main *bmain) { wmWindowManager *wm = bmain->wm.first; @@ -1281,6 +1408,14 @@ void BKE_scene_update_sound(Depsgraph *depsgraph, Main *bmain) BKE_sound_update_scene(depsgraph, scene); } +void BKE_scene_update_tag_audio_volume(Depsgraph *UNUSED(depsgraph), Scene *scene) +{ + BLI_assert(DEG_is_evaluated_id(&scene->id)); + /* The volume is actually updated in BKE_scene_update_sound(), from either + * scene_graph_update_tagged() or from BKE_scene_graph_update_for_newframe(). */ + scene->id.recalc |= ID_RECALC_AUDIO_VOLUME; +} + /* TODO(sergey): This actually should become view_layer_graph or so. * Same applies to update_for_newframe. * @@ -1374,9 +1509,6 @@ void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph, Main *bmain) BKE_image_editors_update_frame(bmain, scene->r.cfra); BKE_sound_set_cfra(scene->r.cfra); DEG_graph_relations_update(depsgraph, bmain, scene, view_layer); -#ifdef POSE_ANIMATION_WORKAROUND - scene_armature_depsgraph_workaround(bmain, depsgraph); -#endif /* Update all objects: drivers, matrices, displists, etc. flags set * by depgraph or manual, no layer check here, gets correct flushed. * @@ -2097,7 +2229,7 @@ static Depsgraph **scene_get_depsgraph_p(Main *bmain, if (allocate_depsgraph) { *depsgraph_ptr = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_VIEWPORT); /* TODO(sergey): Would be cool to avoid string format print, - * but is a bit tricky because we can't know in advance whether + * but is a bit tricky because we can't know in advance whether * we will ever enable debug messages for this depsgraph. */ char name[1024]; @@ -2170,8 +2302,6 @@ GHash *BKE_scene_undo_depsgraphs_extract(Main *bmain) void BKE_scene_undo_depsgraphs_restore(Main *bmain, GHash *depsgraph_extract) { for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { - BLI_assert(scene->depsgraph_hash == NULL); - for (ViewLayer *view_layer = scene->view_layers.first; view_layer != NULL; view_layer = view_layer->next) { char key_full[MAX_ID_NAME + FILE_MAX + MAX_NAME] = {0}; |