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:
authorBastien Montagne <montagne29@wanadoo.fr>2016-06-27 16:59:01 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2016-06-27 16:59:01 +0300
commitcbce7fef1604fdfd3099fd196b2a44f61b22eb76 (patch)
treeb11963a42641ef95c61c01a7b2b83dddce4cd1a2 /source/blender
parentc2dc77983dc4d3271858737a15ee058ef48fb833 (diff)
parente2c7ee773311734450a229051673fbfea61b641a (diff)
Merge branch 'master' into blender2.8
Conflicts: source/blender/blenkernel/intern/pointcache.c source/blender/makesrna/intern/rna_main_api.c source/blender/makesrna/intern/rna_particle.c
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_blender.h5
-rw-r--r--source/blender/blenkernel/BKE_blender_undo.h2
-rw-r--r--source/blender/blenkernel/BKE_displist.h14
-rw-r--r--source/blender/blenkernel/BKE_movieclip.h1
-rw-r--r--source/blender/blenkernel/BKE_text.h1
-rw-r--r--source/blender/blenkernel/CMakeLists.txt3
-rw-r--r--source/blender/blenkernel/intern/blender.c53
-rw-r--r--source/blender/blenkernel/intern/blender_undo.c14
-rw-r--r--source/blender/blenkernel/intern/brush.c15
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c4
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c6
-rw-r--r--source/blender/blenkernel/intern/displist.c14
-rw-r--r--source/blender/blenkernel/intern/idcode.c10
-rw-r--r--source/blender/blenkernel/intern/image.c2
-rw-r--r--source/blender/blenkernel/intern/library_remap.c7
-rw-r--r--source/blender/blenkernel/intern/mesh.c6
-rw-r--r--source/blender/blenkernel/intern/movieclip.c67
-rw-r--r--source/blender/blenkernel/intern/text.c185
-rw-r--r--source/blender/blenlib/BLI_array_utils.h4
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h2
-rw-r--r--source/blender/blenlib/intern/BLI_filelist.c4
-rw-r--r--source/blender/blenlib/intern/array_utils.c18
-rw-r--r--source/blender/blenlib/intern/math_geom.c2
-rw-r--r--source/blender/blenlib/intern/path_util.c2
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/blenloader/intern/writefile.c40
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon_edgenet.c128
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c3
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.c80
-rw-r--r--source/blender/editors/animation/drivers.c8
-rw-r--r--source/blender/editors/animation/keyframes_edit.c74
-rw-r--r--source/blender/editors/animation/keyframing.c3
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c30
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c60
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h1
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c5
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c46
-rw-r--r--source/blender/editors/include/ED_fileselect.h2
-rw-r--r--source/blender/editors/include/ED_gpencil.h2
-rw-r--r--source/blender/editors/include/ED_keyframes_edit.h34
-rw-r--r--source/blender/editors/include/ED_mask.h2
-rw-r--r--source/blender/editors/include/UI_interface.h12
-rw-r--r--source/blender/editors/interface/interface.c2
-rw-r--r--source/blender/editors/interface/interface_handlers.c28
-rw-r--r--source/blender/editors/interface/interface_templates.c12
-rw-r--r--source/blender/editors/mask/mask_editaction.c30
-rw-r--r--source/blender/editors/mesh/editface.c3
-rw-r--r--source/blender/editors/object/object_constraint.c76
-rw-r--r--source/blender/editors/object/object_relations.c2
-rw-r--r--source/blender/editors/space_action/action_intern.h2
-rw-r--r--source/blender/editors/space_action/action_ops.c10
-rw-r--r--source/blender/editors/space_action/action_select.c259
-rw-r--r--source/blender/editors/space_file/file_intern.h1
-rw-r--r--source/blender/editors/space_file/file_ops.c105
-rw-r--r--source/blender/editors/space_file/file_utils.c17
-rw-r--r--source/blender/editors/space_file/filelist.c9
-rw-r--r--source/blender/editors/space_file/filesel.c4
-rw-r--r--source/blender/editors/space_graph/graph_ops.c7
-rw-r--r--source/blender/editors/space_graph/graph_select.c83
-rw-r--r--source/blender/editors/space_graph/space_graph.c45
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c11
-rw-r--r--source/blender/editors/space_text/text_ops.c3
-rw-r--r--source/blender/editors/space_view3d/drawobject.c18
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c4
-rw-r--r--source/blender/editors/transform/transform.c15
-rw-r--r--source/blender/editors/transform/transform.h4
-rw-r--r--source/blender/editors/transform/transform_ops.c3
-rw-r--r--source/blender/editors/transform/transform_snap_object.c2
-rw-r--r--source/blender/freestyle/intern/system/PythonInterpreter.h3
-rw-r--r--source/blender/gpu/GPU_draw.h6
-rw-r--r--source/blender/gpu/intern/gpu_draw.c149
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex.glsl6
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex_world.glsl68
-rw-r--r--source/blender/imbuf/intern/thumbs.c4
-rw-r--r--source/blender/makesdna/DNA_anim_types.h5
-rw-r--r--source/blender/makesdna/DNA_node_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_ID.c9
-rw-r--r--source/blender/makesrna/intern/rna_camera.c6
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c2
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c426
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c6
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c21
-rw-r--r--source/blender/makesrna/intern/rna_space.c8
-rw-r--r--source/blender/nodes/NOD_static_types.h2
-rw-r--r--source/blender/python/intern/bpy_operator.c5
-rw-r--r--source/blender/render/intern/source/convertblender.c15
-rw-r--r--source/blender/windowmanager/WM_api.h6
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c9
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c3
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c144
-rw-r--r--source/blender/windowmanager/wm_subwindow.h2
92 files changed, 1514 insertions, 1125 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 8ce85c8e615..d2d9c763031 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -50,6 +50,11 @@ void BKE_blender_userdef_refresh(void);
void BKE_blender_callback_test_break_set(void (*func)(void));
int BKE_blender_test_break(void);
+/* Blenders' own atexit (avoids leaking) */
+void BKE_blender_atexit_register(void (*func)(void *user_data), void *user_data);
+void BKE_blender_atexit_unregister(void (*func)(void *user_data), const void *user_data);
+void BKE_blender_atexit(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_blender_undo.h b/source/blender/blenkernel/BKE_blender_undo.h
index cd18bd8db40..9547eeb9838 100644
--- a/source/blender/blenkernel/BKE_blender_undo.h
+++ b/source/blender/blenkernel/BKE_blender_undo.h
@@ -45,6 +45,8 @@ extern const char *BKE_undo_get_name(int nr, bool *r_active);
extern bool BKE_undo_save_file(const char *filename);
extern struct Main *BKE_undo_get_main(struct Scene **r_scene);
+extern void BKE_undo_callback_wm_kill_jobs_set(void (*callback)(struct bContext *C));
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index 3b096773d96..9625f05192a 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -45,10 +45,14 @@
#define DL_VERTS 7
/* dl->flag */
-#define DL_CYCL_U 1
-#define DL_CYCL_V 2
-#define DL_FRONT_CURVE 4
-#define DL_BACK_CURVE 8
+enum {
+ /** U/V swapped here compared with #Nurb.flagu, #Nurb.flagv and #CU_NURB_CYCLIC */
+ DL_CYCL_U = (1 << 0),
+ DL_CYCL_V = (1 << 1),
+
+ DL_FRONT_CURVE = (1 << 2),
+ DL_BACK_CURVE = (1 << 3),
+};
/* prototypes */
@@ -70,7 +74,7 @@ typedef struct DispList {
int charidx;
int totindex; /* indexed array drawing surfaces */
- unsigned int *bevelSplitFlag;
+ unsigned int *bevel_split; /* BLI_bitmap */
} DispList;
void BKE_displist_copy(struct ListBase *lbn, struct ListBase *lb);
diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h
index afca326c727..3d963ac109c 100644
--- a/source/blender/blenkernel/BKE_movieclip.h
+++ b/source/blender/blenkernel/BKE_movieclip.h
@@ -40,7 +40,6 @@ struct MovieClipUser;
struct MovieDistortion;
void BKE_movieclip_free(struct MovieClip *clip);
-void BKE_movieclip_unlink(struct Main *bmain, struct MovieClip *clip);
struct MovieClip *BKE_movieclip_file_add(struct Main *bmain, const char *name);
struct MovieClip *BKE_movieclip_file_add_exists_ex(struct Main *bmain, const char *name, bool *r_exists);
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index b14593f5a56..858feeeab10 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -53,7 +53,6 @@ struct Text *BKE_text_load_ex(struct Main *bmain, const char *file, const cha
const bool is_internal);
struct Text *BKE_text_load (struct Main *bmain, const char *file, const char *relpath);
struct Text *BKE_text_copy (struct Main *bmain, struct Text *ta);
-void BKE_text_unlink (struct Main *bmain, struct Text *text);
void BKE_text_clear (struct Text *text);
void BKE_text_write (struct Text *text, const char *str);
int BKE_text_file_modified_check(struct Text *text);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index df715531cb7..74930dbea4a 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -49,9 +49,6 @@ set(INC
../../../intern/smoke/extern
../../../intern/atomic
../../../intern/libmv
-
- # XXX - BAD LEVEL CALL WM_api.h
- ../windowmanager
)
set(INC_SYS
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 15492fbd20d..0805335da66 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -226,3 +226,56 @@ int BKE_blender_test_break(void)
return (G.is_break == true);
}
+
+/** \name Blender's AtExit
+ *
+ * \note Don't use MEM_mallocN so functions can be registered at any time.
+ * \{ */
+
+struct AtExitData {
+ struct AtExitData *next;
+
+ void (*func)(void *user_data);
+ void *user_data;
+} *g_atexit = NULL;
+
+void BKE_blender_atexit_register(void (*func)(void *user_data), void *user_data)
+{
+ struct AtExitData *ae = malloc(sizeof(*ae));
+ ae->next = g_atexit;
+ ae->func = func;
+ ae->user_data = user_data;
+ g_atexit = ae;
+}
+
+void BKE_blender_atexit_unregister(void (*func)(void *user_data), const void *user_data)
+{
+ struct AtExitData *ae = g_atexit;
+ struct AtExitData **ae_p = &g_atexit;
+
+ while (ae) {
+ if ((ae->func == func) && (ae->user_data == user_data)) {
+ *ae_p = ae->next;
+ free(ae);
+ return;
+ }
+ ae_p = &ae;
+ ae = ae->next;
+ }
+}
+
+void BKE_blender_atexit(void)
+{
+ struct AtExitData *ae = g_atexit, *ae_next;
+ while (ae) {
+ ae_next = ae->next;
+
+ ae->func(ae->user_data);
+
+ free(ae);
+ ae = ae_next;
+ }
+ g_atexit = NULL;
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c
index ca0a1b91cea..d64bf7ecf43 100644
--- a/source/blender/blenkernel/intern/blender_undo.c
+++ b/source/blender/blenkernel/intern/blender_undo.c
@@ -66,9 +66,6 @@
#include "BLO_readfile.h"
#include "BLO_writefile.h"
-#include "WM_api.h" // XXXXX BAD, very BAD dependency (bad level call) - remove asap, elubie
-
-
/* -------------------------------------------------------------------- */
/** \name Global Undo
@@ -87,6 +84,15 @@ typedef struct UndoElem {
static ListBase undobase = {NULL, NULL};
static UndoElem *curundo = NULL;
+/**
+ * Avoid bad-level call to #WM_jobs_kill_all_except()
+ */
+static void (*undo_wm_job_kill_callback)(struct bContext *C) = NULL;
+
+void BKE_undo_callback_wm_kill_jobs_set(void (*callback)(struct bContext *C))
+{
+ undo_wm_job_kill_callback = callback;
+}
static int read_undosave(bContext *C, UndoElem *uel)
{
@@ -94,7 +100,7 @@ static int read_undosave(bContext *C, UndoElem *uel)
int success = 0, fileflags;
/* This is needed so undoing/redoing doesn't crash with threaded previews going */
- WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C));
+ undo_wm_job_kill_callback(C);
BLI_strncpy(mainstr, G.main->name, sizeof(mainstr)); /* temporal store */
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index a3e006a162f..44cacffb71f 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -216,21 +216,6 @@ void BKE_brush_free(Brush *brush)
BKE_previewimg_free(&(brush->preview));
}
-/**
- * \note Currently users don't remove brushes from the UI (as is done for scene, text... etc)
- * This is only used by RNA, which can remove brushes.
- */
-void BKE_brush_unlink(Main *bmain, Brush *brush)
-{
- Brush *brush_iter;
-
- for (brush_iter = bmain->brush.first; brush_iter; brush_iter = brush_iter->id.next) {
- if (brush_iter->toggle_brush == brush) {
- brush_iter->toggle_brush = NULL;
- }
- }
-}
-
static void extern_local_brush(Brush *brush)
{
id_lib_extern((ID *)brush->mtex.tex);
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index 7821946eb6e..e0277c38e61 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -565,7 +565,7 @@ BVHTree *bvhtree_from_mesh_verts(
/**
* Builds a bvh tree where nodes are the given vertices (note: does not copy given mverts!).
* \param vert_allocated if true, vert freeing will be done when freeing data.
- * \param mask if not null, true elements give which vert to add to BVH tree.
+ * \param verts_mask if not null, true elements give which vert to add to BVH tree.
* \param verts_num_active if >= 0, number of active verts to add to BVH tree (else will be computed from mask).
*/
BVHTree *bvhtree_from_mesh_verts_ex(
@@ -804,7 +804,7 @@ BVHTree *bvhtree_from_mesh_faces(
* Builds a bvh tree where nodes are the given tessellated faces (note: does not copy given mfaces!).
* \param vert_allocated if true, vert freeing will be done when freeing data.
* \param face_allocated if true, face freeing will be done when freeing data.
- * \param mask if not null, true elements give which faces to add to BVH tree.
+ * \param faces_mask: if not null, true elements give which faces to add to BVH tree.
* \param numFaces_active if >= 0, number of active faces to add to BVH tree (else will be computed from mask).
*/
BVHTree *bvhtree_from_mesh_faces_ex(
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 267f7a65e00..159d5b82a6c 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -61,8 +61,6 @@
#include "GPU_shader.h"
#include "GPU_basic_shader.h"
-#include "WM_api.h"
-
#include <string.h>
#include <limits.h>
#include <math.h>
@@ -699,10 +697,10 @@ static void cdDM_drawMappedFaces(
}
if ((orig != ORIGINDEX_NONE) && !is_hidden)
- WM_framebuffer_index_get(orig + 1, &selcol);
+ GPU_select_index_get(orig + 1, &selcol);
}
else if (orig != ORIGINDEX_NONE)
- WM_framebuffer_index_get(orig + 1, &selcol);
+ GPU_select_index_get(orig + 1, &selcol);
for (j = 0; j < mpoly->totloop; j++)
fi_map[start_element++] = selcol;
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 98cbe47c7f9..49db75a0474 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -71,7 +71,7 @@ void BKE_displist_elem_free(DispList *dl)
if (dl->verts) MEM_freeN(dl->verts);
if (dl->nors) MEM_freeN(dl->nors);
if (dl->index) MEM_freeN(dl->index);
- if (dl->bevelSplitFlag) MEM_freeN(dl->bevelSplitFlag);
+ if (dl->bevel_split) MEM_freeN(dl->bevel_split);
MEM_freeN(dl);
}
}
@@ -144,8 +144,9 @@ void BKE_displist_copy(ListBase *lbn, ListBase *lb)
dln->nors = MEM_dupallocN(dl->nors);
dln->index = MEM_dupallocN(dl->index);
- if (dl->bevelSplitFlag)
- dln->bevelSplitFlag = MEM_dupallocN(dl->bevelSplitFlag);
+ if (dl->bevel_split) {
+ dln->bevel_split = MEM_dupallocN(dl->bevel_split);
+ }
dl = dl->next;
}
@@ -1629,7 +1630,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
if (dlb->type == DL_POLY) {
dl->flag |= DL_CYCL_U;
}
- if ((bl->poly >= 0) && (steps != 2)) {
+ if ((bl->poly >= 0) && (steps > 2)) {
dl->flag |= DL_CYCL_V;
}
@@ -1642,8 +1643,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
/* CU_2D conflicts with R_NOPUNOFLIP */
dl->rt = nu->flag & ~CU_2D;
- dl->bevelSplitFlag = MEM_callocN(sizeof(*dl->bevelSplitFlag) * ((steps + 0x1F) >> 5),
- "bevelSplitFlag");
+ dl->bevel_split = BLI_BITMAP_NEW(steps, "bevel_split");
/* for each point of poly make a bevel piece */
bevp_first = bl->bevpoints;
@@ -1683,7 +1683,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
}
if (bevp->split_tag) {
- dl->bevelSplitFlag[a >> 5] |= 1 << (a & 0x1F);
+ BLI_BITMAP_ENABLE(dl->bevel_split, a);
}
/* rotate bevel piece and write in data */
diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c
index ea99fa8f55a..c7a346d49ec 100644
--- a/source/blender/blenkernel/intern/idcode.c
+++ b/source/blender/blenkernel/intern/idcode.c
@@ -123,7 +123,7 @@ static IDType *idtype_from_code(short idcode)
/**
* Return if the ID code is a valid ID code.
*
- * \param code The code to check.
+ * \param idcode: The code to check.
* \return Boolean, 0 when invalid.
*/
bool BKE_idcode_is_valid(short idcode)
@@ -134,7 +134,7 @@ bool BKE_idcode_is_valid(short idcode)
/**
* Return non-zero when an ID type is linkable.
*
- * \param code The code to check.
+ * \param idcode: The code to check.
* \return Boolean, 0 when non linkable.
*/
bool BKE_idcode_is_linkable(short idcode)
@@ -147,7 +147,7 @@ bool BKE_idcode_is_linkable(short idcode)
/**
* Convert an idcode into a name.
*
- * \param code The code to convert.
+ * \param idcode: The code to convert.
* \return A static string representing the name of
* the code.
*/
@@ -258,7 +258,7 @@ short BKE_idcode_from_idfilter(const int idfilter)
/**
* Convert an idcode into a name (plural).
*
- * \param code The code to convert.
+ * \param idcode: The code to convert.
* \return A static string representing the name of
* the code.
*/
@@ -272,7 +272,7 @@ const char *BKE_idcode_to_name_plural(short idcode)
/**
* Convert an idcode into its translations' context.
*
- * \param code The code to convert.
+ * \param idcode: The code to convert.
* \return A static string representing the i18n context of the code.
*/
const char *BKE_idcode_to_translation_context(short idcode)
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 14a445649ad..69384a70969 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -95,8 +95,6 @@
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
-#include "WM_api.h"
-
static SpinLock image_spin;
/* prototypes */
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index 9335d41f399..3747b09fd99 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -162,15 +162,14 @@ static int foreach_libblock_remap_callback(void *user_data, ID *UNUSED(id_self),
}
if (*id_p && (*id_p == old_id)) {
+ const bool is_indirect = (id->lib != NULL);
+ const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0;
/* Note: proxy usage implies LIB_TAG_EXTERN, so on this aspect it is direct,
* on the other hand since they get reset to lib data on file open/reload it is indirect too...
* Edit Mode is also a 'skip direct' case. */
const bool is_obj = (GS(id->name) == ID_OB);
const bool is_proxy = (is_obj && (((Object *)id)->proxy || ((Object *)id)->proxy_group));
const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id));
- /* Note that indirect data from same file as processed ID is **not** considered indirect! */
- const bool is_indirect = ((id->lib != NULL) && (id->lib != old_id->lib));
- const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0;
const bool is_never_null = ((cb_flag & IDWALK_NEVER_NULL) && (new_id == NULL) &&
(id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0);
const bool skip_never_null = (id_remap_data->flag & ID_REMAP_SKIP_NEVER_NULL_USAGE) != 0;
@@ -184,7 +183,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *UNUSED(id_self),
(is_obj_editmode && (((Object *)id)->data == *id_p)) ||
(skip_indirect && (is_proxy || is_indirect)))
{
- if (is_never_null || is_proxy || is_obj_editmode) {
+ if (!is_indirect && (is_never_null || is_proxy || is_obj_editmode)) {
id_remap_data->skipped_direct++;
}
else {
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 4e47dfcce74..f82e5cf61b3 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -427,12 +427,6 @@ bool BKE_mesh_has_custom_loop_normals(Mesh *me)
}
}
-/* Note: unlinking is called when me->id.us is 0, question remains how
- * much unlinking of Library data in Mesh should be done... probably
- * we need a more generic method, like the expand() functions in
- * readfile.c */
-
-
/** Free (or release) any data used by this mesh (does not free the mesh itself). */
void BKE_mesh_free(Mesh *me)
{
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index 5f667732b04..f99457a4c26 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -1491,73 +1491,6 @@ void BKE_movieclip_free(MovieClip *clip)
BKE_tracking_free(&clip->tracking);
}
-void BKE_movieclip_unlink(Main *bmain, MovieClip *clip)
-{
- bScreen *scr;
- ScrArea *area;
- SpaceLink *sl;
- Scene *sce;
- Object *ob;
-
- for (scr = bmain->screen.first; scr; scr = scr->id.next) {
- for (area = scr->areabase.first; area; area = area->next) {
- for (sl = area->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_CLIP) {
- SpaceClip *sc = (SpaceClip *) sl;
-
- if (sc->clip == clip)
- sc->clip = NULL;
- }
- else if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *) sl;
- BGpic *bgpic;
-
- for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- if (bgpic->clip == clip)
- bgpic->clip = NULL;
- }
- }
- }
- }
- }
-
- for (sce = bmain->scene.first; sce; sce = sce->id.next) {
- if (sce->clip == clip)
- sce->clip = NULL;
- }
-
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- bConstraint *con;
-
- for (con = ob->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
- bFollowTrackConstraint *data = (bFollowTrackConstraint *) con->data;
-
- if (data->clip == clip)
- data->clip = NULL;
- }
- else if (con->type == CONSTRAINT_TYPE_CAMERASOLVER) {
- bCameraSolverConstraint *data = (bCameraSolverConstraint *) con->data;
-
- if (data->clip == clip)
- data->clip = NULL;
- }
- else if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
- bObjectSolverConstraint *data = (bObjectSolverConstraint *) con->data;
-
- if (data->clip == clip)
- data->clip = NULL;
- }
- }
- }
-
- FOREACH_NODETREE(bmain, ntree, id) {
- BKE_node_tree_unlink_id((ID *)clip, ntree);
- } FOREACH_NODETREE_END
-
- clip->id.us = 0;
-}
-
float BKE_movieclip_remap_scene_to_clip_frame(MovieClip *clip, float framenr)
{
return framenr - (float) clip->start_frame + 1.0f;
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 594f9dffbee..fdc2edba57f 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -498,191 +498,6 @@ Text *BKE_text_copy(Main *bmain, Text *ta)
return tan;
}
-void BKE_text_unlink(Main *bmain, Text *text)
-{
- bScreen *scr;
- ScrArea *area;
- SpaceLink *sl;
- Object *ob;
- bController *cont;
- bActuator *act;
- bConstraint *con;
- bNodeTree *ntree;
- bNode *node;
- Material *mat;
- Lamp *la;
- Tex *te;
- World *wo;
- FreestyleLineStyle *linestyle;
- Scene *sce;
- SceneRenderLayer *srl;
- FreestyleModuleConfig *module;
- bool update;
-
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- /* game controllers */
- for (cont = ob->controllers.first; cont; cont = cont->next) {
- if (cont->type == CONT_PYTHON) {
- bPythonCont *pc;
-
- pc = cont->data;
- if (pc->text == text) pc->text = NULL;
- }
- }
- /* game actuators */
- for (act = ob->actuators.first; act; act = act->next) {
- if (act->type == ACT_2DFILTER) {
- bTwoDFilterActuator *tfa;
-
- tfa = act->data;
- if (tfa->text == text) tfa->text = NULL;
- }
- }
-
- /* pyconstraints */
- update = 0;
-
- if (ob->type == OB_ARMATURE && ob->pose) {
- bPoseChannel *pchan;
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- for (con = pchan->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_PYTHON) {
- bPythonConstraint *data = con->data;
- if (data->text == text) data->text = NULL;
- update = 1;
-
- }
- }
- }
- }
-
- for (con = ob->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_PYTHON) {
- bPythonConstraint *data = con->data;
- if (data->text == text) data->text = NULL;
- update = 1;
- }
- }
-
- if (update)
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
-
- /* nodes */
- for (la = bmain->lamp.first; la; la = la->id.next) {
- ntree = la->nodetree;
- if (!ntree)
- continue;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == NODE_FRAME) {
- if ((Text *)node->id == text) {
- node->id = NULL;
- }
- }
- }
- }
-
- for (linestyle = bmain->linestyle.first; linestyle; linestyle = linestyle->id.next) {
- ntree = linestyle->nodetree;
- if (!ntree)
- continue;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == NODE_FRAME) {
- if ((Text *)node->id == text) {
- node->id = NULL;
- }
- }
- }
- }
-
- for (mat = bmain->mat.first; mat; mat = mat->id.next) {
- ntree = mat->nodetree;
- if (!ntree)
- continue;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM(node->type, SH_NODE_SCRIPT, NODE_FRAME)) {
- if ((Text *)node->id == text) {
- node->id = NULL;
- }
- }
- }
- }
-
- for (te = bmain->tex.first; te; te = te->id.next) {
- ntree = te->nodetree;
- if (!ntree)
- continue;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == NODE_FRAME) {
- if ((Text *)node->id == text) {
- node->id = NULL;
- }
- }
- }
- }
-
- for (wo = bmain->world.first; wo; wo = wo->id.next) {
- ntree = wo->nodetree;
- if (!ntree)
- continue;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == NODE_FRAME) {
- if ((Text *)node->id == text) {
- node->id = NULL;
- }
- }
- }
- }
-
- for (sce = bmain->scene.first; sce; sce = sce->id.next) {
- ntree = sce->nodetree;
- if (!ntree)
- continue;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == NODE_FRAME) {
- Text *ntext = (Text *)node->id;
- if (ntext == text) node->id = NULL;
- }
- }
-
- /* Freestyle (while looping over the scene) */
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
- for (module = srl->freestyleConfig.modules.first; module; module = module->next) {
- if (module->script == text)
- module->script = NULL;
- }
- }
- }
-
- for (ntree = bmain->nodetree.first; ntree; ntree = ntree->id.next) {
- for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM(node->type, SH_NODE_SCRIPT, NODE_FRAME)) {
- if ((Text *)node->id == text) {
- node->id = NULL;
- }
- }
- }
- }
-
- /* text space */
- for (scr = bmain->screen.first; scr; scr = scr->id.next) {
- for (area = scr->areabase.first; area; area = area->next) {
- for (sl = area->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_TEXT) {
- SpaceText *st = (SpaceText *) sl;
-
- if (st->text == text) {
- st->text = NULL;
- st->top = 0;
- }
- }
- }
- }
- }
-
- text->id.us = 0;
-}
-
void BKE_text_clear(Text *text) /* called directly from rna */
{
int oldstate;
diff --git a/source/blender/blenlib/BLI_array_utils.h b/source/blender/blenlib/BLI_array_utils.h
index 5ef8421c003..a46c87cec40 100644
--- a/source/blender/blenlib/BLI_array_utils.h
+++ b/source/blender/blenlib/BLI_array_utils.h
@@ -48,6 +48,10 @@ int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_strid
#define BLI_array_findindex(arr, arr_len, p) \
_bli_array_findindex(arr, arr_len, sizeof(*(arr)), p)
+int _bli_array_rfindindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p);
+#define BLI_array_rfindindex(arr, arr_len, p) \
+ _bli_array_rfindindex(arr, arr_len, sizeof(*(arr)), p)
+
void _bli_array_binary_and(
void *arr, const void *arr_a, const void *arr_b,
unsigned int arr_len, size_t arr_stride);
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 9120d9f53f7..8124e07dd47 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -273,7 +273,7 @@ void BLI_space_transform_invert_normal(const struct SpaceTransform *data, float
/*********************************** Other ***********************************/
void print_m3(const char *str, float M[3][3]);
-void print_m4(const char *str, float M[3][4]);
+void print_m4(const char *str, float M[4][4]);
#define print_m3_id(M) print_m3(STRINGIFY(M), M)
#define print_m4_id(M) print_m4(STRINGIFY(M), M)
diff --git a/source/blender/blenlib/intern/BLI_filelist.c b/source/blender/blenlib/intern/BLI_filelist.c
index 527d9934797..76de52bda66 100644
--- a/source/blender/blenlib/intern/BLI_filelist.c
+++ b/source/blender/blenlib/intern/BLI_filelist.c
@@ -352,8 +352,6 @@ void BLI_filelist_entry_datetime_to_string(
/**
* Deep-duplicate of a single direntry.
- *
- * \param dup_poin If given, called for each non-NULL direntry->poin. Otherwise, pointer is always simply copied over.
*/
void BLI_filelist_entry_duplicate(struct direntry *dst, const struct direntry *src)
{
@@ -368,8 +366,6 @@ void BLI_filelist_entry_duplicate(struct direntry *dst, const struct direntry *s
/**
* Deep-duplicate of an array of direntries, including the array itself.
- *
- * \param dup_poin If given, called for each non-NULL direntry->poin. Otherwise, pointer is always simply copied over.
*/
void BLI_filelist_duplicate(
struct direntry **dest_filelist, struct direntry * const src_filelist, const unsigned int nrentries)
diff --git a/source/blender/blenlib/intern/array_utils.c b/source/blender/blenlib/intern/array_utils.c
index 9c91da4abee..32f0111babd 100644
--- a/source/blender/blenlib/intern/array_utils.c
+++ b/source/blender/blenlib/intern/array_utils.c
@@ -134,8 +134,22 @@ void _bli_array_permute(
int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p)
{
const char *arr_step = (const char *)arr;
- unsigned int i;
- for (i = 0; i < arr_len; i++, arr_step += arr_stride) {
+ for (unsigned int i = 0; i < arr_len; i++, arr_step += arr_stride) {
+ if (memcmp(arr_step, p, arr_stride) == 0) {
+ return (int)i;
+ }
+ }
+ return -1;
+}
+
+/**
+ * A version of #BLI_array_findindex that searches from the end of the list.
+ */
+int _bli_array_rfindindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p)
+{
+ const char *arr_step = (const char *)arr + (arr_stride * arr_len);
+ for (unsigned int i = arr_len; i-- != 0; ) {
+ arr_step -= arr_stride;
if (memcmp(arr_step, p, arr_stride) == 0) {
return (int)i;
}
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 370e8bb0035..124f0c7abb8 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -2692,7 +2692,7 @@ bool isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v
}
/**
- * \param r_vi The point \a p projected onto the triangle.
+ * \param r_isect_co: The point \a p projected onto the triangle.
* \return True when \a p is inside the triangle.
* \note Its up to the caller to check the distance between \a p and \a r_vi against an error margin.
*/
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 2b793841c38..ded10ad7713 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -310,7 +310,7 @@ static int BLI_path_unc_prefix_len(const char *path); /* defined below in same f
/**
* Remove redundant characters from \a path and optionally make absolute.
*
- * \param relbase: The path this is relative to, or ignored when NULL.
+ * \param relabase: The path this is relative to, or ignored when NULL.
* \param path: Can be any input, and this function converts it to a regular full path.
* Also removes garbage from directory paths, like `/../` or double slashes etc.
*
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 3262f740b09..2e01456dbd5 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1324,6 +1324,7 @@ bool BLO_has_bfile_extension(const char *str)
*
* \param path the full path to explode.
* \param r_dir the string that'll contain path up to blend file itself ('library' path).
+ * WARNING! Must be FILE_MAX_LIBEXTRA long (it also stores group and name strings)!
* \param r_group the string that'll contain 'group' part of the path, if any. May be NULL.
* \param r_name the string that'll contain data's name part of the path, if any. May be NULL.
* \return true if path contains a blend file.
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 3393be059bd..194ad72100c 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -29,15 +29,22 @@
*/
-/*
- * FILEFORMAT: IFF-style structure (but not IFF compatible!)
+/**
+ *
+ * FILE FORMAT
+ * ===========
+ *
+ * IFF-style structure (but not IFF compatible!)
*
* start file:
+ * <pre>
* BLENDER_V100 12 bytes (versie 1.00)
* V = big endian, v = little endian
* _ = 4 byte pointer, - = 8 byte pointer
+ * </pre>
*
- * datablocks: also see struct BHead
+ * datablocks: (also see struct #BHead).
+ * <pre>
* <bh.code> 4 chars
* <bh.len> int, len data after BHead
* <bh.old> void, old pointer
@@ -46,29 +53,32 @@
* data
* ...
* ...
+ * </pre>
*
* Almost all data in Blender are structures. Each struct saved
* gets a BHead header. With BHead the struct can be linked again
* and compared with StructDNA .
*
+ *
* WRITE
+ * =====
*
* Preferred writing order: (not really a must, but why would you do it random?)
* Any case: direct data is ALWAYS after the lib block
*
* (Local file data)
* - for each LibBlock
- * - write LibBlock
- * - write associated direct data
+ * - write LibBlock
+ * - write associated direct data
* (External file data)
* - per library
- * - write library block
- * - per LibBlock
- * - write the ID of LibBlock
- * - write TEST (128x128, blend file preview, optional)
- * - write FileGlobal (some global vars)
- * - write SDNA
- * - write USER if filename is ~/X.XX/config/startup.blend
+ * - write library block
+ * - per LibBlock
+ * - write the ID of LibBlock
+ * - write #TEST (#RenderInfo struct. 128x128 blend file preview is optional).
+ * - write #GLOB (#FileGlobal struct) (some global vars).
+ * - write #DNA1 (#SDNA struct)
+ * - write #USER (#UserDef struct) if filename is ``~/X.XX/config/startup.blend``.
*/
@@ -309,12 +319,6 @@ static WriteData *writedata_new(WriteWrap *ww)
{
WriteData *wd= MEM_callocN(sizeof(*wd), "writedata");
- /* XXX, see note about this in readfile.c, remove
- * once we have an xp lock - zr
- */
-
- if (wd == NULL) return NULL;
-
wd->sdna = DNA_sdna_from_data(DNAstr, DNAlen, false);
wd->ww = ww;
diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
index c142dcae514..5ee0e904a33 100644
--- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
@@ -97,12 +97,22 @@ static BMLoop *bm_edge_flagged_radial_first(BMEdge *e)
return NULL;
}
+static void normalize_v2_m3_v3v3(float out[2], float axis_mat[3][3], const float v1[3], const float v2[3])
+{
+ float dir[3];
+ sub_v3_v3v3(dir, v1, v2);
+ mul_v2_m3v3(out, axis_mat, dir);
+ normalize_v2(out);
+}
+
+
/**
* \note Be sure to update #bm_face_split_edgenet_find_loop_pair_exists
* when making changed to edge picking logic.
*/
static bool bm_face_split_edgenet_find_loop_pair(
- BMVert *v_init, const float face_normal[3],
+ BMVert *v_init,
+ const float face_normal[3], float face_normal_matrix[3][3],
BMEdge *e_pair[2])
{
/* Always find one boundary edge (to determine winding)
@@ -142,10 +152,17 @@ static bool bm_face_split_edgenet_find_loop_pair(
}
e_pair[0] = BLI_SMALLSTACK_POP(edges_boundary);
+ /* use to hold boundary OR wire edges */
+ BLI_SMALLSTACK_DECLARE(edges_search, BMEdge *);
+
/* attempt one boundary and one wire, or 2 boundary */
if (edges_wire_len == 0) {
- if (edges_boundary_len >= 2) {
+ if (edges_boundary_len > 1) {
e_pair[1] = BLI_SMALLSTACK_POP(edges_boundary);
+
+ if (edges_boundary_len > 2) {
+ BLI_SMALLSTACK_SWAP(edges_search, edges_wire);
+ }
}
else {
/* one boundary and no wire */
@@ -154,28 +171,37 @@ static bool bm_face_split_edgenet_find_loop_pair(
}
else {
e_pair[1] = BLI_SMALLSTACK_POP(edges_wire);
-
if (edges_wire_len > 1) {
- BMVert *v_prev = BM_edge_other_vert(e_pair[0], v_init);
- BMVert *v_next;
- float angle_best;
-
- v_next = BM_edge_other_vert(e_pair[1], v_init);
- angle_best = angle_on_axis_v3v3v3_v3(v_prev->co, v_init->co, v_next->co, face_normal);
-
- BMEdge *e;
- while ((e = BLI_SMALLSTACK_POP(edges_wire))) {
- float angle_test;
- v_next = BM_edge_other_vert(e, v_init);
- angle_test = angle_on_axis_v3v3v3_v3(v_prev->co, v_init->co, v_next->co, face_normal);
- if (angle_test < angle_best) {
- angle_best = angle_test;
- e_pair[1] = e;
- }
- }
+ BLI_SMALLSTACK_SWAP(edges_search, edges_wire);
}
}
+ /* if we swapped above, search this list for the best edge */
+ if (!BLI_SMALLSTACK_IS_EMPTY(edges_search)) {
+ /* find the best edge in 'edge_list' to use for 'e_pair[1]' */
+ const BMVert *v_prev = BM_edge_other_vert(e_pair[0], v_init);
+ const BMVert *v_next = BM_edge_other_vert(e_pair[1], v_init);
+
+ float dir_prev[2], dir_next[2];
+
+ normalize_v2_m3_v3v3(dir_prev, face_normal_matrix, v_prev->co, v_init->co);
+ normalize_v2_m3_v3v3(dir_next, face_normal_matrix, v_next->co, v_init->co);
+ float angle_best_cos = dot_v2v2(dir_next, dir_prev);
+
+ BMEdge *e;
+ while ((e = BLI_SMALLSTACK_POP(edges_search))) {
+ v_next = BM_edge_other_vert(e, v_init);
+ float dir_test[2];
+
+ normalize_v2_m3_v3v3(dir_test, face_normal_matrix, v_next->co, v_init->co);
+ const float angle_test_cos = dot_v2v2(dir_prev, dir_test);
+
+ if (angle_test_cos > angle_best_cos) {
+ angle_best_cos = angle_test_cos;
+ e_pair[1] = e;
+ }
+ }
+ }
/* flip based on winding */
l_walk = bm_edge_flagged_radial_first(e_pair[0]);
@@ -309,36 +335,40 @@ walk_nofork:
BMEdge *e_next, *e_first;
e_first = v->e;
e_next = BM_DISK_EDGE_NEXT(e_first, v); /* always skip this verts edge */
- do {
- BLI_assert(v->e != e_next);
- if ((BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET)) &&
- (bm_edge_flagged_radial_count(e_next) < 2))
- {
- BMVert *v_next;
- v_next = BM_edge_other_vert(e_next, v);
+ /* in rare cases there may be edges with a single connecting vertex */
+ if (e_next != e_first) {
+ do {
+ if ((BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET)) &&
+ (bm_edge_flagged_radial_count(e_next) < 2))
+ {
+ BMVert *v_next;
+
+ v_next = BM_edge_other_vert(e_next, v);
+ BLI_assert(v->e != e_next);
#ifdef DEBUG_PRINT
- /* indent and print */
- {
- BMVert *_v = v;
- do {
- printf(" ");
- } while ((_v = BM_edge_other_vert(_v->e, _v)) != v_init);
- printf("vert %d -> %d (add=%d)\n",
- BM_elem_index_get(v), BM_elem_index_get(v_next),
- BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT) == 0);
- }
+ /* indent and print */
+ {
+ BMVert *_v = v;
+ do {
+ printf(" ");
+ } while ((_v = BM_edge_other_vert(_v->e, _v)) != v_init);
+ printf("vert %d -> %d (add=%d)\n",
+ BM_elem_index_get(v), BM_elem_index_get(v_next),
+ BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT) == 0);
+ }
#endif
- if (!BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT)) {
- eo = STACK_PUSH_RET_PTR(edge_order);
- eo->v = v_next;
+ if (!BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT)) {
+ eo = STACK_PUSH_RET_PTR(edge_order);
+ eo->v = v_next;
- v_next->e = e_next;
+ v_next->e = e_next;
+ }
}
- }
- } while ((e_next = BM_DISK_EDGE_NEXT(e_next, v)) != e_first);
+ } while ((e_next = BM_DISK_EDGE_NEXT(e_next, v)) != e_first);
+ }
#ifdef USE_FASTPATH_NOFORK
if (STACK_SIZE(edge_order) == 1) {
@@ -388,7 +418,7 @@ finally:
}
static bool bm_face_split_edgenet_find_loop(
- BMVert *v_init, const float face_normal[3],
+ BMVert *v_init, const float face_normal[3], float face_normal_matrix[3][3],
/* cache to avoid realloc every time */
struct VertOrder *edge_order, const unsigned int edge_order_len,
BMVert **r_face_verts, int *r_face_verts_len)
@@ -396,7 +426,7 @@ static bool bm_face_split_edgenet_find_loop(
BMEdge *e_pair[2];
BMVert *v;
- if (!bm_face_split_edgenet_find_loop_pair(v_init, face_normal, e_pair)) {
+ if (!bm_face_split_edgenet_find_loop_pair(v_init, face_normal, face_normal_matrix, e_pair)) {
return false;
}
@@ -491,12 +521,18 @@ bool BM_face_split_edgenet(
BM_ELEM_API_FLAG_ENABLE(l_iter->e, EDGE_NET);
} while ((l_iter = l_iter->next) != l_first);
+ float face_normal_matrix[3][3];
+ axis_dominant_v3_to_m3(face_normal_matrix, f->no);
+
/* any vert can be used to begin with */
STACK_PUSH(vert_queue, l_first->v);
while ((v = STACK_POP(vert_queue))) {
- if (bm_face_split_edgenet_find_loop(v, f->no, edge_order, edge_order_len, face_verts, &face_verts_len)) {
+ if (bm_face_split_edgenet_find_loop(
+ v, f->no, face_normal_matrix,
+ edge_order, edge_order_len, face_verts, &face_verts_len))
+ {
BMFace *f_new;
f_new = BM_face_create_verts(bm, face_verts, face_verts_len, f, BM_CREATE_NOP, false);
diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
index b4e8bb06afe..52a0df5b9d1 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
@@ -1292,7 +1292,8 @@ static bool bm_decim_edge_collapse(
* \param factor face count multiplier [0 - 1]
* \param vweights Optional array of vertex aligned weights [0 - 1],
* a vertex group is the usual source for this.
- * \param axis: Axis of symmetry, -1 to disable mirror decimate.
+ * \param symmetry_axis: Axis of symmetry, -1 to disable mirror decimate.
+ * \param symmetry_eps: Threshold when matching mirror verts.
*/
void BM_mesh_decimate_collapse(
BMesh *bm,
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
index 9d1f7fa45d2..bd6a68faabb 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -87,6 +87,18 @@
// #define USE_DUMP
+/* use only for small arrays */
+BLI_INLINE bool array_contains_pointer(const void **arr, unsigned int arr_len, const void *item)
+{
+ BLI_assert(arr_len < 3);
+ for (unsigned int i = 0; i < arr_len; i++) {
+ if (arr[i] == item) {
+ return true;
+ }
+ }
+ return false;
+}
+
static void tri_v3_scale(
float v1[3], float v2[3], float v3[3],
const float t)
@@ -535,6 +547,7 @@ static void bm_isect_tri_tri(
const float *f_b_cos[3] = {UNPACK3_EX(, fv_b, ->co)};
float f_a_nor[3];
float f_b_nor[3];
+ /* track vertices which have been added to 'iv_ls_a' & 'iv_ls_b' */
int a_mask = 0;
int b_mask = 0;
unsigned int i;
@@ -556,6 +569,24 @@ static void bm_isect_tri_tri(
STACK_INIT(iv_ls_a, ARRAY_SIZE(iv_ls_a));
STACK_INIT(iv_ls_b, ARRAY_SIZE(iv_ls_b));
+ /* don't test, but we must be sure not to add doubles (assert instead). */
+#ifndef NDEBUG
+# define STACK_PUSH_NOTEST(arr, ele) \
+ { \
+ BLI_assert(BLI_array_findindex(arr, STACK_SIZE(arr), &(ele)) == -1); \
+ STACK_PUSH(arr, ele); \
+ } ((void)0)
+#else
+# define STACK_PUSH_NOTEST STACK_PUSH
+#endif
+
+ /* warning, this seems like it might be inefficent,
+ * however there will be <3 items in this case. */
+# define STACK_PUSH_TEST(arr, ele, arr_offset) \
+ if (!array_contains_pointer((const void **)(&(arr)[arr_offset]), STACK_SIZE(arr) - (arr_offset), (void *)ele)) { \
+ STACK_PUSH(arr, ele); \
+ } ((void)0)
+
/* vert-vert
* --------- */
{
@@ -568,7 +599,7 @@ static void bm_isect_tri_tri(
for (i_b = 0; i_b < 3; i_b++) {
if (len_squared_v3v3(fv_a[i_a]->co, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) {
if (!((1 << i_a) & a_mask)) {
- STACK_PUSH(iv_ls_a, fv_a[i_a]);
+ STACK_PUSH_NOTEST(iv_ls_a, fv_a[i_a]);
a_mask |= (1 << i_a);
#ifdef USE_DUMP
printf(" ('VERT-VERT-A') %d, %d),\n",
@@ -576,7 +607,7 @@ static void bm_isect_tri_tri(
#endif
}
if (!((1 << i_b) & b_mask)) {
- STACK_PUSH(iv_ls_b, fv_b[i_b]);
+ STACK_PUSH_NOTEST(iv_ls_b, fv_b[i_b]);
b_mask |= (1 << i_b);
#ifdef USE_DUMP
printf(" ('VERT-VERT-B') %d, %d),\n",
@@ -606,8 +637,8 @@ static void bm_isect_tri_tri(
interp_v3_v3v3(ix, fv_b[i_b_e0]->co, fv_b[i_b_e1]->co, fac);
if (len_squared_v3v3(ix, fv_a[i_a]->co) <= s->epsilon.eps2x_sq) {
BMEdge *e;
- STACK_PUSH(iv_ls_b, fv_a[i_a]);
- // STACK_PUSH(iv_ls_a, fv_a[i_a]);
+ STACK_PUSH_NOTEST(iv_ls_b, fv_a[i_a]);
+ // STACK_PUSH_NOTEST(iv_ls_a, fv_a[i_a]);
a_mask |= (1 << i_a);
e = BM_edge_exists(fv_b[i_b_e0], fv_b[i_b_e1]);
#ifdef USE_DUMP
@@ -644,8 +675,8 @@ static void bm_isect_tri_tri(
interp_v3_v3v3(ix, fv_a[i_a_e0]->co, fv_a[i_a_e1]->co, fac);
if (len_squared_v3v3(ix, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) {
BMEdge *e;
- STACK_PUSH(iv_ls_a, fv_b[i_b]);
- // STACK_PUSH(iv_ls_b, fv_b[i_b]);
+ STACK_PUSH_NOTEST(iv_ls_a, fv_b[i_b]);
+ // STACK_PUSH_NOTEST(iv_ls_b, fv_b[i_b]);
b_mask |= (1 << i_b);
e = BM_edge_exists(fv_a[i_a_e0], fv_a[i_a_e1]);
#ifdef USE_DUMP
@@ -685,11 +716,8 @@ static void bm_isect_tri_tri(
continue;
if (isect_point_tri_v3(fv_a[i_a]->co, UNPACK3(t_scale), ix)) {
if (len_squared_v3v3(ix, fv_a[i_a]->co) <= s->epsilon.eps2x_sq) {
- BLI_assert(BLI_array_findindex(iv_ls_a, STACK_SIZE(iv_ls_a), fv_a[i_a]) == -1);
- BLI_assert(BLI_array_findindex(iv_ls_b, STACK_SIZE(iv_ls_b), fv_a[i_a]) == -1);
-
- STACK_PUSH(iv_ls_a, fv_a[i_a]);
- STACK_PUSH(iv_ls_b, fv_a[i_a]);
+ STACK_PUSH_NOTEST(iv_ls_a, fv_a[i_a]);
+ STACK_PUSH_NOTEST(iv_ls_b, fv_a[i_a]);
a_mask |= (1 << i_a);
#ifdef USE_DUMP
printf(" 'VERT TRI-A',\n");
@@ -715,11 +743,8 @@ static void bm_isect_tri_tri(
if (isect_point_tri_v3(fv_b[i_b]->co, UNPACK3(t_scale), ix)) {
if (len_squared_v3v3(ix, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) {
- BLI_assert(BLI_array_findindex((void **)iv_ls_a, STACK_SIZE(iv_ls_a), fv_b[i_b]) == -1);
- BLI_assert(BLI_array_findindex((void **)iv_ls_b, STACK_SIZE(iv_ls_b), fv_b[i_b]) == -1);
-
- STACK_PUSH(iv_ls_a, fv_b[i_b]);
- STACK_PUSH(iv_ls_b, fv_b[i_b]);
+ STACK_PUSH_NOTEST(iv_ls_a, fv_b[i_b]);
+ STACK_PUSH_NOTEST(iv_ls_b, fv_b[i_b]);
b_mask |= (1 << i_b);
#ifdef USE_DUMP
printf(" 'VERT TRI-B',\n");
@@ -744,6 +769,17 @@ static void bm_isect_tri_tri(
/* edge-tri & edge-edge
* -------------------- */
{
+ /**
+ * Note that its possible to add the same vertex multiple times
+ * with near degenerate faces (or a large epsilon).
+ *
+ * For this reason we have #STACK_PUSH_TEST macro which only adds vertices that aren't already added.
+ * Since we know none of the vertices from #bm_isect_edge_tri, the check can be offset.
+ */
+
+ const unsigned int iv_ls_a_offset = STACK_SIZE(iv_ls_a);
+ const unsigned int iv_ls_b_offset = STACK_SIZE(iv_ls_b);
+
unsigned int i_e0;
for (i_e0 = 0; i_e0 < 3; i_e0++) {
unsigned int i_e1 = (i_e0 + 1) % 3;
@@ -753,10 +789,8 @@ static void bm_isect_tri_tri(
continue;
iv = bm_isect_edge_tri(s, fv_a[i_e0], fv_a[i_e1], fv_b, b_index, f_b_cos, f_b_nor, &side);
if (iv) {
- BLI_assert(BLI_array_findindex((void **)iv_ls_a, STACK_SIZE(iv_ls_a), iv) == -1);
- BLI_assert(BLI_array_findindex((void **)iv_ls_b, STACK_SIZE(iv_ls_b), iv) == -1);
- STACK_PUSH(iv_ls_a, iv);
- STACK_PUSH(iv_ls_b, iv);
+ STACK_PUSH_TEST(iv_ls_a, iv, iv_ls_a_offset);
+ STACK_PUSH_TEST(iv_ls_b, iv, iv_ls_b_offset);
#ifdef USE_DUMP
printf(" ('EDGE-TRI-A', %d),\n", side);
#endif
@@ -771,10 +805,8 @@ static void bm_isect_tri_tri(
continue;
iv = bm_isect_edge_tri(s, fv_b[i_e0], fv_b[i_e1], fv_a, a_index, f_a_cos, f_a_nor, &side);
if (iv) {
- BLI_assert(BLI_array_findindex((void **)iv_ls_a, STACK_SIZE(iv_ls_a), iv) == -1);
- BLI_assert(BLI_array_findindex((void **)iv_ls_b, STACK_SIZE(iv_ls_b), iv) == -1);
- STACK_PUSH(iv_ls_a, iv);
- STACK_PUSH(iv_ls_b, iv);
+ STACK_PUSH_TEST(iv_ls_a, iv, iv_ls_a_offset);
+ STACK_PUSH_TEST(iv_ls_b, iv, iv_ls_b_offset);
#ifdef USE_DUMP
printf(" ('EDGE-TRI-B', %d),\n", side);
#endif
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index a82cca9e52a..c24ca1e7027 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -158,7 +158,7 @@ static int add_driver_with_target(
ReportList *UNUSED(reports),
ID *dst_id, const char dst_path[], int dst_index,
ID *src_id, const char src_path[], int src_index,
- PointerRNA *UNUSED(dst_ptr), PropertyRNA *dst_prop,
+ PointerRNA *dst_ptr, PropertyRNA *dst_prop,
PointerRNA *src_ptr, PropertyRNA *src_prop,
short flag, int driver_type)
{
@@ -207,11 +207,15 @@ static int add_driver_with_target(
/* Create a driver variable for the target
* - For transform properties, we want to automatically use "transform channel" instead
* (The only issue is with quat rotations vs euler channels...)
+ * - To avoid problems with transform properties depending on the final transform that they
+ * control (thus creating pseudo-cycles - see T48734), we don't use transform channels
+ * when both the source and destinaions are in same places.
*/
dvar = driver_add_new_variable(driver);
if (ELEM(src_ptr->type, &RNA_Object, &RNA_PoseBone) &&
- (STREQ(prop_name, "location") || STREQ(prop_name, "scale") || STRPREFIX(prop_name, "rotation_")))
+ (STREQ(prop_name, "location") || STREQ(prop_name, "scale") || STRPREFIX(prop_name, "rotation_")) &&
+ (src_ptr->data != dst_ptr->data))
{
/* Transform Channel */
DriverTarget *dtar;
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index 08a7355694b..7b35a154fc8 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -539,10 +539,10 @@ static short ok_bezier_region(KeyframeEditData *ked, BezTriple *bezt)
}
/**
- * only called from #ok_bezier_region_lasso
+ * Called from #ok_bezier_region_lasso and #ok_bezier_channel_lasso
*/
-static bool bezier_region_lasso_test(
- const struct KeyframeEdit_LassoData *data_lasso,
+bool keyframe_region_lasso_test(
+ const KeyframeEdit_LassoData *data_lasso,
const float xy[2])
{
if (BLI_rctf_isect_pt_v(data_lasso->rectf_scaled, xy)) {
@@ -564,7 +564,7 @@ static short ok_bezier_region_lasso(KeyframeEditData *ked, BezTriple *bezt)
if (ked->data) {
short ok = 0;
-#define KEY_CHECK_OK(_index) bezier_region_lasso_test(ked->data, bezt->vec[_index])
+#define KEY_CHECK_OK(_index) keyframe_region_lasso_test(ked->data, bezt->vec[_index])
KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
#undef KEY_CHECK_OK
@@ -575,11 +575,38 @@ static short ok_bezier_region_lasso(KeyframeEditData *ked, BezTriple *bezt)
return 0;
}
+static short ok_bezier_channel_lasso(KeyframeEditData *ked, BezTriple *bezt)
+{
+ /* check for lasso customdata (KeyframeEdit_LassoData) */
+ if (ked->data) {
+ KeyframeEdit_LassoData *data = ked->data;
+ float pt[2];
+
+ /* late-binding remap of the x values (for summary channels) */
+ /* XXX: Ideally we reset, but it should be fine just leaving it as-is
+ * as the next channel will reset it properly, while the next summary-channel
+ * curve will also reset by itself...
+ */
+ if (ked->iterflags & (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP)) {
+ data->rectf_scaled->xmin = ked->f1;
+ data->rectf_scaled->xmax = ked->f2;
+ }
+
+ /* only use the x-coordinate of the point; the y is the channel range... */
+ pt[0] = bezt->vec[1][0];
+ pt[1] = ked->channel_y;
+
+ if (keyframe_region_lasso_test(data, pt))
+ return KEYFRAME_OK_KEY;
+ }
+ return 0;
+}
+
/**
- * only called from #ok_bezier_region_circle
+ * Called from #ok_bezier_region_circle and #ok_bezier_channel_circle
*/
-static bool bezier_region_circle_test(
- const struct KeyframeEdit_CircleData *data_circle,
+bool keyframe_region_circle_test(
+ const KeyframeEdit_CircleData *data_circle,
const float xy[2])
{
if (BLI_rctf_isect_pt_v(data_circle->rectf_scaled, xy)) {
@@ -602,7 +629,7 @@ static short ok_bezier_region_circle(KeyframeEditData *ked, BezTriple *bezt)
if (ked->data) {
short ok = 0;
-#define KEY_CHECK_OK(_index) bezier_region_circle_test(ked->data, bezt->vec[_index])
+#define KEY_CHECK_OK(_index) keyframe_region_circle_test(ked->data, bezt->vec[_index])
KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
#undef KEY_CHECK_OK
@@ -613,6 +640,33 @@ static short ok_bezier_region_circle(KeyframeEditData *ked, BezTriple *bezt)
return 0;
}
+static short ok_bezier_channel_circle(KeyframeEditData *ked, BezTriple *bezt)
+{
+ /* check for circle select customdata (KeyframeEdit_CircleData) */
+ if (ked->data) {
+ KeyframeEdit_CircleData *data = ked->data;
+ float pt[2];
+
+ /* late-binding remap of the x values (for summary channels) */
+ /* XXX: Ideally we reset, but it should be fine just leaving it as-is
+ * as the next channel will reset it properly, while the next summary-channel
+ * curve will also reset by itself...
+ */
+ if (ked->iterflags & (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP)) {
+ data->rectf_scaled->xmin = ked->f1;
+ data->rectf_scaled->xmax = ked->f2;
+ }
+
+ /* only use the x-coordinate of the point; the y is the channel range... */
+ pt[0] = bezt->vec[1][0];
+ pt[1] = ked->channel_y;
+
+ if (keyframe_region_circle_test(data, pt))
+ return KEYFRAME_OK_KEY;
+ }
+ return 0;
+}
+
KeyframeEditFunc ANIM_editkeyframes_ok(short mode)
{
@@ -634,6 +688,10 @@ KeyframeEditFunc ANIM_editkeyframes_ok(short mode)
return ok_bezier_region_lasso;
case BEZT_OK_REGION_CIRCLE: /* only if the point falls within KeyframeEdit_CircleData defined data */
return ok_bezier_region_circle;
+ case BEZT_OK_CHANNEL_LASSO: /* same as BEZT_OK_REGION_LASSO, but we're only using the x-value of the points */
+ return ok_bezier_channel_lasso;
+ case BEZT_OK_CHANNEL_CIRCLE: /* same as BEZT_OK_REGION_CIRCLE, but we're only using the x-value of the points */
+ return ok_bezier_channel_circle;
default: /* nothing was ok */
return NULL;
}
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 66b3a63c669..0c0f54f0179 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -1069,6 +1069,9 @@ short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
if (ELEM(RNA_property_subtype(prop), PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR, PROP_COORDS)) {
fcu->color_mode = FCURVE_COLOR_AUTO_RGB;
}
+ else if (RNA_property_subtype(prop), PROP_QUATERNION) {
+ fcu->color_mode = FCURVE_COLOR_AUTO_YRGB;
+ }
}
/* insert keyframe */
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
index a49b3362155..738496a67c6 100644
--- a/source/blender/editors/gpencil/editaction_gpencil.c
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -205,6 +205,36 @@ void ED_gplayer_frames_select_border(bGPDlayer *gpl, float min, float max, short
}
}
+/* select the frames in this layer that occur within the lasso/circle region specified */
+void ED_gplayer_frames_select_region(KeyframeEditData *ked, bGPDlayer *gpl, short tool, short select_mode)
+{
+ bGPDframe *gpf;
+
+ if (gpl == NULL)
+ return;
+
+ /* only select frames which are within the region */
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ /* construct a dummy point coordinate to do this testing with */
+ float pt[2] = {0};
+
+ pt[0] = gpf->framenum;
+ pt[1] = ked->channel_y;
+
+ /* check the necessary regions */
+ if (tool == BEZT_OK_CHANNEL_LASSO) {
+ /* Lasso */
+ if (keyframe_region_lasso_test(ked->data, pt))
+ gpframe_select(gpf, select_mode);
+ }
+ else if (tool == BEZT_OK_CHANNEL_CIRCLE) {
+ /* Circle */
+ if (keyframe_region_circle_test(ked->data, pt))
+ gpframe_select(gpf, select_mode);
+ }
+ }
+}
+
/* ***************************************** */
/* Frame Editing Tools */
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index bd1697b9a54..ac49a51c716 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -652,7 +652,7 @@ void GPENCIL_OT_active_frame_delete(wmOperatorType *ot)
/* identifiers */
ot->name = "Delete Active Frame";
ot->idname = "GPENCIL_OT_active_frame_delete";
- ot->description = "Delete the active frame for the active Grease Pencil datablock";
+ ot->description = "Delete the active frame for the active Grease Pencil Layer";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -661,6 +661,64 @@ void GPENCIL_OT_active_frame_delete(wmOperatorType *ot)
ot->poll = gp_actframe_delete_poll;
}
+/* **************** Delete All Active Frames ****************** */
+
+static int gp_actframe_delete_all_poll(bContext *C)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ /* 1) There must be grease pencil data
+ * 2) Hopefully some of the layers have stuff we can use
+ */
+ return (gpd && gpd->layers.first);
+}
+
+static int gp_actframe_delete_all_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ bool success = false;
+
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ /* try to get the "active" frame - but only if it actually occurs on this frame */
+ bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0);
+
+ if (gpf == NULL)
+ continue;
+
+ /* delete it... */
+ gpencil_layer_delframe(gpl, gpf);
+
+ /* we successfully modified something */
+ success = true;
+ }
+ CTX_DATA_END;
+
+ /* updates */
+ if (success) {
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No active frame(s) to delete");
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void GPENCIL_OT_active_frames_delete_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Delete All Active Frames";
+ ot->idname = "GPENCIL_OT_active_frames_delete_all";
+ ot->description = "Delete the active frame(s) of all editable Grease Pencil layers";
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* callbacks */
+ ot->exec = gp_actframe_delete_all_exec;
+ ot->poll = gp_actframe_delete_all_poll;
+}
+
/* ******************* Delete Operator ************************ */
typedef enum eGP_DeleteMode {
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index dd28f6ac531..53fb33eeb9b 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -218,6 +218,7 @@ void GPENCIL_OT_unlock_all(struct wmOperatorType *ot);
void GPENCIL_OT_layer_isolate(struct wmOperatorType *ot);
void GPENCIL_OT_active_frame_delete(struct wmOperatorType *ot);
+void GPENCIL_OT_active_frames_delete_all(struct wmOperatorType *ot);
void GPENCIL_OT_convert(struct wmOperatorType *ot);
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 405b673c42b..65ee1122b56 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -105,7 +105,7 @@ static void ed_keymap_gpencil_general(wmKeyConfig *keyconf)
/* Delete Active Frame - For easier video tutorials/review sessions */
/* NOTE: This works even when not in EditMode */
- WM_keymap_add_item(keymap, "GPENCIL_OT_active_frame_delete", XKEY, KM_PRESS, 0, DKEY);
+ WM_keymap_add_item(keymap, "GPENCIL_OT_active_frames_delete_all", XKEY, KM_PRESS, 0, DKEY);
}
/* ==================== */
@@ -238,7 +238,7 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "GPENCIL_OT_dissolve", XKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "GPENCIL_OT_dissolve", DELKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "GPENCIL_OT_active_frame_delete", XKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "GPENCIL_OT_active_frames_delete_all", XKEY, KM_PRESS, KM_SHIFT, 0);
/* copy + paste */
WM_keymap_add_item(keymap, "GPENCIL_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
@@ -364,6 +364,7 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_layer_isolate);
WM_operatortype_append(GPENCIL_OT_active_frame_delete);
+ WM_operatortype_append(GPENCIL_OT_active_frames_delete_all);
WM_operatortype_append(GPENCIL_OT_convert);
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index fba2f30e715..a570d586f50 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -97,7 +97,8 @@ typedef enum eGP_StrokeAdd_Result {
typedef enum eGPencil_PaintFlags {
GP_PAINTFLAG_FIRSTRUN = (1 << 0), /* operator just started */
GP_PAINTFLAG_STROKEADDED = (1 << 1),
- GP_PAINTFLAG_V3D_ERASER_DEPTH = (1 << 2)
+ GP_PAINTFLAG_V3D_ERASER_DEPTH = (1 << 2),
+ GP_PAINTFLAG_SELECTMASK = (1 << 3),
} eGPencil_PaintFlags;
@@ -813,18 +814,21 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
BLI_freelinkN(&gpf->strokes, gps);
}
else if (gps->totpoints == 1) {
- gp_point_to_xy(&p->gsc, gps, gps->points, &pc1[0], &pc1[1]);
-
- /* do boundbox check first */
- if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
- /* only check if point is inside */
- if (len_v2v2_int(mval, pc1) <= radius) {
- /* free stroke */
- // XXX: pressure sensitive eraser should apply here too?
- MEM_freeN(gps->points);
- if (gps->triangles)
- MEM_freeN(gps->triangles);
- BLI_freelinkN(&gpf->strokes, gps);
+ /* only process if it hasn't been masked out... */
+ if (!(p->flags & GP_PAINTFLAG_SELECTMASK) || (gps->points->flag & GP_SPOINT_SELECT)) {
+ gp_point_to_xy(&p->gsc, gps, gps->points, &pc1[0], &pc1[1]);
+
+ /* do boundbox check first */
+ if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
+ /* only check if point is inside */
+ if (len_v2v2_int(mval, pc1) <= radius) {
+ /* free stroke */
+ // XXX: pressure sensitive eraser should apply here too?
+ MEM_freeN(gps->points);
+ if (gps->triangles)
+ MEM_freeN(gps->triangles);
+ BLI_freelinkN(&gpf->strokes, gps);
+ }
}
}
}
@@ -862,6 +866,11 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
pt1 = gps->points + i;
pt2 = gps->points + i + 1;
+ /* only process if it hasn't been masked out... */
+ if ((p->flags & GP_PAINTFLAG_SELECTMASK) && !(gps->points->flag & GP_SPOINT_SELECT))
+ continue;
+
+ /* get coordinates of point in screenspace */
gp_point_to_xy(&p->gsc, gps, pt1, &pc1[0], &pc1[1]);
gp_point_to_xy(&p->gsc, gps, pt2, &pc2[0], &pc2[1]);
@@ -1199,6 +1208,7 @@ static void gp_session_cleanup(tGPsdata *p)
static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode)
{
Scene *scene = p->scene;
+ ToolSettings *ts = scene->toolsettings;
/* get active layer (or add a new one if non-existent) */
p->gpl = gpencil_layer_getactive(p->gpd);
@@ -1242,6 +1252,15 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode)
/* Ensure this gets set... */
p->gpf = p->gpl->actframe;
+ /* Restrict eraser to only affecting selected strokes, if the "selection mask" is on
+ * (though this is only available in editmode)
+ */
+ if (p->gpd->flag & GP_DATA_STROKE_EDITMODE) {
+ if (ts->gp_sculpt.flag & GP_BRUSHEDIT_FLAG_SELECT_MASK) {
+ p->flags |= GP_PAINTFLAG_SELECTMASK;
+ }
+ }
+
if (p->gpf == NULL) {
p->status = GP_STATUS_ERROR;
//if (G.debug & G_DEBUG)
@@ -1251,7 +1270,6 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode)
}
else {
/* Drawing Modes - Add a new frame if needed on the active layer */
- ToolSettings *ts = p->scene->toolsettings;
short add_frame_mode;
if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST)
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
index 80f930a0c30..92acfa6c1d2 100644
--- a/source/blender/editors/include/ED_fileselect.h
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -109,7 +109,7 @@ int ED_file_extension_icon(const char *path);
void ED_file_read_bookmarks(void);
-void ED_file_change_dir(struct bContext *C, const bool checkdir);
+void ED_file_change_dir(struct bContext *C);
/* File menu stuff */
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 255827db373..de5ab80a88f 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -42,6 +42,7 @@ struct bGPDlayer;
struct bGPDframe;
struct bGPDstroke;
struct bAnimContext;
+struct KeyframeEditData;
struct PointerRNA;
struct wmWindowManager;
struct wmKeyConfig;
@@ -120,6 +121,7 @@ void ED_gplayer_make_cfra_list(struct bGPDlayer *gpl, ListBase *elems, bool only
bool ED_gplayer_frame_select_check(struct bGPDlayer *gpl);
void ED_gplayer_frame_select_set(struct bGPDlayer *gpl, short mode);
void ED_gplayer_frames_select_border(struct bGPDlayer *gpl, float min, float max, short select_mode);
+void ED_gplayer_frames_select_region(struct KeyframeEditData *ked, struct bGPDlayer *gpl, short tool, short select_mode);
void ED_gpencil_select_frames(struct bGPDlayer *gpl, short select_mode);
void ED_gpencil_select_frame(struct bGPDlayer *gpl, int selx, short select_mode);
diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h
index fae3e3677a0..c0eb88cd982 100644
--- a/source/blender/editors/include/ED_keyframes_edit.h
+++ b/source/blender/editors/include/ED_keyframes_edit.h
@@ -45,14 +45,21 @@ struct Scene;
/* bezt validation */
typedef enum eEditKeyframes_Validate {
+ /* Frame range */
BEZT_OK_FRAME = 1,
BEZT_OK_FRAMERANGE,
+ /* Selection status */
BEZT_OK_SELECTED,
+ /* Values (y-val) only */
BEZT_OK_VALUE,
BEZT_OK_VALUERANGE,
+ /* For graph editor keyframes (2D tests) */
BEZT_OK_REGION,
BEZT_OK_REGION_LASSO,
BEZT_OK_REGION_CIRCLE,
+ /* Only for keyframes a certain Dopesheet channel */
+ BEZT_OK_CHANNEL_LASSO,
+ BEZT_OK_CHANNEL_CIRCLE,
} eEditKeyframes_Validate;
/* ------------ */
@@ -97,20 +104,20 @@ typedef enum eEditKeyframes_Mirror {
} eEditKeyframes_Mirror;
/* use with BEZT_OK_REGION_LASSO */
-struct KeyframeEdit_LassoData {
- const rctf *rectf_scaled;
+typedef struct KeyframeEdit_LassoData {
+ rctf *rectf_scaled;
const rctf *rectf_view;
const int (*mcords)[2];
int mcords_tot;
-};
+} KeyframeEdit_LassoData;
/* use with BEZT_OK_REGION_CIRCLE */
-struct KeyframeEdit_CircleData {
- const rctf *rectf_scaled;
+typedef struct KeyframeEdit_CircleData {
+ rctf *rectf_scaled;
const rctf *rectf_view;
float mval[2];
float radius_squared;
-};
+} KeyframeEdit_CircleData;
/* ************************************************ */
@@ -157,7 +164,8 @@ typedef struct KeyframeEditData {
/* current iteration data */
struct FCurve *fcu; /* F-Curve that is being iterated over */
int curIndex; /* index of current keyframe being iterated over */
-
+ float channel_y; /* y-position of midpoint of the channel (for the dopesheet) */
+
/* flags */
eKeyframeVertOk curflags; /* current flags for the keyframe we're reached in the iteration process */
eKeyframeIterFlags iterflags; /* settings for iteration process */
@@ -258,6 +266,18 @@ short bezt_to_cfraelem(KeyframeEditData *ked, struct BezTriple *bezt);
*/
void bezt_remap_times(KeyframeEditData *ked, struct BezTriple *bezt);
+/* ------ 1.5-D Region Testing Uitls (Lasso/Circle Select) ------- */
+/* XXX: These are temporary, until we can unify GP/Mask Keyframe handling and standard FCurve Keyframe handling */
+
+bool keyframe_region_lasso_test(
+ const KeyframeEdit_LassoData *data_lasso,
+ const float xy[2]);
+
+bool keyframe_region_circle_test(
+ const KeyframeEdit_CircleData *data_circle,
+ const float xy[2]);
+
+
/* ************************************************ */
/* Destructive Editing API (keyframes_general.c) */
diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h
index 1f13b46ff2a..2ab788d5e2a 100644
--- a/source/blender/editors/include/ED_mask.h
+++ b/source/blender/editors/include/ED_mask.h
@@ -35,6 +35,7 @@ struct bContext;
struct wmKeyConfig;
struct MaskLayer;
struct MaskLayerShape;
+struct KeyframeEditData;
/* mask_edit.c */
void ED_mask_get_size(struct ScrArea *sa, int *width, int *height);
@@ -80,6 +81,7 @@ void ED_masklayer_make_cfra_list(struct MaskLayer *masklay, ListBase *elems, boo
bool ED_masklayer_frame_select_check(struct MaskLayer *masklay);
void ED_masklayer_frame_select_set(struct MaskLayer *masklay, short mode);
void ED_masklayer_frames_select_border(struct MaskLayer *masklay, float min, float max, short select_mode);
+void ED_masklayer_frames_select_region(struct KeyframeEditData *ked, struct MaskLayer *masklay, short tool, short select_mode);
void ED_mask_select_frames(struct MaskLayer *masklay, short select_mode);
void ED_mask_select_frame(struct MaskLayer *masklay, int selx, short select_mode);
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 9aad340d2fb..a623f5cfb9c 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1020,12 +1020,18 @@ bool UI_context_copy_to_selected_list(
/* Helpers for Operators */
uiBut *UI_context_active_but_get(const struct bContext *C);
-void UI_context_active_but_prop_get(const struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop, int *index);
+void UI_context_active_but_prop_get(
+ const struct bContext *C,
+ struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, int *r_index);
void UI_context_active_but_prop_handle(struct bContext *C);
struct wmOperator *UI_context_active_operator_get(const struct bContext *C);
void UI_context_update_anim_flag(const struct bContext *C);
-void UI_context_active_but_prop_get_filebrowser(const struct bContext *C, struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, bool *r_is_undo);
-void UI_context_active_but_prop_get_templateID(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop);
+void UI_context_active_but_prop_get_filebrowser(
+ const struct bContext *C,
+ struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, bool *r_is_undo);
+void UI_context_active_but_prop_get_templateID(
+ struct bContext *C,
+ struct PointerRNA *r_ptr, struct PropertyRNA **r_prop);
/* Styled text draw */
void UI_fontstyle_set(const struct uiFontStyle *fs);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index fac1267cc62..77990066027 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -4323,7 +4323,7 @@ uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxle
/**
- * \param sfunc, bfunc: both get it as \a arg.
+ * \param search_func, bfunc: both get it as \a arg.
* \param arg: user value,
* \param active: when set, button opens with this item visible and selected.
*/
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 133487e1846..f941993a9e1 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -8013,20 +8013,21 @@ uiBut *UI_context_active_but_get(const struct bContext *C)
}
/* helper function for insert keyframe, reset to default, etc operators */
-void UI_context_active_but_prop_get(const bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop, int *index)
+void UI_context_active_but_prop_get(
+ const bContext *C,
+ struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, int *r_index)
{
uiBut *activebut = ui_context_rna_button_active(C);
- memset(ptr, 0, sizeof(*ptr));
-
if (activebut && activebut->rnapoin.data) {
- *ptr = activebut->rnapoin;
- *prop = activebut->rnaprop;
- *index = activebut->rnaindex;
+ *r_ptr = activebut->rnapoin;
+ *r_prop = activebut->rnaprop;
+ *r_index = activebut->rnaindex;
}
else {
- *prop = NULL;
- *index = 0;
+ memset(r_ptr, 0, sizeof(*r_ptr));
+ *r_prop = NULL;
+ *r_index = 0;
}
}
@@ -9812,10 +9813,17 @@ static int ui_handle_menus_recursive(
retval = ui_pie_handler(C, event, menu);
}
else if (event->type == LEFTMOUSE || event->val != KM_DBL_CLICK) {
+ bool handled = false;
+
if (listbox) {
- retval = ui_handle_list_event(C, event, menu->region, listbox);
+ int retval_test = ui_handle_list_event(C, event, menu->region, listbox);
+ if (retval_test != WM_UI_HANDLER_CONTINUE) {
+ retval = retval_test;
+ handled = true;
+ }
}
- if (retval == WM_UI_HANDLER_CONTINUE) {
+
+ if (handled == false) {
retval = ui_handle_menu_event(
C, event, menu, level,
is_parent_inside, is_parent_menu, is_floating);
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index f1f9c4ef0cb..cf3a50d632a 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -231,15 +231,17 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
/* This is for browsing and editing the ID-blocks used */
/* for new/open operators */
-void UI_context_active_but_prop_get_templateID(bContext *C, PointerRNA *ptr, PropertyRNA **prop)
+void UI_context_active_but_prop_get_templateID(
+ bContext *C,
+ PointerRNA *r_ptr, PropertyRNA **r_prop)
{
TemplateID *template;
ARegion *ar = CTX_wm_region(C);
uiBlock *block;
uiBut *but;
- memset(ptr, 0, sizeof(*ptr));
- *prop = NULL;
+ memset(r_ptr, 0, sizeof(*r_ptr));
+ *r_prop = NULL;
if (!ar)
return;
@@ -250,8 +252,8 @@ void UI_context_active_but_prop_get_templateID(bContext *C, PointerRNA *ptr, Pro
if ((but->flag & (UI_BUT_LAST_ACTIVE | UI_ACTIVE))) {
if (but->func_argN) {
template = but->func_argN;
- *ptr = template->ptr;
- *prop = template->prop;
+ *r_ptr = template->ptr;
+ *r_prop = template->prop;
return;
}
}
diff --git a/source/blender/editors/mask/mask_editaction.c b/source/blender/editors/mask/mask_editaction.c
index bcf9ee5c88d..16147bdc7f8 100644
--- a/source/blender/editors/mask/mask_editaction.c
+++ b/source/blender/editors/mask/mask_editaction.c
@@ -201,6 +201,36 @@ void ED_masklayer_frames_select_border(MaskLayer *masklay, float min, float max,
}
}
+/* select the frames in this layer that occur within the lasso/circle region specified */
+void ED_masklayer_frames_select_region(KeyframeEditData *ked, MaskLayer *masklay, short tool, short select_mode)
+{
+ MaskLayerShape *masklay_shape;
+
+ if (masklay == NULL)
+ return;
+
+ /* only select frames which are within the region */
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
+ /* construct a dummy point coordinate to do this testing with */
+ float pt[2] = {0};
+
+ pt[0] = masklay_shape->frame;
+ pt[1] = ked->channel_y;
+
+ /* check the necessary regions */
+ if (tool == BEZT_OK_CHANNEL_LASSO) {
+ /* Lasso */
+ if (keyframe_region_lasso_test(ked->data, pt))
+ masklayshape_select(masklay_shape, select_mode);
+ }
+ else if (tool == BEZT_OK_CHANNEL_CIRCLE) {
+ /* Circle */
+ if (keyframe_region_circle_test(ked->data, pt))
+ masklayshape_select(masklay_shape, select_mode);
+ }
+ }
+}
+
/* ***************************************** */
/* Frame Editing Tools */
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 01be8f848aa..c4e87614732 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -53,6 +53,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "GPU_draw.h"
#include "GPU_buffers.h"
/* own include */
@@ -433,7 +434,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool exten
if (ENDIAN_ORDER == B_ENDIAN) {
IMB_convert_rgba_to_abgr(ibuf);
}
- WM_framebuffer_to_index_array(ibuf->rect, size[0] * size[1]);
+ GPU_select_to_index_array(ibuf->rect, size[0] * size[1]);
a = size[0] * size[1];
while (a--) {
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index efd1ebbd51b..9c2806f6f5a 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -1560,12 +1560,12 @@ void OBJECT_OT_constraints_copy(wmOperatorType *ot)
/************************ add constraint operators *********************/
/* get the Object and/or PoseChannel to use as target */
-static short get_new_constraint_target(bContext *C, int con_type, Object **tar_ob, bPoseChannel **tar_pchan, short add)
+static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob, bPoseChannel **tar_pchan, bool add)
{
Object *obact = ED_object_active_context(C);
bPoseChannel *pchanact = BKE_pose_channel_active(obact);
- short only_curve = 0, only_mesh = 0, only_ob = 0;
- short found = 0;
+ bool only_curve = false, only_mesh = false, only_ob = false;
+ bool found = false;
/* clear tar_ob and tar_pchan fields before use
* - assume for now that both always exist...
@@ -1585,7 +1585,7 @@ static short get_new_constraint_target(bContext *C, int con_type, Object **tar_o
case CONSTRAINT_TYPE_ROTLIMIT:
case CONSTRAINT_TYPE_SIZELIMIT:
case CONSTRAINT_TYPE_SAMEVOL:
- return 0;
+ return false;
/* restricted target-type constraints -------------- */
/* NOTE: for these, we cannot try to add a target object if no valid ones are found, since that doesn't work */
@@ -1593,26 +1593,26 @@ static short get_new_constraint_target(bContext *C, int con_type, Object **tar_o
case CONSTRAINT_TYPE_CLAMPTO:
case CONSTRAINT_TYPE_FOLLOWPATH:
case CONSTRAINT_TYPE_SPLINEIK:
- only_curve = 1;
- only_ob = 1;
- add = 0;
+ only_curve = true;
+ only_ob = true;
+ add = false;
break;
/* mesh only? */
case CONSTRAINT_TYPE_SHRINKWRAP:
- only_mesh = 1;
- only_ob = 1;
- add = 0;
+ only_mesh = true;
+ only_ob = true;
+ add = false;
break;
/* object only - add here is ok? */
case CONSTRAINT_TYPE_RIGIDBODYJOINT:
- only_ob = 1;
+ only_ob = true;
break;
}
/* if the active Object is Armature, and we can search for bones, do so... */
- if ((obact->type == OB_ARMATURE) && (only_ob == 0)) {
+ if ((obact->type == OB_ARMATURE) && (only_ob == false)) {
/* search in list of selected Pose-Channels for target */
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
{
@@ -1620,7 +1620,7 @@ static short get_new_constraint_target(bContext *C, int con_type, Object **tar_o
if (pchan != pchanact) {
*tar_ob = obact;
*tar_pchan = pchan;
- found = 1;
+ found = true;
break;
}
@@ -1629,36 +1629,50 @@ static short get_new_constraint_target(bContext *C, int con_type, Object **tar_o
}
/* if not yet found, try selected Objects... */
- if (found == 0) {
+ if (found == false) {
/* search in selected objects context */
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
/* just use the first object we encounter (that isn't the active object)
* and which fulfills the criteria for the object-target that we've got
*/
- if ((ob != obact) &&
- ((!only_curve) || (ob->type == OB_CURVE)) &&
- ((!only_mesh) || (ob->type == OB_MESH)))
- {
- /* set target */
- *tar_ob = ob;
- found = 1;
-
- /* perform some special operations on the target */
- if (only_curve) {
- /* Curve-Path option must be enabled for follow-path constraints to be able to work */
- Curve *cu = (Curve *)ob->data;
- cu->flag |= CU_PATH;
+ if (ob != obact) {
+ /* for armatures in pose mode, look inside the armature for the active bone
+ * so that we set up cross-armature constraints with less effort
+ */
+ if ((ob->type == OB_ARMATURE) && (ob->mode & OB_MODE_POSE) &&
+ (!only_curve && !only_mesh))
+ {
+ /* just use the active bone, and assume that it is visible + usable */
+ *tar_ob = ob;
+ *tar_pchan = BKE_pose_channel_active(ob);
+ found = true;
+
+ break;
+ }
+ else if (((!only_curve) || (ob->type == OB_CURVE)) &&
+ ((!only_mesh) || (ob->type == OB_MESH)))
+ {
+ /* set target */
+ *tar_ob = ob;
+ found = true;
+
+ /* perform some special operations on the target */
+ if (only_curve) {
+ /* Curve-Path option must be enabled for follow-path constraints to be able to work */
+ Curve *cu = (Curve *)ob->data;
+ cu->flag |= CU_PATH;
+ }
+
+ break;
}
-
- break;
}
}
CTX_DATA_END;
}
/* if still not found, add a new empty to act as a target (if allowed) */
- if ((found == 0) && (add)) {
+ if ((found == false) && (add)) {
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Base *base = BASACT, *newbase = NULL;
@@ -1692,7 +1706,7 @@ static short get_new_constraint_target(bContext *C, int con_type, Object **tar_o
/* make our new target the new object */
*tar_ob = obt;
- found = 1;
+ found = true;
}
/* return whether there's any target */
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 31b7b584a3a..7a55418b082 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -436,7 +436,7 @@ typedef enum eObClearParentTypes {
EnumPropertyItem prop_clear_parent_types[] = {
{CLEAR_PARENT_ALL, "CLEAR", 0, "Clear Parent",
- "Completely clear the parenting relationship, including involved modifiers is any"},
+ "Completely clear the parenting relationship, including involved modifiers if any"},
{CLEAR_PARENT_KEEP_TRANSFORM, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation",
"As 'Clear Parent', but keep the current visual transformations of the object"},
{CLEAR_PARENT_INVERSE, "CLEAR_INVERSE", 0, "Clear Parent Inverse",
diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h
index 50e10e7e154..408eb38d386 100644
--- a/source/blender/editors/space_action/action_intern.h
+++ b/source/blender/editors/space_action/action_intern.h
@@ -59,6 +59,8 @@ void draw_channel_strips(struct bAnimContext *ac, struct SpaceAction *saction, s
void ACTION_OT_select_all_toggle(struct wmOperatorType *ot);
void ACTION_OT_select_border(struct wmOperatorType *ot);
+void ACTION_OT_select_lasso(struct wmOperatorType *ot);
+void ACTION_OT_select_circle(struct wmOperatorType *ot);
void ACTION_OT_select_column(struct wmOperatorType *ot);
void ACTION_OT_select_linked(struct wmOperatorType *ot);
void ACTION_OT_select_more(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c
index f69f9944f8a..a261202b690 100644
--- a/source/blender/editors/space_action/action_ops.c
+++ b/source/blender/editors/space_action/action_ops.c
@@ -59,6 +59,8 @@ void action_operatortypes(void)
WM_operatortype_append(ACTION_OT_clickselect);
WM_operatortype_append(ACTION_OT_select_all_toggle);
WM_operatortype_append(ACTION_OT_select_border);
+ WM_operatortype_append(ACTION_OT_select_lasso);
+ WM_operatortype_append(ACTION_OT_select_circle);
WM_operatortype_append(ACTION_OT_select_column);
WM_operatortype_append(ACTION_OT_select_linked);
WM_operatortype_append(ACTION_OT_select_more);
@@ -178,6 +180,14 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "axis_range", true);
+ /* region select */
+ kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
+ kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "deselect", true);
+
+ WM_keymap_add_item(keymap, "ACTION_OT_select_circle", CKEY, KM_PRESS, 0, 0);
+
/* column select */
RNA_enum_set(WM_keymap_add_item(keymap, "ACTION_OT_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_KEYS);
RNA_enum_set(WM_keymap_add_item(keymap, "ACTION_OT_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_CFRA);
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index f2813b2a8d3..0b6d3cb1f60 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -36,6 +36,7 @@
#include "BLI_blenlib.h"
#include "BLI_dlrbTree.h"
+#include "BLI_lasso.h"
#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
@@ -375,6 +376,264 @@ void ACTION_OT_select_border(wmOperatorType *ot)
ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
}
+/* ******************** Region Select Operators ***************************** */
+/* "Region Select" operators include the Lasso and Circle Select operators.
+ * These two ended up being lumped together, as it was easier in the
+ * original Graph Editor implmentation of these to do it this way.
+ */
+
+static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, void *data)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ KeyframeEditData ked;
+ KeyframeEditFunc ok_cb, select_cb;
+ View2D *v2d = &ac->ar->v2d;
+ rctf rectf, scaled_rectf;
+ float ymin = 0, ymax = (float)(-ACHANNEL_HEIGHT_HALF);
+
+ /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
+ UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf);
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get beztriple editing/validation funcs */
+ select_cb = ANIM_editkeyframes_select(selectmode);
+ ok_cb = ANIM_editkeyframes_ok(mode);
+
+ /* init editing data */
+ memset(&ked, 0, sizeof(KeyframeEditData));
+ if (mode == BEZT_OK_CHANNEL_LASSO) {
+ KeyframeEdit_LassoData *data_lasso = data;
+ data_lasso->rectf_scaled = &scaled_rectf;
+ ked.data = data_lasso;
+ }
+ else if (mode == BEZT_OK_CHANNEL_CIRCLE) {
+ KeyframeEdit_CircleData *data_circle = data;
+ data_circle->rectf_scaled = &scaled_rectf;
+ ked.data = data;
+ }
+ else {
+ ked.data = &scaled_rectf;
+ }
+
+ /* loop over data, doing region select */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ /* get new vertical minimum extent of channel */
+ ymin = ymax - ACHANNEL_STEP;
+
+ /* compute midpoint of channel (used for testing if the key is in the region or not) */
+ ked.channel_y = ymin + ACHANNEL_HEIGHT_HALF;
+
+ /* if channel is mapped in NLA, apply correction
+ * - Apply to the bounds being checked, not all the keyframe points,
+ * to avoid having scaling everything
+ * - Save result to the scaled_rect, which is all that these operators
+ * will read from
+ */
+ if (adt) {
+ ked.iterflags &= ~(KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP);
+ ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
+ ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
+ }
+ else {
+ ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
+ ked.f1 = rectf.xmin;
+ ked.f2 = rectf.xmax;
+ }
+
+ /* Update values for scaled_rectf - which is used to compute the mapping in the callbacks
+ * NOTE: Since summary tracks need late-binding remapping, the callbacks may overwrite these
+ * with the properly remapped ked.f1/f2 values, when needed
+ */
+ scaled_rectf.xmin = ked.f1;
+ scaled_rectf.xmax = ked.f2;
+ scaled_rectf.ymin = ymin;
+ scaled_rectf.ymax = ymax;
+
+ /* perform vertical suitability check (if applicable) */
+ if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) ||
+ !((ymax < rectf.ymin) || (ymin > rectf.ymax)))
+ {
+ /* loop over data selecting */
+ switch (ale->type) {
+ case ANIMTYPE_GPDATABLOCK:
+ {
+ bGPdata *gpd = ale->data;
+ bGPDlayer *gpl;
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ ED_gplayer_frames_select_region(&ked, ale->data, mode, selectmode);
+ }
+ break;
+ }
+ case ANIMTYPE_GPLAYER:
+ {
+ ED_gplayer_frames_select_region(&ked, ale->data, mode, selectmode);
+ break;
+ }
+ case ANIMTYPE_MASKDATABLOCK:
+ {
+ Mask *mask = ale->data;
+ MaskLayer *masklay;
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ ED_masklayer_frames_select_region(&ked, masklay, mode, selectmode);
+ }
+ break;
+ }
+ case ANIMTYPE_MASKLAYER:
+ {
+ ED_masklayer_frames_select_region(&ked, ale->data, mode, selectmode);
+ break;
+ }
+ default:
+ ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
+ break;
+ }
+ }
+
+ /* set minimum extent to be the maximum of the next channel */
+ ymax = ymin;
+ }
+
+ /* cleanup */
+ ANIM_animdata_freelist(&anim_data);
+}
+
+/* ----------------------------------- */
+
+static int actkeys_lassoselect_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ KeyframeEdit_LassoData data_lasso;
+ rcti rect;
+ rctf rect_fl;
+
+ short selectmode;
+ bool extend;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ data_lasso.rectf_view = &rect_fl;
+ data_lasso.mcords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcords_tot);
+ if (data_lasso.mcords == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* clear all selection if not extending selection */
+ extend = RNA_boolean_get(op->ptr, "extend");
+ if (!extend)
+ deselect_action_keys(&ac, 1, SELECT_SUBTRACT);
+
+ if (!RNA_boolean_get(op->ptr, "deselect"))
+ selectmode = SELECT_ADD;
+ else
+ selectmode = SELECT_SUBTRACT;
+
+ /* get settings from operator */
+ BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot);
+ BLI_rctf_rcti_copy(&rect_fl, &rect);
+
+ /* apply borderselect action */
+ region_select_action_keys(&ac, &rect_fl, BEZT_OK_CHANNEL_LASSO, selectmode, &data_lasso);
+
+ MEM_freeN((void *)data_lasso.mcords);
+
+ /* send notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACTION_OT_select_lasso(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Lasso Select";
+ ot->description = "Select keyframe points using lasso selection";
+ ot->idname = "ACTION_OT_select_lasso";
+
+ /* api callbacks */
+ ot->invoke = WM_gesture_lasso_invoke;
+ ot->modal = WM_gesture_lasso_modal;
+ ot->exec = actkeys_lassoselect_exec;
+ ot->poll = ED_operator_action_active;
+ ot->cancel = WM_gesture_lasso_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
+ RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Deselect rather than select items");
+ RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection instead of deselecting everything first");
+}
+
+/* ------------------- */
+
+static int action_circle_select_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ const int gesture_mode = RNA_int_get(op->ptr, "gesture_mode");
+ const short selectmode = (gesture_mode == GESTURE_MODAL_SELECT) ? SELECT_ADD : SELECT_SUBTRACT;
+
+ KeyframeEdit_CircleData data = {0};
+ rctf rect_fl;
+
+ float x = RNA_int_get(op->ptr, "x");
+ float y = RNA_int_get(op->ptr, "y");
+ float radius = RNA_int_get(op->ptr, "radius");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ data.mval[0] = x;
+ data.mval[1] = y;
+ data.radius_squared = radius * radius;
+ data.rectf_view = &rect_fl;
+
+ rect_fl.xmin = x - radius;
+ rect_fl.xmax = x + radius;
+ rect_fl.ymin = y - radius;
+ rect_fl.ymax = y + radius;
+
+ /* apply region select action */
+ region_select_action_keys(&ac, &rect_fl, BEZT_OK_CHANNEL_CIRCLE, selectmode, &data);
+
+ /* send notifier that keyframe selection has changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void ACTION_OT_select_circle(wmOperatorType *ot)
+{
+ ot->name = "Circle Select";
+ ot->description = "Select keyframe points using circle selection";
+ ot->idname = "ACTION_OT_select_circle";
+
+ ot->invoke = WM_gesture_circle_invoke;
+ ot->modal = WM_gesture_circle_modal;
+ ot->exec = action_circle_select_exec;
+ ot->poll = ED_operator_action_active;
+ ot->cancel = WM_gesture_circle_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "radius", 1, 1, INT_MAX, "Radius", "", 1, INT_MAX);
+ RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+}
+
/* ******************** Column Select Operator **************************** */
/* This operator works in one of four ways:
* - 1) select all keyframes in the same frame as a selected one (KKEY)
diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h
index 71e38f72a7a..a55b18a2212 100644
--- a/source/blender/editors/space_file/file_intern.h
+++ b/source/blender/editors/space_file/file_intern.h
@@ -128,6 +128,7 @@ void file_panels_register(struct ARegionType *art);
/* file_utils.c */
void file_tile_boundbox(const ARegion *ar, FileLayout *layout, const int file, rcti *r_bounds);
+bool file_is_dir(struct SpaceFile *sfile, const char *path);
#endif /* __FILE_INTERN_H__ */
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index d83a7d5ea62..c42ff120102 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -208,7 +208,7 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen)
BLI_add_slash(params->dir);
}
- ED_file_change_dir(C, false);
+ ED_file_change_dir(C);
retval = FILE_SELECT_DIR;
}
}
@@ -826,7 +826,7 @@ static int bookmark_select_exec(bContext *C, wmOperator *op)
RNA_property_string_get(op->ptr, prop, entry);
BLI_strncpy(params->dir, entry, sizeof(params->dir));
BLI_cleanup_dir(G.main->name, params->dir);
- ED_file_change_dir(C, true);
+ ED_file_change_dir(C);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
@@ -1379,7 +1379,7 @@ int file_exec(bContext *C, wmOperator *exec_op)
BLI_add_slash(sfile->params->dir);
}
- ED_file_change_dir(C, false);
+ ED_file_change_dir(C);
}
/* opening file - sends events now, so things get handled on windowqueue level */
else if (sfile->op) {
@@ -1447,19 +1447,7 @@ int file_parent_exec(bContext *C, wmOperator *UNUSED(unused))
if (sfile->params) {
if (BLI_parent_dir(sfile->params->dir)) {
BLI_cleanup_dir(G.main->name, sfile->params->dir);
- /* if not browsing in .blend file, we still want to check whether the path is a directory */
- if (sfile->params->type == FILE_LOADLIB) {
- char tdir[FILE_MAX];
- if (BLO_library_path_explode(sfile->params->dir, tdir, NULL, NULL)) {
- ED_file_change_dir(C, false);
- }
- else {
- ED_file_change_dir(C, true);
- }
- }
- else {
- ED_file_change_dir(C, true);
- }
+ ED_file_change_dir(C);
if (sfile->params->recursion_level > 1) {
/* Disable 'dirtree' recursion when going up in tree. */
sfile->params->recursion_level = 0;
@@ -1529,7 +1517,7 @@ int file_previous_exec(bContext *C, wmOperator *UNUSED(unused))
folderlist_popdir(sfile->folders_prev, sfile->params->dir);
folderlist_pushdir(sfile->folders_next, sfile->params->dir);
- ED_file_change_dir(C, true);
+ ED_file_change_dir(C);
}
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
@@ -1561,7 +1549,7 @@ int file_next_exec(bContext *C, wmOperator *UNUSED(unused))
// update folders_prev so we can check for it in folderlist_clear_next()
folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
- ED_file_change_dir(C, true);
+ ED_file_change_dir(C);
}
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
@@ -1809,7 +1797,7 @@ int file_directory_new_exec(bContext *C, wmOperator *op)
if (RNA_boolean_get(op->ptr, "open")) {
BLI_strncpy(sfile->params->dir, path, sizeof(sfile->params->dir));
- ED_file_change_dir(C, true);
+ ED_file_change_dir(C);
}
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
@@ -1906,17 +1894,35 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
file_expand_directory(C);
/* special case, user may have pasted a filepath into the directory */
- if (BLI_is_file(sfile->params->dir)) {
- char path[sizeof(sfile->params->dir)];
- BLI_strncpy(path, sfile->params->dir, sizeof(path));
- BLI_split_dirfile(path, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file));
+ if (!file_is_dir(sfile, sfile->params->dir)) {
+ char tdir[FILE_MAX_LIBEXTRA];
+ char *group, *name;
+
+ if (BLI_is_file(sfile->params->dir)) {
+ char path[sizeof(sfile->params->dir)];
+ BLI_strncpy(path, sfile->params->dir, sizeof(path));
+ BLI_split_dirfile(path, sfile->params->dir, sfile->params->file,
+ sizeof(sfile->params->dir), sizeof(sfile->params->file));
+ }
+ else if (BLO_library_path_explode(sfile->params->dir, tdir, &group, &name)) {
+ if (group) {
+ BLI_path_append(tdir, sizeof(tdir), group);
+ }
+ BLI_strncpy(sfile->params->dir, tdir, sizeof(sfile->params->dir));
+ if (name) {
+ BLI_strncpy(sfile->params->file, name, sizeof(sfile->params->file));
+ }
+ else {
+ sfile->params->file[0] = '\0';
+ }
+ }
}
BLI_cleanup_dir(G.main->name, sfile->params->dir);
- if (BLI_exists(sfile->params->dir)) {
+ if (file_is_dir(sfile, sfile->params->dir)) {
/* if directory exists, enter it immediately */
- ED_file_change_dir(C, true);
+ ED_file_change_dir(C);
/* don't do for now because it selects entire text instead of
* placing cursor at the end */
@@ -1931,20 +1937,26 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
#endif
else {
const char *lastdir = folderlist_peeklastdir(sfile->folders_prev);
+ char tdir[FILE_MAX_LIBEXTRA];
- /* if not, ask to create it and enter if confirmed */
- wmOperatorType *ot = WM_operatortype_find("FILE_OT_directory_new", false);
- PointerRNA ptr;
- WM_operator_properties_create_ptr(&ptr, ot);
- RNA_string_set(&ptr, "directory", sfile->params->dir);
- RNA_boolean_set(&ptr, "open", true);
-
- if (lastdir)
+ /* If we are 'inside' a blend library, we cannot do anything... */
+ if (lastdir && BLO_library_path_explode(lastdir, tdir, NULL, NULL)) {
BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir));
-
-
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
- WM_operator_properties_free(&ptr);
+ }
+ else {
+ /* if not, ask to create it and enter if confirmed */
+ wmOperatorType *ot = WM_operatortype_find("FILE_OT_directory_new", false);
+ PointerRNA ptr;
+ WM_operator_properties_create_ptr(&ptr, ot);
+ RNA_string_set(&ptr, "directory", sfile->params->dir);
+ RNA_boolean_set(&ptr, "open", true);
+
+ if (lastdir)
+ BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir));
+
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
+ WM_operator_properties_free(&ptr);
+ }
}
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
@@ -1971,8 +1983,6 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg
BLI_filename_make_safe(sfile->params->file);
if (matches) {
- /* int i, numfiles = filelist_numfiles(sfile->files); */ /* XXX UNUSED */
- sfile->params->file[0] = '\0';
/* replace the pattern (or filename that the user typed in, with the first selected file of the match */
BLI_strncpy(sfile->params->file, matched_file, sizeof(sfile->params->file));
@@ -1980,30 +1990,17 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg
}
if (matches == 1) {
-
BLI_join_dirfile(filepath, sizeof(sfile->params->dir), sfile->params->dir, sfile->params->file);
/* if directory, open it and empty filename field */
- if (BLI_is_dir(filepath)) {
+ if (file_is_dir(sfile, filepath)) {
BLI_cleanup_dir(G.main->name, filepath);
BLI_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir));
sfile->params->file[0] = '\0';
- ED_file_change_dir(C, true);
+ ED_file_change_dir(C);
UI_textbutton_activate_but(C, but);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
}
- else if (sfile->params->type == FILE_LOADLIB) {
- char tdir[FILE_MAX];
- BLI_add_slash(filepath);
- if (BLO_library_path_explode(filepath, tdir, NULL, NULL)) {
- BLI_cleanup_dir(G.main->name, filepath);
- BLI_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir));
- sfile->params->file[0] = '\0';
- ED_file_change_dir(C, false);
- UI_textbutton_activate_but(C, but);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
- }
- }
}
else if (matches > 1) {
file_draw_check(C);
diff --git a/source/blender/editors/space_file/file_utils.c b/source/blender/editors/space_file/file_utils.c
index 3c007f25da3..f19e301064d 100644
--- a/source/blender/editors/space_file/file_utils.c
+++ b/source/blender/editors/space_file/file_utils.c
@@ -25,6 +25,9 @@
*/
#include "BLI_rect.h"
+#include "BLI_fileops.h"
+
+#include "BLO_readfile.h"
#include "BKE_context.h"
@@ -45,3 +48,17 @@ void file_tile_boundbox(const ARegion *ar, FileLayout *layout, const int file, r
BLI_rcti_init(r_bounds, xmin, xmin + layout->tile_w + layout->tile_border_x,
ymax - layout->tile_h - layout->tile_border_y, ymax);
}
+
+/* Cannot directly use BLI_is_dir in libloading context... */
+bool file_is_dir(struct SpaceFile *sfile, const char *path)
+{
+ if (sfile->params->type == FILE_LOADLIB) {
+ char tdir[FILE_MAX_LIBEXTRA];
+ char *name;
+ if (BLO_library_path_explode(sfile->params->dir, tdir, NULL, &name) && BLI_is_file(tdir)) {
+ /* .blend file itself and group are considered as directories, not final datablock names. */
+ return name ? false : true;
+ }
+ }
+ return BLI_is_dir(path);
+}
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index fc3341bfb92..5e9eb1f9207 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -624,7 +624,7 @@ static bool is_filtered_file(FileListInternEntry *file, const char *UNUSED(root)
static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileListFilter *filter)
{
bool is_filtered;
- char path[FILE_MAX_LIBEXTRA], dir[FILE_MAXDIR], *group, *name;
+ char path[FILE_MAX_LIBEXTRA], dir[FILE_MAX_LIBEXTRA], *group, *name;
BLI_join_dirfile(path, sizeof(path), root, file->relpath);
@@ -697,7 +697,7 @@ void filelist_filter(FileList *filelist)
if (filelist->max_recursion) {
/* Never show lib ID 'categories' directories when we are in 'flat' mode, unless
* root path is a blend file. */
- char dir[FILE_MAXDIR];
+ char dir[FILE_MAX_LIBEXTRA];
if (!filelist_islibrary(filelist, dir, NULL)) {
filelist->filter_data.flags |= FLF_HIDE_LIB_DIR;
}
@@ -947,7 +947,7 @@ static void filelist_checkdir_dir(struct FileList *UNUSED(filelist), char *r_dir
static void filelist_checkdir_lib(struct FileList *UNUSED(filelist), char *r_dir)
{
- char dir[FILE_MAXDIR];
+ char dir[FILE_MAX_LIBEXTRA];
if (!BLO_library_path_explode(r_dir, dir, NULL, NULL)) {
/* if not a valid library, we need it to be a valid directory! */
BLI_make_exist(r_dir);
@@ -2113,6 +2113,7 @@ unsigned int filelist_entry_select_index_get(FileList *filelist, const int index
return 0;
}
+/* WARNING! dir must be FILE_MAX_LIBEXTRA long! */
bool filelist_islibrary(struct FileList *filelist, char *dir, char **group)
{
return BLO_library_path_explode(filelist->filelist.root, dir, group, NULL);
@@ -2208,7 +2209,7 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const
FileListInternEntry *entry;
LinkNode *ln, *names;
int i, nnames, idcode = 0, nbr_entries = 0;
- char dir[FILE_MAX], *group;
+ char dir[FILE_MAX_LIBEXTRA], *group;
bool ok;
struct BlendHandle *libfiledata = NULL;
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 2a3f964f477..2d28108f544 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -576,7 +576,7 @@ FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, ARegion *ar)
return sfile->layout;
}
-void ED_file_change_dir(bContext *C, const bool checkdir)
+void ED_file_change_dir(bContext *C)
{
wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -590,7 +590,7 @@ void ED_file_change_dir(bContext *C, const bool checkdir)
sfile->params->filter_search[0] = '\0';
sfile->params->active_file = -1;
- if (checkdir && !BLI_is_dir(sfile->params->dir)) {
+ if (!file_is_dir(sfile, sfile->params->dir)) {
BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir));
/* could return but just refresh the current dir */
}
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
index 6b860990c10..478dbd3d9c0 100644
--- a/source/blender/editors/space_graph/graph_ops.c
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -555,19 +555,20 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "axis_range", true);
RNA_boolean_set(kmi->ptr, "include_handles", false);
-
+
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "axis_range", false);
RNA_boolean_set(kmi->ptr, "include_handles", true);
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "axis_range", true);
RNA_boolean_set(kmi->ptr, "include_handles", true);
-
+
+ /* region select */
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "deselect", false);
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "deselect", true);
-
+
WM_keymap_add_item(keymap, "GRAPH_OT_select_circle", CKEY, KM_PRESS, 0, 0);
/* column select */
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index eb786d872ec..67b960bfa53 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -210,6 +210,8 @@ void GRAPH_OT_select_all_toggle(wmOperatorType *ot)
* -> ALT-BKEY - depending on which axis of the region was larger...
* -> 2) x-axis, so select all frames within frame range (validation with BEZT_OK_FRAMERANGE)
* -> 3) y-axis, so select all frames within channels that region included (validation with BEZT_OK_VALUERANGE)
+ *
+ * The selection backend is also reused for the Lasso and Circle select operators.
*/
/* Borderselect only selects keyframes now, as overshooting handles often get caught too,
@@ -245,12 +247,12 @@ static void borderselect_graphkeys(
/* init editing data */
memset(&ked, 0, sizeof(KeyframeEditData));
if (mode == BEZT_OK_REGION_LASSO) {
- struct KeyframeEdit_LassoData *data_lasso = data;
+ KeyframeEdit_LassoData *data_lasso = data;
data_lasso->rectf_scaled = &scaled_rectf;
ked.data = data_lasso;
}
else if (mode == BEZT_OK_REGION_CIRCLE) {
- struct KeyframeEdit_CircleData *data_circle = data;
+ KeyframeEdit_CircleData *data_circle = data;
data_circle->rectf_scaled = &scaled_rectf;
ked.data = data;
}
@@ -265,27 +267,27 @@ static void borderselect_graphkeys(
}
else
mapping_flag = ANIM_UNITCONV_ONLYKEYS;
-
+
mapping_flag |= ANIM_get_normalization_flags(ac);
-
+
/* loop over data, doing border select */
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
float offset;
float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
-
+
/* apply NLA mapping to all the keyframes, since it's easier than trying to
* guess when a callback might use something different
*/
if (adt)
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, incl_handles == 0);
-
+
scaled_rectf.xmin = rectf.xmin;
scaled_rectf.xmax = rectf.xmax;
scaled_rectf.ymin = rectf.ymin / unit_scale - offset;
scaled_rectf.ymax = rectf.ymax / unit_scale - offset;
-
+
/* set horizontal range (if applicable)
* NOTE: these values are only used for x-range and y-range but not region
* (which uses ked.data, i.e. rectf)
@@ -406,37 +408,41 @@ void GRAPH_OT_select_border(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "include_handles", 0, "Include Handles", "Are handles tested individually against the selection criteria");
}
+
+/* ------------------- */
+
static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
+
+ KeyframeEdit_LassoData data_lasso = {0};
rcti rect;
rctf rect_fl;
+
short selectmode;
bool incl_handles;
bool extend;
-
- struct KeyframeEdit_LassoData data_lasso;
-
+
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
data_lasso.rectf_view = &rect_fl;
data_lasso.mcords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcords_tot);
if (data_lasso.mcords == NULL)
return OPERATOR_CANCELLED;
-
+
/* clear all selection if not extending selection */
extend = RNA_boolean_get(op->ptr, "extend");
if (!extend)
deselect_graph_keys(&ac, 1, SELECT_SUBTRACT, true);
-
+
if (!RNA_boolean_get(op->ptr, "deselect"))
selectmode = SELECT_ADD;
else
selectmode = SELECT_SUBTRACT;
-
- if (ac.spacetype == SPACE_IPO) {
+
+ {
SpaceIpo *sipo = (SpaceIpo *)ac.sl;
if (selectmode == SELECT_ADD) {
incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) ||
@@ -446,60 +452,57 @@ static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op)
incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0;
}
}
- else {
- incl_handles = false;
- }
-
-
+
/* get settings from operator */
BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot);
-
BLI_rctf_rcti_copy(&rect_fl, &rect);
-
+
/* apply borderselect action */
borderselect_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_LASSO, selectmode, incl_handles, &data_lasso);
-
+
MEM_freeN((void *)data_lasso.mcords);
-
-
+
/* send notifier that keyframe selection has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
-
+
return OPERATOR_FINISHED;
}
-
void GRAPH_OT_select_lasso(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Lasso Select";
ot->description = "Select keyframe points using lasso selection";
ot->idname = "GRAPH_OT_select_lasso";
-
+
/* api callbacks */
ot->invoke = WM_gesture_lasso_invoke;
ot->modal = WM_gesture_lasso_modal;
ot->exec = graphkeys_lassoselect_exec;
ot->poll = graphop_visible_keyframes_poll;
ot->cancel = WM_gesture_lasso_cancel;
-
+
/* flags */
ot->flag = OPTYPE_UNDO;
-
+
/* properties */
RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Deselect rather than select items");
RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection instead of deselecting everything first");
}
+/* ------------------- */
+
static int graph_circle_select_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
const int gesture_mode = RNA_int_get(op->ptr, "gesture_mode");
- short selectmode;
- bool incl_handles;
+ const short selectmode = (gesture_mode == GESTURE_MODAL_SELECT) ? SELECT_ADD : SELECT_SUBTRACT;
+ bool incl_handles = false;
+
+ KeyframeEdit_CircleData data = {0};
rctf rect_fl;
- struct KeyframeEdit_CircleData data;
+
float x = RNA_int_get(op->ptr, "x");
float y = RNA_int_get(op->ptr, "y");
float radius = RNA_int_get(op->ptr, "radius");
@@ -507,23 +510,18 @@ static int graph_circle_select_exec(bContext *C, wmOperator *op)
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
data.mval[0] = x;
data.mval[1] = y;
data.radius_squared = radius * radius;
data.rectf_view = &rect_fl;
- if (gesture_mode == GESTURE_MODAL_SELECT)
- selectmode = SELECT_ADD;
- else
- selectmode = SELECT_SUBTRACT;
-
rect_fl.xmin = x - radius;
rect_fl.xmax = x + radius;
rect_fl.ymin = y - radius;
rect_fl.ymax = y + radius;
- if (ac.spacetype == SPACE_IPO) {
+ {
SpaceIpo *sipo = (SpaceIpo *)ac.sl;
if (selectmode == SELECT_ADD) {
incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) ||
@@ -533,10 +531,7 @@ static int graph_circle_select_exec(bContext *C, wmOperator *op)
incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0;
}
}
- else {
- incl_handles = false;
- }
-
+
/* apply borderselect action */
borderselect_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data);
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index a7284694f64..8ae5932f3fd 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -611,6 +611,51 @@ static void graph_refresh(const bContext *C, ScrArea *sa)
}
break;
}
+ case FCURVE_COLOR_AUTO_YRGB:
+ {
+ /* Like FCURVE_COLOR_AUTO_RGB, except this is for quaternions... */
+ float *col = fcu->color;
+
+ switch (fcu->array_index) {
+ case 1:
+ UI_GetThemeColor3fv(TH_AXIS_X, col);
+ break;
+ case 2:
+ UI_GetThemeColor3fv(TH_AXIS_Y, col);
+ break;
+ case 3:
+ UI_GetThemeColor3fv(TH_AXIS_Z, col);
+ break;
+
+ case 0:
+ {
+ /* Special Case: "W" channel should be yellowish, so blend X and Y channel colors... */
+ float c1[3], c2[3];
+ float h1[3], h2[3];
+ float hresult[3];
+
+ /* - get colors (rgb) */
+ UI_GetThemeColor3fv(TH_AXIS_X, c1);
+ UI_GetThemeColor3fv(TH_AXIS_Y, c2);
+
+ /* - perform blending in HSV space (to keep brightness similar) */
+ rgb_to_hsv_v(c1, h1);
+ rgb_to_hsv_v(c2, h2);
+
+ interp_v3_v3v3(hresult, h1, h2, 0.5f);
+
+ /* - convert back to RGB for display */
+ hsv_to_rgb_v(hresult, col);
+ break;
+ }
+
+ default:
+ /* 'unknown' color - bluish so as to not conflict with handles */
+ col[0] = 0.3f; col[1] = 0.8f; col[2] = 1.0f;
+ break;
+ }
+ break;
+ }
case FCURVE_COLOR_AUTO_RAINBOW:
default:
{
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 687869ae727..57d9ff7825b 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -399,13 +399,22 @@ static int outliner_id_remap_exec(bContext *C, wmOperator *op)
ID *new_id = BLI_findlink(which_libbase(CTX_data_main(C), id_type), RNA_enum_get(op->ptr, "new_id"));
/* check for invalid states */
- if (soops == NULL)
+ if (soops == NULL) {
return OPERATOR_CANCELLED;
+ }
if (!(old_id && (old_id != new_id) && (GS(old_id->name) == GS(new_id->name)))) {
+ BKE_reportf(op->reports, RPT_ERROR_INVALID_INPUT, "Invalid old/new ID pair ('%s' / '%s')",
+ old_id->name, new_id->name);
return OPERATOR_CANCELLED;
}
+ if (old_id->lib) {
+ BKE_reportf(op->reports, RPT_WARNING,
+ "Old ID '%s' is linked from a library, indirect usages of this datablock will not be remapped",
+ old_id->name);
+ }
+
BKE_libblock_remap(bmain, old_id, new_id,
ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index d404e7aaf15..94ed280f792 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -384,8 +384,7 @@ static int text_unlink_exec(bContext *C, wmOperator *UNUSED(op))
}
}
- BKE_text_unlink(bmain, text);
- BKE_libblock_free(bmain, text);
+ BKE_libblock_delete(bmain, text);
text_drawcache_tag_update(st, 1);
WM_event_add_notifier(C, NC_TEXT | NA_REMOVED, NULL);
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index c32de6eafc3..3b1ce5f8ab0 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -7032,7 +7032,7 @@ static void bbs_obmode_mesh_verts__mapFunc(void *userData, int index, const floa
MVert *mv = &data->mvert[index];
if (!(mv->flag & ME_HIDE)) {
- WM_framebuffer_index_set(data->offset + index);
+ GPU_select_index_set(data->offset + index);
glVertex3fv(co);
}
}
@@ -7057,7 +7057,7 @@ static void bbs_mesh_verts__mapFunc(void *userData, int index, const float co[3]
BMVert *eve = BM_vert_at_index(data->bm, index);
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- WM_framebuffer_index_set(data->offset + index);
+ GPU_select_index_set(data->offset + index);
glVertex3fv(co);
}
}
@@ -7076,7 +7076,7 @@ static DMDrawOption bbs_mesh_wire__setDrawOptions(void *userData, int index)
BMEdge *eed = BM_edge_at_index(data->bm, index);
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- WM_framebuffer_index_set(data->offset + index);
+ GPU_select_index_set(data->offset + index);
return DM_DRAW_OPTION_NORMAL;
}
else {
@@ -7090,7 +7090,7 @@ static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset)
}
/**
- * dont set #WM_framebuffer_index_set. just use to mask other
+ * dont set #GPU_framebuffer_index_set. just use to mask other
*/
static DMDrawOption bbs_mesh_mask__setSolidDrawOptions(void *userData, int index)
{
@@ -7109,7 +7109,7 @@ static DMDrawOption bbs_mesh_solid__setSolidDrawOptions(void *userData, int inde
BMFace *efa = BM_face_at_index(userData, index);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- WM_framebuffer_index_set(index + 1);
+ GPU_select_index_set(index + 1);
return DM_DRAW_OPTION_NORMAL;
}
else {
@@ -7122,7 +7122,7 @@ static void bbs_mesh_solid__drawCenter(void *userData, int index, const float ce
BMFace *efa = BM_face_at_index(userData, index);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- WM_framebuffer_index_set(index + 1);
+ GPU_select_index_set(index + 1);
glVertex3fv(cent);
}
@@ -7153,7 +7153,7 @@ static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d,
static DMDrawOption bbs_mesh_solid__setDrawOpts(void *UNUSED(userData), int index)
{
- WM_framebuffer_index_set(index + 1);
+ GPU_select_index_set(index + 1);
return DM_DRAW_OPTION_NORMAL;
}
@@ -7162,7 +7162,7 @@ static DMDrawOption bbs_mesh_solid_hide__setDrawOpts(void *userData, int index)
Mesh *me = userData;
if (!(me->mpoly[index].flag & ME_HIDE)) {
- WM_framebuffer_index_set(index + 1);
+ GPU_select_index_set(index + 1);
return DM_DRAW_OPTION_NORMAL;
}
else {
@@ -7170,7 +7170,7 @@ static DMDrawOption bbs_mesh_solid_hide__setDrawOpts(void *userData, int index)
}
}
-/* must have called WM_framebuffer_index_set beforehand */
+/* must have called GPU_framebuffer_index_set beforehand */
static DMDrawOption bbs_mesh_solid_hide2__setDrawOpts(void *userData, int index)
{
Mesh *me = userData;
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 64b12498ae2..dcab05c80d6 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -1483,7 +1483,7 @@ unsigned int ED_view3d_backbuf_sample(ViewContext *vc, int x, int y)
BLI_endian_switch_uint32(&col);
}
- return WM_framebuffer_to_index(col);
+ return GPU_select_to_index(col);
}
/* reads full rect, converts indices */
@@ -1516,7 +1516,7 @@ ImBuf *ED_view3d_backbuf_read(ViewContext *vc, int xmin, int ymin, int xmax, int
IMB_convert_rgba_to_abgr(ibuf_clip);
}
- WM_framebuffer_to_index_array(ibuf_clip->rect, size_clip[0] * size_clip[1]);
+ GPU_select_to_index_array(ibuf_clip->rect, size_clip[0] * size_clip[1]);
if ((clip.xmin == xmin) &&
(clip.xmax == xmax) &&
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index fd7179d06dd..148db20b41d 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -93,6 +93,8 @@
#include "UI_interface.h"
+#include "GPU_draw.h"
+
#include "view3d_intern.h" /* own include */
float ED_view3d_select_dist_px(void)
@@ -1687,7 +1689,7 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, boo
if (ENDIAN_ORDER == B_ENDIAN) {
IMB_convert_rgba_to_abgr(ibuf);
}
- WM_framebuffer_to_index_array(ibuf->rect, size[0] * size[1]);
+ GPU_select_to_index_array(ibuf->rect, size[0] * size[1]);
a = size[0] * size[1];
while (a--) {
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 943490bbc3a..c94b0d53468 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1202,8 +1202,12 @@ int transformEvent(TransInfo *t, const wmEvent *event)
if (t->flag & T_PROP_EDIT) {
float fac = 1.0f + 0.005f *(event->y - event->prevy);
t->prop_size *= fac;
- if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO)
- t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far);
+ if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) {
+ t->prop_size = max_ff(min_ff(t->prop_size, ((View3D *)t->view)->far), T_PROP_SIZE_MIN);
+ }
+ else {
+ t->prop_size = max_ff(min_ff(t->prop_size, T_PROP_SIZE_MAX), T_PROP_SIZE_MIN);
+ }
calculatePropRatio(t);
t->redraw |= TREDRAW_HARD;
handled = true;
@@ -1212,8 +1216,12 @@ int transformEvent(TransInfo *t, const wmEvent *event)
case TFM_MODAL_PROPSIZE_UP:
if (t->flag & T_PROP_EDIT) {
t->prop_size *= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
- if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO)
+ if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) {
t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far);
+ }
+ else {
+ t->prop_size = min_ff(t->prop_size, T_PROP_SIZE_MAX);
+ }
calculatePropRatio(t);
t->redraw |= TREDRAW_HARD;
handled = true;
@@ -1222,6 +1230,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
case TFM_MODAL_PROPSIZE_DOWN:
if (t->flag & T_PROP_EDIT) {
t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
+ t->prop_size = max_ff(t->prop_size, T_PROP_SIZE_MIN);
calculatePropRatio(t);
t->redraw |= TREDRAW_HARD;
handled = true;
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 4e8aa0cc20b..da448faa16b 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -592,6 +592,10 @@ typedef struct TransInfo {
#define POINT_INIT 4
#define MULTI_POINTS 8
+/* Hard min/max for proportional size. */
+#define T_PROP_SIZE_MIN 1e-6f
+#define T_PROP_SIZE_MAX 1e12f
+
bool initTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op, const struct wmEvent *event, int mode);
void saveTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op);
int transformEvent(TransInfo *t, const struct wmEvent *event);
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 2fb92d73515..6e399d9fde3 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -528,7 +528,8 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
prop = RNA_def_enum(ot->srna, "proportional_edit_falloff", rna_enum_proportional_falloff_items, 0,
"Proportional Editing Falloff", "Falloff type for proportional editing mode");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
- RNA_def_float(ot->srna, "proportional_size", 1, 0.00001f, FLT_MAX, "Proportional Size", "", 0.001, 100);
+ RNA_def_float(ot->srna, "proportional_size", 1, T_PROP_SIZE_MIN, T_PROP_SIZE_MAX,
+ "Proportional Size", "", 0.001f, 100.0f);
}
if (flags & P_SNAP) {
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index d706c574d1f..1db4ee0e2e5 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -1627,7 +1627,7 @@ static bool transform_snap_context_project_view3d_mixed_impl(
* Given a 2D region value, snap to vert/edge/face.
*
* \param sctx: Snap context.
- * \param mval: Screenspace coordinate.
+ * \param mval_fl: Screenspace coordinate.
* \param dist_px: Maximum distance to snap (in pixels).
* \param use_depth: Snap to the closest element, use when using more than one snap type.
* \param r_co: hit location.
diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.h b/source/blender/freestyle/intern/system/PythonInterpreter.h
index 5403ec6b13b..0e08af1bac8 100644
--- a/source/blender/freestyle/intern/system/PythonInterpreter.h
+++ b/source/blender/freestyle/intern/system/PythonInterpreter.h
@@ -84,8 +84,7 @@ public:
Text *text = BKE_text_load(&_freestyle_bmain, fn, G.main->name);
if (text) {
ok = BPY_execute_text(_context, text, reports, false);
- BKE_text_unlink(&_freestyle_bmain, text);
- BKE_libblock_free(&_freestyle_bmain, text);
+ BKE_libblock_delete(&_freestyle_bmain, text);
}
else {
BKE_reportf(reports, RPT_ERROR, "Cannot open file: %s", fn);
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index bc732387c85..90b65af87c8 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -160,6 +160,12 @@ struct DerivedMesh;
void GPU_draw_update_fvar_offset(struct DerivedMesh *dm);
#endif
+/* utilities */
+void GPU_select_index_set(int index);
+void GPU_select_index_get(int index, int *r_col);
+int GPU_select_to_index(unsigned int col);
+void GPU_select_to_index_array(unsigned int *col, const unsigned int size);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 52177b756c5..3ea64e1f6d5 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -2327,3 +2327,152 @@ void GPU_draw_update_fvar_offset(DerivedMesh *dm)
}
}
#endif
+
+
+/** \name Framebuffer color depth, for selection codes
+ * \{ */
+
+#ifdef __APPLE__
+
+/* apple seems to round colors to below and up on some configs */
+
+static unsigned int index_to_framebuffer(int index)
+{
+ unsigned int i = index;
+
+ switch (GPU_color_depth()) {
+ case 12:
+ i = ((i & 0xF00) << 12) + ((i & 0xF0) << 8) + ((i & 0xF) << 4);
+ /* sometimes dithering subtracts! */
+ i |= 0x070707;
+ break;
+ case 15:
+ case 16:
+ i = ((i & 0x7C00) << 9) + ((i & 0x3E0) << 6) + ((i & 0x1F) << 3);
+ i |= 0x030303;
+ break;
+ case 24:
+ break;
+ default: /* 18 bits... */
+ i = ((i & 0x3F000) << 6) + ((i & 0xFC0) << 4) + ((i & 0x3F) << 2);
+ i |= 0x010101;
+ break;
+ }
+
+ return i;
+}
+
+#else
+
+/* this is the old method as being in use for ages.... seems to work? colors are rounded to lower values */
+
+static unsigned int index_to_framebuffer(int index)
+{
+ unsigned int i = index;
+
+ switch (GPU_color_depth()) {
+ case 8:
+ i = ((i & 48) << 18) + ((i & 12) << 12) + ((i & 3) << 6);
+ i |= 0x3F3F3F;
+ break;
+ case 12:
+ i = ((i & 0xF00) << 12) + ((i & 0xF0) << 8) + ((i & 0xF) << 4);
+ /* sometimes dithering subtracts! */
+ i |= 0x0F0F0F;
+ break;
+ case 15:
+ case 16:
+ i = ((i & 0x7C00) << 9) + ((i & 0x3E0) << 6) + ((i & 0x1F) << 3);
+ i |= 0x070707;
+ break;
+ case 24:
+ break;
+ default: /* 18 bits... */
+ i = ((i & 0x3F000) << 6) + ((i & 0xFC0) << 4) + ((i & 0x3F) << 2);
+ i |= 0x030303;
+ break;
+ }
+
+ return i;
+}
+
+#endif
+
+
+void GPU_select_index_set(int index)
+{
+ const int col = index_to_framebuffer(index);
+ glColor3ub(( (col) & 0xFF),
+ (((col) >> 8) & 0xFF),
+ (((col) >> 16) & 0xFF));
+}
+
+void GPU_select_index_get(int index, int *r_col)
+{
+ const int col = index_to_framebuffer(index);
+ char *c_col = (char *)r_col;
+ c_col[0] = (col & 0xFF); /* red */
+ c_col[1] = ((col >> 8) & 0xFF); /* green */
+ c_col[2] = ((col >> 16) & 0xFF); /* blue */
+ c_col[3] = 0xFF; /* alpha */
+}
+
+
+#define INDEX_FROM_BUF_8(col) ((((col) & 0xC00000) >> 18) + (((col) & 0xC000) >> 12) + (((col) & 0xC0) >> 6))
+#define INDEX_FROM_BUF_12(col) ((((col) & 0xF00000) >> 12) + (((col) & 0xF000) >> 8) + (((col) & 0xF0) >> 4))
+#define INDEX_FROM_BUF_15_16(col) ((((col) & 0xF80000) >> 9) + (((col) & 0xF800) >> 6) + (((col) & 0xF8) >> 3))
+#define INDEX_FROM_BUF_18(col) ((((col) & 0xFC0000) >> 6) + (((col) & 0xFC00) >> 4) + (((col) & 0xFC) >> 2))
+#define INDEX_FROM_BUF_24(col) ((col) & 0xFFFFFF)
+
+int GPU_select_to_index(unsigned int col)
+{
+ if (col == 0) {
+ return 0;
+ }
+
+ switch (GPU_color_depth()) {
+ case 8: return INDEX_FROM_BUF_8(col);
+ case 12: return INDEX_FROM_BUF_12(col);
+ case 15:
+ case 16: return INDEX_FROM_BUF_15_16(col);
+ case 24: return INDEX_FROM_BUF_24(col);
+ default: return INDEX_FROM_BUF_18(col);
+ }
+}
+
+void GPU_select_to_index_array(unsigned int *col, const unsigned int size)
+{
+#define INDEX_BUF_ARRAY(INDEX_FROM_BUF_BITS) \
+ for (i = size; i--; col++) { \
+ if ((c = *col)) { \
+ *col = INDEX_FROM_BUF_BITS(c); \
+ } \
+ } ((void)0)
+
+ if (size > 0) {
+ unsigned int i, c;
+
+ switch (GPU_color_depth()) {
+ case 8:
+ INDEX_BUF_ARRAY(INDEX_FROM_BUF_8);
+ break;
+ case 12:
+ INDEX_BUF_ARRAY(INDEX_FROM_BUF_12);
+ break;
+ case 15:
+ case 16:
+ INDEX_BUF_ARRAY(INDEX_FROM_BUF_15_16);
+ break;
+ case 24:
+ INDEX_BUF_ARRAY(INDEX_FROM_BUF_24);
+ break;
+ default:
+ INDEX_BUF_ARRAY(INDEX_FROM_BUF_18);
+ break;
+ }
+ }
+
+#undef INDEX_BUF_ARRAY
+}
+
+/** \} */
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
index 9a6537b4f09..db0068d2f3d 100644
--- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
@@ -14,6 +14,9 @@ varying vec3 varnormal;
varying float gl_ClipDistance[6];
#endif
+
+/* Color, keep in sync with: gpu_shader_vertex_world.glsl */
+
float srgb_to_linearrgb(float c)
{
if (c < 0.04045)
@@ -76,6 +79,9 @@ void set_var_from_attr(vec4 attr, int info, out vec4 var)
}
}
+/* end color code */
+
+
void main()
{
#ifndef USE_OPENSUBDIV
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
index 9dbcaeb7a32..d45a4b316a8 100644
--- a/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
@@ -2,6 +2,74 @@
varying vec3 varposition;
varying vec3 varnormal;
+
+/* Color, keep in sync with: gpu_shader_vertex.glsl */
+
+float srgb_to_linearrgb(float c)
+{
+ if (c < 0.04045)
+ return (c < 0.0) ? 0.0 : c * (1.0 / 12.92);
+ else
+ return pow((c + 0.055) * (1.0 / 1.055), 2.4);
+}
+
+void srgb_to_linearrgb(vec3 col_from, out vec3 col_to)
+{
+ col_to.r = srgb_to_linearrgb(col_from.r);
+ col_to.g = srgb_to_linearrgb(col_from.g);
+ col_to.b = srgb_to_linearrgb(col_from.b);
+}
+
+void srgb_to_linearrgb(vec4 col_from, out vec4 col_to)
+{
+ col_to.r = srgb_to_linearrgb(col_from.r);
+ col_to.g = srgb_to_linearrgb(col_from.g);
+ col_to.b = srgb_to_linearrgb(col_from.b);
+ col_to.a = col_from.a;
+}
+
+bool is_srgb(int info)
+{
+#ifdef USE_NEW_SHADING
+ return (info == 1)? true: false;
+#else
+ return false;
+#endif
+}
+
+void set_var_from_attr(float attr, int info, out float var)
+{
+ var = attr;
+}
+
+void set_var_from_attr(vec2 attr, int info, out vec2 var)
+{
+ var = attr;
+}
+
+void set_var_from_attr(vec3 attr, int info, out vec3 var)
+{
+ if (is_srgb(info)) {
+ srgb_to_linearrgb(attr, var);
+ }
+ else {
+ var = attr;
+ }
+}
+
+void set_var_from_attr(vec4 attr, int info, out vec4 var)
+{
+ if (is_srgb(info)) {
+ srgb_to_linearrgb(attr, var);
+ }
+ else {
+ var = attr;
+ }
+}
+
+/* end color code */
+
+
void main()
{
/* position does not need to be transformed, we already have it */
diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c
index 95d061bcb75..3629332a4ac 100644
--- a/source/blender/imbuf/intern/thumbs.c
+++ b/source/blender/imbuf/intern/thumbs.c
@@ -46,6 +46,8 @@
#include "BLO_readfile.h"
+#include "DNA_space_types.h" /* For FILE_MAX_LIBEXTRA */
+
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_thumbs.h"
@@ -533,7 +535,7 @@ ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source
char thumb_path[FILE_MAX];
char thumb_name[40];
char uri[URI_MAX];
- char path_buff[FILE_MAX];
+ char path_buff[FILE_MAX_LIBEXTRA];
const char *file_path;
const char *path;
BLI_stat_t st;
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index 4c1283452ff..6bd7b3a4999 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -537,8 +537,9 @@ typedef enum eFCurve_Extend {
/* curve coloring modes */
typedef enum eFCurve_Coloring {
FCURVE_COLOR_AUTO_RAINBOW = 0, /* automatically determine color using rainbow (calculated at drawtime) */
- FCURVE_COLOR_AUTO_RGB, /* automatically determine color using XYZ (array index) <-> RGB */
- FCURVE_COLOR_CUSTOM /* custom color */
+ FCURVE_COLOR_AUTO_RGB = 1, /* automatically determine color using XYZ (array index) <-> RGB */
+ FCURVE_COLOR_AUTO_YRGB = 3, /* automatically determine color where XYZ <-> RGB, but index(X) != 0 */
+ FCURVE_COLOR_CUSTOM = 2, /* custom color */
} eFCurve_Coloring;
/* ************************************************ */
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 6cba3322135..46b30f41f5b 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -912,7 +912,8 @@ typedef struct NodeSunBeams {
#define SHD_GLOSSY_BECKMANN 0
#define SHD_GLOSSY_SHARP 1
#define SHD_GLOSSY_GGX 2
-#define SHD_GLOSSY_ASHIKHMIN_SHIRLEY 3
+#define SHD_GLOSSY_ASHIKHMIN_SHIRLEY 3
+#define SHD_GLOSSY_MULTI_GGX 4
/* vector transform */
#define SHD_VECT_TRANSFORM_TYPE_VECTOR 0
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 19545336f46..6851f380cd8 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -324,11 +324,6 @@ static void rna_ID_user_clear(ID *id)
id->us = 0; /* don't save */
}
-static void rna_ID_delete(ID *id, Main *bmain)
-{
- BKE_libblock_delete(bmain, id);
-}
-
static void rna_ID_user_remap(ID *id, Main *bmain, ID *new_id)
{
if (GS(id->name) == GS(new_id->name)) {
@@ -977,10 +972,6 @@ static void rna_def_ID(BlenderRNA *brna)
parm = RNA_def_pointer(func, "id", "ID", "", "New copy of the ID");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "destroy", "rna_ID_delete");
- RNA_def_function_flag(func, FUNC_USE_MAIN);
- RNA_def_function_ui_description(func, "Delete this ID from Blender (WARNING: no undo, do not use it after calling this!)");
-
func = RNA_def_function(srna, "user_clear", "rna_ID_user_clear");
RNA_def_function_ui_description(func, "Clear the user count of a data-block so its not saved, "
"on reload the data will be removed");
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index 678b0ac8f1f..492430fbda6 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -257,13 +257,15 @@ void RNA_def_camera(BlenderRNA *brna)
prop = RNA_def_property(srna, "clip_start", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "clipsta");
- RNA_def_property_range(prop, 0.001f, FLT_MAX);
+ RNA_def_property_range(prop, 1e-6f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
RNA_def_property_ui_text(prop, "Clip Start", "Camera near clipping distance");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
prop = RNA_def_property(srna, "clip_end", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "clipend");
- RNA_def_property_range(prop, 1.0f, FLT_MAX);
+ RNA_def_property_range(prop, 1e-6f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
RNA_def_property_ui_text(prop, "Clip End", "Camera far clipping distance");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 1487dfa074e..3043c5452c0 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -1844,6 +1844,8 @@ static void rna_def_fcurve(BlenderRNA *brna)
"Cycle through the rainbow, trying to give each curve a unique color"},
{FCURVE_COLOR_AUTO_RGB, "AUTO_RGB", 0, "Auto XYZ to RGB",
"Use axis colors for transform and color properties, and auto-rainbow for the rest"},
+ {FCURVE_COLOR_AUTO_YRGB, "AUTO_YRGB", 0, "Auto WXYZ to YRGB",
+ "Use axis colors for XYZ parts of transform, and yellow for the 'W' channel"},
{FCURVE_COLOR_CUSTOM, "CUSTOM", 0, "User Defined",
"Use custom hand-picked color for F-Curve"},
{0, NULL, 0, NULL, NULL}
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index cd379603901..c30414ab585 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -62,6 +62,7 @@
#include "BKE_object.h"
#include "BKE_material.h"
#include "BKE_icons.h"
+#include "BKE_idcode.h"
#include "BKE_image.h"
#include "BKE_texture.h"
#include "BKE_scene.h"
@@ -112,30 +113,38 @@
# include "BPY_extern.h"
#endif
+
+static void rna_Main_ID_remove(Main *bmain, ReportList *reports, PointerRNA *id_ptr, int do_unlink)
+{
+ ID *id = id_ptr->data;
+ if (do_unlink) {
+ BKE_libblock_delete(bmain, id);
+ RNA_POINTER_INVALIDATE(id_ptr);
+ }
+ else if (ID_REAL_USERS(id) <= 0) {
+ BKE_libblock_free(bmain, id);
+ RNA_POINTER_INVALIDATE(id_ptr);
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR,
+ "%s '%s' must have zero users to be removed, found %d (try with unlink=True parameter)",
+ BKE_idcode_to_name(GS(id->name)), id->name + 2, ID_REAL_USERS(id));
+ }
+}
+
+
static Camera *rna_Main_cameras_new(Main *bmain, const char *name)
{
ID *id = BKE_camera_add(bmain, name);
id_us_min(id);
return (Camera *)id;
}
-static void rna_Main_cameras_remove(Main *bmain, ReportList *reports, PointerRNA *camera_ptr)
-{
- Camera *camera = camera_ptr->data;
- if (ID_REAL_USERS(camera) <= 0) {
- BKE_libblock_free(bmain, camera);
- RNA_POINTER_INVALIDATE(camera_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Camera '%s' must have zero users to be removed, found %d",
- camera->id.name + 2, ID_REAL_USERS(camera));
- }
-}
static Scene *rna_Main_scenes_new(Main *bmain, const char *name)
{
return BKE_scene_add(bmain, name);
}
-static void rna_Main_scenes_remove(Main *bmain, bContext *C, ReportList *reports, PointerRNA *scene_ptr)
+static void rna_Main_scenes_remove(Main *bmain, bContext *C, ReportList *reports, PointerRNA *scene_ptr, int do_unlink)
{
/* don't call BKE_libblock_free(...) directly */
Scene *scene = scene_ptr->data;
@@ -144,24 +153,23 @@ static void rna_Main_scenes_remove(Main *bmain, bContext *C, ReportList *reports
if ((scene_new = scene->id.prev) ||
(scene_new = scene->id.next))
{
- bScreen *sc = CTX_wm_screen(C);
- if (sc->scene == scene) {
+ if (do_unlink) {
+ bScreen *sc = CTX_wm_screen(C);
+ if (sc->scene == scene) {
#ifdef WITH_PYTHON
- BPy_BEGIN_ALLOW_THREADS;
+ BPy_BEGIN_ALLOW_THREADS;
#endif
- ED_screen_set_scene(C, sc, scene_new);
+ ED_screen_set_scene(C, sc, scene_new);
#ifdef WITH_PYTHON
- BPy_END_ALLOW_THREADS;
+ BPy_END_ALLOW_THREADS;
#endif
+ }
}
-
- BKE_libblock_remap(bmain, scene, scene_new, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
- BKE_libblock_free(bmain, scene);
- RNA_POINTER_INVALIDATE(scene_ptr);
+ rna_Main_ID_remove(bmain, reports, scene_ptr, do_unlink);
}
else {
BKE_reportf(reports, RPT_ERROR, "Scene '%s' is the last, cannot be removed", scene->id.name + 2);
@@ -222,38 +230,12 @@ static Object *rna_Main_objects_new(Main *bmain, ReportList *reports, const char
return ob;
}
-static void rna_Main_objects_remove(Main *bmain, ReportList *reports, PointerRNA *object_ptr)
-{
- Object *object = object_ptr->data;
- if (ID_REAL_USERS(object) <= 0) {
- BKE_libblock_unlink(bmain, object, false);
- BKE_libblock_free(bmain, object);
- RNA_POINTER_INVALIDATE(object_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Object '%s' must have zero users to be removed, found %d",
- object->id.name + 2, ID_REAL_USERS(object));
- }
-}
-
static Material *rna_Main_materials_new(Main *bmain, const char *name)
{
ID *id = (ID *)BKE_material_add(bmain, name);
id_us_min(id);
return (Material *)id;
}
-static void rna_Main_materials_remove(Main *bmain, ReportList *reports, PointerRNA *material_ptr)
-{
- Material *material = material_ptr->data;
- if (ID_REAL_USERS(material) <= 0) {
- BKE_libblock_free(bmain, material);
- RNA_POINTER_INVALIDATE(material_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Material '%s' must have zero users to be removed, found %d",
- material->id.name + 2, ID_REAL_USERS(material));
- }
-}
static EnumPropertyItem *rna_Main_nodetree_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
{
@@ -271,18 +253,6 @@ static struct bNodeTree *rna_Main_nodetree_new(Main *bmain, const char *name, in
else
return NULL;
}
-static void rna_Main_nodetree_remove(Main *bmain, ReportList *reports, PointerRNA *ntree_ptr)
-{
- bNodeTree *ntree = ntree_ptr->data;
- if (ID_REAL_USERS(ntree) <= 0) {
- BKE_libblock_free(bmain, ntree);
- RNA_POINTER_INVALIDATE(ntree_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Node tree '%s' must have zero users to be removed, found %d",
- ntree->id.name + 2, ID_REAL_USERS(ntree));
- }
-}
static Mesh *rna_Main_meshes_new(Main *bmain, const char *name)
{
@@ -312,19 +282,6 @@ Mesh *rna_Main_meshes_new_from_object(
return BKE_mesh_new_from_object(bmain, sce, ob, apply_modifiers, settings, calc_tessface, calc_undeformed);
}
-static void rna_Main_meshes_remove(Main *bmain, ReportList *reports, PointerRNA *mesh_ptr)
-{
- Mesh *mesh = mesh_ptr->data;
- if (ID_REAL_USERS(mesh) <= 0) {
- BKE_libblock_free(bmain, mesh);
- RNA_POINTER_INVALIDATE(mesh_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Mesh '%s' must have zero users to be removed, found %d",
- mesh->id.name + 2, ID_REAL_USERS(mesh));
- }
-}
-
static Lamp *rna_Main_lamps_new(Main *bmain, const char *name, int type)
{
Lamp *lamp = BKE_lamp_add(bmain, name);
@@ -332,18 +289,6 @@ static Lamp *rna_Main_lamps_new(Main *bmain, const char *name, int type)
id_us_min(&lamp->id);
return lamp;
}
-static void rna_Main_lamps_remove(Main *bmain, ReportList *reports, PointerRNA *lamp_ptr)
-{
- Lamp *lamp = lamp_ptr->data;
- if (ID_REAL_USERS(lamp) <= 0) {
- BKE_libblock_free(bmain, lamp);
- RNA_POINTER_INVALIDATE(lamp_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Lamp '%s' must have zero users to be removed, found %d",
- lamp->id.name + 2, ID_REAL_USERS(lamp));
- }
-}
static Image *rna_Main_images_new(Main *bmain, const char *name, int width, int height, int alpha, int float_buffer, int stereo3d)
{
@@ -372,18 +317,6 @@ static Image *rna_Main_images_load(Main *bmain, ReportList *reports, const char
id_us_min((ID *)ima);
return ima;
}
-static void rna_Main_images_remove(Main *bmain, ReportList *reports, PointerRNA *image_ptr)
-{
- Image *image = image_ptr->data;
- if (ID_REAL_USERS(image) <= 0) {
- BKE_libblock_free(bmain, image);
- RNA_POINTER_INVALIDATE(image_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Image '%s' must have zero users to be removed, found %d",
- image->id.name + 2, ID_REAL_USERS(image));
- }
-}
static Lattice *rna_Main_lattices_new(Main *bmain, const char *name)
{
@@ -391,18 +324,6 @@ static Lattice *rna_Main_lattices_new(Main *bmain, const char *name)
id_us_min(&lt->id);
return lt;
}
-static void rna_Main_lattices_remove(Main *bmain, ReportList *reports, PointerRNA *lt_ptr)
-{
- Lattice *lt = lt_ptr->data;
- if (ID_REAL_USERS(lt) <= 0) {
- BKE_libblock_free(bmain, lt);
- RNA_POINTER_INVALIDATE(lt_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Lattice '%s' must have zero users to be removed, found %d",
- lt->id.name + 2, ID_REAL_USERS(lt));
- }
-}
static Curve *rna_Main_curves_new(Main *bmain, const char *name, int type)
{
@@ -410,18 +331,6 @@ static Curve *rna_Main_curves_new(Main *bmain, const char *name, int type)
id_us_min(&cu->id);
return cu;
}
-static void rna_Main_curves_remove(Main *bmain, ReportList *reports, PointerRNA *cu_ptr)
-{
- Curve *cu = cu_ptr->data;
- if (ID_REAL_USERS(cu) <= 0) {
- BKE_libblock_free(bmain, cu);
- RNA_POINTER_INVALIDATE(cu_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Curve '%s' must have zero users to be removed, found %d",
- cu->id.name + 2, ID_REAL_USERS(cu));
- }
-}
static MetaBall *rna_Main_metaballs_new(Main *bmain, const char *name)
{
@@ -429,18 +338,6 @@ static MetaBall *rna_Main_metaballs_new(Main *bmain, const char *name)
id_us_min(&mb->id);
return mb;
}
-static void rna_Main_metaballs_remove(Main *bmain, ReportList *reports, PointerRNA *mb_ptr)
-{
- MetaBall *mb = mb_ptr->data;
- if (ID_REAL_USERS(mb) <= 0) {
- BKE_libblock_free(bmain, mb);
- RNA_POINTER_INVALIDATE(mb_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Metaball '%s' must have zero users to be removed, found %d",
- mb->id.name + 2, ID_REAL_USERS(mb));
- }
-}
static VFont *rna_Main_fonts_load(Main *bmain, ReportList *reports, const char *filepath, int check_existing)
{
@@ -462,18 +359,6 @@ static VFont *rna_Main_fonts_load(Main *bmain, ReportList *reports, const char *
return font;
}
-static void rna_Main_fonts_remove(Main *bmain, ReportList *reports, PointerRNA *vfont_ptr)
-{
- VFont *vfont = vfont_ptr->data;
- if (ID_REAL_USERS(vfont) <= 0) {
- BKE_libblock_free(bmain, vfont);
- RNA_POINTER_INVALIDATE(vfont_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Font '%s' must have zero users to be removed, found %d",
- vfont->id.name + 2, ID_REAL_USERS(vfont));
- }
-}
static Tex *rna_Main_textures_new(Main *bmain, const char *name, int type)
{
@@ -482,18 +367,6 @@ static Tex *rna_Main_textures_new(Main *bmain, const char *name, int type)
id_us_min(&tex->id);
return tex;
}
-static void rna_Main_textures_remove(Main *bmain, ReportList *reports, PointerRNA *tex_ptr)
-{
- Tex *tex = tex_ptr->data;
- if (ID_REAL_USERS(tex) <= 0) {
- BKE_libblock_free(bmain, tex);
- RNA_POINTER_INVALIDATE(tex_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Texture '%s' must have zero users to be removed, found %d",
- tex->id.name + 2, ID_REAL_USERS(tex));
- }
-}
static Brush *rna_Main_brushes_new(Main *bmain, const char *name, int mode)
{
@@ -502,50 +375,17 @@ static Brush *rna_Main_brushes_new(Main *bmain, const char *name, int mode)
return brush;
}
-static void rna_Main_brushes_remove(Main *bmain, ReportList *reports, PointerRNA *brush_ptr)
-{
- Brush *brush = brush_ptr->data;
- if (ID_REAL_USERS(brush) <= 0) {
- BKE_brush_unlink(bmain, brush);
- BKE_libblock_free(bmain, brush);
- RNA_POINTER_INVALIDATE(brush_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Brush '%s' must have zero users to be removed, found %d",
- brush->id.name + 2, ID_REAL_USERS(brush));
- }
-}
-
static World *rna_Main_worlds_new(Main *bmain, const char *name)
{
World *world = add_world(bmain, name);
id_us_min(&world->id);
return world;
}
-static void rna_Main_worlds_remove(Main *bmain, ReportList *reports, PointerRNA *world_ptr)
-{
- Group *world = world_ptr->data;
- if (ID_REAL_USERS(world) <= 0) {
- BKE_libblock_free(bmain, world);
- RNA_POINTER_INVALIDATE(world_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "World '%s' must have zero users to be removed, found %d",
- world->id.name + 2, ID_REAL_USERS(world));
- }
-}
static Group *rna_Main_groups_new(Main *bmain, const char *name)
{
return BKE_group_add(bmain, name);
}
-static void rna_Main_groups_remove(Main *bmain, PointerRNA *group_ptr)
-{
- Group *group = group_ptr->data;
- BKE_libblock_unlink(bmain, group, false);
- BKE_libblock_free(bmain, group);
- RNA_POINTER_INVALIDATE(group_ptr);
-}
static Speaker *rna_Main_speakers_new(Main *bmain, const char *name)
{
@@ -553,18 +393,6 @@ static Speaker *rna_Main_speakers_new(Main *bmain, const char *name)
id_us_min(&speaker->id);
return speaker;
}
-static void rna_Main_speakers_remove(Main *bmain, ReportList *reports, PointerRNA *speaker_ptr)
-{
- Speaker *speaker = speaker_ptr->data;
- if (ID_REAL_USERS(speaker) <= 0) {
- BKE_libblock_free(bmain, speaker);
- RNA_POINTER_INVALIDATE(speaker_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Speaker '%s' must have zero users to be removed, found %d",
- speaker->id.name + 2, ID_REAL_USERS(speaker));
- }
-}
static bSound *rna_Main_sounds_load(Main *bmain, const char *name, int check_existing)
{
@@ -580,30 +408,11 @@ static bSound *rna_Main_sounds_load(Main *bmain, const char *name, int check_exi
id_us_min(&sound->id);
return sound;
}
-static void rna_Main_sounds_remove(Main *bmain, ReportList *reports, PointerRNA *sound_ptr)
-{
- Speaker *sound = sound_ptr->data;
- if (ID_REAL_USERS(sound) <= 0) {
- BKE_libblock_free(bmain, sound);
- RNA_POINTER_INVALIDATE(sound_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Sound '%s' must have zero users to be removed, found %d",
- sound->id.name + 2, ID_REAL_USERS(sound));
- }
-}
static Text *rna_Main_texts_new(Main *bmain, const char *name)
{
return BKE_text_add(bmain, name);
}
-static void rna_Main_texts_remove(Main *bmain, PointerRNA *text_ptr)
-{
- Text *text = text_ptr->data;
- BKE_text_unlink(bmain, text);
- BKE_libblock_free(bmain, text);
- RNA_POINTER_INVALIDATE(text_ptr);
-}
static Text *rna_Main_texts_load(Main *bmain, ReportList *reports, const char *filepath, int is_internal)
{
@@ -625,37 +434,12 @@ static bArmature *rna_Main_armatures_new(Main *bmain, const char *name)
id_us_min(&arm->id);
return arm;
}
-static void rna_Main_armatures_remove(Main *bmain, ReportList *reports, PointerRNA *arm_ptr)
-{
- bArmature *arm = arm_ptr->data;
- if (ID_REAL_USERS(arm) <= 0) {
- BKE_libblock_free(bmain, arm);
- RNA_POINTER_INVALIDATE(arm_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Armature '%s' must have zero users to be removed, found %d",
- arm->id.name + 2, ID_REAL_USERS(arm));
- }
-}
static bAction *rna_Main_actions_new(Main *bmain, const char *name)
{
bAction *act = add_empty_action(bmain, name);
id_fake_user_clear(&act->id);
return act;
-}
-static void rna_Main_actions_remove(Main *bmain, ReportList *reports, PointerRNA *act_ptr)
-{
- bAction *act = act_ptr->data;
- if (ID_REAL_USERS(act) <= 0) {
- BKE_libblock_free(bmain, act);
- RNA_POINTER_INVALIDATE(act_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Action '%s' must have zero users to be removed, found %d",
- act->id.name + 2, ID_REAL_USERS(act));
- }
-}
static Palette *rna_Main_palettes_new(Main *bmain, const char *name)
{
@@ -663,18 +447,6 @@ static Palette *rna_Main_palettes_new(Main *bmain, const char *name)
id_us_min(&palette->id);
return (Palette *)palette;
}
-static void rna_Main_palettes_remove(Main *bmain, ReportList *reports, PointerRNA *palette_ptr)
-{
- Palette *palette = palette_ptr->data;
- if (ID_REAL_USERS(palette) <= 0) {
- BKE_libblock_free(bmain, palette);
- RNA_POINTER_INVALIDATE(palette_ptr);
- }
- else {
- BKE_reportf(reports, RPT_ERROR, "Palette settings '%s' must have zero users to be removed, found %d",
- palette->id.name + 2, ID_REAL_USERS(palette));
- }
-}
static MovieClip *rna_Main_movieclip_load(Main *bmain, ReportList *reports, const char *filepath, int check_existing)
{
@@ -697,14 +469,6 @@ static MovieClip *rna_Main_movieclip_load(Main *bmain, ReportList *reports, cons
return clip;
}
-static void rna_Main_movieclips_remove(Main *bmain, PointerRNA *clip_ptr)
-{
- MovieClip *clip = clip_ptr->data;
- BKE_movieclip_unlink(bmain, clip);
- BKE_libblock_free(bmain, clip);
- RNA_POINTER_INVALIDATE(clip_ptr);
-}
-
static Mask *rna_Main_mask_new(Main *bmain, const char *name)
{
Mask *mask;
@@ -714,26 +478,6 @@ static Mask *rna_Main_mask_new(Main *bmain, const char *name)
return mask;
}
-static void rna_Main_masks_remove(Main *bmain, PointerRNA *mask_ptr)
-{
- Mask *mask = mask_ptr->data;
- BKE_libblock_free(bmain, mask);
- RNA_POINTER_INVALIDATE(mask_ptr);
-}
-
-static void rna_Main_grease_pencil_remove(Main *bmain, ReportList *reports, PointerRNA *gpd_ptr)
-{
- bGPdata *gpd = gpd_ptr->data;
- if (ID_REAL_USERS(gpd) <= 0) {
- BKE_gpencil_free(gpd);
- BKE_libblock_free(bmain, gpd);
- RNA_POINTER_INVALIDATE(gpd_ptr);
- }
- else
- BKE_reportf(reports, RPT_ERROR, "Grease pencil '%s' must have zero users to be removed, found %d",
- gpd->id.name + 2, ID_REAL_USERS(gpd));
-}
-
static FreestyleLineStyle *rna_Main_linestyles_new(Main *bmain, const char *name)
{
FreestyleLineStyle *linestyle = BKE_linestyle_new(bmain, name);
@@ -741,17 +485,6 @@ static FreestyleLineStyle *rna_Main_linestyles_new(Main *bmain, const char *name
return linestyle;
}
-static void rna_Main_linestyles_remove(Main *bmain, ReportList *reports, FreestyleLineStyle *linestyle)
-{
- if (ID_REAL_USERS(linestyle) <= 0)
- BKE_libblock_free(bmain, linestyle);
- else
- BKE_reportf(reports, RPT_ERROR, "Line style '%s' must have zero users to be removed, found %d",
- linestyle->id.name + 2, ID_REAL_USERS(linestyle));
-
- /* XXX python now has invalid pointer? */
-}
-
/* tag and is_updated functions, all the same */
#define RNA_MAIN_ID_TAG_FUNCS_DEF(_func_name, _listbase_name, _id_type) \
static void rna_Main_##_func_name##_tag(Main *bmain, int value) { \
@@ -833,12 +566,15 @@ void RNA_def_main_cameras(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "camera", "Camera", "", "New camera data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_cameras_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a camera from the current blendfile");
parm = RNA_def_pointer(func, "camera", "Camera", "", "Camera to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "",
+ "Unlink all usages of this camera before deleting it "
+ "(WARNING: will also delete objects instancing that camera data)");
func = RNA_def_function(srna, "tag", "rna_Main_cameras_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -875,6 +611,7 @@ void RNA_def_main_scenes(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this scene before deleting it");
func = RNA_def_function(srna, "tag", "rna_Main_scenes_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -909,12 +646,13 @@ void RNA_def_main_objects(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "object", "Object", "", "New object data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_objects_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_ui_description(func, "Remove a object from the current blendfile");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "object", "Object", "", "Object to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this object before deleting it");
func = RNA_def_function(srna, "tag", "rna_Main_objects_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -945,12 +683,13 @@ void RNA_def_main_materials(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "material", "Material", "", "New material data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_materials_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a material from the current blendfile");
parm = RNA_def_pointer(func, "material", "Material", "", "Material to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this material before deleting it");
func = RNA_def_function(srna, "tag", "rna_Main_materials_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -988,12 +727,13 @@ void RNA_def_main_node_groups(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "tree", "NodeTree", "", "New node tree data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_nodetree_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a node tree from the current blendfile");
parm = RNA_def_pointer(func, "tree", "NodeTree", "", "Node tree to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this node tree before deleting it");
func = RNA_def_function(srna, "tag", "rna_Main_node_groups_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1046,12 +786,15 @@ void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop)
"Mesh created from object, remove it if it is only used for export");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_meshes_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a mesh from the current blendfile");
parm = RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "",
+ "Unlink all usages of this mesh before deleting it "
+ "(WARNING: will also delete objects instancing that mesh data)");
func = RNA_def_function(srna, "tag", "rna_Main_meshes_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1083,12 +826,15 @@ void RNA_def_main_lamps(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "lamp", "Lamp", "", "New lamp data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_lamps_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a lamp from the current blendfile");
parm = RNA_def_pointer(func, "lamp", "Lamp", "", "Lamp to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "",
+ "Unlink all usages of this lamp before deleting it "
+ "(WARNING: will also delete objects instancing that lamp data)");
func = RNA_def_function(srna, "tag", "rna_Main_lamps_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1198,12 +944,13 @@ void RNA_def_main_images(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "image", "Image", "", "New image data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_images_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove an image from the current blendfile");
parm = RNA_def_pointer(func, "image", "Image", "", "Image to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this image before deleting it");
func = RNA_def_function(srna, "tag", "rna_Main_images_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1234,12 +981,15 @@ void RNA_def_main_lattices(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "lattice", "Lattice", "", "New lattices data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_lattices_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a lattice from the current blendfile");
parm = RNA_def_pointer(func, "lattice", "Lattice", "", "Lattice to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "",
+ "Unlink all usages of this lattice before deleting it "
+ "(WARNING: will also delete objects instancing that lattice data)");
func = RNA_def_function(srna, "tag", "rna_Main_lattices_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1271,12 +1021,15 @@ void RNA_def_main_curves(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "curve", "Curve", "", "New curve data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_curves_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a curve from the current blendfile");
parm = RNA_def_pointer(func, "curve", "Curve", "", "Curve to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "",
+ "Unlink all usages of this curve before deleting it "
+ "(WARNING: will also delete objects instancing that curve data)");
func = RNA_def_function(srna, "tag", "rna_Main_curves_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1306,12 +1059,15 @@ void RNA_def_main_metaballs(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "metaball", "MetaBall", "", "New metaball data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_metaballs_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a metaball from the current blendfile");
parm = RNA_def_pointer(func, "metaball", "MetaBall", "", "Metaball to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "",
+ "Unlink all usages of this metaball before deleting it "
+ "(WARNING: will also delete objects instancing that metaball data)");
func = RNA_def_function(srna, "tag", "rna_Main_metaballs_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1343,12 +1099,13 @@ void RNA_def_main_fonts(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "vfont", "VectorFont", "", "New font data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_fonts_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a font from the current blendfile");
parm = RNA_def_pointer(func, "vfont", "VectorFont", "", "Font to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this font before deleting it");
func = RNA_def_function(srna, "tag", "rna_Main_fonts_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1380,12 +1137,13 @@ void RNA_def_main_textures(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "texture", "Texture", "", "New texture data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_textures_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a texture from the current blendfile");
parm = RNA_def_pointer(func, "texture", "Texture", "", "Texture to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this texture before deleting it");
func = RNA_def_function(srna, "tag", "rna_Main_textures_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1416,12 +1174,13 @@ void RNA_def_main_brushes(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "brush", "Brush", "", "New brush data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_brushes_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a brush from the current blendfile");
parm = RNA_def_pointer(func, "brush", "Brush", "", "Brush to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this brush before deleting it");
func = RNA_def_function(srna, "tag", "rna_Main_brushes_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1452,12 +1211,13 @@ void RNA_def_main_worlds(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "world", "World", "", "New world data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_worlds_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a world from the current blendfile");
parm = RNA_def_pointer(func, "world", "World", "", "World to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this world before deleting it");
func = RNA_def_function(srna, "tag", "rna_Main_worlds_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1488,11 +1248,13 @@ void RNA_def_main_groups(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "group", "Group", "", "New group data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_groups_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_ui_description(func, "Remove a group from the current blendfile");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "group", "Group", "", "Group to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this group before deleting it");
func = RNA_def_function(srna, "tag", "rna_Main_groups_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1523,12 +1285,15 @@ void RNA_def_main_speakers(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "speaker", "Speaker", "", "New speaker data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_speakers_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a speaker from the current blendfile");
parm = RNA_def_pointer(func, "speaker", "Speaker", "", "Speaker to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "",
+ "Unlink all usages of this speaker before deleting it "
+ "(WARNING: will also delete objects instancing that speaker data)");
func = RNA_def_function(srna, "tag", "rna_Main_speakers_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1559,11 +1324,13 @@ void RNA_def_main_texts(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "text", "Text", "", "New text data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_texts_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_ui_description(func, "Remove a text from the current blendfile");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "text", "Text", "", "Text to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this text before deleting it");
/* load func */
func = RNA_def_function(srna, "load", "rna_Main_texts_load");
@@ -1607,12 +1374,13 @@ void RNA_def_main_sounds(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "sound", "Sound", "", "New text data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_sounds_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a sound from the current blendfile");
parm = RNA_def_pointer(func, "sound", "Sound", "", "Sound to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this sound before deleting it");
func = RNA_def_function(srna, "tag", "rna_Main_sounds_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1643,12 +1411,15 @@ void RNA_def_main_armatures(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "armature", "Armature", "", "New armature data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_armatures_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a armature from the current blendfile");
parm = RNA_def_pointer(func, "armature", "Armature", "", "Armature to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "",
+ "Unlink all usages of this armature before deleting it "
+ "(WARNING: will also delete objects instancing that armature data)");
func = RNA_def_function(srna, "tag", "rna_Main_armatures_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1678,12 +1449,13 @@ void RNA_def_main_actions(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "action", "Action", "", "New action data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_actions_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a action from the current blendfile");
parm = RNA_def_pointer(func, "action", "Action", "", "Action to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this action before deleting it");
func = RNA_def_function(srna, "tag", "rna_Main_actions_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1713,12 +1485,13 @@ void RNA_def_main_palettes(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "palette", "Palette", "", "New palette data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_palettes_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a palette from the current blendfile");
parm = RNA_def_pointer(func, "palette", "Palette", "", "Palette to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this palette before deleting it");
func = RNA_def_function(srna, "tag", "rna_Main_palettes_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
@@ -1752,12 +1525,13 @@ void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "grease_pencil", "GreasePencil", "", "New grease pencil data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_grease_pencil_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a grease pencil instance from the current blendfile");
parm = RNA_def_pointer(func, "grease_pencil", "GreasePencil", "", "Grease Pencil to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this grease pencil before deleting it");
prop = RNA_def_property(srna, "is_updated", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -1780,11 +1554,13 @@ void RNA_def_main_movieclips(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_boolean(func, "value", 0, "Value", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
- func = RNA_def_function(srna, "remove", "rna_Main_movieclips_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a movie clip from the current blendfile.");
parm = RNA_def_pointer(func, "clip", "MovieClip", "", "Movie clip to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this movie clip before deleting it");
/* load func */
func = RNA_def_function(srna, "load", "rna_Main_movieclip_load");
@@ -1830,11 +1606,13 @@ void RNA_def_main_masks(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_return(func, parm);
/* remove func */
- func = RNA_def_function(srna, "remove", "rna_Main_masks_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a masks from the current blendfile.");
parm = RNA_def_pointer(func, "mask", "Mask", "", "Mask to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this mask before deleting it");
prop = RNA_def_property(srna, "is_updated", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -1865,11 +1643,13 @@ void RNA_def_main_linestyles(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "linestyle", "FreestyleLineStyle", "", "New line style data-block");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Main_linestyles_remove");
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a line style instance from the current blendfile");
parm = RNA_def_pointer(func, "linestyle", "FreestyleLineStyle", "", "Line style to remove");
- RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of this line style before deleting it");
prop = RNA_def_property(srna, "is_updated", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 1ab52aa45d3..e5dc613a0cd 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1812,6 +1812,12 @@ static void rna_def_modifier_hook(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Hook Center", "");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "matrix_inverse", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_float_sdna(prop, NULL, "parentinv");
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(prop, "Matrix", "Reverse the transformation between this object and its target");
+ RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Parent Object for hook, also recalculates and clears offset");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index dffdd7fe6c7..95f258e95f4 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -3162,12 +3162,14 @@ static EnumPropertyItem node_glossy_items[] = {
{SHD_GLOSSY_BECKMANN, "BECKMANN", 0, "Beckmann", ""},
{SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""},
{SHD_GLOSSY_ASHIKHMIN_SHIRLEY, "ASHIKHMIN_SHIRLEY", 0, "Ashikhmin-Shirley", ""},
+ {SHD_GLOSSY_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", ""},
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem node_anisotropic_items[] = {
{SHD_GLOSSY_BECKMANN, "BECKMANN", 0, "Beckmann", ""},
{SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""},
+ {SHD_GLOSSY_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", ""},
{SHD_GLOSSY_ASHIKHMIN_SHIRLEY, "ASHIKHMIN_SHIRLEY", 0, "Ashikhmin-Shirley", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -3176,6 +3178,14 @@ static EnumPropertyItem node_glass_items[] = {
{SHD_GLOSSY_SHARP, "SHARP", 0, "Sharp", ""},
{SHD_GLOSSY_BECKMANN, "BECKMANN", 0, "Beckmann", ""},
{SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""},
+ {SHD_GLOSSY_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static EnumPropertyItem node_refraction_items[] = {
+ {SHD_GLOSSY_SHARP, "SHARP", 0, "Sharp", ""},
+ {SHD_GLOSSY_BECKMANN, "BECKMANN", 0, "Beckmann", ""},
+ {SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -4120,6 +4130,17 @@ static void def_glass(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_refraction(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "distribution", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, node_refraction_items);
+ RNA_def_property_ui_text(prop, "Distribution", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
static void def_anisotropic(StructRNA *srna)
{
PropertyRNA *prop;
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 0b8717fc982..559d7e82076 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -1793,7 +1793,7 @@ static void rna_FileBrowser_FSMenu_active_range(
static void rna_FileBrowser_FSMenu_active_update(struct bContext *C, PointerRNA *UNUSED(ptr))
{
- ED_file_change_dir(C, true);
+ ED_file_change_dir(C);
}
static int rna_FileBrowser_FSMenuSystem_active_get(PointerRNA *ptr)
@@ -2437,14 +2437,16 @@ static void rna_def_space_view3d(BlenderRNA *brna)
prop = RNA_def_property(srna, "clip_start", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "near");
- RNA_def_property_range(prop, 0.001f, FLT_MAX);
+ RNA_def_property_range(prop, 1e-6f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
RNA_def_property_float_default(prop, 0.1f);
RNA_def_property_ui_text(prop, "Clip Start", "3D View near clipping distance (perspective view only)");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "clip_end", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "far");
- RNA_def_property_range(prop, 1.0f, FLT_MAX);
+ RNA_def_property_range(prop, 1e-6f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
RNA_def_property_float_default(prop, 1000.0f);
RNA_def_property_ui_text(prop, "Clip End", "3D View far clipping distance");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 9e1a0c926fa..171d5313c1d 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -82,7 +82,7 @@ DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, def_anisotropic, "BS
DefNode( ShaderNode, SH_NODE_BSDF_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_GLASS, def_glass, "BSDF_GLASS", BsdfGlass, "Glass BSDF", "" )
-DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_glass, "BSDF_REFRACTION", BsdfRefraction, "Refraction BSDF", "" )
+DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_refraction, "BSDF_REFRACTION", BsdfRefraction, "Refraction BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_TRANSLUCENT, 0, "BSDF_TRANSLUCENT", BsdfTranslucent, "Translucent BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_TRANSPARENT, 0, "BSDF_TRANSPARENT", BsdfTransparent, "Transparent BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_VELVET, 0, "BSDF_VELVET", BsdfVelvet, "Velvet BSDF", "" )
diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c
index d6c57f4c302..eaa96e6243c 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -264,6 +264,11 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
if ((reports->flag & RPT_FREE) == 0) {
MEM_freeN(reports);
}
+ else {
+ /* The WM is now responsible for running the modal operator,
+ * show reports in the info window. */
+ reports->flag &= ~RPT_OP_HOLD;
+ }
}
WM_operator_properties_free(&ptr);
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 69ae7433fff..af6ac4a8fbf 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -1672,7 +1672,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
}
}
- if (dl->bevelSplitFlag || timeoffset==0) {
+ if (dl->bevel_split || timeoffset == 0) {
const int startvlak= obr->totvlak;
for (a=0; a<dl->parts; a++) {
@@ -1712,10 +1712,15 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
}
}
- if (dl->bevelSplitFlag) {
- for (a=0; a<dl->parts-1+!!(dl->flag&DL_CYCL_V); a++)
- if (dl->bevelSplitFlag[a>>5]&(1<<(a&0x1F)))
- split_v_renderfaces(obr, startvlak, startvert, dl->parts, dl->nr, a, dl->flag&DL_CYCL_V, dl->flag&DL_CYCL_U);
+ if (dl->bevel_split) {
+ for (a = 0; a < dl->parts - 1 + !!(dl->flag & DL_CYCL_V); a++) {
+ if (BLI_BITMAP_TEST(dl->bevel_split, a)) {
+ split_v_renderfaces(
+ obr, startvlak, startvert, dl->parts, dl->nr, a,
+ /* intentionally swap (v, u) --> (u, v) */
+ dl->flag & DL_CYCL_V, dl->flag & DL_CYCL_U);
+ }
+ }
}
/* vertex normals */
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 9bb2462a4e9..7a247d9791b 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -413,12 +413,6 @@ void wmOrtho2 (float x1, float x2, float y1, float y2);
void wmOrtho2_region_pixelspace(const struct ARegion *ar);
void wmOrtho2_pixelspace(const float x, const float y);
- /* utilities */
-void WM_framebuffer_index_set(int index);
-void WM_framebuffer_index_get(int index, int *r_col);
-int WM_framebuffer_to_index(unsigned int col);
-void WM_framebuffer_to_index_array(unsigned int *col, const unsigned int size);
-
/* threaded Jobs Manager */
enum {
WM_JOB_PRIORITY = (1 << 0),
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index a1ca89c6a8c..9d1083bbf63 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -141,6 +141,11 @@ static void wm_free_reports(bContext *C)
BKE_reports_clear(reports);
}
+static void wm_undo_kill_callback(bContext *C)
+{
+ WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C));
+}
+
bool wm_start_with_console = false; /* used in creator.c */
/* only called once, for startup */
@@ -159,6 +164,8 @@ void WM_init(bContext *C, int argc, const char **argv)
WM_menutype_init();
WM_uilisttype_init();
+ BKE_undo_callback_wm_kill_jobs_set(wm_undo_kill_callback);
+
BKE_library_callback_free_window_manager_set(wm_close_and_free); /* library.c */
BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference); /* library.c */
BKE_library_callback_remap_editor_id_reference_set(WM_main_remap_editor_id_reference); /* library.c */
@@ -579,6 +586,8 @@ void WM_exit_ext(bContext *C, const bool do_python)
BLI_threadapi_exit();
+ BKE_blender_atexit();
+
if (MEM_get_memory_blocks_in_use() != 0) {
size_t mem_in_use = MEM_get_memory_in_use() + MEM_get_memory_in_use();
printf("Error: Not freed memory blocks: %u, total unfreed memory %f MB\n",
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index a51648290db..8968c2a4543 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -4208,7 +4208,8 @@ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_assign(keymap, "MASK_OT_select_circle");
WM_modalkeymap_assign(keymap, "NODE_OT_select_circle");
WM_modalkeymap_assign(keymap, "GPENCIL_OT_select_circle");
- WM_modalkeymap_assign(keymap, "GRAPH_OT_select_circle");
+ WM_modalkeymap_assign(keymap, "GRAPH_OT_select_circle");
+ WM_modalkeymap_assign(keymap, "ACTION_OT_select_circle");
}
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index 6526d419914..458ac4a121a 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -378,149 +378,5 @@ void wmOrtho2_pixelspace(const float x, const float y)
wmOrtho2_offset(x, y, -GLA_PIXEL_OFS);
}
-/* *************************** Framebuffer color depth, for selection codes ********************** */
-
-#ifdef __APPLE__
-
-/* apple seems to round colors to below and up on some configs */
-
-unsigned int index_to_framebuffer(int index)
-{
- unsigned int i = index;
-
- switch (GPU_color_depth()) {
- case 12:
- i = ((i & 0xF00) << 12) + ((i & 0xF0) << 8) + ((i & 0xF) << 4);
- /* sometimes dithering subtracts! */
- i |= 0x070707;
- break;
- case 15:
- case 16:
- i = ((i & 0x7C00) << 9) + ((i & 0x3E0) << 6) + ((i & 0x1F) << 3);
- i |= 0x030303;
- break;
- case 24:
- break;
- default: /* 18 bits... */
- i = ((i & 0x3F000) << 6) + ((i & 0xFC0) << 4) + ((i & 0x3F) << 2);
- i |= 0x010101;
- break;
- }
-
- return i;
-}
-
-#else
-
-/* this is the old method as being in use for ages.... seems to work? colors are rounded to lower values */
-
-unsigned int index_to_framebuffer(int index)
-{
- unsigned int i = index;
-
- switch (GPU_color_depth()) {
- case 8:
- i = ((i & 48) << 18) + ((i & 12) << 12) + ((i & 3) << 6);
- i |= 0x3F3F3F;
- break;
- case 12:
- i = ((i & 0xF00) << 12) + ((i & 0xF0) << 8) + ((i & 0xF) << 4);
- /* sometimes dithering subtracts! */
- i |= 0x0F0F0F;
- break;
- case 15:
- case 16:
- i = ((i & 0x7C00) << 9) + ((i & 0x3E0) << 6) + ((i & 0x1F) << 3);
- i |= 0x070707;
- break;
- case 24:
- break;
- default: /* 18 bits... */
- i = ((i & 0x3F000) << 6) + ((i & 0xFC0) << 4) + ((i & 0x3F) << 2);
- i |= 0x030303;
- break;
- }
-
- return i;
-}
-
-#endif
-
-void WM_framebuffer_index_set(int index)
-{
- const int col = index_to_framebuffer(index);
- cpack(col);
-}
-
-void WM_framebuffer_index_get(int index, int *r_col)
-{
- const int col = index_to_framebuffer(index);
- char *c_col = (char *)r_col;
- c_col[0] = (col & 0xFF); /* red */
- c_col[1] = ((col >> 8) & 0xFF); /* green */
- c_col[2] = ((col >> 16) & 0xFF); /* blue */
- c_col[3] = 0xFF; /* alpha */
-}
-
-
-
-#define INDEX_FROM_BUF_8(col) (((col & 0xC00000) >> 18) + ((col & 0xC000) >> 12) + ((col & 0xC0) >> 6))
-#define INDEX_FROM_BUF_12(col) (((col & 0xF00000) >> 12) + ((col & 0xF000) >> 8) + ((col & 0xF0) >> 4))
-#define INDEX_FROM_BUF_15_16(col) (((col & 0xF80000) >> 9) + ((col & 0xF800) >> 6) + ((col & 0xF8) >> 3))
-#define INDEX_FROM_BUF_18(col) (((col & 0xFC0000) >> 6) + ((col & 0xFC00) >> 4) + ((col & 0xFC) >> 2))
-#define INDEX_FROM_BUF_24(col) (col & 0xFFFFFF)
-
-int WM_framebuffer_to_index(unsigned int col)
-{
- if (col == 0) {
- return 0;
- }
-
- switch (GPU_color_depth()) {
- case 8: return INDEX_FROM_BUF_8(col);
- case 12: return INDEX_FROM_BUF_12(col);
- case 15:
- case 16: return INDEX_FROM_BUF_15_16(col);
- case 24: return INDEX_FROM_BUF_24(col);
- default: return INDEX_FROM_BUF_18(col);
- }
-}
-
-void WM_framebuffer_to_index_array(unsigned int *col, const unsigned int size)
-{
-#define INDEX_BUF_ARRAY(INDEX_FROM_BUF_BITS) \
- for (i = size; i--; col++) { \
- if ((c = *col)) { \
- *col = INDEX_FROM_BUF_BITS(c); \
- } \
- } ((void)0)
-
- if (size > 0) {
- unsigned int i, c;
-
- switch (GPU_color_depth()) {
- case 8:
- INDEX_BUF_ARRAY(INDEX_FROM_BUF_8);
- break;
- case 12:
- INDEX_BUF_ARRAY(INDEX_FROM_BUF_12);
- break;
- case 15:
- case 16:
- INDEX_BUF_ARRAY(INDEX_FROM_BUF_15_16);
- break;
- case 24:
- INDEX_BUF_ARRAY(INDEX_FROM_BUF_24);
- break;
- default:
- INDEX_BUF_ARRAY(INDEX_FROM_BUF_18);
- break;
- }
- }
-
-#undef INDEX_BUF_ARRAY
-}
-
-
/* ********** END MY WINDOW ************** */
diff --git a/source/blender/windowmanager/wm_subwindow.h b/source/blender/windowmanager/wm_subwindow.h
index 2a8118a726b..cc9abf87514 100644
--- a/source/blender/windowmanager/wm_subwindow.h
+++ b/source/blender/windowmanager/wm_subwindow.h
@@ -48,7 +48,5 @@ void wm_subwindow_matrix_get(wmWindow *win, int swinid, float mat[4][4]);
void wm_subwindow_rect_get(wmWindow *win, int swinid, struct rcti *r_rect);
void wm_subwindow_rect_set(wmWindow *win, int swinid, const rcti *rect);
-unsigned int index_to_framebuffer(int index);
-
#endif /* __WM_SUBWINDOW_H__ */