Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2020-10-30 18:40:41 +0300
committerJacques Lucke <jacques@blender.org>2020-10-30 18:40:41 +0300
commit1103809fabe9da4a13755480e19b13d56cd27843 (patch)
tree99d975d7d24ded60fb7f083e0758a3950e8696b0 /source/blender
parent5b89d49b0d297a33271a311f80ff503b3412686a (diff)
parent62e532785dfd5bd25fb6b1269ec41ea81a32c4c9 (diff)
Merge branch 'master' into geometry-nodes
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_collection.h22
-rw-r--r--source/blender/blenkernel/BKE_layer.h9
-rw-r--r--source/blender/blenkernel/BKE_particle.h9
-rw-r--r--source/blender/blenkernel/BKE_screen.h17
-rw-r--r--source/blender/blenkernel/BKE_undo_system.h9
-rw-r--r--source/blender/blenkernel/intern/collection.c179
-rw-r--r--source/blender/blenkernel/intern/constraint.c7
-rw-r--r--source/blender/blenkernel/intern/fluid.c1
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c3
-rw-r--r--source/blender/blenkernel/intern/lattice_deform.c16
-rw-r--r--source/blender/blenkernel/intern/layer.c93
-rw-r--r--source/blender/blenkernel/intern/modifier.c3
-rw-r--r--source/blender/blenkernel/intern/particle.c287
-rw-r--r--source/blender/blenkernel/intern/screen.c844
-rw-r--r--source/blender/blenkernel/intern/shader_fx.c3
-rw-r--r--source/blender/blenkernel/intern/undo_system.c51
-rw-r--r--source/blender/blenkernel/intern/workspace.c102
-rw-r--r--source/blender/blenloader/BLO_read_write.h12
-rw-r--r--source/blender/blenloader/intern/readfile.c1115
-rw-r--r--source/blender/blenloader/intern/readfile.h1
-rw-r--r--source/blender/blenloader/intern/versioning_250.c2
-rw-r--r--source/blender/blenloader/intern/writefile.c435
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_data.c4
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h2
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl8
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c20
-rw-r--r--source/blender/editors/curve/editcurve.c2
-rw-r--r--source/blender/editors/curve/editfont.c11
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c221
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c6
-rw-r--r--source/blender/editors/include/ED_curve.h2
-rw-r--r--source/blender/editors/include/ED_undo.h3
-rw-r--r--source/blender/editors/interface/interface_handlers.c34
-rw-r--r--source/blender/editors/interface/interface_layout.c8
-rw-r--r--source/blender/editors/interface/view2d_ops.c14
-rw-r--r--source/blender/editors/object/object_modes.c58
-rw-r--r--source/blender/editors/object/object_relations.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c103
-rw-r--r--source/blender/editors/space_text/text_ops.c20
-rw-r--r--source/blender/editors/transform/transform_gizmo_2d.c2
-rw-r--r--source/blender/editors/undo/ed_undo.c38
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c2
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h2
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h1
-rw-r--r--source/blender/makesdna/DNA_material_types.h3
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h2
-rw-r--r--source/blender/makesdna/DNA_screen_types.h28
-rw-r--r--source/blender/makesdna/DNA_shader_fx_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_fluid.c13
-rw-r--r--source/blender/makesrna/intern/rna_material.c12
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c9
-rw-r--r--source/blender/makesrna/intern/rna_space.c2
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c3
-rw-r--r--source/blender/modifiers/intern/MOD_array.c2
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c2
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c1
58 files changed, 2143 insertions, 1722 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, &region->panels);
+
+ LISTBASE_FOREACH (PanelCategoryStack *, pc_act, &region->panels_category_active) {
+ BLO_write_struct(writer, PanelCategoryStack, pc_act);
+ }
+
+ LISTBASE_FOREACH (uiList *, ui_list, &region->ui_lists) {
+ write_uilist(writer, ui_list);
+ }
+
+ LISTBASE_FOREACH (uiPreview *, ui_preview, &region->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, &region->panels);
+
+ BLO_read_list(reader, &region->panels_category_active);
+
+ BLO_read_list(reader, &region->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, &region->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, &region->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, &region->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(&region->panels_category);
+ BLI_listbase_clear(&region->handlers);
+ BLI_listbase_clear(&region->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(&region->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, &region->panels);
-
- BLO_read_list(reader, &region->panels_category_active);
-
- BLO_read_list(reader, &region->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, &region->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, &region->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, &region->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(&region->panels_category);
- BLI_listbase_clear(&region->handlers);
- BLI_listbase_clear(&region->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(&region->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, &region->panels);
-
- LISTBASE_FOREACH (PanelCategoryStack *, pc_act, &region->panels_category_active) {
- BLO_write_struct(writer, PanelCategoryStack, pc_act);
- }
-
- LISTBASE_FOREACH (uiList *, ui_list, &region->ui_lists) {
- write_uilist(writer, ui_list);
- }
-
- LISTBASE_FOREACH (uiPreview *, ui_preview, &region->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(
&region->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(
+ &region->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(
- &region->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);