diff options
author | Jacques Lucke <jacques@blender.org> | 2020-10-30 18:40:41 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2020-10-30 18:40:41 +0300 |
commit | 1103809fabe9da4a13755480e19b13d56cd27843 (patch) | |
tree | 99d975d7d24ded60fb7f083e0758a3950e8696b0 /source | |
parent | 5b89d49b0d297a33271a311f80ff503b3412686a (diff) | |
parent | 62e532785dfd5bd25fb6b1269ec41ea81a32c4c9 (diff) |
Merge branch 'master' into geometry-nodes
Diffstat (limited to 'source')
60 files changed, 2148 insertions, 1727 deletions
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index f4393742dff..06fcc038f69 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -40,6 +40,12 @@ struct Main; struct Object; struct Scene; struct ViewLayer; +struct BlendWriter; +struct BlendDataReader; +struct BlendLibReader; +struct BlendExpander; +struct SceneCollection; +struct Library; typedef struct CollectionParent { struct CollectionParent *next, *prev; @@ -160,6 +166,22 @@ bool BKE_collection_has_collection(struct Collection *parent, struct Collection void BKE_collection_parent_relations_rebuild(struct Collection *collection); void BKE_main_collections_parent_relations_rebuild(struct Main *bmain); +/* .blend file I/O */ + +void BKE_collection_blend_write_nolib(struct BlendWriter *writer, struct Collection *collection); +void BKE_collection_blend_read_data(struct BlendDataReader *reader, struct Collection *collection); +void BKE_collection_blend_read_lib(struct BlendLibReader *reader, struct Collection *collection); +void BKE_collection_blend_read_expand(struct BlendExpander *expander, + struct Collection *collection); + +void BKE_collection_compat_blend_read_data(struct BlendDataReader *reader, + struct SceneCollection *sc); +void BKE_collection_compat_blend_read_lib(struct BlendLibReader *reader, + struct Library *lib, + struct SceneCollection *sc); +void BKE_collection_compat_blend_read_expand(struct BlendExpander *expander, + struct SceneCollection *sc); + /* Iteration callbacks. */ typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data); diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index 024d58174e8..39ba417c988 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -42,6 +42,8 @@ struct Object; struct Scene; struct View3D; struct ViewLayer; +struct BlendDataReader; +struct BlendLibReader; typedef enum eViewLayerCopyMethod { VIEWLAYER_ADD_NEW = 0, @@ -147,6 +149,13 @@ void BKE_layer_eval_view_layer_indexed(struct Depsgraph *depsgraph, struct Scene *scene, int view_layer_index); +/* .blend file I/O */ + +void BKE_view_layer_blend_read_data(struct BlendDataReader *reader, struct ViewLayer *view_layer); +void BKE_view_layer_blend_read_lib(struct BlendLibReader *reader, + struct Library *lib, + struct ViewLayer *view_layer); + /* iterators */ typedef struct ObjectsVisibleIteratorData { diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 6ed3b94b8e5..755fca5a2dc 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -60,6 +60,8 @@ struct ModifierData; struct Object; struct RNG; struct Scene; +struct BlendDataReader; +struct BlendLibReader; #define PARTICLE_COLLISION_MAX_COLLISIONS 10 @@ -625,6 +627,13 @@ void BKE_particle_batch_cache_free(struct ParticleSystem *psys); extern void (*BKE_particle_batch_cache_dirty_tag_cb)(struct ParticleSystem *psys, int mode); extern void (*BKE_particle_batch_cache_free_cb)(struct ParticleSystem *psys); +/* .blend file I/O */ +void BKE_particle_partdeflect_blend_read_data(struct BlendDataReader *reader, + struct PartDeflect *pd); +void BKE_particle_partdeflect_blend_read_lib(struct BlendLibReader *reader, + struct ID *id, + struct PartDeflect *pd); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 35a3d0415a8..da87ff3e969 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -58,6 +58,9 @@ struct wmMsgBus; struct wmNotifier; struct wmWindow; struct wmWindowManager; +struct BlendWriter; +struct BlendDataReader; +struct BlendLibReader; /* spacetype has everything stored to get an editor working, it gets initialized via * ED_spacetypes_init() in editors/space_api/spacetypes.c */ @@ -449,6 +452,20 @@ void BKE_screen_remove_unused_scrverts(struct bScreen *screen); void BKE_screen_header_alignment_reset(struct bScreen *screen); +/* .blend file I/O */ +void BKE_screen_view3d_shading_blend_write(struct BlendWriter *writer, + struct View3DShading *shading); +void BKE_screen_view3d_shading_blend_read_data(struct BlendDataReader *reader, + struct View3DShading *shading); + +void BKE_screen_area_map_blend_write(struct BlendWriter *writer, struct ScrAreaMap *area_map); +bool BKE_screen_area_map_blend_read_data(struct BlendDataReader *reader, + struct ScrAreaMap *area_map); +void BKE_screen_view3d_do_versions_250(struct View3D *v3d, ListBase *regions); +void BKE_screen_area_blend_read_lib(struct BlendLibReader *reader, + struct ID *parent_id, + struct ScrArea *area); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h index 4f933ca7a87..58872d6be58 100644 --- a/source/blender/blenkernel/BKE_undo_system.h +++ b/source/blender/blenkernel/BKE_undo_system.h @@ -70,6 +70,12 @@ typedef struct UndoStack { * That is done once end is called. */ struct UndoStep *step_init; + + /** + * Keep track of nested group begin/end calls, + * within which all but the last undo-step is marked for skipping. + */ + int group_level; } UndoStack; typedef struct UndoStep { @@ -156,6 +162,9 @@ void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size #define BKE_undosys_stack_limit_steps_and_memory_defaults(ustack) \ BKE_undosys_stack_limit_steps_and_memory(ustack, U.undosteps, (size_t)U.undomemory * 1024 * 1024) +void BKE_undosys_stack_group_begin(UndoStack *ustack); +void BKE_undosys_stack_group_end(UndoStack *ustack); + /* Only some UndoType's require init. */ UndoStep *BKE_undosys_step_push_init_with_type(UndoStack *ustack, struct bContext *C, diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 0ed6f94ce79..870a137ede9 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -18,6 +18,9 @@ * \ingroup bke */ +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include <string.h> #include "BLI_blenlib.h" @@ -55,6 +58,8 @@ #include "MEM_guardedalloc.h" +#include "BLO_read_write.h" + /* -------------------------------------------------------------------- */ /** \name Prototypes * \{ */ @@ -167,6 +172,172 @@ static void collection_foreach_id(ID *id, LibraryForeachIDData *data) } } +void BKE_collection_blend_write_nolib(BlendWriter *writer, Collection *collection) +{ + /* Shared function for collection data-blocks and scene master collection. */ + BKE_previewimg_blend_write(writer, collection->preview); + + LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { + BLO_write_struct(writer, CollectionObject, cob); + } + + LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { + BLO_write_struct(writer, CollectionChild, child); + } +} + +static void collection_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + Collection *collection = (Collection *)id; + if (collection->id.us > 0 || BLO_write_is_undo(writer)) { + /* Clean up, important in undo case to reduce false detection of changed data-blocks. */ + collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE; + collection->tag = 0; + BLI_listbase_clear(&collection->object_cache); + BLI_listbase_clear(&collection->parents); + + /* write LibData */ + BLO_write_id_struct(writer, Collection, id_address, &collection->id); + BKE_id_blend_write(writer, &collection->id); + + BKE_collection_blend_write_nolib(writer, collection); + } +} + +#ifdef USE_COLLECTION_COMPAT_28 +void BKE_collection_compat_blend_read_data(BlendDataReader *reader, SceneCollection *sc) +{ + BLO_read_list(reader, &sc->objects); + BLO_read_list(reader, &sc->scene_collections); + + LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) { + BKE_collection_compat_blend_read_data(reader, nsc); + } +} +#endif + +void BKE_collection_blend_read_data(BlendDataReader *reader, Collection *collection) +{ + BLO_read_list(reader, &collection->gobject); + BLO_read_list(reader, &collection->children); + + BLO_read_data_address(reader, &collection->preview); + BKE_previewimg_blend_read(reader, collection->preview); + + collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE; + collection->tag = 0; + BLI_listbase_clear(&collection->object_cache); + BLI_listbase_clear(&collection->parents); + +#ifdef USE_COLLECTION_COMPAT_28 + /* This runs before the very first doversion. */ + BLO_read_data_address(reader, &collection->collection); + if (collection->collection != NULL) { + BKE_collection_compat_blend_read_data(reader, collection->collection); + } + + BLO_read_data_address(reader, &collection->view_layer); + if (collection->view_layer != NULL) { + BKE_view_layer_blend_read_data(reader, collection->view_layer); + } +#endif +} + +static void collection_blend_read_data(BlendDataReader *reader, ID *id) +{ + Collection *collection = (Collection *)id; + BKE_collection_blend_read_data(reader, collection); +} + +static void lib_link_collection_data(BlendLibReader *reader, Library *lib, Collection *collection) +{ + LISTBASE_FOREACH_MUTABLE (CollectionObject *, cob, &collection->gobject) { + BLO_read_id_address(reader, lib, &cob->ob); + + if (cob->ob == NULL) { + BLI_freelinkN(&collection->gobject, cob); + } + } + + LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { + BLO_read_id_address(reader, lib, &child->collection); + } +} + +#ifdef USE_COLLECTION_COMPAT_28 +void BKE_collection_compat_blend_read_lib(BlendLibReader *reader, + Library *lib, + SceneCollection *sc) +{ + LISTBASE_FOREACH (LinkData *, link, &sc->objects) { + BLO_read_id_address(reader, lib, &link->data); + BLI_assert(link->data); + } + + LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) { + BKE_collection_compat_blend_read_lib(reader, lib, nsc); + } +} +#endif + +void BKE_collection_blend_read_lib(BlendLibReader *reader, Collection *collection) +{ +#ifdef USE_COLLECTION_COMPAT_28 + if (collection->collection) { + BKE_collection_compat_blend_read_lib(reader, collection->id.lib, collection->collection); + } + + if (collection->view_layer) { + BKE_view_layer_blend_read_lib(reader, collection->id.lib, collection->view_layer); + } +#endif + + lib_link_collection_data(reader, collection->id.lib, collection); +} + +static void collection_blend_read_lib(BlendLibReader *reader, ID *id) +{ + Collection *collection = (Collection *)id; + BKE_collection_blend_read_lib(reader, collection); +} + +#ifdef USE_COLLECTION_COMPAT_28 +void BKE_collection_compat_blend_read_expand(struct BlendExpander *expander, + struct SceneCollection *sc) +{ + LISTBASE_FOREACH (LinkData *, link, &sc->objects) { + BLO_expand(expander, link->data); + } + + LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) { + BKE_collection_compat_blend_read_expand(expander, nsc); + } +} +#endif + +void BKE_collection_blend_read_expand(BlendExpander *expander, Collection *collection) +{ + LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { + BLO_expand(expander, cob->ob); + } + + LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { + BLO_expand(expander, child->collection); + } + +#ifdef USE_COLLECTION_COMPAT_28 + if (collection->collection != NULL) { + BKE_collection_compat_blend_read_expand(expander, collection->collection); + } +#endif +} + +static void collection_blend_read_expand(BlendExpander *expander, ID *id) +{ + Collection *collection = (Collection *)id; + BKE_collection_blend_read_expand(expander, collection); +} + IDTypeInfo IDType_ID_GR = { .id_code = ID_GR, .id_filter = FILTER_ID_GR, @@ -184,10 +355,10 @@ IDTypeInfo IDType_ID_GR = { .foreach_id = collection_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = collection_blend_write, + .blend_read_data = collection_blend_read_data, + .blend_read_lib = collection_blend_read_lib, + .blend_read_expand = collection_blend_read_expand, }; /** \} */ diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 2301267cd21..d21529467a1 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -45,6 +45,7 @@ #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" +#include "DNA_screen_types.h" #include "DNA_lattice_types.h" #include "DNA_movieclip_types.h" @@ -5408,7 +5409,7 @@ bool BKE_constraint_remove_ex(ListBase *list, Object *ob, bConstraint *con, bool void BKE_constraint_panel_expand(bConstraint *con) { - con->ui_expand_flag |= (1 << 0); + con->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT; } /* ......... */ @@ -5426,10 +5427,10 @@ static bConstraint *add_new_constraint_internal(const char *name, short type) con->enforce = 1.0f; /* Only open the main panel when constraints are created, not the sub-panels. */ - con->ui_expand_flag = (1 << 0); + con->ui_expand_flag = UI_PANEL_DATA_EXPAND_ROOT; if (ELEM(type, CONSTRAINT_TYPE_ACTION, CONSTRAINT_TYPE_SPLINEIK)) { /* Expand the two sub-panels in the cases where the main panel barely has any properties. */ - con->ui_expand_flag |= (1 << 1) | (1 << 2); + con->ui_expand_flag |= UI_SUBPANEL_DATA_EXPAND_1 | UI_SUBPANEL_DATA_EXPAND_2; } /* Determine a basic name, and info */ diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index fa1b1997625..af4b98e1c8d 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -4993,6 +4993,7 @@ void BKE_fluid_modifier_copy(const struct FluidModifierData *fmd, tfds->fractions_threshold = fds->fractions_threshold; tfds->fractions_distance = fds->fractions_distance; tfds->sys_particle_maximum = fds->sys_particle_maximum; + tfds->simulation_method = fds->simulation_method; /* diffusion options*/ tfds->surface_tension = fds->surface_tension; diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index f4041fae047..934791ccc35 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -39,6 +39,7 @@ #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_screen_types.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" @@ -413,7 +414,7 @@ void BKE_gpencil_modifierType_panel_id(GpencilModifierType type, char *r_idname) void BKE_gpencil_modifier_panel_expand(GpencilModifierData *md) { - md->ui_expand_flag |= (1 << 0); + md->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT; } /** diff --git a/source/blender/blenkernel/intern/lattice_deform.c b/source/blender/blenkernel/intern/lattice_deform.c index 43965813b84..14c600caa46 100644 --- a/source/blender/blenkernel/intern/lattice_deform.c +++ b/source/blender/blenkernel/intern/lattice_deform.c @@ -169,7 +169,7 @@ void BKE_lattice_deform_data_eval_co(LatticeDeformData *lattice_deform_data, int ui, vi, wi, uu, vv, ww; /* vgroup influence */ - float co_prev[3], weight_blend = 0.0f; + float co_prev[4] = {0}, weight_blend = 0.0f; copy_v3_v3(co_prev, co); #ifdef __SSE2__ __m128 co_vec = _mm_loadu_ps(co_prev); @@ -235,10 +235,16 @@ void BKE_lattice_deform_data_eval_co(LatticeDeformData *lattice_deform_data, #ifdef __SSE2__ { __m128 weight_vec = _mm_set1_ps(u); - /* This will load one extra element, this is ok because - * we ignore that part of register anyway. - */ - __m128 lattice_vec = _mm_loadu_ps(&latticedata[idx * 3]); + /* We need to address special case for last item to avoid accessing invalid memory. */ + __m128 lattice_vec; + if (idx * 3 == idx_w_max) { + copy_v3_v3((float *)&lattice_vec, &latticedata[idx * 3]); + } + else { + /* When not on last item, we can safely access one extra float, it will be ignored + * anyway. */ + lattice_vec = _mm_loadu_ps(&latticedata[idx * 3]); + } co_vec = _mm_add_ps(co_vec, _mm_mul_ps(lattice_vec, weight_vec)); } #else diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index 6efc9d0753e..5b88a68b921 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -18,6 +18,9 @@ * \ingroup bke */ +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include <string.h> #include "BLI_listbase.h" @@ -56,6 +59,8 @@ #include "MEM_guardedalloc.h" +#include "BLO_read_write.h" + /* Set of flags which are dependent on a collection settings. */ static const short g_base_collection_flags = (BASE_VISIBLE_DEPSGRAPH | BASE_VISIBLE_VIEWLAYER | BASE_SELECTABLE | BASE_ENABLED_VIEWPORT | @@ -1830,3 +1835,91 @@ void BKE_layer_eval_view_layer_indexed(struct Depsgraph *depsgraph, BLI_assert(view_layer != NULL); layer_eval_view_layer(depsgraph, scene, view_layer); } + +static void direct_link_layer_collections(BlendDataReader *reader, ListBase *lb, bool master) +{ + BLO_read_list(reader, lb); + LISTBASE_FOREACH (LayerCollection *, lc, lb) { +#ifdef USE_COLLECTION_COMPAT_28 + BLO_read_data_address(reader, &lc->scene_collection); +#endif + + /* Master collection is not a real data-lock. */ + if (master) { + BLO_read_data_address(reader, &lc->collection); + } + + direct_link_layer_collections(reader, &lc->layer_collections, false); + } +} + +void BKE_view_layer_blend_read_data(BlendDataReader *reader, ViewLayer *view_layer) +{ + view_layer->stats = NULL; + BLO_read_list(reader, &view_layer->object_bases); + BLO_read_data_address(reader, &view_layer->basact); + + direct_link_layer_collections(reader, &view_layer->layer_collections, true); + BLO_read_data_address(reader, &view_layer->active_collection); + + BLO_read_data_address(reader, &view_layer->id_properties); + IDP_BlendDataRead(reader, &view_layer->id_properties); + + BLO_read_list(reader, &(view_layer->freestyle_config.modules)); + BLO_read_list(reader, &(view_layer->freestyle_config.linesets)); + + BLI_listbase_clear(&view_layer->drawdata); + view_layer->object_bases_array = NULL; + view_layer->object_bases_hash = NULL; +} + +static void lib_link_layer_collection(BlendLibReader *reader, + Library *lib, + LayerCollection *layer_collection, + bool master) +{ + /* Master collection is not a real data-lock. */ + if (!master) { + BLO_read_id_address(reader, lib, &layer_collection->collection); + } + + LISTBASE_FOREACH ( + LayerCollection *, layer_collection_nested, &layer_collection->layer_collections) { + lib_link_layer_collection(reader, lib, layer_collection_nested, false); + } +} + +void BKE_view_layer_blend_read_lib(BlendLibReader *reader, Library *lib, ViewLayer *view_layer) +{ + LISTBASE_FOREACH (FreestyleModuleConfig *, fmc, &view_layer->freestyle_config.modules) { + BLO_read_id_address(reader, lib, &fmc->script); + } + + LISTBASE_FOREACH (FreestyleLineSet *, fls, &view_layer->freestyle_config.linesets) { + BLO_read_id_address(reader, lib, &fls->linestyle); + BLO_read_id_address(reader, 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 */ + BLO_read_id_address(reader, lib, &base->object); + + if (base->object == NULL) { + /* Free in case linked object got lost. */ + BLI_freelinkN(&view_layer->object_bases, base); + if (view_layer->basact == base) { + view_layer->basact = NULL; + } + } + } + + LISTBASE_FOREACH (LayerCollection *, layer_collection, &view_layer->layer_collections) { + lib_link_layer_collection(reader, lib, layer_collection, true); + } + + BLO_read_id_address(reader, lib, &view_layer->mat_override); + + IDP_BlendReadLib(reader, view_layer->id_properties); +} diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 1ac63e653c0..0054d2f76d1 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -38,6 +38,7 @@ #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_screen_types.h" #include "BLI_linklist.h" #include "BLI_listbase.h" @@ -132,7 +133,7 @@ void BKE_modifier_type_panel_id(ModifierType type, char *r_idname) void BKE_modifier_panel_expand(ModifierData *md) { - md->ui_expand_flag |= (1 << 0); + md->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT; } /***/ diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 7b8ee7343ee..71f78592bc5 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -21,6 +21,9 @@ * \ingroup bke */ +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include <math.h> #include <stdlib.h> #include <string.h> @@ -52,6 +55,7 @@ #include "BLT_translation.h" +#include "BKE_anim_data.h" #include "BKE_anim_path.h" #include "BKE_boids.h" #include "BKE_cloth.h" @@ -80,6 +84,8 @@ #include "RE_render_ext.h" +#include "BLO_read_write.h" + #include "particle_private.h" static void fluid_free_settings(SPHFluidSettings *fluid); @@ -206,6 +212,279 @@ static void particle_settings_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void write_boid_state(BlendWriter *writer, BoidState *state) +{ + BLO_write_struct(writer, BoidState, state); + + LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { + switch (rule->type) { + case eBoidRuleType_Goal: + case eBoidRuleType_Avoid: + BLO_write_struct(writer, BoidRuleGoalAvoid, rule); + break; + case eBoidRuleType_AvoidCollision: + BLO_write_struct(writer, BoidRuleAvoidCollision, rule); + break; + case eBoidRuleType_FollowLeader: + BLO_write_struct(writer, BoidRuleFollowLeader, rule); + break; + case eBoidRuleType_AverageSpeed: + BLO_write_struct(writer, BoidRuleAverageSpeed, rule); + break; + case eBoidRuleType_Fight: + BLO_write_struct(writer, BoidRuleFight, rule); + break; + default: + BLO_write_struct(writer, BoidRule, rule); + break; + } + } +#if 0 + BoidCondition *cond = state->conditions.first; + for (; cond; cond = cond->next) { + BLO_write_struct(writer, BoidCondition, cond); + } +#endif +} + +static void particle_settings_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + ParticleSettings *part = (ParticleSettings *)id; + if (part->id.us > 0 || BLO_write_is_undo(writer)) { + /* write LibData */ + BLO_write_id_struct(writer, ParticleSettings, id_address, &part->id); + BKE_id_blend_write(writer, &part->id); + + if (part->adt) { + BKE_animdata_blend_write(writer, part->adt); + } + BLO_write_struct(writer, PartDeflect, part->pd); + BLO_write_struct(writer, PartDeflect, part->pd2); + BLO_write_struct(writer, EffectorWeights, part->effector_weights); + + if (part->clumpcurve) { + BKE_curvemapping_blend_write(writer, part->clumpcurve); + } + if (part->roughcurve) { + BKE_curvemapping_blend_write(writer, part->roughcurve); + } + if (part->twistcurve) { + BKE_curvemapping_blend_write(writer, part->twistcurve); + } + + LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) { + /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */ + if (dw->ob != NULL) { + dw->index = 0; + if (part->instance_collection) { /* can be NULL if lining fails or set to None */ + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object) { + if (object == dw->ob) { + break; + } + dw->index++; + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + } + } + BLO_write_struct(writer, ParticleDupliWeight, dw); + } + + if (part->boids && part->phystype == PART_PHYS_BOIDS) { + BLO_write_struct(writer, BoidSettings, part->boids); + + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + write_boid_state(writer, state); + } + } + if (part->fluid && part->phystype == PART_PHYS_FLUID) { + BLO_write_struct(writer, SPHFluidSettings, part->fluid); + } + + for (int a = 0; a < MAX_MTEX; a++) { + if (part->mtex[a]) { + BLO_write_struct(writer, MTex, part->mtex[a]); + } + } + } +} + +void BKE_particle_partdeflect_blend_read_data(BlendDataReader *UNUSED(reader), PartDeflect *pd) +{ + if (pd) { + pd->rng = NULL; + } +} + +static void particle_settings_blend_read_data(BlendDataReader *reader, ID *id) +{ + ParticleSettings *part = (ParticleSettings *)id; + BLO_read_data_address(reader, &part->adt); + BLO_read_data_address(reader, &part->pd); + BLO_read_data_address(reader, &part->pd2); + + BKE_animdata_blend_read_data(reader, part->adt); + BKE_particle_partdeflect_blend_read_data(reader, part->pd); + BKE_particle_partdeflect_blend_read_data(reader, part->pd2); + + BLO_read_data_address(reader, &part->clumpcurve); + if (part->clumpcurve) { + BKE_curvemapping_blend_read(reader, part->clumpcurve); + } + BLO_read_data_address(reader, &part->roughcurve); + if (part->roughcurve) { + BKE_curvemapping_blend_read(reader, part->roughcurve); + } + BLO_read_data_address(reader, &part->twistcurve); + if (part->twistcurve) { + BKE_curvemapping_blend_read(reader, part->twistcurve); + } + + BLO_read_data_address(reader, &part->effector_weights); + if (!part->effector_weights) { + part->effector_weights = BKE_effector_add_weights(part->force_group); + } + + BLO_read_list(reader, &part->instance_weights); + + BLO_read_data_address(reader, &part->boids); + BLO_read_data_address(reader, &part->fluid); + + if (part->boids) { + BLO_read_list(reader, &part->boids->states); + + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + BLO_read_list(reader, &state->rules); + BLO_read_list(reader, &state->conditions); + BLO_read_list(reader, &state->actions); + } + } + for (int a = 0; a < MAX_MTEX; a++) { + BLO_read_data_address(reader, &part->mtex[a]); + } + + /* Protect against integer overflow vulnerability. */ + CLAMP(part->trail_count, 1, 100000); +} + +void BKE_particle_partdeflect_blend_read_lib(BlendLibReader *reader, ID *id, PartDeflect *pd) +{ + if (pd && pd->tex) { + BLO_read_id_address(reader, id->lib, &pd->tex); + } + if (pd && pd->f_source) { + BLO_read_id_address(reader, id->lib, &pd->f_source); + } +} + +static void particle_settings_blend_read_lib(BlendLibReader *reader, ID *id) +{ + ParticleSettings *part = (ParticleSettings *)id; + BLO_read_id_address( + reader, part->id.lib, &part->ipo); /* XXX deprecated - old animation system */ + + BLO_read_id_address(reader, part->id.lib, &part->instance_object); + BLO_read_id_address(reader, part->id.lib, &part->instance_collection); + BLO_read_id_address(reader, part->id.lib, &part->force_group); + BLO_read_id_address(reader, part->id.lib, &part->bb_ob); + BLO_read_id_address(reader, part->id.lib, &part->collision_group); + + BKE_particle_partdeflect_blend_read_lib(reader, &part->id, part->pd); + BKE_particle_partdeflect_blend_read_lib(reader, &part->id, part->pd2); + + if (part->effector_weights) { + BLO_read_id_address(reader, part->id.lib, &part->effector_weights->group); + } + else { + part->effector_weights = BKE_effector_add_weights(part->force_group); + } + + if (part->instance_weights.first && part->instance_collection) { + LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) { + BLO_read_id_address(reader, part->id.lib, &dw->ob); + } + } + else { + BLI_listbase_clear(&part->instance_weights); + } + + if (part->boids) { + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { + switch (rule->type) { + case eBoidRuleType_Goal: + case eBoidRuleType_Avoid: { + BoidRuleGoalAvoid *brga = (BoidRuleGoalAvoid *)rule; + BLO_read_id_address(reader, part->id.lib, &brga->ob); + break; + } + case eBoidRuleType_FollowLeader: { + BoidRuleFollowLeader *brfl = (BoidRuleFollowLeader *)rule; + BLO_read_id_address(reader, part->id.lib, &brfl->ob); + break; + } + } + } + } + } + + for (int a = 0; a < MAX_MTEX; a++) { + MTex *mtex = part->mtex[a]; + if (mtex) { + BLO_read_id_address(reader, part->id.lib, &mtex->tex); + BLO_read_id_address(reader, part->id.lib, &mtex->object); + } + } +} + +static void particle_settings_blend_read_expand(BlendExpander *expander, ID *id) +{ + ParticleSettings *part = (ParticleSettings *)id; + BLO_expand(expander, part->instance_object); + BLO_expand(expander, part->instance_collection); + BLO_expand(expander, part->force_group); + BLO_expand(expander, part->bb_ob); + BLO_expand(expander, part->collision_group); + + for (int a = 0; a < MAX_MTEX; a++) { + if (part->mtex[a]) { + BLO_expand(expander, part->mtex[a]->tex); + BLO_expand(expander, part->mtex[a]->object); + } + } + + if (part->effector_weights) { + BLO_expand(expander, part->effector_weights->group); + } + + if (part->pd) { + BLO_expand(expander, part->pd->tex); + BLO_expand(expander, part->pd->f_source); + } + if (part->pd2) { + BLO_expand(expander, part->pd2->tex); + BLO_expand(expander, part->pd2->f_source); + } + + if (part->boids) { + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { + if (rule->type == eBoidRuleType_Avoid) { + BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule; + BLO_expand(expander, gabr->ob); + } + else if (rule->type == eBoidRuleType_FollowLeader) { + BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule; + BLO_expand(expander, flbr->ob); + } + } + } + } + + LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) { + BLO_expand(expander, dw->ob); + } +} + IDTypeInfo IDType_ID_PA = { .id_code = ID_PA, .id_filter = FILTER_ID_PA, @@ -223,10 +502,10 @@ IDTypeInfo IDType_ID_PA = { .foreach_id = particle_settings_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = particle_settings_blend_write, + .blend_read_data = particle_settings_blend_read_data, + .blend_read_lib = particle_settings_blend_read_lib, + .blend_read_expand = particle_settings_blend_read_expand, }; unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT]; diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index d9686eba29a..a357b5d98fb 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -21,6 +21,9 @@ * \ingroup bke */ +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #ifdef WIN32 # include "BLI_winstuff.h" #endif @@ -49,14 +52,18 @@ #include "BLT_translation.h" +#include "BKE_gpencil.h" #include "BKE_icons.h" #include "BKE_idprop.h" #include "BKE_idtype.h" +#include "BKE_lib_id.h" #include "BKE_lib_query.h" #include "BKE_node.h" #include "BKE_screen.h" #include "BKE_workspace.h" +#include "BLO_read_write.h" + static void screen_free_data(ID *id) { bScreen *screen = (bScreen *)id; @@ -230,6 +237,40 @@ static void screen_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void screen_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + bScreen *screen = (bScreen *)id; + /* Screens are reference counted, only saved if used by a workspace. */ + if (screen->id.us > 0 || BLO_write_is_undo(writer)) { + /* write LibData */ + /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */ + BLO_write_struct_at_address_with_filecode(writer, ID_SCRN, bScreen, id_address, screen); + BKE_id_blend_write(writer, &screen->id); + + BKE_previewimg_blend_write(writer, screen->preview); + + /* direct data */ + BKE_screen_area_map_blend_write(writer, AREAMAP_FROM_SCREEN(screen)); + } +} + +/* note: file read without screens option G_FILE_NO_UI; + * check lib pointers in call below */ +static void screen_blend_read_lib(BlendLibReader *reader, ID *id) +{ + bScreen *screen = (bScreen *)id; + /* deprecated, but needed for versioning (will be NULL'ed then) */ + BLO_read_id_address(reader, screen->id.lib, &screen->scene); + + screen->animtimer = NULL; /* saved in rare cases */ + screen->tool_tip = NULL; + screen->scrubbing = false; + + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + BKE_screen_area_blend_read_lib(reader, &screen->id, area); + } +} + IDTypeInfo IDType_ID_SCR = { .id_code = ID_SCR, .id_filter = 0, @@ -247,9 +288,10 @@ IDTypeInfo IDType_ID_SCR = { .foreach_id = screen_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, + .blend_write = screen_blend_write, + /* Cannot be used yet, because #direct_link_screen has a return value. */ .blend_read_data = NULL, - .blend_read_lib = NULL, + .blend_read_lib = screen_blend_read_lib, .blend_read_expand = NULL, }; @@ -1111,3 +1153,801 @@ void BKE_screen_header_alignment_reset(bScreen *screen) } screen->do_refresh = true; } + +void BKE_screen_view3d_shading_blend_write(BlendWriter *writer, View3DShading *shading) +{ + if (shading->prop) { + IDP_BlendWrite(writer, shading->prop); + } +} + +void BKE_screen_view3d_shading_blend_read_data(BlendDataReader *reader, View3DShading *shading) +{ + if (shading->prop) { + BLO_read_data_address(reader, &shading->prop); + IDP_BlendDataRead(reader, &shading->prop); + } +} + +static void write_region(BlendWriter *writer, ARegion *region, int spacetype) +{ + BLO_write_struct(writer, ARegion, region); + + if (region->regiondata) { + if (region->flag & RGN_FLAG_TEMP_REGIONDATA) { + return; + } + + switch (spacetype) { + case SPACE_VIEW3D: + if (region->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3d = region->regiondata; + BLO_write_struct(writer, RegionView3D, rv3d); + + if (rv3d->localvd) { + BLO_write_struct(writer, RegionView3D, rv3d->localvd); + } + if (rv3d->clipbb) { + BLO_write_struct(writer, BoundBox, rv3d->clipbb); + } + } + else { + printf("regiondata write missing!\n"); + } + break; + default: + printf("regiondata write missing!\n"); + } + } +} + +static void write_uilist(BlendWriter *writer, uiList *ui_list) +{ + BLO_write_struct(writer, uiList, ui_list); + + if (ui_list->properties) { + IDP_BlendWrite(writer, ui_list->properties); + } +} + +static void write_space_outliner(BlendWriter *writer, SpaceOutliner *space_outliner) +{ + BLI_mempool *ts = space_outliner->treestore; + + if (ts) { + SpaceOutliner space_outliner_flat = *space_outliner; + + int elems = BLI_mempool_len(ts); + /* linearize mempool to array */ + TreeStoreElem *data = elems ? BLI_mempool_as_arrayN(ts, "TreeStoreElem") : NULL; + + if (data) { + /* In this block we use the memory location of the treestore + * but _not_ its data, the addresses in this case are UUID's, + * since we can't rely on malloc giving us different values each time. + */ + TreeStore ts_flat = {0}; + + /* we know the treestore is at least as big as a pointer, + * so offsetting works to give us a UUID. */ + void *data_addr = (void *)POINTER_OFFSET(ts, sizeof(void *)); + + ts_flat.usedelem = elems; + ts_flat.totelem = elems; + ts_flat.data = data_addr; + + BLO_write_struct(writer, SpaceOutliner, space_outliner); + + BLO_write_struct_at_address(writer, TreeStore, ts, &ts_flat); + BLO_write_struct_array_at_address(writer, TreeStoreElem, elems, data_addr, data); + + MEM_freeN(data); + } + else { + space_outliner_flat.treestore = NULL; + BLO_write_struct_at_address(writer, SpaceOutliner, space_outliner, &space_outliner_flat); + } + } + else { + BLO_write_struct(writer, SpaceOutliner, space_outliner); + } +} + +static void write_panel_list(BlendWriter *writer, ListBase *lb) +{ + LISTBASE_FOREACH (Panel *, panel, lb) { + BLO_write_struct(writer, Panel, panel); + write_panel_list(writer, &panel->children); + } +} + +static void write_area_regions(BlendWriter *writer, ScrArea *area) +{ + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + write_region(writer, region, area->spacetype); + write_panel_list(writer, ®ion->panels); + + LISTBASE_FOREACH (PanelCategoryStack *, pc_act, ®ion->panels_category_active) { + BLO_write_struct(writer, PanelCategoryStack, pc_act); + } + + LISTBASE_FOREACH (uiList *, ui_list, ®ion->ui_lists) { + write_uilist(writer, ui_list); + } + + LISTBASE_FOREACH (uiPreview *, ui_preview, ®ion->ui_previews) { + BLO_write_struct(writer, uiPreview, ui_preview); + } + } + + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + LISTBASE_FOREACH (ARegion *, region, &sl->regionbase) { + write_region(writer, region, sl->spacetype); + } + + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + BLO_write_struct(writer, View3D, v3d); + + if (v3d->localvd) { + BLO_write_struct(writer, View3D, v3d->localvd); + } + + BKE_screen_view3d_shading_blend_write(writer, &v3d->shading); + } + else if (sl->spacetype == SPACE_GRAPH) { + SpaceGraph *sipo = (SpaceGraph *)sl; + ListBase tmpGhosts = sipo->runtime.ghost_curves; + + /* temporarily disable ghost curves when saving */ + BLI_listbase_clear(&sipo->runtime.ghost_curves); + + BLO_write_struct(writer, SpaceGraph, sl); + if (sipo->ads) { + BLO_write_struct(writer, bDopeSheet, sipo->ads); + } + + /* reenable ghost curves */ + sipo->runtime.ghost_curves = tmpGhosts; + } + else if (sl->spacetype == SPACE_PROPERTIES) { + BLO_write_struct(writer, SpaceProperties, sl); + } + else if (sl->spacetype == SPACE_FILE) { + SpaceFile *sfile = (SpaceFile *)sl; + + BLO_write_struct(writer, SpaceFile, sl); + if (sfile->params) { + BLO_write_struct(writer, FileSelectParams, sfile->params); + } + } + else if (sl->spacetype == SPACE_SEQ) { + BLO_write_struct(writer, SpaceSeq, sl); + } + else if (sl->spacetype == SPACE_OUTLINER) { + SpaceOutliner *space_outliner = (SpaceOutliner *)sl; + write_space_outliner(writer, space_outliner); + } + else if (sl->spacetype == SPACE_IMAGE) { + BLO_write_struct(writer, SpaceImage, sl); + } + else if (sl->spacetype == SPACE_TEXT) { + BLO_write_struct(writer, SpaceText, sl); + } + else if (sl->spacetype == SPACE_SCRIPT) { + SpaceScript *scr = (SpaceScript *)sl; + scr->but_refs = NULL; + BLO_write_struct(writer, SpaceScript, sl); + } + else if (sl->spacetype == SPACE_ACTION) { + BLO_write_struct(writer, SpaceAction, sl); + } + else if (sl->spacetype == SPACE_NLA) { + SpaceNla *snla = (SpaceNla *)sl; + + BLO_write_struct(writer, SpaceNla, snla); + if (snla->ads) { + BLO_write_struct(writer, bDopeSheet, snla->ads); + } + } + else if (sl->spacetype == SPACE_NODE) { + SpaceNode *snode = (SpaceNode *)sl; + BLO_write_struct(writer, SpaceNode, snode); + + LISTBASE_FOREACH (bNodeTreePath *, path, &snode->treepath) { + BLO_write_struct(writer, bNodeTreePath, path); + } + } + else if (sl->spacetype == SPACE_CONSOLE) { + SpaceConsole *con = (SpaceConsole *)sl; + + LISTBASE_FOREACH (ConsoleLine *, cl, &con->history) { + /* 'len_alloc' is invalid on write, set from 'len' on read */ + BLO_write_struct(writer, ConsoleLine, cl); + BLO_write_raw(writer, (size_t)cl->len + 1, cl->line); + } + BLO_write_struct(writer, SpaceConsole, sl); + } +#ifdef WITH_GLOBAL_AREA_WRITING + else if (sl->spacetype == SPACE_TOPBAR) { + BLO_write_struct(writer, SpaceTopBar, sl); + } + else if (sl->spacetype == SPACE_STATUSBAR) { + BLO_write_struct(writer, SpaceStatusBar, sl); + } +#endif + else if (sl->spacetype == SPACE_USERPREF) { + BLO_write_struct(writer, SpaceUserPref, sl); + } + else if (sl->spacetype == SPACE_CLIP) { + BLO_write_struct(writer, SpaceClip, sl); + } + else if (sl->spacetype == SPACE_INFO) { + BLO_write_struct(writer, SpaceInfo, sl); + } + } +} + +void BKE_screen_area_map_blend_write(BlendWriter *writer, ScrAreaMap *area_map) +{ + BLO_write_struct_list(writer, ScrVert, &area_map->vertbase); + BLO_write_struct_list(writer, ScrEdge, &area_map->edgebase); + LISTBASE_FOREACH (ScrArea *, area, &area_map->areabase) { + area->butspacetype = area->spacetype; /* Just for compatibility, will be reset below. */ + + BLO_write_struct(writer, ScrArea, area); + +#ifdef WITH_GLOBAL_AREA_WRITING + BLO_write_struct(writer, ScrGlobalAreaData, area->global); +#endif + + write_area_regions(writer, area); + + area->butspacetype = SPACE_EMPTY; /* Unset again, was changed above. */ + } +} + +static void direct_link_panel_list(BlendDataReader *reader, ListBase *lb) +{ + BLO_read_list(reader, lb); + + LISTBASE_FOREACH (Panel *, panel, lb) { + panel->runtime_flag = 0; + panel->activedata = NULL; + panel->type = NULL; + panel->runtime.custom_data_ptr = NULL; + direct_link_panel_list(reader, &panel->children); + } +} + +static void direct_link_region(BlendDataReader *reader, ARegion *region, int spacetype) +{ + direct_link_panel_list(reader, ®ion->panels); + + BLO_read_list(reader, ®ion->panels_category_active); + + BLO_read_list(reader, ®ion->ui_lists); + + /* The area's search filter is runtime only, so we need to clear the active flag on read. */ + region->flag &= ~RGN_FLAG_SEARCH_FILTER_ACTIVE; + + LISTBASE_FOREACH (uiList *, ui_list, ®ion->ui_lists) { + ui_list->type = NULL; + ui_list->dyn_data = NULL; + BLO_read_data_address(reader, &ui_list->properties); + IDP_BlendDataRead(reader, &ui_list->properties); + } + + BLO_read_list(reader, ®ion->ui_previews); + + if (spacetype == SPACE_EMPTY) { + /* unknown space type, don't leak regiondata */ + region->regiondata = NULL; + } + else if (region->flag & RGN_FLAG_TEMP_REGIONDATA) { + /* Runtime data, don't use. */ + region->regiondata = NULL; + } + else { + BLO_read_data_address(reader, ®ion->regiondata); + if (region->regiondata) { + if (spacetype == SPACE_VIEW3D) { + RegionView3D *rv3d = region->regiondata; + + BLO_read_data_address(reader, &rv3d->localvd); + BLO_read_data_address(reader, &rv3d->clipbb); + + rv3d->depths = NULL; + rv3d->render_engine = NULL; + rv3d->sms = NULL; + rv3d->smooth_timer = NULL; + + rv3d->rflag &= ~(RV3D_NAVIGATING | RV3D_PAINTING); + rv3d->runtime_viewlock = 0; + } + } + } + + region->v2d.sms = NULL; + region->v2d.alpha_hor = region->v2d.alpha_vert = 255; /* visible by default */ + BLI_listbase_clear(®ion->panels_category); + BLI_listbase_clear(®ion->handlers); + BLI_listbase_clear(®ion->uiblocks); + region->headerstr = NULL; + region->visible = 0; + region->type = NULL; + region->do_draw = 0; + region->gizmo_map = NULL; + region->regiontimer = NULL; + region->draw_buffer = NULL; + memset(®ion->drawrct, 0, sizeof(region->drawrct)); +} + +/* for the saved 2.50 files without regiondata */ +/* and as patch for 2.48 and older */ +void BKE_screen_view3d_do_versions_250(View3D *v3d, ListBase *regions) +{ + LISTBASE_FOREACH (ARegion *, region, regions) { + if (region->regiontype == RGN_TYPE_WINDOW && region->regiondata == NULL) { + RegionView3D *rv3d; + + rv3d = region->regiondata = MEM_callocN(sizeof(RegionView3D), "region v3d patch"); + rv3d->persp = (char)v3d->persp; + rv3d->view = (char)v3d->view; + rv3d->dist = v3d->dist; + copy_v3_v3(rv3d->ofs, v3d->ofs); + copy_qt_qt(rv3d->viewquat, v3d->viewquat); + } + } + + /* this was not initialized correct always */ + if (v3d->gridsubdiv == 0) { + v3d->gridsubdiv = 10; + } +} + +static void direct_link_area(BlendDataReader *reader, ScrArea *area) +{ + BLO_read_list(reader, &(area->spacedata)); + BLO_read_list(reader, &(area->regionbase)); + + BLI_listbase_clear(&area->handlers); + area->type = NULL; /* spacetype callbacks */ + + /* Should always be unset so that rna_Area_type_get works correctly. */ + area->butspacetype = SPACE_EMPTY; + + area->region_active_win = -1; + + area->flag &= ~AREA_FLAG_ACTIVE_TOOL_UPDATE; + + BLO_read_data_address(reader, &area->global); + + /* if we do not have the spacetype registered we cannot + * free it, so don't allocate any new memory for such spacetypes. */ + if (!BKE_spacetype_exists(area->spacetype)) { + /* Hint for versioning code to replace deprecated space types. */ + area->butspacetype = area->spacetype; + + area->spacetype = SPACE_EMPTY; + } + + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + direct_link_region(reader, region, area->spacetype); + } + + /* accident can happen when read/save new file with older version */ + /* 2.50: we now always add spacedata for info */ + if (area->spacedata.first == NULL) { + SpaceInfo *sinfo = MEM_callocN(sizeof(SpaceInfo), "spaceinfo"); + area->spacetype = sinfo->spacetype = SPACE_INFO; + BLI_addtail(&area->spacedata, sinfo); + } + /* add local view3d too */ + else if (area->spacetype == SPACE_VIEW3D) { + BKE_screen_view3d_do_versions_250(area->spacedata.first, &area->regionbase); + } + + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + BLO_read_list(reader, &(sl->regionbase)); + + /* if we do not have the spacetype registered we cannot + * free it, so don't allocate any new memory for such spacetypes. */ + if (!BKE_spacetype_exists(sl->spacetype)) { + sl->spacetype = SPACE_EMPTY; + } + + LISTBASE_FOREACH (ARegion *, region, &sl->regionbase) { + direct_link_region(reader, region, sl->spacetype); + } + + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + + v3d->flag |= V3D_INVALID_BACKBUF; + + if (v3d->gpd) { + BLO_read_data_address(reader, &v3d->gpd); + BKE_gpencil_blend_read_data(reader, v3d->gpd); + } + BLO_read_data_address(reader, &v3d->localvd); + + /* Runtime data */ + v3d->runtime.properties_storage = NULL; + v3d->runtime.flag = 0; + + /* render can be quite heavy, set to solid on load */ + if (v3d->shading.type == OB_RENDER) { + v3d->shading.type = OB_SOLID; + } + v3d->shading.prev_type = OB_SOLID; + + BKE_screen_view3d_shading_blend_read_data(reader, &v3d->shading); + + BKE_screen_view3d_do_versions_250(v3d, &sl->regionbase); + } + else if (sl->spacetype == SPACE_GRAPH) { + SpaceGraph *sipo = (SpaceGraph *)sl; + + BLO_read_data_address(reader, &sipo->ads); + BLI_listbase_clear(&sipo->runtime.ghost_curves); + } + else if (sl->spacetype == SPACE_NLA) { + SpaceNla *snla = (SpaceNla *)sl; + + BLO_read_data_address(reader, &snla->ads); + } + else if (sl->spacetype == SPACE_OUTLINER) { + SpaceOutliner *space_outliner = (SpaceOutliner *)sl; + + /* use #BLO_read_get_new_data_address_no_us and do not free old memory avoiding double + * frees and use of freed memory. this could happen because of a + * bug fixed in revision 58959 where the treestore memory address + * was not unique */ + TreeStore *ts = BLO_read_get_new_data_address_no_us(reader, space_outliner->treestore); + space_outliner->treestore = NULL; + if (ts) { + TreeStoreElem *elems = BLO_read_get_new_data_address_no_us(reader, ts->data); + + space_outliner->treestore = BLI_mempool_create( + sizeof(TreeStoreElem), ts->usedelem, 512, BLI_MEMPOOL_ALLOW_ITER); + if (ts->usedelem && elems) { + for (int i = 0; i < ts->usedelem; i++) { + TreeStoreElem *new_elem = BLI_mempool_alloc(space_outliner->treestore); + *new_elem = elems[i]; + } + } + /* we only saved what was used */ + space_outliner->storeflag |= SO_TREESTORE_CLEANUP; /* at first draw */ + } + space_outliner->treehash = NULL; + space_outliner->tree.first = space_outliner->tree.last = NULL; + } + else if (sl->spacetype == SPACE_IMAGE) { + SpaceImage *sima = (SpaceImage *)sl; + + sima->iuser.scene = NULL; + sima->iuser.ok = 1; + sima->scopes.waveform_1 = NULL; + sima->scopes.waveform_2 = NULL; + sima->scopes.waveform_3 = NULL; + sima->scopes.vecscope = NULL; + sima->scopes.ok = 0; + + /* WARNING: gpencil data is no longer stored directly in sima after 2.5 + * so sacrifice a few old files for now to avoid crashes with new files! + * committed: r28002 */ +#if 0 + sima->gpd = newdataadr(fd, sima->gpd); + if (sima->gpd) { + BKE_gpencil_blend_read_data(fd, sima->gpd); + } +#endif + } + else if (sl->spacetype == SPACE_NODE) { + SpaceNode *snode = (SpaceNode *)sl; + + if (snode->gpd) { + BLO_read_data_address(reader, &snode->gpd); + BKE_gpencil_blend_read_data(reader, snode->gpd); + } + + BLO_read_list(reader, &snode->treepath); + snode->edittree = NULL; + snode->iofsd = NULL; + BLI_listbase_clear(&snode->linkdrag); + } + else if (sl->spacetype == SPACE_TEXT) { + SpaceText *st = (SpaceText *)sl; + memset(&st->runtime, 0, sizeof(st->runtime)); + } + else if (sl->spacetype == SPACE_SEQ) { + SpaceSeq *sseq = (SpaceSeq *)sl; + + /* grease pencil data is not a direct data and can't be linked from direct_link* + * functions, it should be linked from lib_link* functions instead + * + * otherwise it'll lead to lost grease data on open because it'll likely be + * read from file after all other users of grease pencil and newdataadr would + * simple return NULL here (sergey) + */ +#if 0 + if (sseq->gpd) { + sseq->gpd = newdataadr(fd, sseq->gpd); + BKE_gpencil_blend_read_data(fd, sseq->gpd); + } +#endif + sseq->scopes.reference_ibuf = NULL; + sseq->scopes.zebra_ibuf = NULL; + sseq->scopes.waveform_ibuf = NULL; + sseq->scopes.sep_waveform_ibuf = NULL; + sseq->scopes.vector_ibuf = NULL; + sseq->scopes.histogram_ibuf = NULL; + } + else if (sl->spacetype == SPACE_PROPERTIES) { + SpaceProperties *sbuts = (SpaceProperties *)sl; + + sbuts->path = NULL; + sbuts->texuser = NULL; + sbuts->mainbo = sbuts->mainb; + sbuts->mainbuser = sbuts->mainb; + sbuts->runtime = NULL; + } + else if (sl->spacetype == SPACE_CONSOLE) { + SpaceConsole *sconsole = (SpaceConsole *)sl; + + BLO_read_list(reader, &sconsole->scrollback); + BLO_read_list(reader, &sconsole->history); + + /* comma expressions, (e.g. expr1, expr2, expr3) evaluate each expression, + * from left to right. the right-most expression sets the result of the comma + * expression as a whole*/ + LISTBASE_FOREACH_MUTABLE (ConsoleLine *, cl, &sconsole->history) { + BLO_read_data_address(reader, &cl->line); + if (cl->line) { + /* the allocted length is not written, so reset here */ + cl->len_alloc = cl->len + 1; + } + else { + BLI_remlink(&sconsole->history, cl); + MEM_freeN(cl); + } + } + } + else if (sl->spacetype == SPACE_FILE) { + SpaceFile *sfile = (SpaceFile *)sl; + + /* this sort of info is probably irrelevant for reloading... + * plus, it isn't saved to files yet! + */ + sfile->folders_prev = sfile->folders_next = NULL; + sfile->files = NULL; + sfile->layout = NULL; + sfile->op = NULL; + sfile->previews_timer = NULL; + BLO_read_data_address(reader, &sfile->params); + } + else if (sl->spacetype == SPACE_CLIP) { + SpaceClip *sclip = (SpaceClip *)sl; + + sclip->scopes.track_search = NULL; + sclip->scopes.track_preview = NULL; + sclip->scopes.ok = 0; + } + } + + BLI_listbase_clear(&area->actionzones); + + BLO_read_data_address(reader, &area->v1); + BLO_read_data_address(reader, &area->v2); + BLO_read_data_address(reader, &area->v3); + BLO_read_data_address(reader, &area->v4); +} + +/** + * \return false on error. + */ +bool BKE_screen_area_map_blend_read_data(BlendDataReader *reader, ScrAreaMap *area_map) +{ + BLO_read_list(reader, &area_map->vertbase); + BLO_read_list(reader, &area_map->edgebase); + BLO_read_list(reader, &area_map->areabase); + LISTBASE_FOREACH (ScrArea *, area, &area_map->areabase) { + direct_link_area(reader, area); + } + + /* edges */ + LISTBASE_FOREACH (ScrEdge *, se, &area_map->edgebase) { + BLO_read_data_address(reader, &se->v1); + BLO_read_data_address(reader, &se->v2); + BKE_screen_sort_scrvert(&se->v1, &se->v2); + + if (se->v1 == NULL) { + BLI_remlink(&area_map->edgebase, se); + + return false; + } + } + + return true; +} + +void BKE_screen_area_blend_read_lib(BlendLibReader *reader, ID *parent_id, ScrArea *area) +{ + BLO_read_id_address(reader, parent_id->lib, &area->full); + + memset(&area->runtime, 0x0, sizeof(area->runtime)); + + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + switch (sl->spacetype) { + case SPACE_VIEW3D: { + View3D *v3d = (View3D *)sl; + + BLO_read_id_address(reader, parent_id->lib, &v3d->camera); + BLO_read_id_address(reader, parent_id->lib, &v3d->ob_center); + + if (v3d->localvd) { + BLO_read_id_address(reader, parent_id->lib, &v3d->localvd->camera); + } + break; + } + case SPACE_GRAPH: { + SpaceGraph *sipo = (SpaceGraph *)sl; + bDopeSheet *ads = sipo->ads; + + if (ads) { + BLO_read_id_address(reader, parent_id->lib, &ads->source); + BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp); + } + break; + } + case SPACE_PROPERTIES: { + SpaceProperties *sbuts = (SpaceProperties *)sl; + BLO_read_id_address(reader, parent_id->lib, &sbuts->pinid); + if (sbuts->pinid == NULL) { + sbuts->flag &= ~SB_PIN_CONTEXT; + } + break; + } + case SPACE_FILE: + break; + case SPACE_ACTION: { + SpaceAction *saction = (SpaceAction *)sl; + bDopeSheet *ads = &saction->ads; + + if (ads) { + BLO_read_id_address(reader, parent_id->lib, &ads->source); + BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp); + } + + BLO_read_id_address(reader, parent_id->lib, &saction->action); + break; + } + case SPACE_IMAGE: { + SpaceImage *sima = (SpaceImage *)sl; + + BLO_read_id_address(reader, parent_id->lib, &sima->image); + BLO_read_id_address(reader, parent_id->lib, &sima->mask_info.mask); + + /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data + * so fingers crossed this works fine! + */ + BLO_read_id_address(reader, parent_id->lib, &sima->gpd); + break; + } + case SPACE_SEQ: { + SpaceSeq *sseq = (SpaceSeq *)sl; + + /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data + * so fingers crossed this works fine! + */ + BLO_read_id_address(reader, parent_id->lib, &sseq->gpd); + break; + } + case SPACE_NLA: { + SpaceNla *snla = (SpaceNla *)sl; + bDopeSheet *ads = snla->ads; + + if (ads) { + BLO_read_id_address(reader, parent_id->lib, &ads->source); + BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp); + } + break; + } + case SPACE_TEXT: { + SpaceText *st = (SpaceText *)sl; + + BLO_read_id_address(reader, parent_id->lib, &st->text); + break; + } + case SPACE_SCRIPT: { + SpaceScript *scpt = (SpaceScript *)sl; + /*scpt->script = NULL; - 2.45 set to null, better re-run the script */ + if (scpt->script) { + BLO_read_id_address(reader, parent_id->lib, &scpt->script); + if (scpt->script) { + SCRIPT_SET_NULL(scpt->script); + } + } + break; + } + case SPACE_OUTLINER: { + SpaceOutliner *space_outliner = (SpaceOutliner *)sl; + BLO_read_id_address(reader, NULL, &space_outliner->search_tse.id); + + if (space_outliner->treestore) { + TreeStoreElem *tselem; + BLI_mempool_iter iter; + + BLI_mempool_iternew(space_outliner->treestore, &iter); + while ((tselem = BLI_mempool_iterstep(&iter))) { + BLO_read_id_address(reader, NULL, &tselem->id); + } + if (space_outliner->treehash) { + /* rebuild hash table, because it depends on ids too */ + space_outliner->storeflag |= SO_TREESTORE_REBUILD; + } + } + break; + } + case SPACE_NODE: { + SpaceNode *snode = (SpaceNode *)sl; + + /* node tree can be stored locally in id too, link this first */ + BLO_read_id_address(reader, parent_id->lib, &snode->id); + BLO_read_id_address(reader, parent_id->lib, &snode->from); + + bNodeTree *ntree = snode->id ? ntreeFromID(snode->id) : NULL; + if (ntree) { + snode->nodetree = ntree; + } + else { + BLO_read_id_address(reader, parent_id->lib, &snode->nodetree); + } + + bNodeTreePath *path; + for (path = snode->treepath.first; path; path = path->next) { + if (path == snode->treepath.first) { + /* first nodetree in path is same as snode->nodetree */ + path->nodetree = snode->nodetree; + } + else { + BLO_read_id_address(reader, parent_id->lib, &path->nodetree); + } + + if (!path->nodetree) { + break; + } + } + + /* remaining path entries are invalid, remove */ + bNodeTreePath *path_next; + for (; path; path = path_next) { + path_next = path->next; + + BLI_remlink(&snode->treepath, path); + MEM_freeN(path); + } + + /* edittree is just the last in the path, + * set this directly since the path may have been shortened above */ + if (snode->treepath.last) { + path = snode->treepath.last; + snode->edittree = path->nodetree; + } + else { + snode->edittree = NULL; + } + break; + } + case SPACE_CLIP: { + SpaceClip *sclip = (SpaceClip *)sl; + BLO_read_id_address(reader, parent_id->lib, &sclip->clip); + BLO_read_id_address(reader, parent_id->lib, &sclip->mask_info.mask); + break; + } + default: + break; + } + } +} diff --git a/source/blender/blenkernel/intern/shader_fx.c b/source/blender/blenkernel/intern/shader_fx.c index 29cb574c7bc..2ae95492708 100644 --- a/source/blender/blenkernel/intern/shader_fx.c +++ b/source/blender/blenkernel/intern/shader_fx.c @@ -36,6 +36,7 @@ #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_screen_types.h" #include "DNA_shader_fx_types.h" #include "BKE_gpencil.h" @@ -177,7 +178,7 @@ void BKE_shaderfxType_panel_id(ShaderFxType type, char *r_idname) void BKE_shaderfx_panel_expand(ShaderFxData *fx) { - fx->ui_expand_flag |= (1 << 0); + fx->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT; } void BKE_shaderfx_copydata_generic(const ShaderFxData *fx_src, ShaderFxData *fx_dst) diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c index 0a0f81f7829..a319c55709d 100644 --- a/source/blender/blenkernel/intern/undo_system.c +++ b/source/blender/blenkernel/intern/undo_system.c @@ -95,7 +95,7 @@ static bool g_undo_callback_running = false; /** \name Public Undo Types * * Unfortunately we need this for a handful of places. - */ + * \{ */ const UndoType *BKE_UNDOSYS_TYPE_IMAGE = NULL; const UndoType *BKE_UNDOSYS_TYPE_MEMFILE = NULL; const UndoType *BKE_UNDOSYS_TYPE_PAINTCURVE = NULL; @@ -549,6 +549,8 @@ bool BKE_undosys_step_push_with_type(UndoStack *ustack, BLI_strncpy(us->name, name, sizeof(us->name)); } us->type = ut; + /* True by default, code needs to explicitely set it to false if necessary. */ + us->use_old_bmain_data = true; /* Initialized, not added yet. */ CLOG_INFO(&LOG, 1, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name); @@ -580,6 +582,12 @@ bool BKE_undosys_step_push_with_type(UndoStack *ustack, } } + if (ustack->group_level > 0) { + /* Temporarily set skip for the active step. + * This is an invalid state which must be corrected once the last group ends. */ + ustack->step_active->skip = true; + } + undosys_stack_validate(ustack, true); return true; } @@ -849,10 +857,49 @@ void BKE_undosys_type_free_all(void) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Undo Stack Grouping + * + * This enables skip while group-level is set. + * In general it's not allowed that #UndoStack.step_active have 'skip' enabled. + * + * This rule is relaxed for grouping, however it's important each call to + * #BKE_undosys_stack_group_begin has a matching #BKE_undosys_stack_group_end. + * + * - Levels are used so nesting is supported, where the last call to #BKE_undosys_stack_group_end + * will set the active undo step that should not be skipped. + * + * - Correct begin/end is checked by an assert since any errors here will cause undo + * to consider all steps part of one large group. + * + * - Calls to begin/end with no undo steps being pushed is supported and does nothing. + * + * \{ */ + +void BKE_undosys_stack_group_begin(UndoStack *ustack) +{ + BLI_assert(ustack->group_level >= 0); + ustack->group_level += 1; +} + +void BKE_undosys_stack_group_end(UndoStack *ustack) +{ + ustack->group_level -= 1; + BLI_assert(ustack->group_level >= 0); + + if (ustack->group_level == 0) { + if (LIKELY(ustack->step_active != NULL)) { + ustack->step_active->skip = false; + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name ID Reference Utilities * * Unfortunately we need this for a handful of places. - */ + * \{ */ static void UNUSED_FUNCTION(BKE_undosys_foreach_ID_ref(UndoStack *ustack, UndoTypeForEachIDRefFn foreach_ID_ref_fn, diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c index 43e03fb5165..52420810171 100644 --- a/source/blender/blenkernel/intern/workspace.c +++ b/source/blender/blenkernel/intern/workspace.c @@ -48,6 +48,8 @@ #include "MEM_guardedalloc.h" +#include "BLO_read_write.h" + /* -------------------------------------------------------------------- */ static void workspace_free_data(ID *id) @@ -75,6 +77,98 @@ static void workspace_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void workspace_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + WorkSpace *workspace = (WorkSpace *)id; + + BLO_write_id_struct(writer, WorkSpace, id_address, &workspace->id); + BKE_id_blend_write(writer, &workspace->id); + BLO_write_struct_list(writer, WorkSpaceLayout, &workspace->layouts); + BLO_write_struct_list(writer, WorkSpaceDataRelation, &workspace->hook_layout_relations); + BLO_write_struct_list(writer, wmOwnerID, &workspace->owner_ids); + BLO_write_struct_list(writer, bToolRef, &workspace->tools); + LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { + if (tref->properties) { + IDP_BlendWrite(writer, tref->properties); + } + } +} + +static void workspace_blend_read_data(BlendDataReader *reader, ID *id) +{ + WorkSpace *workspace = (WorkSpace *)id; + + BLO_read_list(reader, &workspace->layouts); + BLO_read_list(reader, &workspace->hook_layout_relations); + BLO_read_list(reader, &workspace->owner_ids); + BLO_read_list(reader, &workspace->tools); + + LISTBASE_FOREACH (WorkSpaceDataRelation *, relation, &workspace->hook_layout_relations) { + /* parent pointer does not belong to workspace data and is therefore restored in lib_link step + * of window manager.*/ + BLO_read_data_address(reader, &relation->value); + } + + LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { + tref->runtime = NULL; + BLO_read_data_address(reader, &tref->properties); + IDP_BlendDataRead(reader, &tref->properties); + } + + workspace->status_text = NULL; + + id_us_ensure_real(&workspace->id); +} + +static void workspace_blend_read_lib(BlendLibReader *reader, ID *id) +{ + WorkSpace *workspace = (WorkSpace *)id; + Main *bmain = BLO_read_lib_get_main(reader); + + /* Restore proper 'parent' pointers to relevant data, and clean up unused/invalid entries. */ + LISTBASE_FOREACH_MUTABLE (WorkSpaceDataRelation *, relation, &workspace->hook_layout_relations) { + relation->parent = NULL; + LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) { + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { + if (win->winid == relation->parentid) { + relation->parent = win->workspace_hook; + } + } + } + if (relation->parent == NULL) { + BLI_freelinkN(&workspace->hook_layout_relations, relation); + } + } + + LISTBASE_FOREACH_MUTABLE (WorkSpaceLayout *, layout, &workspace->layouts) { + BLO_read_id_address(reader, id->lib, &layout->screen); + + if (layout->screen) { + if (ID_IS_LINKED(id)) { + layout->screen->winid = 0; + if (layout->screen->temp) { + /* delete temp layouts when appending */ + BKE_workspace_layout_remove(bmain, workspace, layout); + } + } + } + else { + /* If we're reading a layout without screen stored, it's useless and we shouldn't keep it + * around. */ + BKE_workspace_layout_remove(bmain, workspace, layout); + } + } +} + +static void workspace_blend_read_expand(BlendExpander *expander, ID *id) +{ + WorkSpace *workspace = (WorkSpace *)id; + + LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) { + BLO_expand(expander, BKE_workspace_layout_screen_get(layout)); + } +} + IDTypeInfo IDType_ID_WS = { .id_code = ID_WS, .id_filter = FILTER_ID_WS, @@ -92,10 +186,10 @@ IDTypeInfo IDType_ID_WS = { .foreach_id = workspace_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = workspace_blend_write, + .blend_read_data = workspace_blend_read_data, + .blend_read_lib = workspace_blend_read_lib, + .blend_read_expand = workspace_blend_read_expand, }; /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenloader/BLO_read_write.h b/source/blender/blenloader/BLO_read_write.h index 5d685cc6687..3600ae504a1 100644 --- a/source/blender/blenloader/BLO_read_write.h +++ b/source/blender/blenloader/BLO_read_write.h @@ -52,6 +52,8 @@ typedef struct BlendExpander BlendExpander; typedef struct BlendLibReader BlendLibReader; typedef struct BlendWriter BlendWriter; +struct Main; + /* Blend Write API * =============== * @@ -106,6 +108,14 @@ void BLO_write_struct_at_address_by_id(BlendWriter *writer, BLO_write_struct_at_address_by_id( \ writer, BLO_get_struct_id(writer, struct_name), address, data_ptr) +/* Write single struct at address and specify a filecode. */ +void BLO_write_struct_at_address_by_id_with_filecode( + BlendWriter *writer, int filecode, int struct_id, const void *address, const void *data_ptr); +#define BLO_write_struct_at_address_with_filecode( \ + writer, filecode, struct_name, address, data_ptr) \ + BLO_write_struct_at_address_by_id_with_filecode( \ + writer, filecode, BLO_get_struct_id(writer, struct_name), address, data_ptr) + /* Write struct array. */ void BLO_write_struct_array_by_name(BlendWriter *writer, const char *struct_name, @@ -177,6 +187,7 @@ bool BLO_write_is_undo(BlendWriter *writer); */ void *BLO_read_get_new_data_address(BlendDataReader *reader, const void *old_address); +void *BLO_read_get_new_data_address_no_us(BlendDataReader *reader, const void *old_address); void *BLO_read_get_new_packed_address(BlendDataReader *reader, const void *old_address); #define BLO_read_data_address(reader, ptr_p) \ @@ -214,6 +225,7 @@ ID *BLO_read_get_new_id_address(BlendLibReader *reader, struct Library *lib, str /* Misc. */ bool BLO_read_lib_is_undo(BlendLibReader *reader); +struct Main *BLO_read_lib_get_main(BlendLibReader *reader); /* Blend Expand API * =================== diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 5ff3d383a72..32056d03509 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -267,10 +267,6 @@ static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const static BHead *find_bhead_from_idname(FileData *fd, const char *idname); static bool library_link_idcode_needs_tag_check(const short idcode, const int flag); -#ifdef USE_COLLECTION_COMPAT_28 -static void expand_scene_collection(BlendExpander *expander, SceneCollection *sc); -#endif - typedef struct BHeadN { struct BHeadN *next, *prev; #ifdef USE_BHEAD_READ_ON_DEMAND @@ -2261,7 +2257,6 @@ static void link_glob_list(FileData *fd, ListBase *lb) /* for glob data */ * \{ */ static void lib_link_id(BlendLibReader *reader, ID *id); -static void lib_link_collection(BlendLibReader *reader, Collection *collection); static void lib_link_id_embedded_id(BlendLibReader *reader, ID *id) { @@ -2277,7 +2272,7 @@ static void lib_link_id_embedded_id(BlendLibReader *reader, ID *id) Scene *scene = (Scene *)id; if (scene->master_collection != NULL) { lib_link_id(reader, &scene->master_collection->id); - lib_link_collection(reader, scene->master_collection); + BKE_collection_blend_read_lib(reader, scene->master_collection); } } } @@ -2324,7 +2319,6 @@ static void direct_link_id_override_property_cb(BlendDataReader *reader, void *d static void direct_link_id_common( BlendDataReader *reader, Library *current_library, ID *id, ID *id_old, const int tag); -static void direct_link_collection(BlendDataReader *reader, Collection *collection); static void direct_link_id_embedded_id(BlendDataReader *reader, Library *current_library, @@ -2352,7 +2346,7 @@ static void direct_link_id_embedded_id(BlendDataReader *reader, &scene->master_collection->id, id_old != NULL ? &((Scene *)id_old)->master_collection->id : NULL, 0); - direct_link_collection(reader, scene->master_collection); + BKE_collection_blend_read_data(reader, scene->master_collection); } } } @@ -2574,69 +2568,6 @@ static void lib_link_constraint_channels(BlendLibReader *reader, ID *id, ListBas /** \name Read ID: WorkSpace * \{ */ -static void lib_link_workspaces(BlendLibReader *reader, WorkSpace *workspace) -{ - ID *id = (ID *)workspace; - - /* Restore proper 'parent' pointers to relevant data, and clean up unused/invalid entries. */ - LISTBASE_FOREACH_MUTABLE (WorkSpaceDataRelation *, relation, &workspace->hook_layout_relations) { - relation->parent = NULL; - LISTBASE_FOREACH (wmWindowManager *, wm, &reader->main->wm) { - LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { - if (win->winid == relation->parentid) { - relation->parent = win->workspace_hook; - } - } - } - if (relation->parent == NULL) { - BLI_freelinkN(&workspace->hook_layout_relations, relation); - } - } - - LISTBASE_FOREACH_MUTABLE (WorkSpaceLayout *, layout, &workspace->layouts) { - BLO_read_id_address(reader, id->lib, &layout->screen); - - if (layout->screen) { - if (ID_IS_LINKED(id)) { - layout->screen->winid = 0; - if (layout->screen->temp) { - /* delete temp layouts when appending */ - BKE_workspace_layout_remove(reader->main, workspace, layout); - } - } - } - else { - /* If we're reading a layout without screen stored, it's useless and we shouldn't keep it - * around. */ - BKE_workspace_layout_remove(reader->main, workspace, layout); - } - } -} - -static void direct_link_workspace(BlendDataReader *reader, WorkSpace *workspace) -{ - BLO_read_list(reader, &workspace->layouts); - BLO_read_list(reader, &workspace->hook_layout_relations); - BLO_read_list(reader, &workspace->owner_ids); - BLO_read_list(reader, &workspace->tools); - - LISTBASE_FOREACH (WorkSpaceDataRelation *, relation, &workspace->hook_layout_relations) { - /* parent pointer does not belong to workspace data and is therefore restored in lib_link step - * of window manager.*/ - BLO_read_data_address(reader, &relation->value); - } - - LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { - tref->runtime = NULL; - BLO_read_data_address(reader, &tref->properties); - IDP_BlendDataRead(reader, &tref->properties); - } - - workspace->status_text = NULL; - - id_us_ensure_real(&workspace->id); -} - static void lib_link_workspace_instance_hook(BlendLibReader *reader, WorkSpaceInstanceHook *hook, ID *id) @@ -2910,132 +2841,6 @@ static void direct_link_pointcache_list(BlendDataReader *reader, } } -static void lib_link_partdeflect(BlendLibReader *reader, ID *id, PartDeflect *pd) -{ - if (pd && pd->tex) { - BLO_read_id_address(reader, id->lib, &pd->tex); - } - if (pd && pd->f_source) { - BLO_read_id_address(reader, id->lib, &pd->f_source); - } -} - -static void lib_link_particlesettings(BlendLibReader *reader, ParticleSettings *part) -{ - BLO_read_id_address( - reader, part->id.lib, &part->ipo); /* XXX deprecated - old animation system */ - - BLO_read_id_address(reader, part->id.lib, &part->instance_object); - BLO_read_id_address(reader, part->id.lib, &part->instance_collection); - BLO_read_id_address(reader, part->id.lib, &part->force_group); - BLO_read_id_address(reader, part->id.lib, &part->bb_ob); - BLO_read_id_address(reader, part->id.lib, &part->collision_group); - - lib_link_partdeflect(reader, &part->id, part->pd); - lib_link_partdeflect(reader, &part->id, part->pd2); - - if (part->effector_weights) { - BLO_read_id_address(reader, part->id.lib, &part->effector_weights->group); - } - else { - part->effector_weights = BKE_effector_add_weights(part->force_group); - } - - if (part->instance_weights.first && part->instance_collection) { - LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) { - BLO_read_id_address(reader, part->id.lib, &dw->ob); - } - } - else { - BLI_listbase_clear(&part->instance_weights); - } - - if (part->boids) { - LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { - LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { - switch (rule->type) { - case eBoidRuleType_Goal: - case eBoidRuleType_Avoid: { - BoidRuleGoalAvoid *brga = (BoidRuleGoalAvoid *)rule; - BLO_read_id_address(reader, part->id.lib, &brga->ob); - break; - } - case eBoidRuleType_FollowLeader: { - BoidRuleFollowLeader *brfl = (BoidRuleFollowLeader *)rule; - BLO_read_id_address(reader, part->id.lib, &brfl->ob); - break; - } - } - } - } - } - - for (int a = 0; a < MAX_MTEX; a++) { - MTex *mtex = part->mtex[a]; - if (mtex) { - BLO_read_id_address(reader, part->id.lib, &mtex->tex); - BLO_read_id_address(reader, part->id.lib, &mtex->object); - } - } -} - -static void direct_link_partdeflect(PartDeflect *pd) -{ - if (pd) { - pd->rng = NULL; - } -} - -static void direct_link_particlesettings(BlendDataReader *reader, ParticleSettings *part) -{ - BLO_read_data_address(reader, &part->adt); - BLO_read_data_address(reader, &part->pd); - BLO_read_data_address(reader, &part->pd2); - - BKE_animdata_blend_read_data(reader, part->adt); - direct_link_partdeflect(part->pd); - direct_link_partdeflect(part->pd2); - - BLO_read_data_address(reader, &part->clumpcurve); - if (part->clumpcurve) { - BKE_curvemapping_blend_read(reader, part->clumpcurve); - } - BLO_read_data_address(reader, &part->roughcurve); - if (part->roughcurve) { - BKE_curvemapping_blend_read(reader, part->roughcurve); - } - BLO_read_data_address(reader, &part->twistcurve); - if (part->twistcurve) { - BKE_curvemapping_blend_read(reader, part->twistcurve); - } - - BLO_read_data_address(reader, &part->effector_weights); - if (!part->effector_weights) { - part->effector_weights = BKE_effector_add_weights(part->force_group); - } - - BLO_read_list(reader, &part->instance_weights); - - BLO_read_data_address(reader, &part->boids); - BLO_read_data_address(reader, &part->fluid); - - if (part->boids) { - BLO_read_list(reader, &part->boids->states); - - LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { - BLO_read_list(reader, &state->rules); - BLO_read_list(reader, &state->conditions); - BLO_read_list(reader, &state->actions); - } - } - for (int a = 0; a < MAX_MTEX; a++) { - BLO_read_data_address(reader, &part->mtex[a]); - } - - /* Protect against integer overflow vulnerability. */ - CLAMP(part->trail_count, 1, 100000); -} - static void lib_link_particlesystems(BlendLibReader *reader, Object *ob, ID *id, @@ -3361,7 +3166,7 @@ static void lib_link_object(BlendLibReader *reader, Object *ob) /* texture field */ if (ob->pd) { - lib_link_partdeflect(reader, &ob->id, ob->pd); + BKE_particle_partdeflect_blend_read_lib(reader, &ob->id, ob->pd); } if (ob->soft) { @@ -3945,7 +3750,7 @@ static void direct_link_object(BlendDataReader *reader, Object *ob) } BLO_read_data_address(reader, &ob->pd); - direct_link_partdeflect(ob->pd); + BKE_particle_partdeflect_blend_read_data(reader, ob->pd); BLO_read_data_address(reader, &ob->soft); if (ob->soft) { SoftBody *sb = ob->soft; @@ -4061,187 +3866,6 @@ static void direct_link_view_settings(BlendDataReader *reader, /** \} */ /* -------------------------------------------------------------------- */ -/** \name Read View Layer (Collection Data) - * \{ */ - -static void direct_link_layer_collections(BlendDataReader *reader, ListBase *lb, bool master) -{ - BLO_read_list(reader, lb); - LISTBASE_FOREACH (LayerCollection *, lc, lb) { -#ifdef USE_COLLECTION_COMPAT_28 - BLO_read_data_address(reader, &lc->scene_collection); -#endif - - /* Master collection is not a real data-lock. */ - if (master) { - BLO_read_data_address(reader, &lc->collection); - } - - direct_link_layer_collections(reader, &lc->layer_collections, false); - } -} - -static void direct_link_view_layer(BlendDataReader *reader, ViewLayer *view_layer) -{ - view_layer->stats = NULL; - BLO_read_list(reader, &view_layer->object_bases); - BLO_read_data_address(reader, &view_layer->basact); - - direct_link_layer_collections(reader, &view_layer->layer_collections, true); - BLO_read_data_address(reader, &view_layer->active_collection); - - BLO_read_data_address(reader, &view_layer->id_properties); - IDP_BlendDataRead(reader, &view_layer->id_properties); - - BLO_read_list(reader, &(view_layer->freestyle_config.modules)); - BLO_read_list(reader, &(view_layer->freestyle_config.linesets)); - - BLI_listbase_clear(&view_layer->drawdata); - view_layer->object_bases_array = NULL; - view_layer->object_bases_hash = NULL; -} - -static void lib_link_layer_collection(BlendLibReader *reader, - Library *lib, - LayerCollection *layer_collection, - bool master) -{ - /* Master collection is not a real data-lock. */ - if (!master) { - BLO_read_id_address(reader, lib, &layer_collection->collection); - } - - LISTBASE_FOREACH ( - LayerCollection *, layer_collection_nested, &layer_collection->layer_collections) { - lib_link_layer_collection(reader, lib, layer_collection_nested, false); - } -} - -static void lib_link_view_layer(BlendLibReader *reader, Library *lib, ViewLayer *view_layer) -{ - LISTBASE_FOREACH (FreestyleModuleConfig *, fmc, &view_layer->freestyle_config.modules) { - BLO_read_id_address(reader, lib, &fmc->script); - } - - LISTBASE_FOREACH (FreestyleLineSet *, fls, &view_layer->freestyle_config.linesets) { - BLO_read_id_address(reader, lib, &fls->linestyle); - BLO_read_id_address(reader, 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 */ - BLO_read_id_address(reader, lib, &base->object); - - if (base->object == NULL) { - /* Free in case linked object got lost. */ - BLI_freelinkN(&view_layer->object_bases, base); - if (view_layer->basact == base) { - view_layer->basact = NULL; - } - } - } - - LISTBASE_FOREACH (LayerCollection *, layer_collection, &view_layer->layer_collections) { - lib_link_layer_collection(reader, lib, layer_collection, true); - } - - BLO_read_id_address(reader, lib, &view_layer->mat_override); - - IDP_BlendReadLib(reader, view_layer->id_properties); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Read ID: Collection - * \{ */ - -#ifdef USE_COLLECTION_COMPAT_28 -static void direct_link_scene_collection(BlendDataReader *reader, SceneCollection *sc) -{ - BLO_read_list(reader, &sc->objects); - BLO_read_list(reader, &sc->scene_collections); - - LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) { - direct_link_scene_collection(reader, nsc); - } -} - -static void lib_link_scene_collection(BlendLibReader *reader, Library *lib, SceneCollection *sc) -{ - LISTBASE_FOREACH (LinkData *, link, &sc->objects) { - BLO_read_id_address(reader, lib, &link->data); - BLI_assert(link->data); - } - - LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) { - lib_link_scene_collection(reader, lib, nsc); - } -} -#endif - -static void direct_link_collection(BlendDataReader *reader, Collection *collection) -{ - BLO_read_list(reader, &collection->gobject); - BLO_read_list(reader, &collection->children); - - BLO_read_data_address(reader, &collection->preview); - BKE_previewimg_blend_read(reader, collection->preview); - - collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE; - collection->tag = 0; - BLI_listbase_clear(&collection->object_cache); - BLI_listbase_clear(&collection->parents); - -#ifdef USE_COLLECTION_COMPAT_28 - /* This runs before the very first doversion. */ - BLO_read_data_address(reader, &collection->collection); - if (collection->collection != NULL) { - direct_link_scene_collection(reader, collection->collection); - } - - BLO_read_data_address(reader, &collection->view_layer); - if (collection->view_layer != NULL) { - direct_link_view_layer(reader, collection->view_layer); - } -#endif -} - -static void lib_link_collection_data(BlendLibReader *reader, Library *lib, Collection *collection) -{ - LISTBASE_FOREACH_MUTABLE (CollectionObject *, cob, &collection->gobject) { - BLO_read_id_address(reader, lib, &cob->ob); - - if (cob->ob == NULL) { - BLI_freelinkN(&collection->gobject, cob); - } - } - - LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { - BLO_read_id_address(reader, lib, &child->collection); - } -} - -static void lib_link_collection(BlendLibReader *reader, Collection *collection) -{ -#ifdef USE_COLLECTION_COMPAT_28 - if (collection->collection) { - lib_link_scene_collection(reader, collection->id.lib, collection->collection); - } - - if (collection->view_layer) { - lib_link_view_layer(reader, collection->id.lib, collection->view_layer); - } -#endif - - lib_link_collection_data(reader, collection->id.lib, collection); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Read ID: Scene * \{ */ @@ -4322,14 +3946,6 @@ static void direct_link_lightcache(BlendDataReader *reader, LightCache *cache) BLO_read_data_address(reader, &cache->grid_data); } -static void direct_link_view3dshading(BlendDataReader *reader, View3DShading *shading) -{ - if (shading->prop) { - BLO_read_data_address(reader, &shading->prop); - IDP_BlendDataRead(reader, &shading->prop); - } -} - /* check for cyclic set-scene, * libs can cause this case which is normally prevented, see (T#####) */ #define USE_SETSCENE_CHECK @@ -4527,12 +4143,12 @@ static void lib_link_scene(BlendLibReader *reader, Scene *sce) #ifdef USE_COLLECTION_COMPAT_28 if (sce->collection) { - lib_link_scene_collection(reader, sce->id.lib, sce->collection); + BKE_collection_compat_blend_read_lib(reader, sce->id.lib, sce->collection); } #endif LISTBASE_FOREACH (ViewLayer *, view_layer, &sce->view_layers) { - lib_link_view_layer(reader, sce->id.lib, view_layer); + BKE_view_layer_blend_read_lib(reader, sce->id.lib, view_layer); } if (sce->r.bake.cage_object) { @@ -4916,14 +4532,14 @@ static void direct_link_scene(BlendDataReader *reader, Scene *sce) /* this runs before the very first doversion */ if (sce->collection) { BLO_read_data_address(reader, &sce->collection); - direct_link_scene_collection(reader, sce->collection); + BKE_collection_compat_blend_read_data(reader, sce->collection); } #endif /* insert into global old-new map for reading without UI (link_global accesses it again) */ link_glob_list(reader->fd, &sce->view_layers); LISTBASE_FOREACH (ViewLayer *, view_layer, &sce->view_layers) { - direct_link_view_layer(reader, view_layer); + BKE_view_layer_blend_read_data(reader, view_layer); } if (BLO_read_data_is_undo(reader)) { @@ -4938,7 +4554,7 @@ static void direct_link_scene(BlendDataReader *reader, Scene *sce) } EEVEE_lightcache_info_update(&sce->eevee); - direct_link_view3dshading(reader, &sce->display.shading); + BKE_screen_view3d_shading_blend_read_data(reader, &sce->display.shading); BLO_read_data_address(reader, &sce->layer_properties); IDP_BlendDataRead(reader, &sce->layer_properties); @@ -4947,540 +4563,12 @@ static void direct_link_scene(BlendDataReader *reader, Scene *sce) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Read Screen Area/Region (Screen Data) - * \{ */ - -static void direct_link_panel_list(BlendDataReader *reader, ListBase *lb) -{ - BLO_read_list(reader, lb); - - LISTBASE_FOREACH (Panel *, panel, lb) { - panel->runtime_flag = 0; - panel->activedata = NULL; - panel->type = NULL; - panel->runtime.custom_data_ptr = NULL; - direct_link_panel_list(reader, &panel->children); - } -} - -static void direct_link_region(BlendDataReader *reader, ARegion *region, int spacetype) -{ - direct_link_panel_list(reader, ®ion->panels); - - BLO_read_list(reader, ®ion->panels_category_active); - - BLO_read_list(reader, ®ion->ui_lists); - - /* The area's search filter is runtime only, so we need to clear the active flag on read. */ - region->flag &= ~RGN_FLAG_SEARCH_FILTER_ACTIVE; - - LISTBASE_FOREACH (uiList *, ui_list, ®ion->ui_lists) { - ui_list->type = NULL; - ui_list->dyn_data = NULL; - BLO_read_data_address(reader, &ui_list->properties); - IDP_BlendDataRead(reader, &ui_list->properties); - } - - BLO_read_list(reader, ®ion->ui_previews); - - if (spacetype == SPACE_EMPTY) { - /* unknown space type, don't leak regiondata */ - region->regiondata = NULL; - } - else if (region->flag & RGN_FLAG_TEMP_REGIONDATA) { - /* Runtime data, don't use. */ - region->regiondata = NULL; - } - else { - BLO_read_data_address(reader, ®ion->regiondata); - if (region->regiondata) { - if (spacetype == SPACE_VIEW3D) { - RegionView3D *rv3d = region->regiondata; - - BLO_read_data_address(reader, &rv3d->localvd); - BLO_read_data_address(reader, &rv3d->clipbb); - - rv3d->depths = NULL; - rv3d->render_engine = NULL; - rv3d->sms = NULL; - rv3d->smooth_timer = NULL; - - rv3d->rflag &= ~(RV3D_NAVIGATING | RV3D_PAINTING); - rv3d->runtime_viewlock = 0; - } - } - } - - region->v2d.sms = NULL; - region->v2d.alpha_hor = region->v2d.alpha_vert = 255; /* visible by default */ - BLI_listbase_clear(®ion->panels_category); - BLI_listbase_clear(®ion->handlers); - BLI_listbase_clear(®ion->uiblocks); - region->headerstr = NULL; - region->visible = 0; - region->type = NULL; - region->do_draw = 0; - region->gizmo_map = NULL; - region->regiontimer = NULL; - region->draw_buffer = NULL; - memset(®ion->drawrct, 0, sizeof(region->drawrct)); -} - -static void direct_link_area(BlendDataReader *reader, ScrArea *area) -{ - BLO_read_list(reader, &(area->spacedata)); - BLO_read_list(reader, &(area->regionbase)); - - BLI_listbase_clear(&area->handlers); - area->type = NULL; /* spacetype callbacks */ - - /* Should always be unset so that rna_Area_type_get works correctly. */ - area->butspacetype = SPACE_EMPTY; - - area->region_active_win = -1; - - area->flag &= ~AREA_FLAG_ACTIVE_TOOL_UPDATE; - - BLO_read_data_address(reader, &area->global); - - /* if we do not have the spacetype registered we cannot - * free it, so don't allocate any new memory for such spacetypes. */ - if (!BKE_spacetype_exists(area->spacetype)) { - /* Hint for versioning code to replace deprecated space types. */ - area->butspacetype = area->spacetype; - - area->spacetype = SPACE_EMPTY; - } - - LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { - direct_link_region(reader, region, area->spacetype); - } - - /* accident can happen when read/save new file with older version */ - /* 2.50: we now always add spacedata for info */ - if (area->spacedata.first == NULL) { - SpaceInfo *sinfo = MEM_callocN(sizeof(SpaceInfo), "spaceinfo"); - area->spacetype = sinfo->spacetype = SPACE_INFO; - BLI_addtail(&area->spacedata, sinfo); - } - /* add local view3d too */ - else if (area->spacetype == SPACE_VIEW3D) { - blo_do_versions_view3d_split_250(area->spacedata.first, &area->regionbase); - } - - LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { - BLO_read_list(reader, &(sl->regionbase)); - - /* if we do not have the spacetype registered we cannot - * free it, so don't allocate any new memory for such spacetypes. */ - if (!BKE_spacetype_exists(sl->spacetype)) { - sl->spacetype = SPACE_EMPTY; - } - - LISTBASE_FOREACH (ARegion *, region, &sl->regionbase) { - direct_link_region(reader, region, sl->spacetype); - } - - if (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D *)sl; - - v3d->flag |= V3D_INVALID_BACKBUF; - - if (v3d->gpd) { - BLO_read_data_address(reader, &v3d->gpd); - BKE_gpencil_blend_read_data(reader, v3d->gpd); - } - BLO_read_data_address(reader, &v3d->localvd); - - /* Runtime data */ - v3d->runtime.properties_storage = NULL; - v3d->runtime.flag = 0; - - /* render can be quite heavy, set to solid on load */ - if (v3d->shading.type == OB_RENDER) { - v3d->shading.type = OB_SOLID; - } - v3d->shading.prev_type = OB_SOLID; - - direct_link_view3dshading(reader, &v3d->shading); - - blo_do_versions_view3d_split_250(v3d, &sl->regionbase); - } - else if (sl->spacetype == SPACE_GRAPH) { - SpaceGraph *sipo = (SpaceGraph *)sl; - - BLO_read_data_address(reader, &sipo->ads); - BLI_listbase_clear(&sipo->runtime.ghost_curves); - } - else if (sl->spacetype == SPACE_NLA) { - SpaceNla *snla = (SpaceNla *)sl; - - BLO_read_data_address(reader, &snla->ads); - } - else if (sl->spacetype == SPACE_OUTLINER) { - SpaceOutliner *space_outliner = (SpaceOutliner *)sl; - - /* use newdataadr_no_us and do not free old memory avoiding double - * frees and use of freed memory. this could happen because of a - * bug fixed in revision 58959 where the treestore memory address - * was not unique */ - TreeStore *ts = newdataadr_no_us(reader->fd, space_outliner->treestore); - space_outliner->treestore = NULL; - if (ts) { - TreeStoreElem *elems = newdataadr_no_us(reader->fd, ts->data); - - space_outliner->treestore = BLI_mempool_create( - sizeof(TreeStoreElem), ts->usedelem, 512, BLI_MEMPOOL_ALLOW_ITER); - if (ts->usedelem && elems) { - for (int i = 0; i < ts->usedelem; i++) { - TreeStoreElem *new_elem = BLI_mempool_alloc(space_outliner->treestore); - *new_elem = elems[i]; - } - } - /* we only saved what was used */ - space_outliner->storeflag |= SO_TREESTORE_CLEANUP; /* at first draw */ - } - space_outliner->treehash = NULL; - space_outliner->tree.first = space_outliner->tree.last = NULL; - } - else if (sl->spacetype == SPACE_IMAGE) { - SpaceImage *sima = (SpaceImage *)sl; - - sima->iuser.scene = NULL; - sima->iuser.ok = 1; - sima->scopes.waveform_1 = NULL; - sima->scopes.waveform_2 = NULL; - sima->scopes.waveform_3 = NULL; - sima->scopes.vecscope = NULL; - sima->scopes.ok = 0; - - /* WARNING: gpencil data is no longer stored directly in sima after 2.5 - * so sacrifice a few old files for now to avoid crashes with new files! - * committed: r28002 */ -#if 0 - sima->gpd = newdataadr(fd, sima->gpd); - if (sima->gpd) { - BKE_gpencil_blend_read_data(fd, sima->gpd); - } -#endif - } - else if (sl->spacetype == SPACE_NODE) { - SpaceNode *snode = (SpaceNode *)sl; - - if (snode->gpd) { - BLO_read_data_address(reader, &snode->gpd); - BKE_gpencil_blend_read_data(reader, snode->gpd); - } - - BLO_read_list(reader, &snode->treepath); - snode->edittree = NULL; - snode->iofsd = NULL; - BLI_listbase_clear(&snode->linkdrag); - } - else if (sl->spacetype == SPACE_TEXT) { - SpaceText *st = (SpaceText *)sl; - memset(&st->runtime, 0, sizeof(st->runtime)); - } - else if (sl->spacetype == SPACE_SEQ) { - SpaceSeq *sseq = (SpaceSeq *)sl; - - /* grease pencil data is not a direct data and can't be linked from direct_link* - * functions, it should be linked from lib_link* functions instead - * - * otherwise it'll lead to lost grease data on open because it'll likely be - * read from file after all other users of grease pencil and newdataadr would - * simple return NULL here (sergey) - */ -#if 0 - if (sseq->gpd) { - sseq->gpd = newdataadr(fd, sseq->gpd); - BKE_gpencil_blend_read_data(fd, sseq->gpd); - } -#endif - sseq->scopes.reference_ibuf = NULL; - sseq->scopes.zebra_ibuf = NULL; - sseq->scopes.waveform_ibuf = NULL; - sseq->scopes.sep_waveform_ibuf = NULL; - sseq->scopes.vector_ibuf = NULL; - sseq->scopes.histogram_ibuf = NULL; - } - else if (sl->spacetype == SPACE_PROPERTIES) { - SpaceProperties *sbuts = (SpaceProperties *)sl; - - sbuts->path = NULL; - sbuts->texuser = NULL; - sbuts->mainbo = sbuts->mainb; - sbuts->mainbuser = sbuts->mainb; - sbuts->runtime = NULL; - } - else if (sl->spacetype == SPACE_CONSOLE) { - SpaceConsole *sconsole = (SpaceConsole *)sl; - - BLO_read_list(reader, &sconsole->scrollback); - BLO_read_list(reader, &sconsole->history); - - /* comma expressions, (e.g. expr1, expr2, expr3) evaluate each expression, - * from left to right. the right-most expression sets the result of the comma - * expression as a whole*/ - LISTBASE_FOREACH_MUTABLE (ConsoleLine *, cl, &sconsole->history) { - BLO_read_data_address(reader, &cl->line); - if (cl->line) { - /* the allocted length is not written, so reset here */ - cl->len_alloc = cl->len + 1; - } - else { - BLI_remlink(&sconsole->history, cl); - MEM_freeN(cl); - } - } - } - else if (sl->spacetype == SPACE_FILE) { - SpaceFile *sfile = (SpaceFile *)sl; - - /* this sort of info is probably irrelevant for reloading... - * plus, it isn't saved to files yet! - */ - sfile->folders_prev = sfile->folders_next = NULL; - sfile->files = NULL; - sfile->layout = NULL; - sfile->op = NULL; - sfile->previews_timer = NULL; - BLO_read_data_address(reader, &sfile->params); - } - else if (sl->spacetype == SPACE_CLIP) { - SpaceClip *sclip = (SpaceClip *)sl; - - sclip->scopes.track_search = NULL; - sclip->scopes.track_preview = NULL; - sclip->scopes.ok = 0; - } - } - - BLI_listbase_clear(&area->actionzones); - - BLO_read_data_address(reader, &area->v1); - BLO_read_data_address(reader, &area->v2); - BLO_read_data_address(reader, &area->v3); - BLO_read_data_address(reader, &area->v4); -} - -static void lib_link_area(BlendLibReader *reader, ID *parent_id, ScrArea *area) -{ - BLO_read_id_address(reader, parent_id->lib, &area->full); - - memset(&area->runtime, 0x0, sizeof(area->runtime)); - - LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { - switch (sl->spacetype) { - case SPACE_VIEW3D: { - View3D *v3d = (View3D *)sl; - - BLO_read_id_address(reader, parent_id->lib, &v3d->camera); - BLO_read_id_address(reader, parent_id->lib, &v3d->ob_center); - - if (v3d->localvd) { - BLO_read_id_address(reader, parent_id->lib, &v3d->localvd->camera); - } - break; - } - case SPACE_GRAPH: { - SpaceGraph *sipo = (SpaceGraph *)sl; - bDopeSheet *ads = sipo->ads; - - if (ads) { - BLO_read_id_address(reader, parent_id->lib, &ads->source); - BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp); - } - break; - } - case SPACE_PROPERTIES: { - SpaceProperties *sbuts = (SpaceProperties *)sl; - BLO_read_id_address(reader, parent_id->lib, &sbuts->pinid); - if (sbuts->pinid == NULL) { - sbuts->flag &= ~SB_PIN_CONTEXT; - } - break; - } - case SPACE_FILE: - break; - case SPACE_ACTION: { - SpaceAction *saction = (SpaceAction *)sl; - bDopeSheet *ads = &saction->ads; - - if (ads) { - BLO_read_id_address(reader, parent_id->lib, &ads->source); - BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp); - } - - BLO_read_id_address(reader, parent_id->lib, &saction->action); - break; - } - case SPACE_IMAGE: { - SpaceImage *sima = (SpaceImage *)sl; - - BLO_read_id_address(reader, parent_id->lib, &sima->image); - BLO_read_id_address(reader, parent_id->lib, &sima->mask_info.mask); - - /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data - * so fingers crossed this works fine! - */ - BLO_read_id_address(reader, parent_id->lib, &sima->gpd); - break; - } - case SPACE_SEQ: { - SpaceSeq *sseq = (SpaceSeq *)sl; - - /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data - * so fingers crossed this works fine! - */ - BLO_read_id_address(reader, parent_id->lib, &sseq->gpd); - break; - } - case SPACE_NLA: { - SpaceNla *snla = (SpaceNla *)sl; - bDopeSheet *ads = snla->ads; - - if (ads) { - BLO_read_id_address(reader, parent_id->lib, &ads->source); - BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp); - } - break; - } - case SPACE_TEXT: { - SpaceText *st = (SpaceText *)sl; - - BLO_read_id_address(reader, parent_id->lib, &st->text); - break; - } - case SPACE_SCRIPT: { - SpaceScript *scpt = (SpaceScript *)sl; - /*scpt->script = NULL; - 2.45 set to null, better re-run the script */ - if (scpt->script) { - BLO_read_id_address(reader, parent_id->lib, &scpt->script); - if (scpt->script) { - SCRIPT_SET_NULL(scpt->script); - } - } - break; - } - case SPACE_OUTLINER: { - SpaceOutliner *space_outliner = (SpaceOutliner *)sl; - BLO_read_id_address(reader, NULL, &space_outliner->search_tse.id); - - if (space_outliner->treestore) { - TreeStoreElem *tselem; - BLI_mempool_iter iter; - - BLI_mempool_iternew(space_outliner->treestore, &iter); - while ((tselem = BLI_mempool_iterstep(&iter))) { - BLO_read_id_address(reader, NULL, &tselem->id); - } - if (space_outliner->treehash) { - /* rebuild hash table, because it depends on ids too */ - space_outliner->storeflag |= SO_TREESTORE_REBUILD; - } - } - break; - } - case SPACE_NODE: { - SpaceNode *snode = (SpaceNode *)sl; - - /* node tree can be stored locally in id too, link this first */ - BLO_read_id_address(reader, parent_id->lib, &snode->id); - BLO_read_id_address(reader, parent_id->lib, &snode->from); - - bNodeTree *ntree = snode->id ? ntreeFromID(snode->id) : NULL; - if (ntree) { - snode->nodetree = ntree; - } - else { - BLO_read_id_address(reader, parent_id->lib, &snode->nodetree); - } - - bNodeTreePath *path; - for (path = snode->treepath.first; path; path = path->next) { - if (path == snode->treepath.first) { - /* first nodetree in path is same as snode->nodetree */ - path->nodetree = snode->nodetree; - } - else { - BLO_read_id_address(reader, parent_id->lib, &path->nodetree); - } - - if (!path->nodetree) { - break; - } - } - - /* remaining path entries are invalid, remove */ - bNodeTreePath *path_next; - for (; path; path = path_next) { - path_next = path->next; - - BLI_remlink(&snode->treepath, path); - MEM_freeN(path); - } - - /* edittree is just the last in the path, - * set this directly since the path may have been shortened above */ - if (snode->treepath.last) { - path = snode->treepath.last; - snode->edittree = path->nodetree; - } - else { - snode->edittree = NULL; - } - break; - } - case SPACE_CLIP: { - SpaceClip *sclip = (SpaceClip *)sl; - BLO_read_id_address(reader, parent_id->lib, &sclip->clip); - BLO_read_id_address(reader, parent_id->lib, &sclip->mask_info.mask); - break; - } - default: - break; - } - } -} - -/** - * \return false on error. - */ -static bool direct_link_area_map(BlendDataReader *reader, ScrAreaMap *area_map) -{ - BLO_read_list(reader, &area_map->vertbase); - BLO_read_list(reader, &area_map->edgebase); - BLO_read_list(reader, &area_map->areabase); - LISTBASE_FOREACH (ScrArea *, area, &area_map->areabase) { - direct_link_area(reader, area); - } - - /* edges */ - LISTBASE_FOREACH (ScrEdge *, se, &area_map->edgebase) { - BLO_read_data_address(reader, &se->v1); - BLO_read_data_address(reader, &se->v2); - BKE_screen_sort_scrvert(&se->v1, &se->v2); - - if (se->v1 == NULL) { - BLI_remlink(&area_map->edgebase, se); - - return false; - } - } - - return true; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name XR-data * \{ */ static void direct_link_wm_xr_data(BlendDataReader *reader, wmXrData *xr_data) { - direct_link_view3dshading(reader, &xr_data->session_settings.shading); + BKE_screen_view3d_shading_blend_read_data(reader, &xr_data->session_settings.shading); } static void lib_link_wm_xr_data(BlendLibReader *reader, ID *parent_id, wmXrData *xr_data) @@ -5517,7 +4605,7 @@ static void direct_link_windowmanager(BlendDataReader *reader, wmWindowManager * win->workspace_hook->temp_layout_store = NULL; } - direct_link_area_map(reader, &win->global_areas); + BKE_screen_area_map_blend_read_data(reader, &win->global_areas); win->ghostwin = NULL; win->gpuctx = NULL; @@ -5588,7 +4676,7 @@ static void lib_link_windowmanager(BlendLibReader *reader, wmWindowManager *wm) BLO_read_id_address(reader, NULL, &win->screen); LISTBASE_FOREACH (ScrArea *, area, &win->global_areas.areabase) { - lib_link_area(reader, &wm->id, area); + BKE_screen_area_blend_read_lib(reader, &wm->id, area); } lib_link_wm_xr_data(reader, &wm->id, &wm->xr); @@ -5601,22 +4689,6 @@ static void lib_link_windowmanager(BlendLibReader *reader, wmWindowManager *wm) /** \name Read ID: Screen * \{ */ -/* note: file read without screens option G_FILE_NO_UI; - * check lib pointers in call below */ -static void lib_link_screen(BlendLibReader *reader, bScreen *screen) -{ - /* deprecated, but needed for versioning (will be NULL'ed then) */ - BLO_read_id_address(reader, screen->id.lib, &screen->scene); - - screen->animtimer = NULL; /* saved in rare cases */ - screen->tool_tip = NULL; - screen->scrubbing = false; - - LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { - lib_link_area(reader, &screen->id, area); - } -} - /* how to handle user count on pointer restore */ typedef enum ePointerUserMode { USER_IGNORE = 0, /* ignore user count */ @@ -6093,29 +5165,6 @@ void blo_lib_link_restore(Main *oldmain, BKE_main_idmap_destroy(id_map); } -/* for the saved 2.50 files without regiondata */ -/* and as patch for 2.48 and older */ -void blo_do_versions_view3d_split_250(View3D *v3d, ListBase *regions) -{ - LISTBASE_FOREACH (ARegion *, region, regions) { - if (region->regiontype == RGN_TYPE_WINDOW && region->regiondata == NULL) { - RegionView3D *rv3d; - - rv3d = region->regiondata = MEM_callocN(sizeof(RegionView3D), "region v3d patch"); - rv3d->persp = (char)v3d->persp; - rv3d->view = (char)v3d->view; - rv3d->dist = v3d->dist; - copy_v3_v3(rv3d->ofs, v3d->ofs); - copy_qt_qt(rv3d->viewquat, v3d->viewquat); - } - } - - /* this was not initialized correct always */ - if (v3d->gridsubdiv == 0) { - v3d->gridsubdiv = 10; - } -} - static bool direct_link_screen(BlendDataReader *reader, bScreen *screen) { bool success = true; @@ -6127,7 +5176,7 @@ static bool direct_link_screen(BlendDataReader *reader, bScreen *screen) BLO_read_data_address(reader, &screen->preview); BKE_previewimg_blend_read(reader, screen->preview); - if (!direct_link_area_map(reader, AREAMAP_FROM_SCREEN(screen))) { + if (!BKE_screen_area_map_blend_read_data(reader, AREAMAP_FROM_SCREEN(screen))) { printf("Error reading Screen %s... removing it.\n", screen->id.name + 2); success = false; } @@ -6396,15 +5445,9 @@ static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID * case ID_LI: direct_link_library(fd, (Library *)id, main); break; - case ID_GR: - direct_link_collection(&reader, (Collection *)id); - break; - case ID_PA: - direct_link_particlesettings(&reader, (ParticleSettings *)id); - break; case ID_WS: - direct_link_workspace(&reader, (WorkSpace *)id); - break; + case ID_PA: + case ID_GR: case ID_ME: case ID_LT: case ID_AC: @@ -7023,27 +6066,12 @@ static void lib_link_all(FileData *fd, Main *bmain) case ID_WM: lib_link_windowmanager(&reader, (wmWindowManager *)id); break; - case ID_WS: - /* Could we skip WS in undo case? */ - lib_link_workspaces(&reader, (WorkSpace *)id); - break; case ID_SCE: lib_link_scene(&reader, (Scene *)id); break; case ID_OB: lib_link_object(&reader, (Object *)id); break; - case ID_SCR: - /* DO NOT skip screens here, 3D viewport may contains pointers - * to other ID data (like #View3D.ob_center)! See T41411. */ - lib_link_screen(&reader, (bScreen *)id); - break; - case ID_PA: - lib_link_particlesettings(&reader, (ParticleSettings *)id); - break; - case ID_GR: - lib_link_collection(&reader, (Collection *)id); - break; case ID_IP: /* XXX deprecated... still needs to be maintained for version patches still. */ lib_link_ipo(&reader, (Ipo *)id); @@ -7051,6 +6079,10 @@ static void lib_link_all(FileData *fd, Main *bmain) case ID_LI: lib_link_library(&reader, (Library *)id); /* Only init users. */ break; + case ID_WS: + case ID_SCR: + case ID_PA: + case ID_GR: case ID_ME: case ID_LT: case ID_AC: @@ -7665,7 +6697,6 @@ static void expand_constraint_channels(BlendExpander *expander, ListBase *chanba } static void expand_id(BlendExpander *expander, ID *id); -static void expand_collection(BlendExpander *expander, Collection *collection); static void expand_id_embedded_id(BlendExpander *expander, ID *id) { @@ -7680,7 +6711,7 @@ static void expand_id_embedded_id(BlendExpander *expander, ID *id) Scene *scene = (Scene *)id; if (scene->master_collection != NULL) { expand_id(expander, &scene->master_collection->id); - expand_collection(expander, scene->master_collection); + BKE_collection_blend_read_expand(expander, scene->master_collection); } } } @@ -7702,71 +6733,6 @@ static void expand_id(BlendExpander *expander, ID *id) expand_id_embedded_id(expander, id); } -static void expand_particlesettings(BlendExpander *expander, ParticleSettings *part) -{ - BLO_expand(expander, part->instance_object); - BLO_expand(expander, part->instance_collection); - BLO_expand(expander, part->force_group); - BLO_expand(expander, part->bb_ob); - BLO_expand(expander, part->collision_group); - - for (int a = 0; a < MAX_MTEX; a++) { - if (part->mtex[a]) { - BLO_expand(expander, part->mtex[a]->tex); - BLO_expand(expander, part->mtex[a]->object); - } - } - - if (part->effector_weights) { - BLO_expand(expander, part->effector_weights->group); - } - - if (part->pd) { - BLO_expand(expander, part->pd->tex); - BLO_expand(expander, part->pd->f_source); - } - if (part->pd2) { - BLO_expand(expander, part->pd2->tex); - BLO_expand(expander, part->pd2->f_source); - } - - if (part->boids) { - LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { - LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { - if (rule->type == eBoidRuleType_Avoid) { - BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule; - BLO_expand(expander, gabr->ob); - } - else if (rule->type == eBoidRuleType_FollowLeader) { - BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule; - BLO_expand(expander, flbr->ob); - } - } - } - } - - LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) { - BLO_expand(expander, dw->ob); - } -} - -static void expand_collection(BlendExpander *expander, Collection *collection) -{ - LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { - BLO_expand(expander, cob->ob); - } - - LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { - BLO_expand(expander, child->collection); - } - -#ifdef USE_COLLECTION_COMPAT_28 - if (collection->collection != NULL) { - expand_scene_collection(expander, collection->collection); - } -#endif -} - /* callback function used to expand constraint ID-links */ static void expand_constraint_cb(bConstraint *UNUSED(con), ID **idpoin, @@ -7892,19 +6858,6 @@ static void expand_object(BlendExpander *expander, Object *ob) } } -#ifdef USE_COLLECTION_COMPAT_28 -static void expand_scene_collection(BlendExpander *expander, SceneCollection *sc) -{ - LISTBASE_FOREACH (LinkData *, link, &sc->objects) { - BLO_expand(expander, link->data); - } - - LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) { - expand_scene_collection(expander, nsc); - } -} -#endif - static void expand_scene(BlendExpander *expander, Scene *sce) { LISTBASE_FOREACH (Base *, base_legacy, &sce->base) { @@ -8002,7 +6955,7 @@ static void expand_scene(BlendExpander *expander, Scene *sce) #ifdef USE_COLLECTION_COMPAT_28 if (sce->collection) { - expand_scene_collection(expander, sce->collection); + BKE_collection_compat_blend_read_expand(expander, sce->collection); } #endif @@ -8011,13 +6964,6 @@ static void expand_scene(BlendExpander *expander, Scene *sce) } } -static void expand_workspace(BlendExpander *expander, WorkSpace *workspace) -{ - LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) { - BLO_expand(expander, BKE_workspace_layout_screen_get(layout)); - } -} - /** * Set the callback func used over all ID data found by \a BLO_expand_main func. * @@ -8067,18 +7013,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) case ID_SCE: expand_scene(&expander, (Scene *)id); break; - case ID_GR: - expand_collection(&expander, (Collection *)id); - break; case ID_IP: expand_ipo(&expander, (Ipo *)id); /* XXX deprecated - old animation system */ break; - case ID_PA: - expand_particlesettings(&expander, (ParticleSettings *)id); - break; - case ID_WS: - expand_workspace(&expander, (WorkSpace *)id); - break; default: break; } @@ -9039,6 +7976,11 @@ void *BLO_read_get_new_data_address(BlendDataReader *reader, const void *old_add return newdataadr(reader->fd, old_address); } +void *BLO_read_get_new_data_address_no_us(BlendDataReader *reader, const void *old_address) +{ + return newdataadr_no_us(reader->fd, old_address); +} + void *BLO_read_get_new_packed_address(BlendDataReader *reader, const void *old_address) { return newpackedadr(reader->fd, old_address); @@ -9209,6 +8151,11 @@ bool BLO_read_lib_is_undo(BlendLibReader *reader) return reader->fd->memfile != NULL; } +Main *BLO_read_lib_get_main(BlendLibReader *reader) +{ + return reader->main; +} + void BLO_expand_id(BlendExpander *expander, ID *id) { expand_doit(expander->fd, expander->main, id); diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index 4fa41731454..57d6779d1cb 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -187,7 +187,6 @@ void *blo_do_versions_newlibadr_us(struct FileData *fd, const void *lib, const v struct PartEff *blo_do_version_give_parteff_245(struct Object *ob); void blo_do_version_old_trackto_to_constraints(struct Object *ob); -void blo_do_versions_view3d_split_250(struct View3D *v3d, struct ListBase *regions); void blo_do_versions_key_uidgen(struct Key *key); void blo_do_versions_userdef(struct UserDef *userdef); diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index f7592308023..1988b2e1f33 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -266,7 +266,7 @@ static void area_add_window_regions(ScrArea *area, SpaceLink *sl, ListBase *lb) /* and we split view3d */ switch (sl->spacetype) { case SPACE_VIEW3D: - blo_do_versions_view3d_split_250((View3D *)sl, lb); + BKE_screen_view3d_do_versions_250((View3D *)sl, lb); break; case SPACE_OUTLINER: { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index a37ec2d9f0a..835e2f92c7c 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -155,6 +155,7 @@ #include "BKE_packedFile.h" #include "BKE_pointcache.h" #include "BKE_report.h" +#include "BKE_screen.h" #include "BKE_sequencer.h" #include "BKE_shader_fx.h" #include "BKE_subsurf.h" @@ -804,41 +805,6 @@ static void write_userdef(BlendWriter *writer, const UserDef *userdef) } } -static void write_boid_state(BlendWriter *writer, BoidState *state) -{ - BLO_write_struct(writer, BoidState, state); - - LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { - switch (rule->type) { - case eBoidRuleType_Goal: - case eBoidRuleType_Avoid: - BLO_write_struct(writer, BoidRuleGoalAvoid, rule); - break; - case eBoidRuleType_AvoidCollision: - BLO_write_struct(writer, BoidRuleAvoidCollision, rule); - break; - case eBoidRuleType_FollowLeader: - BLO_write_struct(writer, BoidRuleFollowLeader, rule); - break; - case eBoidRuleType_AverageSpeed: - BLO_write_struct(writer, BoidRuleAverageSpeed, rule); - break; - case eBoidRuleType_Fight: - BLO_write_struct(writer, BoidRuleFight, rule); - break; - default: - BLO_write_struct(writer, BoidRule, rule); - break; - } - } -#if 0 - BoidCondition *cond = state->conditions.first; - for (; cond; cond = cond->next) { - BLO_write_struct(writer, BoidCondition, cond); - } -#endif -} - /* update this also to readfile.c */ static const char *ptcache_data_struct[] = { "", // BPHYS_DATA_INDEX @@ -889,68 +855,6 @@ static void write_pointcaches(BlendWriter *writer, ListBase *ptcaches) } } -static void write_particlesettings(BlendWriter *writer, - ParticleSettings *part, - const void *id_address) -{ - if (part->id.us > 0 || BLO_write_is_undo(writer)) { - /* write LibData */ - BLO_write_id_struct(writer, ParticleSettings, id_address, &part->id); - BKE_id_blend_write(writer, &part->id); - - if (part->adt) { - BKE_animdata_blend_write(writer, part->adt); - } - BLO_write_struct(writer, PartDeflect, part->pd); - BLO_write_struct(writer, PartDeflect, part->pd2); - BLO_write_struct(writer, EffectorWeights, part->effector_weights); - - if (part->clumpcurve) { - BKE_curvemapping_blend_write(writer, part->clumpcurve); - } - if (part->roughcurve) { - BKE_curvemapping_blend_write(writer, part->roughcurve); - } - if (part->twistcurve) { - BKE_curvemapping_blend_write(writer, part->twistcurve); - } - - LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) { - /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */ - if (dw->ob != NULL) { - dw->index = 0; - if (part->instance_collection) { /* can be NULL if lining fails or set to None */ - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object) { - if (object == dw->ob) { - break; - } - dw->index++; - } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; - } - } - BLO_write_struct(writer, ParticleDupliWeight, dw); - } - - if (part->boids && part->phystype == PART_PHYS_BOIDS) { - BLO_write_struct(writer, BoidSettings, part->boids); - - LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { - write_boid_state(writer, state); - } - } - if (part->fluid && part->phystype == PART_PHYS_FLUID) { - BLO_write_struct(writer, SPHFluidSettings, part->fluid); - } - - for (int a = 0; a < MAX_MTEX; a++) { - if (part->mtex[a]) { - BLO_write_struct(writer, MTex, part->mtex[a]); - } - } - } -} - static void write_particlesystems(BlendWriter *writer, ListBase *particles) { LISTBASE_FOREACH (ParticleSystem *, psys, particles) { @@ -1384,37 +1288,6 @@ static void write_object(BlendWriter *writer, Object *ob, const void *id_address } } -static void write_collection_nolib(BlendWriter *writer, Collection *collection) -{ - /* Shared function for collection data-blocks and scene master collection. */ - BKE_previewimg_blend_write(writer, collection->preview); - - LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { - BLO_write_struct(writer, CollectionObject, cob); - } - - LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { - BLO_write_struct(writer, CollectionChild, child); - } -} - -static void write_collection(BlendWriter *writer, Collection *collection, const void *id_address) -{ - if (collection->id.us > 0 || BLO_write_is_undo(writer)) { - /* Clean up, important in undo case to reduce false detection of changed data-blocks. */ - collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE; - collection->tag = 0; - BLI_listbase_clear(&collection->object_cache); - BLI_listbase_clear(&collection->parents); - - /* write LibData */ - BLO_write_id_struct(writer, Collection, id_address, &collection->id); - BKE_id_blend_write(writer, &collection->id); - - write_collection_nolib(writer, collection); - } -} - static void write_sequence_modifiers(BlendWriter *writer, ListBase *modbase) { LISTBASE_FOREACH (SequenceModifierData *, smd, modbase) { @@ -1447,13 +1320,6 @@ static void write_view_settings(BlendWriter *writer, ColorManagedViewSettings *v } } -static void write_view3dshading(BlendWriter *writer, View3DShading *shading) -{ - if (shading->prop) { - IDP_BlendWrite(writer, shading->prop); - } -} - static void write_paint(BlendWriter *writer, Paint *p) { if (p->cavity_curve) { @@ -1745,7 +1611,7 @@ static void write_scene(BlendWriter *writer, Scene *sce, const void *id_address) if (sce->master_collection) { BLO_write_struct(writer, Collection, sce->master_collection); - write_collection_nolib(writer, sce->master_collection); + BKE_collection_blend_write_nolib(writer, sce->master_collection); } /* Eevee Lightcache */ @@ -1754,7 +1620,7 @@ static void write_scene(BlendWriter *writer, Scene *sce, const void *id_address) write_lightcache(writer, sce->eevee.light_cache_data); } - write_view3dshading(writer, &sce->display.shading); + BKE_screen_view3d_shading_blend_write(writer, &sce->display.shading); /* Freed on doversion. */ BLI_assert(sce->layer_properties == NULL); @@ -1762,245 +1628,7 @@ static void write_scene(BlendWriter *writer, Scene *sce, const void *id_address) static void write_wm_xr_data(BlendWriter *writer, wmXrData *xr_data) { - write_view3dshading(writer, &xr_data->session_settings.shading); -} - -static void write_region(BlendWriter *writer, ARegion *region, int spacetype) -{ - BLO_write_struct(writer, ARegion, region); - - if (region->regiondata) { - if (region->flag & RGN_FLAG_TEMP_REGIONDATA) { - return; - } - - switch (spacetype) { - case SPACE_VIEW3D: - if (region->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3d = region->regiondata; - BLO_write_struct(writer, RegionView3D, rv3d); - - if (rv3d->localvd) { - BLO_write_struct(writer, RegionView3D, rv3d->localvd); - } - if (rv3d->clipbb) { - BLO_write_struct(writer, BoundBox, rv3d->clipbb); - } - } - else { - printf("regiondata write missing!\n"); - } - break; - default: - printf("regiondata write missing!\n"); - } - } -} - -static void write_uilist(BlendWriter *writer, uiList *ui_list) -{ - BLO_write_struct(writer, uiList, ui_list); - - if (ui_list->properties) { - IDP_BlendWrite(writer, ui_list->properties); - } -} - -static void write_space_outliner(BlendWriter *writer, SpaceOutliner *space_outliner) -{ - BLI_mempool *ts = space_outliner->treestore; - - if (ts) { - SpaceOutliner space_outliner_flat = *space_outliner; - - int elems = BLI_mempool_len(ts); - /* linearize mempool to array */ - TreeStoreElem *data = elems ? BLI_mempool_as_arrayN(ts, "TreeStoreElem") : NULL; - - if (data) { - /* In this block we use the memory location of the treestore - * but _not_ its data, the addresses in this case are UUID's, - * since we can't rely on malloc giving us different values each time. - */ - TreeStore ts_flat = {0}; - - /* we know the treestore is at least as big as a pointer, - * so offsetting works to give us a UUID. */ - void *data_addr = (void *)POINTER_OFFSET(ts, sizeof(void *)); - - ts_flat.usedelem = elems; - ts_flat.totelem = elems; - ts_flat.data = data_addr; - - BLO_write_struct(writer, SpaceOutliner, space_outliner); - - BLO_write_struct_at_address(writer, TreeStore, ts, &ts_flat); - BLO_write_struct_array_at_address(writer, TreeStoreElem, elems, data_addr, data); - - MEM_freeN(data); - } - else { - space_outliner_flat.treestore = NULL; - BLO_write_struct_at_address(writer, SpaceOutliner, space_outliner, &space_outliner_flat); - } - } - else { - BLO_write_struct(writer, SpaceOutliner, space_outliner); - } -} - -static void write_panel_list(BlendWriter *writer, ListBase *lb) -{ - LISTBASE_FOREACH (Panel *, panel, lb) { - BLO_write_struct(writer, Panel, panel); - write_panel_list(writer, &panel->children); - } -} - -static void write_area_regions(BlendWriter *writer, ScrArea *area) -{ - LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { - write_region(writer, region, area->spacetype); - write_panel_list(writer, ®ion->panels); - - LISTBASE_FOREACH (PanelCategoryStack *, pc_act, ®ion->panels_category_active) { - BLO_write_struct(writer, PanelCategoryStack, pc_act); - } - - LISTBASE_FOREACH (uiList *, ui_list, ®ion->ui_lists) { - write_uilist(writer, ui_list); - } - - LISTBASE_FOREACH (uiPreview *, ui_preview, ®ion->ui_previews) { - BLO_write_struct(writer, uiPreview, ui_preview); - } - } - - LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { - LISTBASE_FOREACH (ARegion *, region, &sl->regionbase) { - write_region(writer, region, sl->spacetype); - } - - if (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D *)sl; - BLO_write_struct(writer, View3D, v3d); - - if (v3d->localvd) { - BLO_write_struct(writer, View3D, v3d->localvd); - } - - write_view3dshading(writer, &v3d->shading); - } - else if (sl->spacetype == SPACE_GRAPH) { - SpaceGraph *sipo = (SpaceGraph *)sl; - ListBase tmpGhosts = sipo->runtime.ghost_curves; - - /* temporarily disable ghost curves when saving */ - BLI_listbase_clear(&sipo->runtime.ghost_curves); - - BLO_write_struct(writer, SpaceGraph, sl); - if (sipo->ads) { - BLO_write_struct(writer, bDopeSheet, sipo->ads); - } - - /* reenable ghost curves */ - sipo->runtime.ghost_curves = tmpGhosts; - } - else if (sl->spacetype == SPACE_PROPERTIES) { - BLO_write_struct(writer, SpaceProperties, sl); - } - else if (sl->spacetype == SPACE_FILE) { - SpaceFile *sfile = (SpaceFile *)sl; - - BLO_write_struct(writer, SpaceFile, sl); - if (sfile->params) { - BLO_write_struct(writer, FileSelectParams, sfile->params); - } - } - else if (sl->spacetype == SPACE_SEQ) { - BLO_write_struct(writer, SpaceSeq, sl); - } - else if (sl->spacetype == SPACE_OUTLINER) { - SpaceOutliner *space_outliner = (SpaceOutliner *)sl; - write_space_outliner(writer, space_outliner); - } - else if (sl->spacetype == SPACE_IMAGE) { - BLO_write_struct(writer, SpaceImage, sl); - } - else if (sl->spacetype == SPACE_TEXT) { - BLO_write_struct(writer, SpaceText, sl); - } - else if (sl->spacetype == SPACE_SCRIPT) { - SpaceScript *scr = (SpaceScript *)sl; - scr->but_refs = NULL; - BLO_write_struct(writer, SpaceScript, sl); - } - else if (sl->spacetype == SPACE_ACTION) { - BLO_write_struct(writer, SpaceAction, sl); - } - else if (sl->spacetype == SPACE_NLA) { - SpaceNla *snla = (SpaceNla *)sl; - - BLO_write_struct(writer, SpaceNla, snla); - if (snla->ads) { - BLO_write_struct(writer, bDopeSheet, snla->ads); - } - } - else if (sl->spacetype == SPACE_NODE) { - SpaceNode *snode = (SpaceNode *)sl; - BLO_write_struct(writer, SpaceNode, snode); - - LISTBASE_FOREACH (bNodeTreePath *, path, &snode->treepath) { - BLO_write_struct(writer, bNodeTreePath, path); - } - } - else if (sl->spacetype == SPACE_CONSOLE) { - SpaceConsole *con = (SpaceConsole *)sl; - - LISTBASE_FOREACH (ConsoleLine *, cl, &con->history) { - /* 'len_alloc' is invalid on write, set from 'len' on read */ - BLO_write_struct(writer, ConsoleLine, cl); - BLO_write_raw(writer, (size_t)cl->len + 1, cl->line); - } - BLO_write_struct(writer, SpaceConsole, sl); - } -#ifdef WITH_GLOBAL_AREA_WRITING - else if (sl->spacetype == SPACE_TOPBAR) { - BLO_write_struct(writer, SpaceTopBar, sl); - } - else if (sl->spacetype == SPACE_STATUSBAR) { - BLO_write_struct(writer, SpaceStatusBar, sl); - } -#endif - else if (sl->spacetype == SPACE_USERPREF) { - BLO_write_struct(writer, SpaceUserPref, sl); - } - else if (sl->spacetype == SPACE_CLIP) { - BLO_write_struct(writer, SpaceClip, sl); - } - else if (sl->spacetype == SPACE_INFO) { - BLO_write_struct(writer, SpaceInfo, sl); - } - } -} - -static void write_area_map(BlendWriter *writer, ScrAreaMap *area_map) -{ - BLO_write_struct_list(writer, ScrVert, &area_map->vertbase); - BLO_write_struct_list(writer, ScrEdge, &area_map->edgebase); - LISTBASE_FOREACH (ScrArea *, area, &area_map->areabase) { - area->butspacetype = area->spacetype; /* Just for compatibility, will be reset below. */ - - BLO_write_struct(writer, ScrArea, area); - -#ifdef WITH_GLOBAL_AREA_WRITING - BLO_write_struct(writer, ScrGlobalAreaData, area->global); -#endif - - write_area_regions(writer, area); - - area->butspacetype = SPACE_EMPTY; /* Unset again, was changed above. */ - } + BKE_screen_view3d_shading_blend_write(writer, &xr_data->session_settings.shading); } static void write_windowmanager(BlendWriter *writer, wmWindowManager *wm, const void *id_address) @@ -2024,7 +1652,7 @@ static void write_windowmanager(BlendWriter *writer, wmWindowManager *wm, const BLO_write_struct(writer, Stereo3dFormat, win->stereo3d_format); #ifdef WITH_GLOBAL_AREA_WRITING - write_area_map(writer, &win->global_areas); + BKE_screen_area_map_blend_write(writer, &win->global_areas); #else win->global_areas = global_areas; #endif @@ -2034,37 +1662,6 @@ static void write_windowmanager(BlendWriter *writer, wmWindowManager *wm, const } } -static void write_screen(BlendWriter *writer, bScreen *screen, const void *id_address) -{ - /* Screens are reference counted, only saved if used by a workspace. */ - if (screen->id.us > 0 || BLO_write_is_undo(writer)) { - /* write LibData */ - /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */ - writestruct_at_address(writer->wd, ID_SCRN, bScreen, 1, id_address, screen); - BKE_id_blend_write(writer, &screen->id); - - BKE_previewimg_blend_write(writer, screen->preview); - - /* direct data */ - write_area_map(writer, AREAMAP_FROM_SCREEN(screen)); - } -} - -static void write_workspace(BlendWriter *writer, WorkSpace *workspace, const void *id_address) -{ - BLO_write_id_struct(writer, WorkSpace, id_address, &workspace->id); - BKE_id_blend_write(writer, &workspace->id); - BLO_write_struct_list(writer, WorkSpaceLayout, &workspace->layouts); - BLO_write_struct_list(writer, WorkSpaceDataRelation, &workspace->hook_layout_relations); - BLO_write_struct_list(writer, wmOwnerID, &workspace->owner_ids); - BLO_write_struct_list(writer, bToolRef, &workspace->tools); - LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { - if (tref->properties) { - IDP_BlendWrite(writer, tref->properties); - } - } -} - /* Keep it last of write_foodata functions. */ static void write_libraries(WriteData *wd, Main *main) { @@ -2326,24 +1923,16 @@ static bool write_file_handle(Main *mainvar, case ID_WM: write_windowmanager(&writer, (wmWindowManager *)id_buffer, id); break; - case ID_WS: - write_workspace(&writer, (WorkSpace *)id_buffer, id); - break; - case ID_SCR: - write_screen(&writer, (bScreen *)id_buffer, id); - break; case ID_SCE: write_scene(&writer, (Scene *)id_buffer, id); break; - case ID_GR: - write_collection(&writer, (Collection *)id_buffer, id); - break; case ID_OB: write_object(&writer, (Object *)id_buffer, id); break; + case ID_WS: + case ID_SCR: case ID_PA: - write_particlesettings(&writer, (ParticleSettings *)id_buffer, id); - break; + case ID_GR: case ID_ME: case ID_LT: case ID_AC: @@ -2678,7 +2267,13 @@ void BLO_write_struct_at_address_by_id(BlendWriter *writer, const void *address, const void *data_ptr) { - writestruct_at_address_nr(writer->wd, DATA, struct_id, 1, address, data_ptr); + BLO_write_struct_at_address_by_id_with_filecode(writer, DATA, struct_id, address, data_ptr); +} + +void BLO_write_struct_at_address_by_id_with_filecode( + BlendWriter *writer, int filecode, int struct_id, const void *address, const void *data_ptr) +{ + writestruct_at_address_nr(writer->wd, filecode, struct_id, 1, address, data_ptr); } void BLO_write_struct_array_by_id(BlendWriter *writer, diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c index 52b41726276..4361f6f9b51 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c @@ -247,6 +247,10 @@ GPENCIL_MaterialPool *gpencil_material_pool_create(GPENCIL_PrivateData *pd, Obje gp_style = gpencil_viewport_material_overrides(pd, ob, color_type, gp_style); + /* Dots or Squares rotation. */ + mat_data->alignment_rot_cos = cosf(gp_style->alignment_rotation); + mat_data->alignment_rot_sin = sinf(gp_style->alignment_rotation); + /* Stroke Style */ if ((gp_style->stroke_style == GP_MATERIAL_STROKE_STYLE_TEXTURE) && (gp_style->sima)) { bool premul; diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 0922ab6552c..04128dc157e 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -62,7 +62,7 @@ typedef struct gpMaterial { float stroke_color[4]; float fill_color[4]; float fill_mix_color[4]; - float fill_uv_transform[3][2], _pad0[2]; + float fill_uv_transform[3][2], alignment_rot_cos, alignment_rot_sin; float stroke_texture_mix; float stroke_u_scale; float fill_texture_mix; diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl index 5e930af7bd7..94b066c12e5 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl @@ -461,6 +461,14 @@ void stroke_vertex() float rot_cos = abs(uv_rot); x_axis = mat2(rot_cos, -rot_sin, rot_sin, rot_cos) * x_axis; +# ifdef GP_MATERIAL_BUFFER_LEN + if (is_dot) { + float alignment_cos = MATERIAL(m).fill_uv_offset.z; + float alignment_sin = MATERIAL(m).fill_uv_offset.w; + x_axis = mat2(alignment_cos, -alignment_sin, alignment_sin, alignment_cos) * x_axis; + } +# endif + vec2 y_axis = rotate_90deg(x_axis); strokeAspect = decode_aspect(aspect1); diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index fc622c7a52e..deebf1d1efc 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -21,13 +21,11 @@ * \ingroup edanimation */ -/* User-Interface Stuff for F-Modifiers: - * This file defines the (C-Coded) templates + editing callbacks needed - * by the interface stuff or F-Modifiers, as used by F-Curves in the Graph Editor, - * and NLA-Strips in the NLA Editor. +/** + * User Interface for F-Modifiers * - * Copy/Paste Buffer for F-Modifiers: - * For now, this is also defined in this file so that it can be shared between the + * This file defines templates and some editing callbacks needed by the interface for + * F-Modifiers, as used by F-Curves in the Graph Editor and NLA-Strips in the NLA Editor. */ #include <string.h> @@ -1047,8 +1045,12 @@ void ANIM_uiTemplate_fmodifier_draw(uiLayout *layout, } } -/* ********************************************** */ -/* COPY/PASTE BUFFER STUFF */ +/* -------------------------------------------------------------------- */ +/** \name Copy / Paste Buffer Code + * + * For now, this is also defined in this file so that it can be shared between the graph editor + * and the NLA editor. + * \{ */ /* Copy/Paste Buffer itself (list of FModifier 's) */ static ListBase fmodifier_copypaste_buf = {NULL, NULL}; @@ -1139,4 +1141,4 @@ bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace, FCurve *c return ok; } -/* ********************************************** */ +/** \} */ diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 15f3939b2f6..d39c7eb0d95 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -1131,7 +1131,7 @@ static int *init_index_map(Object *obedit, int *r_old_totvert) } int vertex_index = 0; - LISTBASE_FOREACH (Nurb *, nu, &curve->nurb) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if (nu->bezt) { BezTriple *bezt = nu->bezt; int a = nu->pntsu; diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 2a880c11afb..1e5984ee14c 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -635,7 +635,10 @@ void FONT_OT_text_paste_from_file(wmOperatorType *ot) /** \name Text To Object * \{ */ -static void txt_add_object(bContext *C, TextLine *firstline, int totline, const float offset[3]) +static void txt_add_object(bContext *C, + const TextLine *firstline, + int totline, + const float offset[3]) { Main *bmain = CTX_data_main(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -644,7 +647,7 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const Curve *cu; Object *obedit; Base *base; - struct TextLine *tmp; + const struct TextLine *tmp; int nchars = 0, nbytes = 0; char *s; int a; @@ -709,10 +712,10 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, obedit); } -void ED_text_to_object(bContext *C, Text *text, const bool split_lines) +void ED_text_to_object(bContext *C, const Text *text, const bool split_lines) { RegionView3D *rv3d = CTX_wm_region_view3d(C); - TextLine *line; + const TextLine *line; float offset[3]; int linenum = 0; diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 98789706a13..aae92f5ed50 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -3398,24 +3398,50 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, } /* define start and end points of each stroke */ - float area[3], sb[3], ea[3], eb[3]; + float start_a[3], start_b[3], end_a[3], end_b[3]; pt = &gps_a->points[0]; - copy_v3_v3(area, &pt->x); + copy_v3_v3(start_a, &pt->x); pt = &gps_a->points[gps_a->totpoints - 1]; - copy_v3_v3(ea, &pt->x); + copy_v3_v3(end_a, &pt->x); pt = &gps_b->points[0]; - copy_v3_v3(sb, &pt->x); + copy_v3_v3(start_b, &pt->x); pt = &gps_b->points[gps_b->totpoints - 1]; - copy_v3_v3(eb, &pt->x); + copy_v3_v3(end_b, &pt->x); - /* review if need flip stroke B */ - float ea_sb = len_squared_v3v3(ea, sb); - float ea_eb = len_squared_v3v3(ea, eb); - /* flip if distance to end point is shorter */ - if (ea_eb < ea_sb) { + /* Check if need flip strokes. */ + float dist = len_squared_v3v3(end_a, start_b); + bool flip_a = false; + bool flip_b = false; + float lowest = dist; + + dist = len_squared_v3v3(end_a, end_b); + if (dist < lowest) { + lowest = dist; + flip_a = false; + flip_b = true; + } + + dist = len_squared_v3v3(start_a, start_b); + if (dist < lowest) { + lowest = dist; + flip_a = true; + flip_b = false; + } + + dist = len_squared_v3v3(start_a, end_b); + if (dist < lowest) { + lowest = dist; + flip_a = true; + flip_b = true; + } + + if (flip_a) { + gpencil_flip_stroke(gps_a); + } + if (flip_b) { gpencil_flip_stroke(gps_b); } @@ -3439,16 +3465,69 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, } } +typedef struct tJoinStrokes { + bGPDframe *gpf; + bGPDstroke *gps; + bool used; +} tJoinStrokes; + +static int gpencil_get_nearest_stroke_index(tJoinStrokes *strokes_list, + const bGPDstroke *gps, + const int totstrokes) +{ + int index = -1; + float min_dist = FLT_MAX; + float dist, start_a[3], end_a[3], start_b[3], end_b[3]; + + bGPDspoint *pt = &gps->points[0]; + copy_v3_v3(start_a, &pt->x); + + pt = &gps->points[gps->totpoints - 1]; + copy_v3_v3(end_a, &pt->x); + + for (int i = 0; i < totstrokes; i++) { + tJoinStrokes *elem = &strokes_list[i]; + if (elem->used) { + continue; + } + pt = &elem->gps->points[0]; + copy_v3_v3(start_b, &pt->x); + + pt = &elem->gps->points[elem->gps->totpoints - 1]; + copy_v3_v3(end_b, &pt->x); + + dist = len_squared_v3v3(start_a, start_b); + if (dist < min_dist) { + min_dist = dist; + index = i; + } + dist = len_squared_v3v3(start_a, end_b); + if (dist < min_dist) { + min_dist = dist; + index = i; + } + dist = len_squared_v3v3(end_a, start_b); + if (dist < min_dist) { + min_dist = dist; + index = i; + } + dist = len_squared_v3v3(end_a, end_b); + if (dist < min_dist) { + min_dist = dist; + index = i; + } + } + + return index; +} + static int gpencil_stroke_join_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *activegpl = BKE_gpencil_layer_active_get(gpd); Object *ob = CTX_data_active_object(C); - - bGPDframe *gpf_a = NULL; - bGPDstroke *stroke_a = NULL; - bGPDstroke *stroke_b = NULL; - bGPDstroke *new_stroke = NULL; + /* Limit the number of strokes to join. */ + const int max_join_strokes = 64; const int type = RNA_enum_get(op->ptr, "type"); const bool leave_gaps = RNA_boolean_get(op->ptr, "leave_gaps"); @@ -3464,87 +3543,89 @@ static int gpencil_stroke_join_exec(bContext *C, wmOperator *op) BLI_assert(ELEM(type, GP_STROKE_JOIN, GP_STROKE_JOINCOPY)); - /* read all selected strokes */ - bool first = false; + int tot_strokes = 0; + /** Alloc memory */ + tJoinStrokes *strokes_list = MEM_malloc_arrayN(sizeof(tJoinStrokes), max_join_strokes, __func__); + tJoinStrokes *elem = NULL; + /* Read all selected strokes to create a list. */ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { bGPDframe *gpf = gpl->actframe; if (gpf == NULL) { continue; } - LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { + /* Add all stroke selected of the frame. */ + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { if (gps->flag & GP_STROKE_SELECT) { /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) { continue; } - /* check if the color is editable */ + /* check if the color is editable. */ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { continue; } - - /* to join strokes, cyclic must be disabled */ - gps->flag &= ~GP_STROKE_CYCLIC; - - /* saves first frame and stroke */ - if (!first) { - first = true; - gpf_a = gpf; - stroke_a = gps; + elem = &strokes_list[tot_strokes]; + elem->gpf = gpf; + elem->gps = gps; + elem->used = false; + + tot_strokes++; + /* Limit the number of strokes. */ + if (tot_strokes == max_join_strokes) { + BKE_reportf(op->reports, + RPT_WARNING, + "Too many strokes selected. Only joined first %d strokes.", + max_join_strokes); + break; } - else { - stroke_b = gps; - - /* create a new stroke if was not created before (only created if something to join) */ - if (new_stroke == NULL) { - new_stroke = BKE_gpencil_stroke_duplicate(stroke_a, true); + } + } + } + CTX_DATA_END; - /* if new, set current color */ - if (type == GP_STROKE_JOINCOPY) { - new_stroke->mat_nr = stroke_a->mat_nr; - } - } + /* Nothing to join. */ + if (tot_strokes < 2) { + MEM_SAFE_FREE(strokes_list); + return OPERATOR_CANCELLED; + } - /* join new_stroke and stroke B. New stroke will contain all the previous data */ - gpencil_stroke_join_strokes(new_stroke, stroke_b, leave_gaps); + /* Take first stroke. */ + elem = &strokes_list[0]; + elem->used = true; - /* if join only, delete old strokes */ - if (type == GP_STROKE_JOIN) { - if (stroke_a) { - /* Calc geometry data. */ - BKE_gpencil_stroke_geometry_update(new_stroke); + /* Create a new stroke. */ + bGPDstroke *gps_new = BKE_gpencil_stroke_duplicate(elem->gps, true); + gps_new->flag &= ~GP_STROKE_CYCLIC; + BLI_insertlinkbefore(&elem->gpf->strokes, elem->gps, gps_new); - BLI_insertlinkbefore(&gpf_a->strokes, stroke_a, new_stroke); - BLI_remlink(&gpf->strokes, stroke_a); - BKE_gpencil_free_stroke(stroke_a); - stroke_a = NULL; - } - if (stroke_b) { - BLI_remlink(&gpf->strokes, stroke_b); - BKE_gpencil_free_stroke(stroke_b); - stroke_b = NULL; - } - } - } - } + /* Join all strokes until the list is completed. */ + while (true) { + int i = gpencil_get_nearest_stroke_index(strokes_list, gps_new, tot_strokes); + if (i < 0) { + break; } + elem = &strokes_list[i]; + /* Join new_stroke and stroke B. */ + gpencil_stroke_join_strokes(gps_new, elem->gps, leave_gaps); + elem->used = true; } - CTX_DATA_END; - /* add new stroke if was not added before */ - if (type == GP_STROKE_JOINCOPY) { - if (new_stroke) { - /* Add a new frame if needed */ - if (activegpl->actframe == NULL) { - activegpl->actframe = BKE_gpencil_frame_addnew(activegpl, gpf_a->framenum); - } - /* Calc geometry data. */ - BKE_gpencil_stroke_geometry_update(new_stroke); + /* Calc geometry data for new stroke. */ + BKE_gpencil_stroke_geometry_update(gps_new); - BLI_addtail(&activegpl->actframe->strokes, new_stroke); + /* If join only, delete old strokes. */ + if (type == GP_STROKE_JOIN) { + for (int i = 0; i < tot_strokes; i++) { + elem = &strokes_list[i]; + BLI_remlink(&elem->gpf->strokes, elem->gps); + BKE_gpencil_free_stroke(elem->gps); } } + /* Free memory. */ + MEM_SAFE_FREE(strokes_list); + /* notifiers */ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 380dfd1a7a2..320357dc678 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -220,7 +220,7 @@ static bool gpencil_interpolate_check_todo(bContext *C, bGPdata *gpd) int fFrame; /* only selected */ - if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && + if ((GPENCIL_EDIT_MODE(gpd)) && (flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) { continue; } @@ -300,7 +300,7 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) bool valid = true; /* only selected */ - if ((tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && + if ((GPENCIL_EDIT_MODE(gpd)) && (tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) { valid = false; } @@ -1018,7 +1018,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) for (gps_from = prevFrame->strokes.first; gps_from; gps_from = gps_from->next) { /* only selected */ - if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && + if ((GPENCIL_EDIT_MODE(gpd)) && (flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) { continue; } diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h index f9b1d9cdc64..8015a665970 100644 --- a/source/blender/editors/include/ED_curve.h +++ b/source/blender/editors/include/ED_curve.h @@ -84,7 +84,7 @@ void ED_curve_editfont_load(struct Object *obedit); void ED_curve_editfont_make(struct Object *obedit); void ED_curve_editfont_free(struct Object *obedit); -void ED_text_to_object(struct bContext *C, struct Text *text, const bool split_lines); +void ED_text_to_object(struct bContext *C, const struct Text *text, const bool split_lines); void ED_curve_beztcpy(struct EditNurb *editnurb, struct BezTriple *dst, diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h index dbd374415b0..989854872f3 100644 --- a/source/blender/editors/include/ED_undo.h +++ b/source/blender/editors/include/ED_undo.h @@ -36,6 +36,9 @@ struct wmOperator; struct wmOperatorType; /* undo.c */ +bool ED_undo_is_state_valid(struct bContext *C); +void ED_undo_group_begin(struct bContext *C); +void ED_undo_group_end(struct bContext *C); void ED_undo_push(struct bContext *C, const char *str); void ED_undo_push_op(struct bContext *C, struct wmOperator *op); void ED_undo_grouped_push(struct bContext *C, const char *str); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 4451199bb7c..ac31148340a 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -4550,10 +4550,22 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons button_activate_state(C, but, BUTTON_STATE_EXIT); return WM_UI_HANDLER_BREAK; } - if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { - /* Support alt+wheel on expanded enum rows */ + if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { + /* Support ctrl-wheel to cycle values on expanded enum rows. */ if (but->type == UI_BTYPE_ROW) { - const int direction = (event->type == WHEELDOWNMOUSE) ? -1 : 1; + int type = event->type; + int val = event->val; + + /* Convert pan to scroll-wheel. */ + if (type == MOUSEPAN) { + ui_pan_to_scroll(event, &type, &val); + + if (type == MOUSEPAN) { + return WM_UI_HANDLER_BREAK; + } + } + + const int direction = (type == WHEELDOWNMOUSE) ? -1 : 1; uiBut *but_select = ui_but_find_select_in_enum(but, direction); if (but_select) { uiBut *but_other = (direction == -1) ? but_select->next : but_select->prev; @@ -5648,8 +5660,20 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co return WM_UI_HANDLER_BREAK; } if (ui_but_supports_cycling(but)) { - if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { - const int direction = (event->type == WHEELDOWNMOUSE) ? 1 : -1; + if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { + int type = event->type; + int val = event->val; + + /* Convert pan to scroll-wheel. */ + if (type == MOUSEPAN) { + ui_pan_to_scroll(event, &type, &val); + + if (type == MOUSEPAN) { + return WM_UI_HANDLER_BREAK; + } + } + + const int direction = (type == WHEELDOWNMOUSE) ? 1 : -1; data->value = ui_but_menu_step(but, direction); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index cf589e43858..efb29fe75c3 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -964,7 +964,11 @@ static uiBut *ui_item_with_label(uiLayout *layout, UI_block_layout_set_current(block, layout); /* Only add new row if more than 1 item will be added. */ - if (name[0] || use_prop_decorate) { + if (name[0] +#ifdef UI_PROP_DECORATE + || use_prop_decorate +#endif + ) { /* Also avoid setting 'align' if possible. Set the space to zero instead as aligning a large * number of labels can end up aligning thousands of buttons when displaying key-map search (a * heavy operation), see: T78636. */ @@ -972,8 +976,8 @@ static uiBut *ui_item_with_label(uiLayout *layout, sub->space = 0; } -#ifdef UI_PROP_DECORATE if (name[0]) { +#ifdef UI_PROP_DECORATE if (use_prop_sep) { layout_prop_decorate = uiItemL_respect_property_split(layout, name, 0); } diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 66194cf8783..258516a1c61 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -1059,6 +1059,7 @@ static int view_zoomout_invoke(bContext *C, wmOperator *op, const wmEvent *event /* store initial mouse position (in view space) */ UI_view2d_region_to_view( ®ion->v2d, event->mval[0], event->mval[1], &vzd->mx_2d, &vzd->my_2d); + vzd->zoom_to_mouse_pos = true; } return view_zoomout_exec(C, op); @@ -1232,6 +1233,11 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even v2d = vzd->v2d; if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { + ARegion *region = CTX_wm_region(C); + + /* Store initial mouse position (in view space). */ + UI_view2d_region_to_view( + ®ion->v2d, event->mval[0], event->mval[1], &vzd->mx_2d, &vzd->my_2d); vzd->zoom_to_mouse_pos = true; } @@ -1278,14 +1284,6 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even /* for modal exit test */ vzd->invoke_event = event->type; - if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { - ARegion *region = CTX_wm_region(C); - - /* store initial mouse position (in view space) */ - UI_view2d_region_to_view( - ®ion->v2d, event->mval[0], event->mval[1], &vzd->mx_2d, &vzd->my_2d); - } - if (v2d->keepofs & V2D_LOCKOFS_X) { WM_cursor_modal_set(window, WM_CURSOR_NS_SCROLL); } diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c index 089bd5567a7..9eaa8f3d31b 100644 --- a/source/blender/editors/object/object_modes.c +++ b/source/blender/editors/object/object_modes.c @@ -445,37 +445,41 @@ static int object_switch_object_invoke(bContext *C, wmOperator *op, const wmEven return OPERATOR_CANCELLED; } - if (!ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports)) { - return OPERATOR_CANCELLED; - } - - Object *ob_dst_orig = DEG_get_original_object(ob_dst); - Base *base = BKE_view_layer_base_find(view_layer, ob_dst_orig); - BKE_view_layer_base_deselect_all(view_layer); - BKE_view_layer_base_select_and_set_active(view_layer, base); - DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); - - /* FIXME: Do a single undo push. */ - ED_undo_push(C, "Change Active"); - - ob_dst_orig = DEG_get_original_object(ob_dst); - ED_object_mode_set_ex(C, last_mode, true, op->reports); - - /* Update the viewport rotation origin to the mouse cursor. */ - if (last_mode & OB_MODE_ALL_PAINT) { - float global_loc[3]; - if (ED_view3d_autodist_simple(ar, event->mval, global_loc, 0, NULL)) { - UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; - copy_v3_v3(ups->average_stroke_accum, global_loc); - ups->average_stroke_counter = 1; - ups->last_stroke_valid = true; + int retval = OPERATOR_CANCELLED; + + ED_undo_group_begin(C); + + if (ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports)) { + Object *ob_dst_orig = DEG_get_original_object(ob_dst); + Base *base = BKE_view_layer_base_find(view_layer, ob_dst_orig); + BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_select_and_set_active(view_layer, base); + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + + ED_undo_push(C, "Change Active"); + + ob_dst_orig = DEG_get_original_object(ob_dst); + ED_object_mode_set_ex(C, last_mode, true, op->reports); + + /* Update the viewport rotation origin to the mouse cursor. */ + if (last_mode & OB_MODE_ALL_PAINT) { + float global_loc[3]; + if (ED_view3d_autodist_simple(ar, event->mval, global_loc, 0, NULL)) { + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + copy_v3_v3(ups->average_stroke_accum, global_loc); + ups->average_stroke_counter = 1; + ups->last_stroke_valid = true; + } } + + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + WM_toolsystem_update_from_context_view3d(C); + retval = OPERATOR_FINISHED; } - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - WM_toolsystem_update_from_context_view3d(C); + ED_undo_group_end(C); - return OPERATOR_FINISHED; + return retval; } void OBJECT_OT_switch_object(wmOperatorType *ot) diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 3d65a9e5fcb..12c61b75ff7 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -696,7 +696,7 @@ bool ED_object_parent_set(ReportList *reports, /* Preconditions. */ if (ob == par) { /* Parenting an object to itself is impossible. */ - return true; + return false; } if (BKE_object_parent_loop_check(par, ob)) { diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 5a789ee0b01..d961813d04a 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -2013,6 +2013,8 @@ static void outliner_draw_mode_column_toggle(uiBlock *block, tip); UI_but_func_set(but, outliner_mode_toggle_fn, tselem, NULL); UI_but_flag_enable(but, UI_BUT_DRAG_LOCK); + /* Mode toggling handles it's own undo state because undo steps need to be grouped. */ + UI_but_flag_disable(but, UI_BUT_UNDO); if (ID_IS_LINKED(&ob->id)) { UI_but_disable(but, TIP_("Can't edit external library data")); diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index c818aa8caa9..acdedf8a238 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -85,64 +85,107 @@ #include "outliner_intern.h" +/** + * \note changes to selection are by convention and not essential. + * + * \note Handles own undo push. + */ static void do_outliner_item_editmode_toggle(bContext *C, Scene *scene, Base *base) { Main *bmain = CTX_data_main(C); Object *ob = base->object; + bool changed = false; if (BKE_object_is_in_editmode(ob)) { - ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA); - WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); + changed = ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA); + if (changed) { + ED_object_base_select(base, BA_DESELECT); + WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); + } } else { - ED_object_editmode_enter_ex(CTX_data_main(C), scene, ob, EM_NO_CONTEXT); - WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL); + changed = ED_object_editmode_enter_ex(CTX_data_main(C), scene, ob, EM_NO_CONTEXT); + if (changed) { + ED_object_base_select(base, BA_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL); + } + } + + if (changed) { + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + ED_outliner_select_sync_from_object_tag(C); + ED_undo_push(C, "Outliner Edit Mode Toggle"); } } -static void do_outliner_item_posemode_toggle(bContext *C, Base *base) +/** + * \note changes to selection are by convention and not essential. + * + * \note Handles own undo push. + */ +static void do_outliner_item_posemode_toggle(bContext *C, Scene *scene, Base *base) { Main *bmain = CTX_data_main(C); Object *ob = base->object; if (ID_IS_LINKED(ob)) { BKE_report(CTX_wm_reports(C), RPT_WARNING, "Cannot pose libdata"); + return; } - else if (ob->mode & OB_MODE_POSE) { - ED_object_posemode_exit_ex(bmain, ob); - WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); + + bool changed = false; + if (ob->mode & OB_MODE_POSE) { + changed = ED_object_posemode_exit_ex(bmain, ob); + if (changed) { + ED_object_base_select(base, BA_DESELECT); + WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); + } } else { - ED_object_posemode_enter_ex(bmain, ob); - WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL); + changed = ED_object_posemode_enter_ex(bmain, ob); + if (changed) { + ED_object_base_select(base, BA_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL); + } + } + + if (changed) { + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + ED_outliner_select_sync_from_object_tag(C); + ED_undo_push(C, "Outliner Pose Mode Toggle"); } } -/* Swap the current active object from the interaction mode with the given base. */ +/** + * Swap the current active object from the interaction mode with the given base. + * + * \note Changes to selection _are_ needed in this case, + * since entering the object mode uses the selection. + * + * If we didn't want to touch selection we could add an option to the operators + * not to do multi-object editing. + * + * \note Handles own undo push. + */ static void do_outliner_item_mode_toggle_generic(bContext *C, TreeViewContext *tvc, Base *base) { - Main *bmain = CTX_data_main(C); - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); const int active_mode = tvc->obact->mode; + ED_undo_group_begin(C); - /* Return all objects to object mode. */ - FOREACH_OBJECT_BEGIN (tvc->view_layer, ob_iter) { - ED_object_mode_generic_exit(bmain, depsgraph, tvc->scene, ob_iter); - } - FOREACH_OBJECT_END; - WM_toolsystem_update_from_context_view3d(C); - - Base *base_active = BKE_view_layer_base_find(tvc->view_layer, tvc->obact); - if (base_active != base) { - ED_object_base_select(base_active, BA_DESELECT); - ED_object_base_activate(C, base); - ED_object_base_select(base, BA_SELECT); + if (ED_object_mode_set(C, OB_MODE_OBJECT)) { + Base *base_active = BKE_view_layer_base_find(tvc->view_layer, tvc->obact); + if (base_active != base) { + BKE_view_layer_base_deselect_all(tvc->view_layer); + BKE_view_layer_base_select_and_set_active(tvc->view_layer, base); + DEG_id_tag_update(&tvc->scene->id, ID_RECALC_SELECT); + ED_undo_push(C, "Change Active"); - /* XXX: Must add undo step between activation and setting mode to prevent an assert. */ - ED_undo_push(C, "outliner mode toggle"); - ED_object_mode_set(C, active_mode); - ED_outliner_select_sync_from_object_tag(C); + /* Operator call does undo push. */ + ED_object_mode_set(C, active_mode); + ED_outliner_select_sync_from_object_tag(C); + } } + ED_undo_group_end(C); } /* Toggle the item's interaction mode if supported */ @@ -169,7 +212,7 @@ void outliner_item_mode_toggle(bContext *C, do_outliner_item_editmode_toggle(C, tvc->scene, base); } else if (tvc->ob_pose && ob->type == OB_ARMATURE) { - do_outliner_item_posemode_toggle(C, base); + do_outliner_item_posemode_toggle(C, tvc->scene, base); } } } diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 97d0db51de0..1ca7222e02d 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -159,6 +159,15 @@ static bool text_new_poll(bContext *UNUSED(C)) return 1; } +static bool text_data_poll(bContext *C) +{ + Text *text = CTX_data_edit_text(C); + if (!text) { + return false; + } + return true; +} + static bool text_edit_poll(bContext *C) { Text *text = CTX_data_edit_text(C); @@ -751,11 +760,6 @@ void TEXT_OT_save_as(wmOperatorType *ot) /** \name Run Script Operator * \{ */ -static bool text_run_script_poll(bContext *C) -{ - return (CTX_data_edit_text(C) != NULL); -} - static int text_run_script(bContext *C, ReportList *reports) { #ifdef WITH_PYTHON @@ -817,7 +821,7 @@ void TEXT_OT_run_script(wmOperatorType *ot) ot->description = "Run active script"; /* api callbacks */ - ot->poll = text_run_script_poll; + ot->poll = text_data_poll; ot->exec = text_run_script_exec; /* flags */ @@ -3911,7 +3915,7 @@ void TEXT_OT_resolve_conflict(wmOperatorType *ot) static int text_to_3d_object_exec(bContext *C, wmOperator *op) { - Text *text = CTX_data_edit_text(C); + const Text *text = CTX_data_edit_text(C); const bool split_lines = RNA_boolean_get(op->ptr, "split_lines"); ED_text_to_object(C, text, split_lines); @@ -3928,7 +3932,7 @@ void TEXT_OT_to_3d_object(wmOperatorType *ot) /* api callbacks */ ot->exec = text_to_3d_object_exec; - ot->poll = text_edit_poll; + ot->poll = text_data_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c index c40f3d3f140..09100bb50cc 100644 --- a/source/blender/editors/transform/transform_gizmo_2d.c +++ b/source/blender/editors/transform/transform_gizmo_2d.c @@ -53,7 +53,7 @@ /* -------------------------------------------------------------------- */ /** \name Shared Callback's - */ + * \{ */ static bool gizmo2d_generic_poll(const bContext *C, wmGizmoGroupType *gzgt) { diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c index 47d60cff0f9..2328f7d5256 100644 --- a/source/blender/editors/undo/ed_undo.c +++ b/source/blender/editors/undo/ed_undo.c @@ -76,6 +76,44 @@ static CLG_LogRef LOG = {"ed.undo"}; * Non-operator undo editor functions. * \{ */ +/** + * Run from the main event loop, basic checks that undo is left in a correct state. + */ +bool ED_undo_is_state_valid(bContext *C) +{ + wmWindowManager *wm = CTX_wm_manager(C); + + /* Currently only checks matching begin/end calls. */ + if (wm->undo_stack == NULL) { + /* No undo stack is valid, nothing to do. */ + return true; + } + if (wm->undo_stack->group_level != 0) { + /* If this fails #ED_undo_grouped_begin, #ED_undo_grouped_end calls don't match. */ + return false; + } + if (wm->undo_stack->step_active != NULL) { + if (wm->undo_stack->step_active->skip == true) { + /* Skip is only allowed between begin/end calls, + * a state that should never happen in main event loop. */ + return false; + } + } + return true; +} + +void ED_undo_group_begin(bContext *C) +{ + wmWindowManager *wm = CTX_wm_manager(C); + BKE_undosys_stack_group_begin(wm->undo_stack); +} + +void ED_undo_group_end(bContext *C) +{ + wmWindowManager *wm = CTX_wm_manager(C); + BKE_undosys_stack_group_end(wm->undo_stack); +} + void ED_undo_push(bContext *C, const char *str) { CLOG_INFO(&LOG, 1, "name='%s'", str); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c index dec6ef63ffb..628c5bc0476 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c @@ -86,7 +86,7 @@ static void initData(GpencilModifierData *md) MEMCPY_STRUCT_AFTER(gpmd, DNA_struct_default_get(ArrayGpencilModifierData), modifier); /* Open the first subpanel too, because it's activated by default. */ - md->ui_expand_flag = (1 << 0) | (1 << 1); + md->ui_expand_flag = UI_PANEL_DATA_EXPAND_ROOT | UI_SUBPANEL_DATA_EXPAND_1; } static void copyData(const GpencilModifierData *md, GpencilModifierData *target) diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index c95e5376670..93a67602047 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -60,7 +60,7 @@ typedef struct bConstraint { /** Constraint name, MAX_NAME. */ char name[64]; - /* Flag for panel and subpanel closed / open state in the UI. */ + /* An "expand" bit for each of the constraint's (sub)panels (uiPanelDataExpansion). */ short ui_expand_flag; /** Amount of influence exherted by constraint (0.0-1.0). */ diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index 1a83120cae9..7107e131eda 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -74,6 +74,7 @@ typedef struct GpencilModifierData { int type, mode; char _pad0[4]; short flag; + /* An "expand" bit for each of the modifier's (sub)panels (uiPanelDataExpansion). */ short ui_expand_flag; /** MAX_NAME. */ char name[64]; diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 355d3d6439b..1d31b876068 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -99,7 +99,8 @@ typedef struct MaterialGPencilStyle { float mix_stroke_factor; /** Mode used to align Dots and Boxes with stroke drawing path and object rotation */ int alignment_mode; - char _pad[4]; + /** Rotation for texture for Dots and Squares. */ + float alignment_rotation; } MaterialGPencilStyle; /* MaterialGPencilStyle->flag */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 9dec5230c6c..d7ad1d59002 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -121,7 +121,7 @@ typedef struct ModifierData { int type, mode; char _pad0[4]; short flag; - /* An "expand" bit for each of the modifier's (sub)panels. */ + /* An "expand" bit for each of the modifier's (sub)panels (uiPanelDataExpansion). */ short ui_expand_flag; /** MAX_NAME. */ char name[64]; diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index f0ff02d3668..d2360d700d2 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -184,6 +184,34 @@ typedef struct Panel { } Panel; /** + * Used for passing expansion between instanced panel data and the panels themselves. + * There are 16 defines because the expansion data is typically stored in a short. + * + * \note Expansion for instanced panels is stored in depth first order. For example, the value of + * UI_SUBPANEL_DATA_EXPAND_2 correspond to mean the expansion of the second subpanel or the first + * subpanel's first subpanel. + */ +typedef enum uiPanelDataExpansion { + UI_PANEL_DATA_EXPAND_ROOT = (1 << 0), + UI_SUBPANEL_DATA_EXPAND_1 = (1 << 1), + UI_SUBPANEL_DATA_EXPAND_2 = (1 << 2), + UI_SUBPANEL_DATA_EXPAND_3 = (1 << 3), + UI_SUBPANEL_DATA_EXPAND_4 = (1 << 4), + UI_SUBPANEL_DATA_EXPAND_5 = (1 << 5), + UI_SUBPANEL_DATA_EXPAND_6 = (1 << 6), + UI_SUBPANEL_DATA_EXPAND_7 = (1 << 7), + UI_SUBPANEL_DATA_EXPAND_8 = (1 << 8), + UI_SUBPANEL_DATA_EXPAND_9 = (1 << 9), + UI_SUBPANEL_DATA_EXPAND_10 = (1 << 10), + UI_SUBPANEL_DATA_EXPAND_11 = (1 << 11), + UI_SUBPANEL_DATA_EXPAND_12 = (1 << 12), + UI_SUBPANEL_DATA_EXPAND_13 = (1 << 13), + UI_SUBPANEL_DATA_EXPAND_14 = (1 << 14), + UI_SUBPANEL_DATA_EXPAND_15 = (1 << 15), + UI_SUBPANEL_DATA_EXPAND_16 = (1 << 16), +} uiPanelDataExpansion; + +/** * Notes on Panel Categories: * * - #ARegion.panels_category (#PanelCategoryDyn) diff --git a/source/blender/makesdna/DNA_shader_fx_types.h b/source/blender/makesdna/DNA_shader_fx_types.h index 5567d65b6db..07ccac5ba29 100644 --- a/source/blender/makesdna/DNA_shader_fx_types.h +++ b/source/blender/makesdna/DNA_shader_fx_types.h @@ -65,7 +65,7 @@ typedef struct ShaderFxData { int type, mode; char _pad0[4]; short flag; - /* Expansion for shader effect panels and sub-panels. */ + /* An "expand" bit for each of the constraint's (sub)panels (uiPanelDataExpansion). */ short ui_expand_flag; /** MAX_NAME. */ char name[64]; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 4a02ac8f429..733b459495d 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -589,6 +589,7 @@ typedef struct WalkNavigation { } WalkNavigation; typedef struct UserDef_Runtime { + /** Mark as changed so the preferences are saved on exit. */ char is_dirty; char _pad0[7]; } UserDef_Runtime; diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index 60eed60ace1..02ae71e3b3d 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -1456,8 +1456,16 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem simulation_methods[] = { - {FLUID_DOMAIN_METHOD_FLIP, "FLIP", 0, "FLIP", "Use FLIP as the simulation method"}, - /*{FLUID_DOMAIN_METHOD_APIC, "APIC", 0, "APIC", "Use APIC as the simulation method"},*/ + {FLUID_DOMAIN_METHOD_FLIP, + "FLIP", + 0, + "FLIP", + "Use FLIP as the simulation method (more splashy behavior)"}, + {FLUID_DOMAIN_METHOD_APIC, + "APIC", + 0, + "APIC", + "Use APIC as the simulation method (more energetic and stable behavior)"}, {0, NULL, 0, NULL, NULL}, }; @@ -1820,6 +1828,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "simulation_method"); RNA_def_property_enum_items(prop, simulation_methods); RNA_def_property_ui_text(prop, "Simulation Method", "Change the underlying simulation method"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_data_reset"); prop = RNA_def_property(srna, "flip_ratio", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 5e16f1187fb..086a182e085 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -24,6 +24,8 @@ #include "DNA_material_types.h" #include "DNA_texture_types.h" +#include "BLI_math.h" + #include "RNA_define.h" #include "RNA_enum_types.h" @@ -594,6 +596,16 @@ static void rna_def_material_greasepencil(BlenderRNA *brna) prop, "Alignment", "Defines how align Dots and Boxes with drawing path and object rotation"); RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update"); + /* Rotation of texture for Dots or Strokes. */ + prop = RNA_def_property(srna, "alignment_rotation", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "alignment_rotation"); + RNA_def_property_float_default(prop, 0.0f); + RNA_def_property_range(prop, -DEG2RADF(90.0f), DEG2RADF(90.0f)); + RNA_def_property_ui_range(prop, -DEG2RADF(90.0f), DEG2RADF(90.0f), 10, 3); + RNA_def_property_ui_text( + prop, "Rotation", "Additional rotation applied to dots and square strokes"); + RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update"); + /* pass index for future compositing and editing tools */ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "index"); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 0ce56e66fab..349b6327ecb 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1527,12 +1527,7 @@ static void rna_ParticleInstanceModifier_particle_system_set(PointerRNA *ptr, static void rna_Modifier_show_expanded_set(PointerRNA *ptr, bool value) { ModifierData *md = ptr->data; - if (value) { - md->ui_expand_flag |= (1 << 0); - } - else { - md->ui_expand_flag &= ~(1 << 0); - } + SET_FLAG_FROM_TEST(md->ui_expand_flag, value, UI_PANEL_DATA_EXPAND_ROOT); } /** @@ -1543,7 +1538,7 @@ static void rna_Modifier_show_expanded_set(PointerRNA *ptr, bool value) static bool rna_Modifier_show_expanded_get(PointerRNA *ptr) { ModifierData *md = ptr->data; - return md->ui_expand_flag & (1 << 0); + return md->ui_expand_flag & UI_PANEL_DATA_EXPAND_ROOT; } static int rna_MeshSequenceCacheModifier_has_velocity_get(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index eab48888d48..0f6136ef287 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -3175,7 +3175,7 @@ static void rna_def_space_outliner(BlenderRNA *brna) prop = RNA_def_property(srna, "filter_id_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "filter_id_type"); RNA_def_property_enum_items(prop, rna_enum_id_type_items); - RNA_def_property_ui_text(prop, "Filter ID Type", "Data-block type to show"); + RNA_def_property_ui_text(prop, "Filter by Type", "Data-block type to show"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID); } diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 17fe5d90eca..d4ba7e570c6 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -217,9 +217,10 @@ static void rna_userdef_version_get(PointerRNA *ptr, int *value) value[2] = userdef->subversionfile; } +/** Mark the preferences as being changed so they are saved on exit. */ # define USERDEF_TAG_DIRTY rna_userdef_is_dirty_update_impl() -/* Use single function so we can more easily breakpoint it. */ +/** Use single function so we can more easily break-point it. */ void rna_userdef_is_dirty_update_impl(void) { /* We can't use 'ptr->data' because this update function diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 6ca50a34ebf..12930a7e9b8 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -69,7 +69,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(amd, DNA_struct_default_get(ArrayModifierData), modifier); /* Open the first subpanel by default, it corresspnds to Relative offset which is enabled too. */ - md->ui_expand_flag = (1 << 0) | (1 << 1); + md->ui_expand_flag = UI_PANEL_DATA_EXPAND_ROOT | UI_SUBPANEL_DATA_EXPAND_1; } static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index 131c02374a7..9f99e036601 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -74,7 +74,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(mmd, DNA_struct_default_get(MultiresModifierData), modifier); /* Open subdivision panels by default. */ - md->ui_expand_flag = (1 << 0) | (1 << 1); + md->ui_expand_flag = UI_PANEL_DATA_EXPAND_ROOT | UI_SUBPANEL_DATA_EXPAND_1; } static void requiredDataMask(Object *UNUSED(ob), diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 8eb9a3b0650..8f141a8e23b 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -3159,6 +3159,7 @@ static void wm_event_free_and_remove_from_queue_if_valid(wmEvent *event) void wm_event_do_handlers(bContext *C) { wmWindowManager *wm = CTX_wm_manager(C); + BLI_assert(ED_undo_is_state_valid(C)); /* Update key configuration before handling events. */ WM_keyconfig_update(wm); diff --git a/source/creator/creator.c b/source/creator/creator.c index 4f5af4bf4ac..738b49dff84 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -415,6 +415,9 @@ int main(int argc, * since they impact `BKE_appdir` behavior. */ BKE_appdir_init(); + /* After parsing number of threads argument. */ + BLI_task_scheduler_init(); + /* Initialize sub-systems that use `BKE_appdir.h`. */ IMB_init(); @@ -425,9 +428,6 @@ int main(int argc, main_signal_setup(); #endif - /* After parsing number of threads argument. */ - BLI_task_scheduler_init(); - #ifdef WITH_FFMPEG /* Keep after #ARG_PASS_SETTINGS since debug flags are checked. */ IMB_ffmpeg_init(); diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index ef1c8e935c3..a36bdbf8a87 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -2071,6 +2071,8 @@ void main_args_setup(bContext *C, bArgs *ba) BLI_argsAdd(ba, NULL, "--env-system-scripts", CB_EX(arg_handle_env_system_set, scripts), NULL); BLI_argsAdd(ba, NULL, "--env-system-python", CB_EX(arg_handle_env_system_set, python), NULL); + BLI_argsAdd(ba, "-t", "--threads", CB(arg_handle_threads_set), NULL); + /* Pass: Background Mode & Settings * * Also and commands that exit after usage. */ @@ -2088,8 +2090,6 @@ void main_args_setup(bContext *C, bArgs *ba) BLI_argsAdd(ba, NULL, "--disable-crash-handler", CB(arg_handle_crash_handler_disable), NULL); BLI_argsAdd(ba, NULL, "--disable-abort-handler", CB(arg_handle_abort_handler_disable), NULL); - BLI_argsAdd(ba, "-t", "--threads", CB(arg_handle_threads_set), NULL); - BLI_argsAdd(ba, "-b", "--background", CB(arg_handle_background_mode_set), NULL); BLI_argsAdd(ba, "-a", NULL, CB(arg_handle_playback_mode), NULL); |