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:
authorSergej Reich <sergej.reich@googlemail.com>2013-09-06 12:35:00 +0400
committerSergej Reich <sergej.reich@googlemail.com>2013-09-06 12:35:00 +0400
commit36e6bddb5c155b4ae27a9cd17b4af26bbcdc8dae (patch)
tree025a56b2e71adc77d53a4a33ac17a6cf55d360c2 /source/blender/editors
parentdf3974b6d1c6469ca1a0b8a1c505b09385198780 (diff)
parent63ade11564798e68943ad5d8c82d45771df67677 (diff)
svn merge -r59229:59868 ^/trunk/blender
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c7
-rw-r--r--source/blender/editors/animation/anim_filter.c21
-rw-r--r--source/blender/editors/animation/drivers.c38
-rw-r--r--source/blender/editors/animation/keyframing.c2
-rw-r--r--source/blender/editors/armature/armature_skinning.c5
-rw-r--r--source/blender/editors/armature/meshlaplacian.c2
-rw-r--r--source/blender/editors/armature/reeb.c2
-rw-r--r--source/blender/editors/curve/curve_intern.h1
-rw-r--r--source/blender/editors/curve/curve_ops.c2
-rw-r--r--source/blender/editors/curve/editcurve.c877
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt10
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c13
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c2
-rw-r--r--source/blender/editors/include/ED_clip.h8
-rw-r--r--source/blender/editors/include/ED_curve.h1
-rw-r--r--source/blender/editors/include/ED_keyframing.h1
-rw-r--r--source/blender/editors/include/ED_mask.h2
-rw-r--r--source/blender/editors/include/ED_object.h5
-rw-r--r--source/blender/editors/include/ED_screen_types.h6
-rw-r--r--source/blender/editors/include/ED_uvedit.h2
-rw-r--r--source/blender/editors/include/UI_icons.h10
-rw-r--r--source/blender/editors/include/UI_interface.h33
-rw-r--r--source/blender/editors/include/UI_resources.h3
-rw-r--r--source/blender/editors/include/UI_view2d.h1
-rw-r--r--source/blender/editors/interface/interface.c23
-rw-r--r--source/blender/editors/interface/interface_handlers.c350
-rw-r--r--source/blender/editors/interface/interface_intern.h2
-rw-r--r--source/blender/editors/interface/interface_layout.c19
-rw-r--r--source/blender/editors/interface/interface_regions.c10
-rw-r--r--source/blender/editors/interface/interface_templates.c537
-rw-r--r--source/blender/editors/interface/interface_widgets.c15
-rw-r--r--source/blender/editors/interface/resources.c21
-rw-r--r--source/blender/editors/interface/view2d.c11
-rw-r--r--source/blender/editors/interface/view2d_ops.c17
-rw-r--r--source/blender/editors/io/io_collada.c20
-rw-r--r--source/blender/editors/mask/mask_add.c156
-rw-r--r--source/blender/editors/mask/mask_edit.c53
-rw-r--r--source/blender/editors/mask/mask_intern.h5
-rw-r--r--source/blender/editors/mask/mask_ops.c127
-rw-r--r--source/blender/editors/mask/mask_relationships.c1
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt1
-rw-r--r--source/blender/editors/mesh/editmesh_bisect.c331
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c6
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c252
-rw-r--r--source/blender/editors/mesh/editmesh_path.c3
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c122
-rw-r--r--source/blender/editors/mesh/editmesh_select.c4
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c220
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c2
-rw-r--r--source/blender/editors/mesh/mesh_intern.h2
-rw-r--r--source/blender/editors/mesh/mesh_navmesh.c4
-rw-r--r--source/blender/editors/mesh/mesh_ops.c1
-rw-r--r--source/blender/editors/mesh/meshtools.c3
-rw-r--r--source/blender/editors/metaball/mball_edit.c12
-rw-r--r--source/blender/editors/object/object_add.c14
-rw-r--r--source/blender/editors/object/object_edit.c124
-rw-r--r--source/blender/editors/object/object_modifier.c4
-rw-r--r--source/blender/editors/object/object_relations.c90
-rw-r--r--source/blender/editors/object/object_transform.c21
-rw-r--r--source/blender/editors/object/object_vgroup.c7
-rw-r--r--source/blender/editors/physics/particle_edit.c40
-rw-r--r--source/blender/editors/render/render_internal.c36
-rw-r--r--source/blender/editors/render/render_opengl.c2
-rw-r--r--source/blender/editors/render/render_preview.c7
-rw-r--r--source/blender/editors/screen/area.c2
-rw-r--r--source/blender/editors/screen/glutil.c11
-rw-r--r--source/blender/editors/screen/screen_edit.c22
-rw-r--r--source/blender/editors/screen/screen_ops.c34
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c38
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c35
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c5
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c23
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c136
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c66
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c37
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c15
-rw-r--r--source/blender/editors/space_clip/clip_draw.c47
-rw-r--r--source/blender/editors/space_clip/clip_editor.c33
-rw-r--r--source/blender/editors/space_clip/clip_graph_draw.c6
-rw-r--r--source/blender/editors/space_clip/clip_graph_ops.c33
-rw-r--r--source/blender/editors/space_clip/clip_intern.h2
-rw-r--r--source/blender/editors/space_clip/clip_ops.c65
-rw-r--r--source/blender/editors/space_clip/clip_utils.c15
-rw-r--r--source/blender/editors/space_clip/space_clip.c126
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c42
-rw-r--r--source/blender/editors/space_clip/tracking_select.c28
-rw-r--r--source/blender/editors/space_file/filelist.c34
-rw-r--r--source/blender/editors/space_file/filesel.c56
-rw-r--r--source/blender/editors/space_file/space_file.c7
-rw-r--r--source/blender/editors/space_graph/graph_edit.c36
-rw-r--r--source/blender/editors/space_graph/graph_select.c31
-rw-r--r--source/blender/editors/space_image/image_ops.c38
-rw-r--r--source/blender/editors/space_image/space_image.c8
-rw-r--r--source/blender/editors/space_info/info_stats.c4
-rw-r--r--source/blender/editors/space_logic/logic_window.c10
-rw-r--r--source/blender/editors/space_node/drawnode.c33
-rw-r--r--source/blender/editors/space_node/node_add.c14
-rw-r--r--source/blender/editors/space_node/node_buttons.c6
-rw-r--r--source/blender/editors/space_node/node_draw.c23
-rw-r--r--source/blender/editors/space_node/node_edit.c22
-rw-r--r--source/blender/editors/space_node/node_intern.h5
-rw-r--r--source/blender/editors/space_node/node_ops.c2
-rw-r--r--source/blender/editors/space_node/node_relationships.c42
-rw-r--r--source/blender/editors/space_node/node_select.c15
-rw-r--r--source/blender/editors/space_node/node_view.c54
-rw-r--r--source/blender/editors/space_node/space_node.c8
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c4
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c109
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c3
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c6
-rw-r--r--source/blender/editors/space_sequencer/sequencer_view.c3
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c1
-rw-r--r--source/blender/editors/space_text/text_draw.c22
-rw-r--r--source/blender/editors/space_text/text_intern.h4
-rw-r--r--source/blender/editors/space_text/text_ops.c39
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c18
-rw-r--r--source/blender/editors/space_view3d/drawobject.c85
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c12
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c183
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c22
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h1
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c8
-rw-r--r--source/blender/editors/transform/transform.c45
-rw-r--r--source/blender/editors/transform/transform.h1
-rw-r--r--source/blender/editors/transform/transform_constraints.c8
-rw-r--r--source/blender/editors/transform/transform_conversions.c13
-rw-r--r--source/blender/editors/transform/transform_generics.c34
-rw-r--r--source/blender/editors/transform/transform_snap.c46
-rw-r--r--source/blender/editors/util/crazyspace.c9
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c14
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c8
138 files changed, 4143 insertions, 1587 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 845ad72d7aa..142342997be 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -1828,7 +1828,7 @@ static void *acf_dsmball_setting_ptr(bAnimListElem *ale, int setting, short *typ
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(mb->flag, type);
+ return GET_ACF_FLAG_PTR(mb->flag2, type);
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
@@ -2781,6 +2781,9 @@ static void ANIM_init_channel_typeinfo_data(void)
if (ACF_INIT) {
ACF_INIT = 0;
+ /* NOTE: need to keep the order of these synchronized with the definition of
+ * channel types (eAnim_ChannelType) in ED_anim_api.h
+ */
animchannelTypeInfo[type++] = NULL; /* None */
animchannelTypeInfo[type++] = NULL; /* AnimData */
animchannelTypeInfo[type++] = NULL; /* Special */
@@ -2808,8 +2811,8 @@ static void ANIM_init_channel_typeinfo_data(void)
animchannelTypeInfo[type++] = &ACF_DSMESH; /* Mesh Channel */
animchannelTypeInfo[type++] = &ACF_DSTEX; /* Texture Channel */
animchannelTypeInfo[type++] = &ACF_DSLAT; /* Lattice Channel */
- animchannelTypeInfo[type++] = &ACF_DSSPK; /* Speaker Channel */
animchannelTypeInfo[type++] = &ACF_DSLINESTYLE; /* LineStyle Channel */
+ animchannelTypeInfo[type++] = &ACF_DSSPK; /* Speaker Channel */
animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 91003674524..041a2c2216e 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -1541,10 +1541,16 @@ static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data,
static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
{
SceneRenderLayer *srl;
+ FreestyleLineSet *lineset;
size_t items = 0;
for (srl = sce->r.layers.first; srl; srl = srl->next) {
- FreestyleLineSet *lineset;
+ for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ lineset->linestyle->id.flag |= LIB_DOIT;
+ }
+ }
+
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
/* skip render layers without Freestyle enabled */
if (!(srl->layflag & SCE_LAY_FRS))
@@ -1555,6 +1561,10 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data
FreestyleLineStyle *linestyle = lineset->linestyle;
ListBase tmp_data = {NULL, NULL};
size_t tmp_items = 0;
+
+ if (!(linestyle->id.flag & LIB_DOIT))
+ continue;
+ linestyle->id.flag &= ~LIB_DOIT;
/* add scene-level animation channels */
BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_LS_SCED(linestyle))
@@ -2533,13 +2543,13 @@ static size_t animdata_filter_remove_invalid(ListBase *anim_data)
static size_t animdata_filter_remove_duplis(ListBase *anim_data)
{
bAnimListElem *ale, *next;
- GHash *gh;
+ GSet *gs;
size_t items = 0;
/* build new hashtable to efficiently store and retrieve which entries have been
* encountered already while searching
*/
- gh = BLI_ghash_ptr_new("animdata_filter_duplis_remove gh");
+ gs = BLI_gset_ptr_new(__func__);
/* loop through items, removing them from the list if a similar item occurs already */
for (ale = anim_data->first; ale; ale = next) {
@@ -2549,9 +2559,8 @@ static size_t animdata_filter_remove_duplis(ListBase *anim_data)
* - just use ale->data for now, though it would be nicer to involve
* ale->type in combination too to capture corner cases (where same data performs differently)
*/
- if (BLI_ghash_haskey(gh, ale->data) == 0) {
+ if (BLI_gset_reinsert(gs, ale->data, NULL)) {
/* this entry is 'unique' and can be kept */
- BLI_ghash_insert(gh, ale->data, NULL);
items++;
}
else {
@@ -2561,7 +2570,7 @@ static size_t animdata_filter_remove_duplis(ListBase *anim_data)
}
/* free the hash... */
- BLI_ghash_free(gh, NULL, NULL);
+ BLI_gset_free(gs, NULL);
/* return the number of items still in the list */
return items;
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index df93da8b7c1..826e204d981 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -75,7 +75,8 @@ void free_anim_drivers_copybuf(void);
* for the given Animation Data block. This assumes that all the destinations are valid.
*
* - add: 0 - don't add anything if not found,
- * 1 - add new Driver FCurve,
+ * 1 - add new Driver FCurve (with keyframes for visual tweaking),
+ * 2 - add new Driver FCurve (with generator, for script backwards compatability)
* -1 - add new Driver FCurve without driver stuff (for pasting)
*/
FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_index, short add)
@@ -114,11 +115,38 @@ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_inde
/* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */
if (add > 0) {
+ BezTriple *bezt;
+ size_t i;
+
/* add some new driver data */
fcu->driver = MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
+ fcu->driver->flag |= DRIVER_FLAG_SHOWDEBUG;
- /* add simple generator modifier for driver so that there is some visible representation */
- add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR);
+ /* F-Modifier or Keyframes? */
+ // FIXME: replace these magic numbers with defines
+ if (add == 2) {
+ /* Python API Backwards compatability hack:
+ * Create FModifier so that old scripts won't break
+ * for now before 2.7 series -- (September 4, 2013)
+ */
+ add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR);
+ }
+ else {
+ /* add 2 keyframes so that user has something to work with
+ * - These are configured to 0,0 and 1,1 to give a 1-1 mapping
+ * which can be easily tweaked from there.
+ */
+ insert_vert_fcurve(fcu, 0.0f, 0.0f, INSERTKEY_FAST);
+ insert_vert_fcurve(fcu, 1.0f, 1.0f, INSERTKEY_FAST);
+
+ /* configure this curve to extrapolate */
+ for (i = 0, bezt = fcu->bezt; (i < fcu->totvert) && bezt; i++, bezt++) {
+ bezt->h1 = bezt->h2 = HD_VECT;
+ }
+
+ fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
+ calchandles_fcurve(fcu);
+ }
}
/* just add F-Curve to end of driver list */
@@ -166,8 +194,10 @@ short ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int ar
/* will only loop once unless the array index was -1 */
for (; array_index < array_index_max; array_index++) {
+ short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1;
+
/* create F-Curve with Driver */
- fcu = verify_driver_fcurve(id, rna_path, array_index, 1);
+ fcu = verify_driver_fcurve(id, rna_path, array_index, add_mode);
if (fcu && fcu->driver) {
ChannelDriver *driver = fcu->driver;
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 63acc5a943c..cfc03050a9e 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -256,7 +256,7 @@ int insert_bezt_fcurve(FCurve *fcu, BezTriple *bezt, short flag)
dst->f1 = bezt->f1;
dst->f2 = bezt->f2;
dst->f3 = bezt->f3;
-
+
/* TODO: perform some other operations? */
}
}
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index 22bd22c8561..0301db4b4cf 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -255,7 +255,7 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
bDeformGroup *dgroup;
bPoseChannel *pchan;
Mesh *mesh;
- Mat4 *bbone = NULL;
+ Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = NULL;
float (*root)[3], (*tip)[3], (*verts)[3];
int *selected;
int numbones, vertsfilled = 0, i, j, segments = 0;
@@ -309,7 +309,8 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
if ((par->pose) && (pchan = BKE_pose_channel_find_name(par->pose, bone->name))) {
if (bone->segments > 1) {
segments = bone->segments;
- bbone = b_bone_spline_setup(pchan, 1);
+ b_bone_spline_setup(pchan, 1, bbone_array);
+ bbone = bbone_array;
}
}
}
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 76068c122bf..16d7f9c9420 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -281,7 +281,7 @@ static void laplacian_system_construct_end(LaplacianSystem *sys)
sys->varea = MEM_callocN(sizeof(float) * totvert, "LaplacianSystemVarea");
- sys->edgehash = BLI_edgehash_new();
+ sys->edgehash = BLI_edgehash_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(sys->totface));
for (a = 0, face = sys->faces; a < sys->totface; a++, face++) {
laplacian_increase_edge_count(sys->edgehash, (*face)[0], (*face)[1]);
laplacian_increase_edge_count(sys->edgehash, (*face)[1], (*face)[2]);
diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c
index f66fb38a2a6..3a09f531d44 100644
--- a/source/blender/editors/armature/reeb.c
+++ b/source/blender/editors/armature/reeb.c
@@ -198,7 +198,7 @@ ReebGraph *newReebGraph(void)
rg = MEM_callocN(sizeof(ReebGraph), "reeb graph");
rg->totnodes = 0;
- rg->emap = BLI_edgehash_new();
+ rg->emap = BLI_edgehash_new(__func__);
rg->free_arc = REEB_freeArc;
diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h
index d197697e60b..8a5e4b338d3 100644
--- a/source/blender/editors/curve/curve_intern.h
+++ b/source/blender/editors/curve/curve_intern.h
@@ -76,6 +76,7 @@ void CURVE_OT_hide(struct wmOperatorType *ot);
void CURVE_OT_reveal(struct wmOperatorType *ot);
void CURVE_OT_separate(struct wmOperatorType *ot);
+void CURVE_OT_split(struct wmOperatorType *ot);
void CURVE_OT_duplicate(struct wmOperatorType *ot);
void CURVE_OT_delete(struct wmOperatorType *ot);
diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c
index 2452a5d1a4b..1cf194e02c4 100644
--- a/source/blender/editors/curve/curve_ops.c
+++ b/source/blender/editors/curve/curve_ops.c
@@ -87,6 +87,7 @@ void ED_operatortypes_curve(void)
WM_operatortype_append(CURVE_OT_reveal);
WM_operatortype_append(CURVE_OT_separate);
+ WM_operatortype_append(CURVE_OT_split);
WM_operatortype_append(CURVE_OT_duplicate);
WM_operatortype_append(CURVE_OT_delete);
@@ -244,6 +245,7 @@ void ED_keymap_curve(wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "deselect", TRUE);
WM_keymap_add_item(keymap, "CURVE_OT_separate", PKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "CURVE_OT_split", YKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "CURVE_OT_extrude_move", EKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "CURVE_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "CURVE_OT_make_segment", FKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 660f8098a38..ce0881b2e11 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -106,11 +106,25 @@ typedef struct {
Nurb *orig_nu;
} CVKeyIndex;
-void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatus);
-static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short selstatus);
-
-/* still need to eradicate a few :( */
-#define CALLOC_STRUCT_N(x, y, name) (x *)MEM_callocN((y) * sizeof(x), name)
+typedef enum eVisible_Types {
+ HIDDEN = true,
+ VISIBLE = false,
+} eVisible_Types;
+
+typedef enum eEndPoint_Types {
+ FIRST = true,
+ LAST = false,
+} eEndPoint_Types;
+
+typedef enum eCurveElem_Types {
+ CURVE_VERTEX = 0,
+ CURVE_SEGMENT,
+} eCurveElem_Types;
+
+void selectend_nurb(Object *obedit, enum eEndPoint_Types selfirst, bool doswap, bool selstatus);
+static void select_adjacent_cp(ListBase *editnurb, short next, const bool cont, const bool selstatus);
+static void adduplicateflagNurb(Object *obedit, ListBase *newnurb, const short flag, const bool split);
+static int curve_delete_selected(Object *obedit, const eCurveElem_Types type, const bool split);
static float nurbcircle[8][2] = {
{0.0, -1.0}, {-1.0, -1.0}, {-1.0, 0.0}, {-1.0, 1.0},
@@ -149,69 +163,59 @@ static Nurb *get_actNurb(Object *obedit)
/* ******************* SELECTION FUNCTIONS ********************* */
-#define HIDDEN 1
-#define VISIBLE 0
-
-#define FIRST 1
-#define LAST 0
-
/* returns 1 in case (de)selection was successful */
-static short select_beztriple(BezTriple *bezt, short selstatus, short flag, short hidden)
+static bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden)
{
- if (bezt) {
- if ((bezt->hide == 0) || (hidden == 1)) {
- if (selstatus == 1) { /* selects */
- bezt->f1 |= flag;
- bezt->f2 |= flag;
- bezt->f3 |= flag;
- return 1;
- }
- else { /* deselects */
- bezt->f1 &= ~flag;
- bezt->f2 &= ~flag;
- bezt->f3 &= ~flag;
- return 1;
- }
+ if ((bezt->hide == 0) || (hidden == HIDDEN)) {
+ if (selstatus == SELECT) { /* selects */
+ bezt->f1 |= flag;
+ bezt->f2 |= flag;
+ bezt->f3 |= flag;
+ return true;
+ }
+ else { /* deselects */
+ bezt->f1 &= ~flag;
+ bezt->f2 &= ~flag;
+ bezt->f3 &= ~flag;
+ return true;
}
}
- return 0;
+ return false;
}
/* returns 1 in case (de)selection was successful */
-static short select_bpoint(BPoint *bp, short selstatus, short flag, short hidden)
+static bool select_bpoint(BPoint *bp, bool selstatus, short flag, bool hidden)
{
- if (bp) {
- if ((bp->hide == 0) || (hidden == 1)) {
- if (selstatus == 1) {
- bp->f1 |= flag;
- return 1;
- }
- else {
- bp->f1 &= ~flag;
- return 1;
- }
+ if ((bp->hide == 0) || (hidden == 1)) {
+ if (selstatus == SELECT) {
+ bp->f1 |= flag;
+ return true;
+ }
+ else {
+ bp->f1 &= ~flag;
+ return true;
}
}
- return 0;
+ return false;
}
-static short swap_selection_beztriple(BezTriple *bezt)
+static bool swap_selection_beztriple(BezTriple *bezt)
{
if (bezt->f2 & SELECT)
- return select_beztriple(bezt, DESELECT, 1, VISIBLE);
+ return select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
else
- return select_beztriple(bezt, SELECT, 1, VISIBLE);
+ return select_beztriple(bezt, SELECT, SELECT, VISIBLE);
}
-static short swap_selection_bpoint(BPoint *bp)
+static bool swap_selection_bpoint(BPoint *bp)
{
if (bp->f1 & SELECT)
- return select_bpoint(bp, DESELECT, 1, VISIBLE);
+ return select_bpoint(bp, DESELECT, SELECT, VISIBLE);
else
- return select_bpoint(bp, SELECT, 1, VISIBLE);
+ return select_bpoint(bp, SELECT, SELECT, VISIBLE);
}
int isNurbsel(Nurb *nu)
@@ -361,7 +365,7 @@ static CVKeyIndex *getCVKeyIndex(EditNurb *editnurb, void *cv)
static CVKeyIndex *popCVKeyIndex(EditNurb *editnurb, void *cv)
{
- return BLI_ghash_pop(editnurb->keyindex, cv, NULL);
+ return BLI_ghash_popkey(editnurb->keyindex, cv, NULL);
}
static BezTriple *getKeyIndexOrig_bezt(EditNurb *editnurb, BezTriple *bezt)
@@ -674,7 +678,7 @@ static GHash *dupli_keyIndexHash(GHash *keyindex)
GHash *gh;
GHashIterator *hashIter;
- gh = BLI_ghash_ptr_new("dupli_keyIndex gh");
+ gh = BLI_ghash_ptr_new_ex("dupli_keyIndex gh", BLI_ghash_size(keyindex));
for (hashIter = BLI_ghashIterator_new(keyindex);
BLI_ghashIterator_done(hashIter) == false;
@@ -1463,6 +1467,49 @@ void CURVE_OT_separate(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/******************** split operator ***********************/
+
+static int curve_split_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ ListBase newnurb = {NULL, NULL};
+
+ adduplicateflagNurb(obedit, &newnurb, SELECT, true);
+
+ if (newnurb.first != NULL) {
+ curve_delete_selected(obedit, CURVE_SEGMENT, true);
+ BLI_movelisttolist(editnurb, &newnurb);
+
+ if (ED_curve_updateAnimPaths(obedit->data))
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DAG_id_tag_update(obedit->data, 0);
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Cannot split current selection");
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_split(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Split";
+ ot->idname = "CURVE_OT_split";
+ ot->description = "Split off selected points from connected unselected points";
+
+ /* api callbacks */
+ ot->exec = curve_split_exec;
+ ot->poll = ED_operator_editcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
/* ******************* FLAGS ********************* */
static short isNurbselUV(Nurb *nu, int *u, int *v, int flag)
@@ -1614,9 +1661,8 @@ static void weightflagNurb(ListBase *editnurb, short flag, float w)
}
}
-static int deleteflagNurb(bContext *C, wmOperator *UNUSED(op), int flag)
+static int deleteflagNurb(Object *obedit, short flag)
{
- Object *obedit = CTX_data_edit_object(C);
Curve *cu = obedit->data;
ListBase *editnurb = object_editcurve_get(obedit);
Nurb *nu, *next;
@@ -1744,9 +1790,6 @@ static int deleteflagNurb(bContext *C, wmOperator *UNUSED(op), int flag)
nu = next;
}
- if (ED_curve_updateAnimPaths(obedit->data))
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
-
return OPERATOR_FINISHED;
}
@@ -1869,40 +1912,54 @@ static short extrudeflagNurb(EditNurb *editnurb, int flag)
return ok;
}
-static void adduplicateflagNurb(Object *obedit, short flag)
+static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
+ const short flag, const bool split)
{
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu, *newnu;
+ Nurb *nu, *newnu, *startnu;
BezTriple *bezt, *bezt1;
BPoint *bp, *bp1;
Curve *cu = (Curve *)obedit->data;
- int a, b, starta, enda, newu, newv;
+ int a, b, starta, enda, diffa, newu, newv;
char *usel;
cu->lastsel = NULL;
nu = editnurb->last;
while (nu) {
+ startnu = NULL;
if (nu->type == CU_BEZIER) {
bezt = nu->bezt;
for (a = 0; a < nu->pntsu; a++) {
enda = -1;
starta = a;
while ((bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag)) {
- select_beztriple(bezt, DESELECT, flag, HIDDEN);
+ if (!split) select_beztriple(bezt, DESELECT, flag, HIDDEN);
enda = a;
if (a >= nu->pntsu - 1) break;
a++;
bezt++;
}
if (enda >= starta) {
- newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN");
- memcpy(newnu, nu, sizeof(Nurb));
- BLI_addtail(editnurb, newnu);
- set_actNurb(obedit, newnu);
- newnu->pntsu = enda - starta + 1;
- newnu->bezt = (BezTriple *)MEM_mallocN((enda - starta + 1) * sizeof(BezTriple), "adduplicateN");
- memcpy(newnu->bezt, &nu->bezt[starta], newnu->pntsu * sizeof(BezTriple));
+ diffa = enda - starta + 1;
+
+ if (startnu != NULL && enda == nu->pntsu - 1) {
+ /* end point of cyclic spline selected, so merge end points with start points */
+ bezt1 = (BezTriple *)MEM_mallocN((startnu->pntsu + diffa) * sizeof(BezTriple), "adduplicateN");
+ memcpy(bezt1, &nu->bezt[starta], diffa * sizeof(BezTriple));
+ memcpy(&bezt1[diffa], startnu->bezt, startnu->pntsu * sizeof(BezTriple));
+
+ MEM_freeN(startnu->bezt);
+ startnu->bezt = bezt1;
+ startnu->pntsu += diffa;
+ newnu = startnu;
+ }
+ else {
+ newnu = ED_curve_nurbcpy(nu, diffa);
+ BLI_addtail(newnurb, newnu);
+ set_actNurb(obedit, newnu);
+ memcpy(newnu->bezt, &nu->bezt[starta], newnu->pntsu * sizeof(BezTriple));
+ }
b = newnu->pntsu;
bezt1 = newnu->bezt;
@@ -1914,6 +1971,7 @@ static void adduplicateflagNurb(Object *obedit, short flag)
if (nu->flagu & CU_NURB_CYCLIC) {
if (starta != 0 || enda != nu->pntsu - 1) {
newnu->flagu &= ~CU_NURB_CYCLIC;
+ if (starta == 0) startnu = newnu;
}
}
}
@@ -1926,20 +1984,32 @@ static void adduplicateflagNurb(Object *obedit, short flag)
enda = -1;
starta = a;
while (bp->f1 & flag) {
- select_bpoint(bp, DESELECT, flag, HIDDEN);
+ if (!split) select_bpoint(bp, DESELECT, flag, HIDDEN);
enda = a;
if (a >= nu->pntsu - 1) break;
a++;
bp++;
}
if (enda >= starta) {
- newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN3");
- memcpy(newnu, nu, sizeof(Nurb));
- set_actNurb(obedit, newnu);
- BLI_addtail(editnurb, newnu);
- newnu->pntsu = enda - starta + 1;
- newnu->bp = (BPoint *)MEM_mallocN((enda - starta + 1) * sizeof(BPoint), "adduplicateN4");
- memcpy(newnu->bp, &nu->bp[starta], newnu->pntsu * sizeof(BPoint));
+ diffa = enda - starta + 1;
+
+ if (startnu != NULL && enda == nu->pntsu - 1) {
+ /* end point of cyclic spline selected, so merge end points with start points */
+ bp1 = (BPoint *)MEM_mallocN((startnu->pntsu + diffa) * sizeof(BPoint), "adduplicateN2");
+ memcpy(bp1, &nu->bp[starta], diffa * sizeof(BPoint));
+ memcpy(&bp1[diffa], startnu->bp, startnu->pntsu * sizeof(BPoint));
+
+ MEM_freeN(startnu->bp);
+ startnu->bp = bp1;
+ startnu->pntsu += diffa;
+ newnu = startnu;
+ }
+ else {
+ newnu = ED_curve_nurbcpy(nu, diffa);
+ BLI_addtail(newnurb, newnu);
+ set_actNurb(obedit, newnu);
+ memcpy(newnu->bp, &nu->bp[starta], newnu->pntsu * sizeof(BPoint));
+ }
b = newnu->pntsu;
bp1 = newnu->bp;
@@ -1951,12 +2021,9 @@ static void adduplicateflagNurb(Object *obedit, short flag)
if (nu->flagu & CU_NURB_CYCLIC) {
if (starta != 0 || enda != nu->pntsu - 1) {
newnu->flagu &= ~CU_NURB_CYCLIC;
+ if (starta == 0) startnu = newnu;
}
}
-
- /* knots */
- newnu->knotsu = NULL;
- BKE_nurb_knot_calc_u(newnu);
}
bp++;
}
@@ -1964,7 +2031,7 @@ static void adduplicateflagNurb(Object *obedit, short flag)
else {
/* a rectangular area in nurb has to be selected */
if (isNurbsel(nu)) {
- usel = MEM_callocN(nu->pntsu, "adduplicateN4");
+ usel = MEM_callocN(nu->pntsu, "adduplicateN3");
bp = nu->bp;
for (a = 0; a < nu->pntsv; a++) {
for (b = 0; b < nu->pntsu; b++, bp++) {
@@ -1993,13 +2060,13 @@ static void adduplicateflagNurb(Object *obedit, short flag)
if (newu == 1) SWAP(int, newu, newv);
- newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN5");
+ newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN4");
memcpy(newnu, nu, sizeof(Nurb));
- BLI_addtail(editnurb, newnu);
+ BLI_addtail(newnurb, newnu);
set_actNurb(obedit, newnu);
newnu->pntsu = newu;
newnu->pntsv = newv;
- newnu->bp = (BPoint *)MEM_mallocN(newu * newv * sizeof(BPoint), "adduplicateN6");
+ newnu->bp = (BPoint *)MEM_mallocN(newu * newv * sizeof(BPoint), "adduplicateN5");
BKE_nurb_order_clamp_u(newnu);
BKE_nurb_order_clamp_v(newnu);
@@ -2040,6 +2107,22 @@ static void adduplicateflagNurb(Object *obedit, short flag)
nu = nu->prev;
}
+ for (nu = newnurb->first; nu; nu = nu->next) {
+ /* knots done after duplicate as pntsu may change */
+ if (nu->pntsv == 1) {
+ nu->knotsu = NULL;
+ BKE_nurb_knot_calc_u(nu);
+ }
+
+ if (split) {
+ if (nu->type == CU_BEZIER) {
+ /* recalc first and last */
+ BKE_nurb_handle_calc_simple(nu, &nu->bezt[0]);
+ BKE_nurb_handle_calc_simple(nu, &nu->bezt[nu->pntsu - 1]);
+ }
+ }
+ }
+
/* actnu changed */
}
@@ -2513,7 +2596,8 @@ void CURVE_OT_smooth_tilt(wmOperatorType *ot)
/* next == -1 -> select previous */
/* cont == 1 -> select continuously */
/* selstatus, inverts behavior */
-static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short selstatus)
+static void select_adjacent_cp(ListBase *editnurb, short next,
+ const bool cont, const bool selstatus)
{
Nurb *nu;
BezTriple *bezt;
@@ -2531,10 +2615,10 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short
if (next < 0) bezt = &nu->bezt[a - 1];
while (a--) {
if (a - abs(next) < 0) break;
- if ((lastsel == 0) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == 0))) {
+ if ((lastsel == 0) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == DESELECT))) {
bezt += next;
- if (!(bezt->f2 & SELECT) || (selstatus == 0)) {
- short sel = select_beztriple(bezt, selstatus, 1, VISIBLE);
+ if (!(bezt->f2 & SELECT) || (selstatus == DESELECT)) {
+ short sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
if ((sel == 1) && (cont == 0)) lastsel = true;
}
}
@@ -2552,10 +2636,10 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short
if (next < 0) bp = &nu->bp[a - 1];
while (a--) {
if (a - abs(next) < 0) break;
- if ((lastsel == 0) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == 0))) {
+ if ((lastsel == 0) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == DESELECT))) {
bp += next;
- if (!(bp->f1 & SELECT) || (selstatus == 0)) {
- short sel = select_bpoint(bp, selstatus, 1, VISIBLE);
+ if (!(bp->f1 & SELECT) || (selstatus == DESELECT)) {
+ short sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
if ((sel == 1) && (cont == 0)) lastsel = true;
}
}
@@ -2577,7 +2661,7 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short
* doswap: defines if selection state of each first/last control point is swapped
* selstatus: selection status in case doswap is false
*/
-void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatus)
+void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap, bool selstatus)
{
ListBase *editnurb = object_editcurve_get(obedit);
Nurb *nu;
@@ -2596,7 +2680,7 @@ void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatu
a = nu->pntsu;
/* which point? */
- if (selfirst == 0) { /* select last */
+ if (selfirst == LAST) { /* select last */
bezt = &nu->bezt[a - 1];
}
else { /* select first */
@@ -2604,18 +2688,18 @@ void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatu
}
while (a--) {
- short sel;
+ bool sel;
if (doswap) sel = swap_selection_beztriple(bezt);
- else sel = select_beztriple(bezt, selstatus, 1, VISIBLE);
+ else sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
- if (sel == 1) break;
+ if (sel == true) break;
}
}
else {
a = nu->pntsu * nu->pntsv;
/* which point? */
- if (selfirst == 0) { /* select last */
+ if (selfirst == LAST) { /* select last */
bp = &nu->bp[a - 1];
}
else { /* select first */
@@ -2624,11 +2708,11 @@ void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatu
while (a--) {
if (bp->hide == 0) {
- short sel;
+ bool sel;
if (doswap) sel = swap_selection_bpoint(bp);
- else sel = select_bpoint(bp, selstatus, 1, VISIBLE);
+ else sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
- if (sel == 1) break;
+ if (sel == true) break;
}
}
}
@@ -2639,7 +2723,7 @@ static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit = CTX_data_edit_object(C);
- selectend_nurb(obedit, FIRST, 1, DESELECT);
+ selectend_nurb(obedit, FIRST, true, DESELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -2664,7 +2748,7 @@ static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit = CTX_data_edit_object(C);
- selectend_nurb(obedit, LAST, 1, DESELECT);
+ selectend_nurb(obedit, LAST, true, DESELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -2789,11 +2873,11 @@ static int hide_exec(bContext *C, wmOperator *op)
sel = 0;
while (a--) {
if (invert == 0 && BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
- select_beztriple(bezt, DESELECT, 1, HIDDEN);
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
bezt->hide = 1;
}
else if (invert && !BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
- select_beztriple(bezt, DESELECT, 1, HIDDEN);
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
bezt->hide = 1;
}
if (bezt->hide) sel++;
@@ -2807,11 +2891,11 @@ static int hide_exec(bContext *C, wmOperator *op)
sel = 0;
while (a--) {
if (invert == 0 && (bp->f1 & SELECT)) {
- select_bpoint(bp, DESELECT, 1, HIDDEN);
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
bp->hide = 1;
}
else if (invert && (bp->f1 & SELECT) == 0) {
- select_bpoint(bp, DESELECT, 1, HIDDEN);
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
bp->hide = 1;
}
if (bp->hide) sel++;
@@ -2863,7 +2947,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
a = nu->pntsu;
while (a--) {
if (bezt->hide) {
- select_beztriple(bezt, SELECT, 1, HIDDEN);
+ select_beztriple(bezt, SELECT, SELECT, HIDDEN);
bezt->hide = 0;
}
bezt++;
@@ -2874,7 +2958,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
a = nu->pntsu * nu->pntsv;
while (a--) {
if (bp->hide) {
- select_bpoint(bp, SELECT, 1, HIDDEN);
+ select_bpoint(bp, SELECT, SELECT, HIDDEN);
bp->hide = 0;
}
bp++;
@@ -3840,7 +3924,7 @@ static void merge_2_nurb(wmOperator *op, ListBase *editnurb, Nurb *nu1, Nurb *nu
for (u = 0; u < nu1->pntsu; u++, bp++) {
if (u < origu) {
*bp = *bp1; bp1++;
- select_bpoint(bp, SELECT, 1, HIDDEN);
+ select_bpoint(bp, SELECT, SELECT, HIDDEN);
}
else {
*bp = *bp2; bp2++;
@@ -4148,7 +4232,7 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
if (extend) {
if (bezt) {
if (hand == 1) {
- select_beztriple(bezt, SELECT, 1, HIDDEN);
+ select_beztriple(bezt, SELECT, SELECT, HIDDEN);
cu->lastsel = bezt;
}
else {
@@ -4160,13 +4244,13 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
}
else {
cu->lastsel = bp;
- select_bpoint(bp, SELECT, 1, HIDDEN);
+ select_bpoint(bp, SELECT, SELECT, HIDDEN);
}
}
else if (deselect) {
if (bezt) {
if (hand == 1) {
- select_beztriple(bezt, DESELECT, 1, HIDDEN);
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
if (bezt == cu->lastsel) cu->lastsel = NULL;
}
else if (hand == 0) {
@@ -4177,7 +4261,7 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
}
}
else {
- select_bpoint(bp, DESELECT, 1, HIDDEN);
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
if (cu->lastsel == bp) cu->lastsel = NULL;
}
}
@@ -4185,11 +4269,11 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
if (bezt) {
if (hand == 1) {
if (bezt->f2 & SELECT) {
- select_beztriple(bezt, DESELECT, 1, HIDDEN);
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
if (bezt == cu->lastsel) cu->lastsel = NULL;
}
else {
- select_beztriple(bezt, SELECT, 1, HIDDEN);
+ select_beztriple(bezt, SELECT, SELECT, HIDDEN);
cu->lastsel = bezt;
}
}
@@ -4202,11 +4286,11 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
}
else {
if (bp->f1 & SELECT) {
- select_bpoint(bp, DESELECT, 1, HIDDEN);
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
if (cu->lastsel == bp) cu->lastsel = NULL;
}
else {
- select_bpoint(bp, SELECT, 1, HIDDEN);
+ select_bpoint(bp, SELECT, SELECT, HIDDEN);
cu->lastsel = bp;
}
}
@@ -4217,7 +4301,7 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
if (bezt) {
if (hand == 1) {
- select_beztriple(bezt, SELECT, 1, HIDDEN);
+ select_beztriple(bezt, SELECT, SELECT, HIDDEN);
cu->lastsel = bezt;
}
else {
@@ -4229,7 +4313,7 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
}
else {
cu->lastsel = bp;
- select_bpoint(bp, SELECT, 1, HIDDEN);
+ select_bpoint(bp, SELECT, SELECT, HIDDEN);
}
}
@@ -4944,7 +5028,7 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
a = nu->pntsu;
bezt = nu->bezt;
while (a--) {
- select_beztriple(bezt, SELECT, 1, VISIBLE);
+ select_beztriple(bezt, SELECT, SELECT, VISIBLE);
bezt++;
}
break;
@@ -4960,7 +5044,7 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
a = nu->pntsu * nu->pntsv;
bp = nu->bp;
while (a--) {
- select_bpoint(bp, SELECT, 1, VISIBLE);
+ select_bpoint(bp, SELECT, SELECT, VISIBLE);
bp++;
}
break;
@@ -5021,8 +5105,8 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent
a = nu->pntsu;
bezt = nu->bezt;
while (a--) {
- if (deselect) select_beztriple(bezt, DESELECT, 1, VISIBLE);
- else select_beztriple(bezt, SELECT, 1, VISIBLE);
+ if (deselect) select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
+ else select_beztriple(bezt, SELECT, SELECT, VISIBLE);
bezt++;
}
}
@@ -5030,8 +5114,8 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent
a = nu->pntsu * nu->pntsv;
bp = nu->bp;
while (a--) {
- if (deselect) select_bpoint(bp, DESELECT, 1, VISIBLE);
- else select_bpoint(bp, SELECT, 1, VISIBLE);
+ if (deselect) select_bpoint(bp, DESELECT, SELECT, VISIBLE);
+ else select_bpoint(bp, SELECT, SELECT, VISIBLE);
bp++;
}
}
@@ -5103,10 +5187,10 @@ static int select_row_exec(bContext *C, wmOperator *UNUSED(op))
for (a = 0; a < nu->pntsv; a++) {
for (b = 0; b < nu->pntsu; b++, bp++) {
if (direction) {
- if (a == v) select_bpoint(bp, SELECT, 1, VISIBLE);
+ if (a == v) select_bpoint(bp, SELECT, SELECT, VISIBLE);
}
else {
- if (b == u) select_bpoint(bp, SELECT, 1, VISIBLE);
+ if (b == u) select_bpoint(bp, SELECT, SELECT, VISIBLE);
}
}
}
@@ -5217,14 +5301,14 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
/* upper control point */
if (a % nu->pntsu != 0) {
tempbp = bp - 1;
- if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, 1, VISIBLE);
+ if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
}
/* left control point. select only if it is not selected already */
if (a - nu->pntsu > 0) {
sel = 0;
tempbp = bp + nu->pntsu;
- if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, 1, VISIBLE);
+ if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
/* make sure selected bpoint is discarded */
if (sel == 1) BLI_BITMAP_SET(selbpoints, a - nu->pntsu);
}
@@ -5232,14 +5316,14 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
/* right control point */
if (a + nu->pntsu < nu->pntsu * nu->pntsv) {
tempbp = bp - nu->pntsu;
- if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, 1, VISIBLE);
+ if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
}
/* lower control point. skip next bp in case selection was made */
if (a % nu->pntsu != 1) {
sel = 0;
tempbp = bp + 1;
- if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, 1, VISIBLE);
+ if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
if (sel) {
bp++;
a--;
@@ -5341,7 +5425,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
}
if (sel != 4) {
- select_bpoint(bp, DESELECT, 1, VISIBLE);
+ select_bpoint(bp, DESELECT, SELECT, VISIBLE);
BLI_BITMAP_SET(selbpoints, a);
}
}
@@ -5387,7 +5471,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
}
if (sel != 2) {
- select_beztriple(bezt, DESELECT, 1, VISIBLE);
+ select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
lastsel = true;
}
else {
@@ -5429,7 +5513,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
}
if (sel != 2) {
- select_bpoint(bp, DESELECT, 1, VISIBLE);
+ select_bpoint(bp, DESELECT, SELECT, VISIBLE);
lastsel = true;
}
else {
@@ -5481,7 +5565,7 @@ static void selectrandom_curve(ListBase *editnurb, float randfac)
a = nu->pntsu;
while (a--) {
if (BLI_frand() < randfac)
- select_beztriple(bezt, SELECT, 1, VISIBLE);
+ select_beztriple(bezt, SELECT, SELECT, VISIBLE);
bezt++;
}
}
@@ -5491,7 +5575,7 @@ static void selectrandom_curve(ListBase *editnurb, float randfac)
while (a--) {
if (BLI_frand() < randfac)
- select_bpoint(bp, SELECT, 1, VISIBLE);
+ select_bpoint(bp, SELECT, SELECT, VISIBLE);
bp++;
}
}
@@ -5534,15 +5618,13 @@ void CURVE_OT_select_random(wmOperatorType *ot)
/********************* every nth number of point *******************/
-static int point_on_nurb(Nurb *nu, void *point)
+static bool point_in_nurb(Nurb *nu, void *point)
{
if (nu->bezt) {
- BezTriple *bezt = (BezTriple *)point;
- return bezt >= nu->bezt && bezt < &nu->bezt[nu->pntsu];
+ return ARRAY_HAS_ITEM((BezTriple *)point, nu->bezt, nu->pntsu);
}
else {
- BPoint *bp = (BPoint *)point;
- return bp >= nu->bp && bp < &nu->bp[nu->pntsu * nu->pntsv];
+ return ARRAY_HAS_ITEM((BPoint *)point, nu->bp, nu->pntsu);
}
}
@@ -5555,7 +5637,7 @@ static Nurb *get_lastsel_nurb(Curve *cu)
return NULL;
while (nu) {
- if (point_on_nurb(nu, cu->lastsel))
+ if (point_in_nurb(nu, cu->lastsel))
return nu;
nu = nu->next;
@@ -5574,7 +5656,7 @@ static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth)
while (a--) {
if (abs(start - a) % nth) {
- select_beztriple(bezt, DESELECT, 1, HIDDEN);
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
}
bezt--;
@@ -5597,7 +5679,7 @@ static void select_nth_bp(Nurb *nu, BPoint *bp, int nth)
while (a--) {
dist = abs(pnt - startpnt) + abs(row - startrow);
if (dist % nth) {
- select_bpoint(bp, DESELECT, 1, HIDDEN);
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
}
pnt--;
@@ -5672,9 +5754,14 @@ void CURVE_OT_select_nth(wmOperatorType *ot)
static int duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit = CTX_data_edit_object(C);
+ ListBase newnurb = {NULL, NULL};
- adduplicateflagNurb(obedit, 1);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ adduplicateflagNurb(obedit, &newnurb, SELECT, false);
+
+ if (newnurb.first != NULL) {
+ BLI_movelisttolist(object_editcurve_get(obedit), &newnurb);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
return OPERATOR_FINISHED;
}
@@ -5696,37 +5783,31 @@ void CURVE_OT_duplicate(wmOperatorType *ot)
/********************** delete operator *********************/
-static int delete_exec(bContext *C, wmOperator *op)
+static int curve_delete_selected(Object *obedit, eCurveElem_Types type, const bool split)
{
- Object *obedit = CTX_data_edit_object(C);
Curve *cu = obedit->data;
EditNurb *editnurb = cu->editnurb;
ListBase *nubase = &editnurb->nurbs;
- Nurb *nu, *nu1;
+ Nurb *nu, *nu1, *startnu;
BezTriple *bezt, *bezt1, *bezt2;
BPoint *bp, *bp1, *bp2;
- int a, cut = 0, type = RNA_enum_get(op->ptr, "type");
+ int a, b, starta, enda, cut = 0;
int nuindex = 0;
+ ListBase newnurb = {NULL, NULL};
if (obedit->type == OB_SURF) {
- if (type == 0) {
- deleteflagNurb(C, op, 1);
+ if (type == CURVE_VERTEX) {
+ return deleteflagNurb(obedit, SELECT);
}
else {
keyIndex_delNurbList(editnurb, nubase);
BKE_nurbList_free(nubase);
- if (ED_curve_updateAnimPaths(obedit->data))
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ return OPERATOR_FINISHED;
}
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
-
- return OPERATOR_FINISHED;
}
- if (type == 0) {
+ if (type == CURVE_VERTEX) {
/* first loop, can we remove entire pieces? */
Nurb *next;
nu = nubase->first;
@@ -5861,204 +5942,343 @@ static int delete_exec(bContext *C, wmOperator *op)
nu = next;
}
}
- else if (type == 1) { /* erase segment */
- /* find the 2 selected points */
- bezt1 = bezt2 = NULL;
- bp1 = bp2 = NULL;
- nu1 = NULL;
- nuindex = 0;
+ else if (type == CURVE_SEGMENT) {
for (nu = nubase->first; nu; nu = nu->next) {
+ startnu = nu1 = NULL;
+ starta = enda = cut = -1;
+
if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- for (a = 0; a < nu->pntsu - 1; a++) {
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
- bezt1 = bezt;
- bezt2 = bezt + 1;
- if ((bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT)) {
- /* pass */
+ for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
+ if (!BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ enda = a;
+ if (starta == -1) starta = a;
+ if (a < nu->pntsu - 1) continue;
+ }
+ else if (a < nu->pntsu - 1 && !BEZSELECTED_HIDDENHANDLES(cu, bezt + 1)) {
+ /* if just single selected point then continue */
+ continue;
+ }
+
+ if (starta >= 0) {
+ /* got selected segment, now check where and copy */
+ if (starta <= 1 && a == nu->pntsu - 1) {
+ /* copying all points in spline */
+ if (starta == 1 && enda != a) nu->flagu &= ~CU_NURB_CYCLIC;
+
+ starta = 0;
+ enda = a;
+ cut = enda - starta + 1;
+
+ nu1 = ED_curve_nurbcpy(nu, cut);
+ }
+ else if (starta == 0) {
+ /* if start of curve copy next end point */
+ enda++;
+ cut = enda - starta + 1;
+
+ bezt1 = &nu->bezt[nu->pntsu - 1];
+ bezt2 = &nu->bezt[nu->pntsu - 2];
+
+ if ((nu->flagu & CU_NURB_CYCLIC) &&
+ BEZSELECTED_HIDDENHANDLES(cu, bezt1) &&
+ BEZSELECTED_HIDDENHANDLES(cu, bezt2))
+ {
+ /* check if need to join start of spline to end */
+ nu1 = ED_curve_nurbcpy(nu, cut + 1);
+ ED_curve_beztcpy(editnurb, &nu1->bezt[1], nu->bezt, cut);
+ starta = nu->pntsu - 1;
+ cut = 1;
+ }
+ else {
+ nu1 = ED_curve_nurbcpy(nu, cut);
+
+ if (nu->flagu & CU_NURB_CYCLIC) startnu = nu1;
+ }
+ }
+ else if (enda == nu->pntsu - 1) {
+ /* if end of curve copy previous start point */
+ starta--;
+ cut = enda - starta + 1;
+
+ bezt1 = nu->bezt;
+ bezt2 = &nu->bezt[1];
+
+ if ((nu->flagu & CU_NURB_CYCLIC) &&
+ BEZSELECTED_HIDDENHANDLES(cu, bezt1) &&
+ BEZSELECTED_HIDDENHANDLES(cu, bezt2))
+ {
+ /* check if need to join start of spline to end */
+ nu1 = ED_curve_nurbcpy(nu, cut + 1);
+ ED_curve_beztcpy(editnurb, &nu1->bezt[cut], nu->bezt, 1);
+ }
+ else if (startnu != NULL) {
+ /* if startnu exists it is a cyclic spline, start and end should be connected */
+ bezt1 = (BezTriple *)MEM_mallocN((cut + startnu->pntsu) * sizeof(BezTriple), "delNurb3");
+ ED_curve_beztcpy(editnurb, bezt1, &nu->bezt[starta], cut);
+ ED_curve_beztcpy(editnurb, &bezt1[cut], nu->bezt, startnu->pntsu);
+
+ MEM_freeN(startnu->bezt);
+ startnu->bezt = bezt1;
+ startnu->pntsu += cut;
+
+ if (split) {
+ for (b = 0; b < startnu->pntsu; b++, bezt1++) {
+ select_beztriple(bezt1, DESELECT, SELECT, true);
+ }
+ }
+
+ BKE_nurb_handles_calc(startnu);
+ }
+ else {
+ nu1 = ED_curve_nurbcpy(nu, cut);
+ }
}
- else { /* maybe do not make cyclic */
- if (a == 0 && (nu->flagu & CU_NURB_CYCLIC)) {
- bezt2 = bezt + (nu->pntsu - 1);
- if ((bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT)) {
- nu->flagu &= ~CU_NURB_CYCLIC;
- BKE_nurb_handles_calc(nu);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ else {
+ /* mid spline selection, copy adjacent start and end */
+ starta--;
+ enda++;
+ cut = enda - starta + 1;
+
+ nu1 = ED_curve_nurbcpy(nu, cut);
+ }
+
+ if (nu1 != NULL) {
+ ED_curve_beztcpy(editnurb, nu1->bezt, &nu->bezt[starta], cut);
+
+ if (starta != 0 || enda != nu->pntsu - 1) nu1->flagu &= ~CU_NURB_CYCLIC;
+
+ if (split) {
+ /* deselect for split operator */
+ for (b = 0, bezt1 = nu1->bezt; b < nu1->pntsu; b++, bezt1++) {
+ select_beztriple(bezt1, DESELECT, SELECT, true);
}
}
- return OPERATOR_FINISHED;
+ BLI_addtail(&newnurb, nu1);
+ BKE_nurb_handles_calc(nu1);
+ nu1 = NULL;
}
- cut = a;
- nu1 = nu;
- break;
+ starta = enda = -1;
+ }
+ }
+
+ if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) {
+ /* start and points copied if connecting segment was deleted and not cylic spline */
+ bezt1 = nu->bezt;
+ bezt2 = &nu->bezt[1];
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt1) && BEZSELECTED_HIDDENHANDLES(cu, bezt2)) {
+ nu1 = ED_curve_nurbcpy(nu, 1);
+ ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1);
+ BLI_addtail(&newnurb, nu1);
+ }
+
+ bezt1 = &nu->bezt[nu->pntsu - 1];
+ bezt2 = &nu->bezt[nu->pntsu - 2];
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt1) && BEZSELECTED_HIDDENHANDLES(cu, bezt2)) {
+ nu1 = ED_curve_nurbcpy(nu, 1);
+ ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1);
+ BLI_addtail(&newnurb, nu1);
}
- bezt++;
}
}
else if (nu->pntsv == 1) {
- bp = nu->bp;
- for (a = 0; a < nu->pntsu - 1; a++) {
- if (bp->f1 & SELECT) {
- bp1 = bp;
- bp2 = bp + 1;
- if (bp2->f1 & SELECT) {
- /* pass */
+ for (a = 0, bp = nu->bp; a < nu->pntsu; a++, bp++) {
+ if (!(bp->f1 & SELECT)) {
+ enda = a;
+ if (starta == -1) starta = a;
+ if (a < nu->pntsu - 1) continue;
+ }
+ else if (a < nu->pntsu - 1 && !((bp + 1)->f1 & SELECT)) {
+ /* if just single selected point then continue */
+ continue;
+ }
+
+ if (starta >= 0) {
+ /* got selected segment, now check where and copy */
+ if (starta <= 1 && a == nu->pntsu - 1) {
+ /* copying all points in spline */
+ if (starta == 1 && enda != a) nu->flagu &= ~CU_NURB_CYCLIC;
+
+ starta = 0;
+ enda = a;
+ cut = enda - starta + 1;
+
+ nu1 = ED_curve_nurbcpy(nu, cut);
}
- else { /* maybe do not make cyclic */
- if (a == 0 && (nu->flagu & CU_NURB_CYCLIC)) {
- bp2 = bp + (nu->pntsu - 1);
- if (bp2->f1 & SELECT) {
- nu->flagu &= ~CU_NURB_CYCLIC;
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ else if (starta == 0) {
+ /* if start of curve copy next end point */
+ enda++;
+ cut = enda - starta + 1;
+
+ bp1 = &nu->bp[nu->pntsu - 1];
+ bp2 = &nu->bp[nu->pntsu - 2];
+
+ if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ /* check if need to join start of spline to end */
+ nu1 = ED_curve_nurbcpy(nu, cut + 1);
+ ED_curve_bpcpy(editnurb, &nu1->bp[1], nu->bp, cut);
+ starta = nu->pntsu - 1;
+ cut = 1;
+ }
+ else {
+ nu1 = ED_curve_nurbcpy(nu, cut);
+
+ if (nu->flagu & CU_NURB_CYCLIC) startnu = nu1;
+ }
+ }
+ else if (enda == nu->pntsu - 1) {
+ /* if end of curve copy previous start point */
+ starta--;
+ cut = enda - starta + 1;
+
+ bp1 = nu->bp;
+ bp2 = &nu->bp[1];
+
+ if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ /* check if need to join start of spline to end */
+ nu1 = ED_curve_nurbcpy(nu, cut + 1);
+ ED_curve_bpcpy(editnurb, &nu1->bp[cut], nu->bp, 1);
+ }
+ else if (startnu != NULL) {
+ /* if startnu exists it is a cyclic spline, start and end should be connected */
+ bp1 = (BPoint *)MEM_mallocN((cut + startnu->pntsu) * sizeof(BPoint), "delNurb4");
+ ED_curve_bpcpy(editnurb, bp1, &nu->bp[starta], cut);
+ ED_curve_bpcpy(editnurb, &bp1[cut], nu->bp, startnu->pntsu);
+
+ MEM_freeN(startnu->bp);
+ startnu->bp = bp1;
+ startnu->pntsu += cut;
+
+ if (split) {
+ for (b = 0; b < startnu->pntsu; b++, bp1++) {
+ select_bpoint(bp1, DESELECT, SELECT, HIDDEN);
+ }
}
+
+ BKE_nurb_order_clamp_u(startnu);
+ BKE_nurb_knot_calc_u(startnu);
+ }
+ else {
+ nu1 = ED_curve_nurbcpy(nu, cut);
}
+ }
+ else {
+ /* mid spline selection, copy adjacent start and end */
+ starta--;
+ enda++;
+ cut = enda - starta + 1;
- return OPERATOR_FINISHED;
+ nu1 = ED_curve_nurbcpy(nu, cut);
}
- cut = a;
- nu1 = nu;
- break;
- }
- bp++;
- }
- }
- if (nu1) break;
- nuindex++;
- }
- if (nu1) {
- if (bezt1) {
- if (nu1->pntsu == 2) { /* remove completely */
- if (cu->actnu == nuindex)
- cu->actnu = -1;
- BLI_remlink(nubase, nu);
- BKE_nurb_free(nu); nu = NULL;
- }
- else if (nu1->flagu & CU_NURB_CYCLIC) { /* cyclic */
- bezt = (BezTriple *)MEM_mallocN((cut + 1) * sizeof(BezTriple), "delNurb1");
- ED_curve_beztcpy(editnurb, bezt, nu1->bezt, cut + 1);
- a = nu1->pntsu - cut - 1;
- ED_curve_beztcpy(editnurb, nu1->bezt, bezt2, a);
- ED_curve_beztcpy(editnurb, &nu1->bezt[a], bezt, cut + 1);
+ if (nu1 != NULL) {
+ ED_curve_bpcpy(editnurb, nu1->bp, &nu->bp[starta], cut);
- nu1->flagu &= ~CU_NURB_CYCLIC;
- MEM_freeN(bezt);
- BKE_nurb_handles_calc(nu);
- }
- else { /* add new curve */
+ if (starta != 0 || enda != nu->pntsu - 1) nu1->flagu &= ~CU_NURB_CYCLIC;
-/* seems to be an error here... but where? (a can become zero) */
+ if (split) {
+ /* deselect for split operator */
+ for (b = 0, bp1 = nu1->bp; b < nu1->pntsu; b++, bp1++) {
+ select_bpoint(bp1, DESELECT, SELECT, HIDDEN);
+ }
+ }
- nu = (Nurb *)MEM_mallocN(sizeof(Nurb), "delNurb2");
- memcpy(nu, nu1, sizeof(Nurb));
- BLI_addtail(nubase, nu);
- nu->bezt = (BezTriple *)MEM_mallocN((cut + 1) * sizeof(BezTriple), "delNurb3");
- ED_curve_beztcpy(editnurb, nu->bezt, nu1->bezt, cut + 1);
- a = nu1->pntsu - cut - 1;
+ BLI_addtail(&newnurb, nu1);
+ nu1->knotsu = NULL;
+ BKE_nurb_order_clamp_u(nu1);
+ BKE_nurb_knot_calc_u(nu1);
+ nu1 = NULL;
+ }
+ starta = enda = -1;
+ }
+ }
- bezt = (BezTriple *)MEM_mallocN(a * sizeof(BezTriple), "delNurb4");
- ED_curve_beztcpy(editnurb, bezt, &nu1->bezt[cut + 1], a);
- MEM_freeN(nu1->bezt);
- nu1->bezt = bezt;
- nu1->pntsu = a;
- nu->pntsu = cut + 1;
-
-
- BKE_nurb_handles_calc(nu);
- BKE_nurb_handles_calc(nu1);
- }
- }
- else if (bp1) {
- if (nu1->pntsu == 2) { /* remove completely */
- if (cu->actnu == nuindex)
- cu->actnu = -1;
-
- BLI_remlink(nubase, nu);
- BKE_nurb_free(nu); nu = NULL;
- }
- else if (nu1->flagu & CU_NURB_CYCLIC) { /* cyclic */
- bp = (BPoint *)MEM_mallocN((cut + 1) * sizeof(BPoint), "delNurb5");
- ED_curve_bpcpy(editnurb, bp, nu1->bp, cut + 1);
- a = nu1->pntsu - cut - 1;
- ED_curve_bpcpy(editnurb, nu1->bp, bp2, a);
- ED_curve_bpcpy(editnurb, &nu1->bp[a], bp, cut + 1);
-
- nu1->flagu &= ~CU_NURB_CYCLIC;
- MEM_freeN(bp);
- }
- else { /* add new curve */
- nu = (Nurb *)MEM_mallocN(sizeof(Nurb), "delNurb6");
- memcpy(nu, nu1, sizeof(Nurb));
- BLI_addtail(nubase, nu);
- nu->bp = (BPoint *)MEM_mallocN((cut + 1) * sizeof(BPoint), "delNurb7");
- ED_curve_bpcpy(editnurb, nu->bp, nu1->bp, cut + 1);
- a = nu1->pntsu - cut - 1;
- bp = (BPoint *)MEM_mallocN(a * sizeof(BPoint), "delNurb8");
- ED_curve_bpcpy(editnurb, bp, &nu1->bp[cut + 1], a);
- MEM_freeN(nu1->bp);
- nu1->bp = bp;
- nu1->pntsu = a;
- nu1->knotsu = NULL;
- nu->pntsu = cut + 1;
-
- BKE_nurb_order_clamp_u(nu);
- BKE_nurb_knot_calc_u(nu);
+ if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) {
+ /* start and points copied if connecting segment was deleted and not cylic spline */
+ bp1 = nu->bp;
+ bp2 = &nu->bp[1];
+ if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ nu1 = ED_curve_nurbcpy(nu, 1);
+ ED_curve_bpcpy(editnurb, nu1->bp, bp1, 1);
+ BLI_addtail(&newnurb, nu1);
+ nu1->knotsu = NULL;
+ }
- BKE_nurb_order_clamp_u(nu1);
- BKE_nurb_knot_calc_u(nu1);
+ bp1 = &nu->bp[nu->pntsu - 1];
+ bp2 = &nu->bp[nu->pntsu - 2];
+ if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ nu1 = ED_curve_nurbcpy(nu, 1);
+ ED_curve_bpcpy(editnurb, nu1->bp, bp1, 1);
+ BLI_addtail(&newnurb, nu1);
+ nu1->knotsu = NULL;
+ }
}
}
}
- }
- else if (type == 2) {
- cu->actnu = -1;
- keyIndex_delNurbList(editnurb, nubase);
+
BKE_nurbList_free(nubase);
+ BLI_movelisttolist(nubase, &newnurb);
+ }
+ else {
+ BLI_assert(0);
}
- if (ED_curve_updateAnimPaths(obedit->data))
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
-
return OPERATOR_FINISHED;
}
-static int delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int curve_delete_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
- uiPopupMenu *pup;
- uiLayout *layout;
+ eCurveElem_Types type = RNA_enum_get(op->ptr, "type");
+ int retval = curve_delete_selected(obedit, type, false);
+
+ if (retval == OPERATOR_FINISHED) {
+ if (ED_curve_updateAnimPaths(obedit->data)) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DAG_id_tag_update(obedit->data, 0);
+ return retval;
+ }
+
+ return retval;
+}
+
+static EnumPropertyItem curve_delete_type_items[] = {
+ {CURVE_VERTEX, "VERTICES", 0, "Vertices", ""},
+ {CURVE_SEGMENT, "SEGMENT", 0, "Segments", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static EnumPropertyItem *rna_curve_delete_type_itemf(bContext *C, PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop), int *free)
+{
+ Object *obedit;
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+
+
+ if (!C) /* needed for docs and i18n tools */
+ return curve_delete_type_items;
+
+ obedit = CTX_data_edit_object(C);
if (obedit->type == OB_SURF) {
- pup = uiPupMenuBegin(C, IFACE_("Delete"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
- uiItemEnumO_ptr(layout, op->type, NULL, 0, "type", 0);
- uiItemEnumO_ptr(layout, op->type, NULL, 0, "type", 2);
- uiPupMenuEnd(C, pup);
+ RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_VERTEX);
}
else {
- pup = uiPupMenuBegin(C, IFACE_("Delete"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
- uiItemsEnumO(layout, op->type->idname, "type");
- uiPupMenuEnd(C, pup);
+ RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_VERTEX);
+ RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_SEGMENT);
}
- return OPERATOR_CANCELLED;
+ RNA_enum_item_end(&item, &totitem);
+ *free = true;
+
+ return item;
}
void CURVE_OT_delete(wmOperatorType *ot)
{
- static EnumPropertyItem type_items[] = {
- {0, "SELECTED", 0, "Select", ""},
- {1, "SEGMENT", 0, "Segment", ""},
- {2, "ALL", 0, "All", ""},
- {0, NULL, 0, NULL, NULL}
- };
+ PropertyRNA *prop;
/* identifiers */
ot->name = "Delete";
@@ -6066,15 +6286,18 @@ void CURVE_OT_delete(wmOperatorType *ot)
ot->idname = "CURVE_OT_delete";
/* api callbacks */
- ot->exec = delete_exec;
- ot->invoke = delete_invoke;
+ ot->exec = curve_delete_exec;
+ ot->invoke = WM_menu_invoke;
ot->poll = ED_operator_editsurfcurve;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "Which elements to delete");
+ prop = RNA_def_enum(ot->srna, "type", curve_delete_type_items, 0, "Type", "Which elements to delete");
+ RNA_def_enum_funcs(prop, rna_curve_delete_type_itemf);
+
+ ot->prop = prop;
}
/********************** shade smooth/flat operator *********************/
@@ -6345,7 +6568,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type
nu->pntsu = 4;
nu->pntsv = 1;
nu->orderu = 4;
- nu->bp = CALLOC_STRUCT_N(BPoint, 4, "addNurbprim3");
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 4, "addNurbprim3");
bp = nu->bp;
for (a = 0; a < 4; a++, bp++) {
@@ -6381,7 +6604,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type
nu->orderu = 5;
nu->flagu = CU_NURB_ENDPOINT; /* endpoint */
nu->resolu = cu->resolu;
- nu->bp = CALLOC_STRUCT_N(BPoint, 5, "addNurbprim3");
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim3");
bp = nu->bp;
for (a = 0; a < 5; a++, bp++) {
@@ -6414,7 +6637,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type
if (cutype == CU_BEZIER) {
if (!force_3d) nu->flag |= CU_2D;
nu->pntsu = 4;
- nu->bezt = CALLOC_STRUCT_N(BezTriple, 4, "addNurbprim1");
+ nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * 4, "addNurbprim1");
nu->flagu = CU_NURB_CYCLIC;
bezt = nu->bezt;
@@ -6451,7 +6674,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type
nu->pntsu = 8;
nu->pntsv = 1;
nu->orderu = 4;
- nu->bp = CALLOC_STRUCT_N(BPoint, 8, "addNurbprim6");
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 8, "addNurbprim6");
nu->flagu = CU_NURB_CYCLIC;
bp = nu->bp;
@@ -6484,7 +6707,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type
nu->orderu = 4;
nu->orderv = 4;
nu->flag = CU_SMOOTH;
- nu->bp = CALLOC_STRUCT_N(BPoint, 4 * 4, "addNurbprim6");
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * (4 * 4), "addNurbprim6");
nu->flagu = 0;
nu->flagv = 0;
bp = nu->bp;
@@ -6546,7 +6769,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type
nu->resolu = cu->resolu;
nu->resolv = cu->resolv;
nu->flag = CU_SMOOTH;
- nu->bp = CALLOC_STRUCT_N(BPoint, 5, "addNurbprim6");
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim6");
nu->flagu = 0;
bp = nu->bp;
@@ -7158,6 +7381,22 @@ void ED_curve_bpcpy(EditNurb *editnurb, BPoint *dst, BPoint *src, int count)
keyIndex_updateBP(editnurb, src, dst, count);
}
+Nurb *ED_curve_nurbcpy(Nurb *src, int count)
+{
+ Nurb *newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "copyNurb");
+ memcpy(newnu, src, sizeof(Nurb));
+ newnu->pntsu = count;
+
+ if (src->bezt) {
+ newnu->bezt = (BezTriple *)MEM_mallocN(count * sizeof(BezTriple), "copyNurb2");
+ }
+ else {
+ newnu->bp = (BPoint *)MEM_mallocN(count * sizeof(BPoint), "copyNurb3");
+ }
+
+ return newnu;
+}
+
int ED_curve_actSelection(Curve *cu, float center[3])
{
Nurb *nu = get_lastsel_nurb(cu);
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 8d108644470..6adc500baa4 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -47,8 +47,18 @@ if(WITH_BLENDER)
# images
data_to_c_simple(../../../../release/datafiles/splash.png SRC)
+ # XXX These are handy, but give nasty "false changes" in svn :/
+ #svg_to_png(../../../../release/datafiles/blender_icons.svg
+ #../../../../release/datafiles/blender_icons16.png
+ #90 SRC)
data_to_c_simple(../../../../release/datafiles/blender_icons16.png SRC)
+ #svg_to_png(../../../../release/datafiles/blender_icons.svg
+ #../../../../release/datafiles/blender_icons32.png
+ #180 SRC)
data_to_c_simple(../../../../release/datafiles/blender_icons32.png SRC)
+ #svg_to_png(../../../../release/datafiles/prvicons.svg
+ #../../../../release/datafiles/prvicons.png
+ #90 SRC)
data_to_c_simple(../../../../release/datafiles/prvicons.png SRC)
# brushes
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 99157b074fd..c5dc8654e9d 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -106,8 +106,8 @@ bGPdata **gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr)
/* TODO: we can include other data-types such as bones later if need be... */
- /* just in case no active object */
- if (ob) {
+ /* just in case no active/selected object */
+ if (ob && (ob->flag & SELECT)) {
/* for now, as long as there's an object, default to using that in 3D-View */
if (ptr) RNA_id_pointer_create(&ob->id, ptr);
return &ob->gpd;
@@ -192,7 +192,14 @@ bGPdata *gpencil_data_get_active(const bContext *C)
/* needed for offscreen rendering */
bGPdata *gpencil_data_get_active_v3d(Scene *scene)
{
- bGPdata *gpd = scene->basact ? scene->basact->object->gpd : NULL;
+ Base *base = scene->basact;
+ bGPdata *gpd = NULL;
+ /* We have to make sure active object is actually visible and selected, else we must use default scene gpd,
+ * to be consistent with gpencil_data_get_active's behavior.
+ */
+ if (base && (scene->lay & base->lay) && (base->object->flag & SELECT)) {
+ gpd = base->object->gpd;
+ }
return gpd ? gpd : scene->gpd;
}
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 4c5727f16ed..da832554443 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -1679,7 +1679,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
/* loop over the stroke RNA elements recorded (i.e. progress of mouse movement),
* setting the relevant values in context at each step, then applying
*/
- RNA_BEGIN(op->ptr, itemptr, "stroke")
+ RNA_BEGIN (op->ptr, itemptr, "stroke")
{
float mousef[2];
diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h
index 541956136bd..27e62928f1b 100644
--- a/source/blender/editors/include/ED_clip.h
+++ b/source/blender/editors/include/ED_clip.h
@@ -63,18 +63,18 @@ int ED_space_clip_get_clip_frame_number(struct SpaceClip *sc);
struct ImBuf *ED_space_clip_get_buffer(struct SpaceClip *sc);
struct ImBuf *ED_space_clip_get_stable_buffer(struct SpaceClip *sc, float loc[2], float *scale, float *angle);
-int ED_space_clip_color_sample(struct SpaceClip *sc, struct ARegion *ar, int mval[2], float r_col[3]);
+bool ED_space_clip_color_sample(struct SpaceClip *sc, struct ARegion *ar, int mval[2], float r_col[3]);
void ED_clip_update_frame(const struct Main *mainp, int cfra);
-int ED_clip_view_selection(const struct bContext *C, struct ARegion *ar, int fit);
+bool ED_clip_view_selection(const struct bContext *C, struct ARegion *ar, bool fit);
void ED_clip_point_undistorted_pos(struct SpaceClip *sc, const float co[2], float r_co[2]);
void ED_clip_point_stable_pos(struct SpaceClip *sc, struct ARegion *ar, float x, float y, float *xr, float *yr);
void ED_clip_point_stable_pos__reverse(struct SpaceClip *sc, struct ARegion *ar, const float co[2], float r_co[2]);
void ED_clip_mouse_pos(struct SpaceClip *sc, struct ARegion *ar, const int mval[2], float co[2]);
-int ED_space_clip_check_show_trackedit(struct SpaceClip *sc);
-int ED_space_clip_check_show_maskedit(struct SpaceClip *sc);
+bool ED_space_clip_check_show_trackedit(struct SpaceClip *sc);
+bool ED_space_clip_check_show_maskedit(struct SpaceClip *sc);
struct MovieClip *ED_space_clip_get_clip(struct SpaceClip *sc);
void ED_space_clip_set_clip(struct bContext *C, struct bScreen *screen, struct SpaceClip *sc, struct MovieClip *clip);
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
index 1d26204095c..571788f4f8f 100644
--- a/source/blender/editors/include/ED_curve.h
+++ b/source/blender/editors/include/ED_curve.h
@@ -83,6 +83,7 @@ int CU_select_nth(struct Object *obedit, int nth);
void ED_curve_beztcpy(struct EditNurb *editnurb, struct BezTriple *dst, struct BezTriple *src, int count);
void ED_curve_bpcpy(struct EditNurb *editnurb, struct BPoint *dst, struct BPoint *src, int count);
+struct Nurb *ED_curve_nurbcpy(struct Nurb *src, int count);
int ED_curve_updateAnimPaths(struct Curve *cu);
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 95fad17274e..dc40efc748b 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -222,6 +222,7 @@ short ANIM_keyingset_context_ok_poll(struct bContext *C, struct KeyingSet *ks);
/* Flags for use by driver creation calls */
typedef enum eCreateDriverFlags {
CREATEDRIVER_WITH_DEFAULT_DVAR = (1 << 0), /* create drivers with a default variable for nicer UI */
+ CREATEDRIVER_WITH_FMODIFIER = (1 << 1), /* create drivers with Generator FModifier (for backwards compat) */
} eCreateDriverFlags;
/* -------- */
diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h
index 420ab24e5e9..3e2dbe255df 100644
--- a/source/blender/editors/include/ED_mask.h
+++ b/source/blender/editors/include/ED_mask.h
@@ -48,6 +48,8 @@ void ED_mask_point_pos(struct ScrArea *sa, struct ARegion *ar, float x, float y,
void ED_mask_point_pos__reverse(struct ScrArea *sa, struct ARegion *ar,
float x, float y, float *xr, float *yr);
+void ED_mask_cursor_location_get(struct ScrArea *sa, float cursor[2]);
+
void ED_operatortypes_mask(void);
void ED_keymap_mask(struct wmKeyConfig *keyconf);
void ED_operatormacros_mask(void);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 90b131e5acc..7553cb3699c 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -92,7 +92,7 @@ typedef enum eParentType {
PAR_PATH_CONST,
PAR_LATTICE,
PAR_VERTEX,
- PAR_TRIA
+ PAR_VERTEX_TRI
} eParentType;
#ifdef __RNA_TYPES_H__
@@ -101,7 +101,7 @@ extern struct EnumPropertyItem prop_make_parent_types[];
#endif
int ED_object_parent_set(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob,
- struct Object *par, int partype, int xmirror, int keep_transform);
+ struct Object *par, int partype, bool xmirror, bool keep_transform, const int vert_par[3]);
void ED_object_parent_clear(struct Object *ob, int type);
struct Base *ED_object_scene_link(struct Scene *scene, struct Object *ob);
@@ -123,6 +123,7 @@ struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, st
void ED_object_parent(struct Object *ob, struct Object *parent, int type, const char *substr);
+bool ED_object_mode_compat_set(struct bContext *C, struct Object *ob, int mode, struct ReportList *reports);
void ED_object_toggle_modes(struct bContext *C, int mode);
/* bitflags for enter/exit editmode */
diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h
index 9f42fd042c3..2b02606c6d9 100644
--- a/source/blender/editors/include/ED_screen_types.h
+++ b/source/blender/editors/include/ED_screen_types.h
@@ -79,7 +79,7 @@ typedef enum {
AE_RIGHT_TO_TOPLEFT, /* Region located on the left, _right_ edge is action zone. Region minimized to the top left */
AE_LEFT_TO_TOPRIGHT, /* Region located on the right, _left_ edge is action zone. Region minimized to the top right */
AE_TOP_TO_BOTTOMRIGHT, /* Region located at the bottom, _top_ edge is action zone. Region minimized to the bottom right */
- AE_BOTTOM_TO_TOPLEFT /* Region located at the top, _bottom_edge is action zone. Region minimized to the top left */
+ AE_BOTTOM_TO_TOPLEFT /* Region located at the top, _bottom_ edge is action zone. Region minimized to the top left */
} AZEdge;
/* for editing areas/regions */
@@ -87,10 +87,8 @@ typedef struct AZone {
struct AZone *next, *prev;
ARegion *ar;
int type;
- /* region-azone, which of the edges */
+ /* region-azone, which of the edges (only for AZONE_REGION) */
AZEdge edge;
- /* internal */
- short do_draw;
/* for draw */
short x1, y1, x2, y2;
/* for clip */
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index ffc9e6651bc..735227ae9b5 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -102,7 +102,7 @@ void ED_uvedit_live_unwrap(struct Scene *scene, struct Object *obedit);
void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel);
/* uvedit_draw.c */
-void draw_image_cursor(struct SpaceImage *sima, struct ARegion *ar);
+void draw_image_cursor(struct ARegion *ar, const float cursor[2]);
void draw_uvedit_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct Object *obedit, struct Object *obact);
/* uvedit_buttons.c */
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 3929cf9788c..f8e1bbb2413 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -49,9 +49,7 @@ DEF_ICON(RADIOBUT_OFF)
DEF_ICON(RADIOBUT_ON)
DEF_ICON(MENU_PANEL)
DEF_ICON(BLENDER)
-#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK003)
-#endif
+DEF_ICON(GRIP)
DEF_ICON(DOT)
#ifndef DEF_ICON_BLANK_SKIP
DEF_ICON(BLANK004)
@@ -75,9 +73,9 @@ DEF_ICON(VIEWZOOM)
DEF_ICON(ZOOMIN)
DEF_ICON(ZOOMOUT)
DEF_ICON(PANEL_CLOSE)
-DEF_ICON(COPY_ID) //ICON_BLANK009
+DEF_ICON(COPY_ID)
DEF_ICON(EYEDROPPER)
-DEF_ICON(LINK_AREA) //ICON_BLANK010
+DEF_ICON(LINK_AREA)
DEF_ICON(AUTO)
DEF_ICON(CHECKBOX_DEHLT)
DEF_ICON(CHECKBOX_HLT)
@@ -138,7 +136,7 @@ DEF_ICON(SCRIPT)
DEF_ICON(PARTICLES)
DEF_ICON(PHYSICS)
DEF_ICON(SPEAKER)
-DEF_ICON(TEXTURE_SHADED) //ICON_BLANK041
+DEF_ICON(TEXTURE_SHADED)
#ifndef DEF_ICON_BLANK_SKIP
DEF_ICON(BLANK042)
DEF_ICON(BLANK043)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 9a9cab9b46c..8b395505623 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -32,6 +32,7 @@
#ifndef __UI_INTERFACE_H__
#define __UI_INTERFACE_H__
+#include "BLI_compiler_attrs.h"
#include "BLI_sys_types.h" /* size_t */
#include "RNA_types.h"
#include "DNA_userdef_types.h"
@@ -327,30 +328,14 @@ typedef void (*uiMenuHandleFunc)(struct bContext *C, void *arg, int event);
typedef struct uiPopupMenu uiPopupMenu;
-struct uiPopupMenu *uiPupMenuBegin(struct bContext *C, const char *title, int icon)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
+struct uiPopupMenu *uiPupMenuBegin(struct bContext *C, const char *title, int icon) ATTR_NONNULL();
void uiPupMenuEnd(struct bContext *C, struct uiPopupMenu *head);
struct uiLayout *uiPupMenuLayout(uiPopupMenu *head);
-void uiPupMenuOkee(struct bContext *C, const char *opname, const char *str, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 3, 4)))
-#endif
-;
+void uiPupMenuOkee(struct bContext *C, const char *opname, const char *str, ...) ATTR_PRINTF_FORMAT(3, 4);
void uiPupMenuSaveOver(struct bContext *C, struct wmOperator *op, const char *filename);
-void uiPupMenuNotice(struct bContext *C, const char *str, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 2, 3)))
-#endif
-;
-void uiPupMenuError(struct bContext *C, const char *str, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 2, 3)))
-#endif
-;
+void uiPupMenuNotice(struct bContext *C, const char *str, ...) ATTR_PRINTF_FORMAT(2, 3);
+void uiPupMenuError(struct bContext *C, const char *str, ...) ATTR_PRINTF_FORMAT(2, 3);
void uiPupMenuReports(struct bContext *C, struct ReportList *reports);
void uiPupMenuInvoke(struct bContext *C, const char *idname); /* popup registered menu */
@@ -550,11 +535,7 @@ typedef struct uiStringInfo {
/* Note: Expects pointers to uiStringInfo structs as parameters.
* Will fill them with translated strings, when possible.
* Strings in uiStringInfo must be MEM_freeN'ed by caller. */
-void uiButGetStrInfo(struct bContext *C, uiBut *but, ...)
-#ifdef __GNUC__
-__attribute__((sentinel))
-#endif
-;
+void uiButGetStrInfo(struct bContext *C, uiBut *but, ...) ATTR_SENTINEL(0);
/* Edit i18n stuff. */
/* Name of the main py op from i18n addon. */
@@ -845,7 +826,7 @@ void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
#define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list"
void uiTemplateList(uiLayout *layout, struct bContext *C, const char *listtype_name, const char *list_id,
struct PointerRNA *dataptr, const char *propname, struct PointerRNA *active_dataptr,
- const char *active_propname, int rows, int maxrows, int layout_type);
+ const char *active_propname, int rows, int maxrows, int layout_type, int columns);
void uiTemplateNodeLink(uiLayout *layout, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input);
void uiTemplateNodeView(uiLayout *layout, struct bContext *C, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input);
void uiTemplateTextureUser(uiLayout *layout, struct bContext *C);
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 42e9d892871..0c8a39a6714 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -210,6 +210,9 @@ enum {
TH_STITCH_PREVIEW_UNSTITCHABLE,
TH_STITCH_PREVIEW_ACTIVE,
+ TH_UV_SHADOW,
+ TH_UV_OTHERS,
+
TH_FREESTYLE_EDGE_MARK,
TH_FREESTYLE_FACE_MARK,
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index e46334b06e7..fb70ad50b5d 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -192,6 +192,7 @@ void UI_view2d_listview_visible_cells(struct View2D *v2d, float columnwidth, flo
void UI_view2d_region_to_view(struct View2D *v2d, float x, float y, float *viewx, float *viewy);
void UI_view2d_view_to_region(struct View2D *v2d, float x, float y, int *regionx, int *regiony);
void UI_view2d_to_region_no_clip(struct View2D *v2d, float x, float y, int *regionx, int *region_y);
+void UI_view2d_to_region_float(struct View2D *v2d, float x, float y, float *regionx, float *regiony);
/* utilities */
struct View2D *UI_view2d_fromcontext(const struct bContext *C);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 21a63183c1a..ec5a4d0027d 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -985,7 +985,7 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but,
IDPropertyTemplate val = {0};
prop_path = IDP_New(IDP_GROUP, &val, __func__);
- prop_path_value = IDP_NewString(data_path, "data_path", strlen(data_path) + 1); /* len + 1, or else will be truncated */
+ prop_path_value = IDP_NewString(data_path, "data_path", strlen(data_path) + 1);
IDP_AddToGroup(prop_path, prop_path_value);
/* check each until one works... */
@@ -1807,12 +1807,14 @@ static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double va
static float ui_get_but_step_unit(uiBut *but, float step_default)
{
int unit_type = RNA_SUBTYPE_UNIT_VALUE(uiButGetUnitType(but));
- float step;
+ double step;
step = bUnit_ClosestScalar(ui_get_but_scale_unit(but, step_default), but->block->unit->system, unit_type);
- if (step > 0.0f) { /* -1 is an error value */
- return (float)((double)step / ui_get_but_scale_unit(but, 1.0)) * 100.0f;
+ /* -1 is an error value */
+ if (step != -1.0) {
+ BLI_assert(step > 0.0);
+ return (float)(step / ui_get_but_scale_unit(but, 1.0)) * 100.0f;
}
else {
return step_default;
@@ -2047,13 +2049,14 @@ bool ui_set_but_string(bContext *C, uiBut *but, const char *str)
return false;
}
-void ui_set_but_default(bContext *C, short all)
+void ui_set_but_default(bContext *C, const bool all)
{
+ const char *opstring = "UI_OT_reset_default_button";
PointerRNA ptr;
- WM_operator_properties_create(&ptr, "UI_OT_reset_default_button");
+ WM_operator_properties_create(&ptr, opstring);
RNA_boolean_set(&ptr, "all", all);
- WM_operator_name_call(C, "UI_OT_reset_default_button", WM_OP_EXEC_DEFAULT, &ptr);
+ WM_operator_name_call(C, opstring, WM_OP_EXEC_DEFAULT, &ptr);
WM_operator_properties_free(&ptr);
}
@@ -2230,8 +2233,7 @@ void uiFreeBlock(const bContext *C, uiBlock *block)
{
uiBut *but;
- while ( (but = block->buttons.first) ) {
- BLI_remlink(&block->buttons, but);
+ while ((but = BLI_pophead(&block->buttons))) {
ui_free_but(C, but);
}
@@ -2255,8 +2257,7 @@ void uiFreeBlocks(const bContext *C, ListBase *lb)
{
uiBlock *block;
- while ( (block = lb->first) ) {
- BLI_remlink(lb, block);
+ while ((block = BLI_pophead(lb))) {
uiFreeBlock(C, block);
}
}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index f9ee2b67e6b..dc7813510ec 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -152,7 +152,9 @@ typedef struct uiHandleButtonData {
char *str, *origstr;
double value, origvalue, startvalue;
float vec[3], origvec[3];
+#if 0 /* UNUSED */
int togdual, togonly;
+#endif
ColorBand *coba;
/* tooltip */
@@ -170,6 +172,7 @@ typedef struct uiHandleButtonData {
/* coords are Window/uiBlock relative (depends on the button) */
int draglastx, draglasty;
int dragstartx, dragstarty;
+ int draglastvalue;
bool dragchange, draglock;
int dragsel;
float dragf, dragfstart;
@@ -2660,8 +2663,10 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
#ifdef USE_DRAG_TOGGLE
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (event->type == LEFTMOUSE && event->val == KM_PRESS && ui_is_but_bool(but)) {
+#if 0 /* UNUSED */
data->togdual = event->ctrl;
data->togonly = !event->shift;
+#endif
ui_apply_button(C, but->block, but, data, true);
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
data->dragstartx = event->x;
@@ -2677,8 +2682,10 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
#endif
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+#if 0 /* UNUSED */
data->togdual = event->ctrl;
data->togonly = !event->shift;
+#endif
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_BREAK;
}
@@ -3406,6 +3413,100 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
return retval;
}
+static int ui_do_but_LISTBOX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ uiList *ui_list = but->custom_data;
+ int *size = (int *)but->poin;
+ int mx, my, raw_dir_sign;
+ int retval = WM_UI_HANDLER_CONTINUE;
+
+ mx = event->x;
+ my = event->y;
+
+ /* We find the direction of the mouse since last time, before converting coordinates into block's space.
+ * We'll use it to avoid flickering in case some rows are higher than UI_UNIT_Y.
+ */
+ raw_dir_sign = (data->draglasty - my < 0) ? -1 : 1;
+ data->draglasty = my;
+
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if (data->state == BUTTON_STATE_NUM_EDITING) {
+ if (event->type == ESCKEY) {
+ data->cancel = true;
+ data->escapecancel = true;
+ *size = (int)data->origvalue;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ ui_list->flag &= ~UILST_RESIZING;
+ ED_region_tag_redraw(data->region);
+ }
+ else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ ui_list->flag &= ~UILST_RESIZING;
+ ED_region_tag_redraw(data->region);
+ }
+ else if (event->type == MOUSEMOVE) {
+ /* If we switched from dragged to auto size, suspend shrinking dragging and set dragstarty to a temp
+ * refpoint.
+ */
+ if (data->draglastvalue > 0 && *size == 0) {
+ data->draglastvalue = *size;
+ data->dragstartx = data->dragstarty; /* draglasty already used... */
+ data->dragstarty = my;
+ }
+ else {
+ int delta = data->dragstarty - my;
+ /* We only actually do something if the real mousemouve direction matches the "virtual"
+ * mousemove direction in current block's space. This avoids flickering when drag-resizing lists with
+ * items drawing higher that UI_UNIT_Y.
+ */
+ if (delta * raw_dir_sign > 0) {
+ /* Number of rows to show/hide, UI_UNIT_Y should work nice in most cases. */
+ delta = (int)floorf(((float)delta / (float)UI_UNIT_Y) + 0.5f);
+
+ /* If we are not in autosize mode, default behavior... */
+ if (*size > 0 && delta != 0) {
+ /* This prevents some instability in case some items draw more/less than UI_UNIT_Y height. */
+ delta = (delta < -5) ? -5 : (delta > 5) ? 5 : delta;
+ /* We can't use ui_numedit_apply()... */
+ /* list template will clamp, but we do not want to reach 0 aka autosize mode! */
+ *size = max_ii(*size + delta, 1);
+
+ /* Used to detect switch to/from autosize mode. */
+ data->draglastvalue = *size;
+
+ data->dragchange = true;
+ data->applied = data->applied_interactive = true;
+
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+ ED_region_tag_redraw(data->region);
+ }
+ /* If we are leaving autosize mode (growing dragging), restore to minimal size. */
+ else if (delta > 0) {
+ /* We can't use ui_numedit_apply()... */
+ *size = ui_list->dyn_data->visual_height_min;
+
+ /* Restore real dragstarty value! */
+ data->dragstarty = data->dragstartx;
+
+ /* Used to detect switch to/from autosize mode. */
+ data->draglastvalue = *size;
+
+ data->dragchange = true;
+ data->applied = data->applied_interactive = true;
+
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+ ED_region_tag_redraw(data->region);
+ }
+ }
+ }
+ }
+
+ retval = WM_UI_HANDLER_BREAK;
+ }
+
+ return retval;
+}
static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
@@ -5161,13 +5262,12 @@ static bool ui_but_menu(bContext *C, uiBut *but)
}
/* Show header tools for header buttons. */
- if (CTX_wm_region(C)) {
+ {
ARegion *ar = CTX_wm_region(C);
- if (ar->regiontype == RGN_TYPE_HEADER) {
-
- uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL);
- uiItemS(layout);
- }
+ if (ar && (ar->regiontype == RGN_TYPE_HEADER)) {
+ uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL);
+ uiItemS(layout);
+ }
}
{ /* Docs */
@@ -5273,7 +5373,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
ui_but_anim_insert_keyframe(C);
}
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw(data->region);
return WM_UI_HANDLER_BREAK;
}
@@ -5287,7 +5387,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
else
ui_but_anim_add_driver(C);
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw(data->region);
return WM_UI_HANDLER_BREAK;
}
@@ -5301,17 +5401,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
else
ui_but_anim_add_keyingset(C);
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw(data->region);
return WM_UI_HANDLER_BREAK;
}
- /* reset to default */
- /* XXX hardcoded keymap check.... */
- else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) {
- /* ctrl+backspace = reset active button; backspace = reset a whole array*/
- if (!(ELEM3(but->type, HSVCIRCLE, HSVCUBE, HISTOGRAM)))
- ui_set_but_default(C, !event->ctrl);
- }
/* handle menu */
else if (event->type == RIGHTMOUSE && event->val == KM_PRESS) {
/* RMB has two options now */
@@ -5367,8 +5460,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case NUMSLI:
retval = ui_do_but_SLI(C, block, but, data, event);
break;
- case ROUNDBOX:
case LISTBOX:
+ retval = ui_do_but_LISTBOX(C, block, but, data, event);
+ break;
+ case ROUNDBOX:
case LABEL:
case LISTLABEL:
case ROW:
@@ -5436,7 +5531,22 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case BUT_EXTRA:
break;
}
-
+
+
+ /* reset to default (generic function, only use if not handled by switch above) */
+ /* XXX hardcoded keymap check.... */
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if ((retval == WM_UI_HANDLER_CONTINUE) &&
+ (event->type == BACKSPACEKEY && event->val == KM_PRESS))
+ {
+ /* ctrl+backspace = reset active button; backspace = reset a whole array*/
+ ui_set_but_default(C, !event->ctrl);
+ ED_region_tag_redraw(data->region);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
+
+
return retval;
}
@@ -5622,8 +5732,6 @@ static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y)
uiBut *but;
int mx, my;
-// if (!win->active)
-// return NULL;
if (!ui_mouse_inside_region(ar, x, y))
return NULL;
@@ -5768,7 +5876,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
WM_cursor_grab_disable(data->window, NULL);
}
#else
- WM_cursor_grab_disable(data->window, );
+ WM_cursor_grab_disable(data->window, NULL);
#endif
}
}
@@ -6423,90 +6531,166 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar)
{
- uiBut *but = ui_list_find_mouse_over(ar, event->x, event->y);
+ uiBut *but, *dragbut;
+ uiList *ui_list;
+ uiListDyn *dyn_data;
int retval = WM_UI_HANDLER_CONTINUE;
int type = event->type, val = event->val;
+ int mx, my;
+ bool is_over_dragbut = false;
- if (but) {
- uiList *ui_list = but->custom_data;
+ but = ui_list_find_mouse_over(ar, event->x, event->y);
+ if (!but) {
+ return retval;
+ }
- if (ui_list) {
-
- /* convert pan to scrollwheel */
- if (type == MOUSEPAN) {
- ui_pan_to_scroll(event, &type, &val);
-
- /* if type still is mousepan, we call it handled, since delta-y accumulate */
- /* also see wm_event_system.c do_wheel_ui hack */
- if (type == MOUSEPAN)
- retval = WM_UI_HANDLER_BREAK;
- }
-
- if (val == KM_PRESS) {
-
- if (ELEM(type, UPARROWKEY, DOWNARROWKEY) ||
- ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
- {
- const int value_orig = RNA_property_int_get(&but->rnapoin, but->rnaprop);
- int value, min, max;
+ ui_list = but->custom_data;
+ if (!ui_list || !ui_list->dyn_data) {
+ return retval;
+ }
+ dyn_data = ui_list->dyn_data;
- /* activate up/down the list */
- value = value_orig;
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(ar, but->block, &mx, &my);
- if (ELEM(type, UPARROWKEY, WHEELUPMOUSE))
- value--;
- else
- value++;
+ /* Find our "dragging" button. */
+ for (dragbut = but->block->buttons.first; dragbut; dragbut = dragbut->next) {
+ if (dragbut->poin == (void *)ui_list) {
+ break;
+ }
+ }
+ if (dragbut && dragbut == ui_but_find_mouse_over(ar, event->x, event->y)) {
+ is_over_dragbut = true;
+ }
- CLAMP(value, 0, ui_list->list_last_len - 1);
+ if (is_over_dragbut && type == LEFTMOUSE && val == KM_PRESS) {
+ uiHandleButtonData *data;
+ int *size = (int *)but->poin;
- if (value < ui_list->list_scroll)
- ui_list->list_scroll = value;
- else if (value >= ui_list->list_scroll + ui_list->list_size)
- ui_list->list_scroll = value - ui_list->list_size + 1;
+ ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE);
+ button_activate_state(C, but, BUTTON_STATE_INIT);
+
+ data = but->active;
+ data->dragstarty = my;
- RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
- value = CLAMPIS(value, min, max);
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- if (value != value_orig) {
- RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
- RNA_property_update(C, &but->rnapoin, but->rnaprop);
+ /* Again, have to override values set by ui_numedit_begin, because our listbox button also has a rnapoin... */
+ *size = data->origvalue = (double)dyn_data->visual_height;
+ ui_list->flag |= UILST_RESIZING;
- ui_apply_undo(but);
- ED_region_tag_redraw(ar);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else {
+ /* convert pan to scrollwheel */
+ if (type == MOUSEPAN) {
+ ui_pan_to_scroll(event, &type, &val);
+
+ /* if type still is mousepan, we call it handled, since delta-y accumulate */
+ /* also see wm_event_system.c do_wheel_ui hack */
+ if (type == MOUSEPAN)
+ retval = WM_UI_HANDLER_BREAK;
+ }
+
+ if (val == KM_PRESS) {
+ if (ELEM(type, UPARROWKEY, DOWNARROWKEY) ||
+ ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
+ {
+ const int value_orig = RNA_property_int_get(&but->rnapoin, but->rnaprop);
+ int value, min, max, inc;
+
+ /* activate up/down the list */
+ value = value_orig;
+ if ((ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0) {
+ inc = ELEM(type, UPARROWKEY, WHEELUPMOUSE) ? 1 : -1;
+ }
+ else {
+ inc = ELEM(type, UPARROWKEY, WHEELUPMOUSE) ? -1 : 1;
+ }
+
+ if (dyn_data->items_filter_neworder || dyn_data->items_filter_flags) {
+ /* If we have a display order different from collection order, we have some work! */
+ int *org_order = MEM_mallocN(dyn_data->items_shown * sizeof(int), AT);
+ int *new_order = dyn_data->items_filter_neworder;
+ int i, org_idx = -1, len = dyn_data->items_len;
+ int current_idx = -1;
+ int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
+
+ for (i = 0; i < len; i++) {
+ if (!dyn_data->items_filter_flags ||
+ ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude))
+ {
+ org_order[new_order ? new_order[++org_idx] : ++org_idx] = i;
+ if (i == value) {
+ current_idx = new_order ? new_order[org_idx] : org_idx;
+ }
+ }
+ else if (i == value && org_idx >= 0) {
+ current_idx = -(new_order ? new_order[org_idx] : org_idx) - 1;
+ }
+ }
+ /* Now, org_order maps displayed indices to real indices,
+ * and current_idx either contains the displayed index of active value (positive),
+ * or its more-nearest one (negated).
+ */
+ if (current_idx < 0) {
+ current_idx = (current_idx * -1) + (inc < 0 ? inc : inc - 1);
+ }
+ else {
+ current_idx += inc;
}
+ CLAMP(current_idx, 0, dyn_data->items_shown - 1);
+ value = org_order[current_idx];
+ MEM_freeN(org_order);
+ }
+ else {
+ value += inc;
+ }
- retval = WM_UI_HANDLER_BREAK;
+ CLAMP(value, 0, dyn_data->items_len - 1);
+
+ RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
+ CLAMP(value, min, max);
+
+ if (value != value_orig) {
+ RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
+ RNA_property_update(C, &but->rnapoin, but->rnaprop);
+
+ ui_apply_undo(but);
+
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+ ED_region_tag_redraw(ar);
}
- else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
- /* silly replacement for proper grip */
- if (ui_list->list_grip_size == 0)
- ui_list->list_grip_size = ui_list->list_size;
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
+ /* We now have proper grip, but keep this anyway! */
+ if (ui_list->list_grip == 0)
+ ui_list->list_grip = dyn_data->visual_height;
+ /* list template will clamp */
+ if (type == WHEELUPMOUSE)
+ ui_list->list_grip--;
+ else
+ ui_list->list_grip++;
+
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+ ED_region_tag_redraw(ar);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
+ if (dyn_data->height > dyn_data->visual_height) {
+ /* list template will clamp */
if (type == WHEELUPMOUSE)
- ui_list->list_grip_size--;
+ ui_list->list_scroll--;
else
- ui_list->list_grip_size++;
-
- ui_list->list_grip_size = MAX2(ui_list->list_grip_size, 1);
+ ui_list->list_scroll++;
ED_region_tag_redraw(ar);
retval = WM_UI_HANDLER_BREAK;
}
- else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
- if (ui_list->list_last_len > ui_list->list_size) {
- /* list template will clamp */
- if (type == WHEELUPMOUSE)
- ui_list->list_scroll--;
- else
- ui_list->list_scroll++;
-
- ED_region_tag_redraw(ar);
-
- retval = WM_UI_HANDLER_BREAK;
- }
- }
}
}
}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index d2a8c47b347..0b02a1a5db4 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -393,7 +393,7 @@ extern bool ui_set_but_string(struct bContext *C, uiBut *but, const char *str);
extern bool ui_set_but_string_eval_num(struct bContext *C, uiBut *but, const char *str, double *value);
extern int ui_get_but_string_max_length(uiBut *but);
-extern void ui_set_but_default(struct bContext *C, short all);
+extern void ui_set_but_default(struct bContext *C, const bool all);
extern void ui_check_but(uiBut *but);
extern bool ui_is_but_float(uiBut *but);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 079ba97aa9d..424d2231a03 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -471,6 +471,8 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
but->type = NUMSLI;
if (toggle && but->type == OPTION)
but->type = TOG;
+ if ((a == 0) && (subtype == PROP_AXISANGLE))
+ uiButSetUnitType(but, PROP_UNIT_ROTATION);
}
if (boolarr) {
@@ -568,7 +570,7 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n
PropertySubType subtype;
int labelw;
- sub = uiLayoutRow(layout, FALSE);
+ sub = uiLayoutRow(layout, layout->align);
uiBlockSetCurLayout(block, sub);
if (name[0]) {
@@ -1465,6 +1467,7 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna
uiBlock *block;
StructRNA *icontype;
int w, h;
+ char namestr[UI_MAX_NAME_STR];
/* validate arguments */
prop = RNA_struct_find_property(ptr, propname);
@@ -1507,6 +1510,8 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna
if (!name)
name = RNA_property_ui_name(prop);
+ name = ui_item_name_add_colon(name, namestr);
+
/* create button */
block = uiLayoutGetBlock(layout);
@@ -2429,6 +2434,15 @@ uiLayout *uiLayoutListBox(uiLayout *layout, uiList *ui_list, PointerRNA *ptr, Pr
but->rnapoin = *actptr;
but->rnaprop = actprop;
+ /* Resizing data. */
+ /* Note: we can't use usual "num button" value handling, as it only tries rnapoin when it is non-NULL... :/
+ * So just setting but->poin, not but->pointype.
+ */
+ but->poin = (void *)&ui_list->list_grip;
+ but->hardmin = but->softmin = 0.0f;
+ but->hardmax = but->softmax = 1000.0f; /* Should be more than enough! */
+ but->a1 = 0.0f;
+
/* only for the undo string */
if (but->flag & UI_BUT_UNDO) {
but->tip = RNA_property_description(actprop);
@@ -2678,8 +2692,9 @@ static void ui_item_align(uiLayout *litem, short nr)
BLI_remlink(&litem->root->block->buttons, box->roundbox);
BLI_addhead(&litem->root->block->buttons, box->roundbox);
}
- else
+ else if (((uiLayout *)item)->align) {
ui_item_align((uiLayout *)item, nr);
+ }
}
}
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 95f47be0b70..832dd4d23ce 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -2605,12 +2605,10 @@ static void confirm_cancel_operator(bContext *UNUSED(C), void *opv)
WM_operator_free(opv);
}
-static void vconfirm_opname(bContext *C, const char *opname, const char *title, const char *itemfmt, va_list ap)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 4, 0)))
-#endif
-;
-static void vconfirm_opname(bContext *C, const char *opname, const char *title, const char *itemfmt, va_list ap)
+static void vconfirm_opname(bContext *C, const char *opname, const char *title,
+ const char *itemfmt, va_list ap) ATTR_PRINTF_FORMAT(4, 0);
+static void vconfirm_opname(bContext *C, const char *opname, const char *title,
+ const char *itemfmt, va_list ap)
{
uiPopupBlockHandle *handle;
char *s, buf[512];
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 61cc021800e..4e79fd19f24 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -1,4 +1,5 @@
/*
+
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -43,6 +44,7 @@
#include "BLI_rect.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_fnmatch.h"
#include "BLF_api.h"
#include "BLF_translation.h"
@@ -1017,6 +1019,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
Scene *scene = CTX_data_scene(C);
Object *ob;
ModifierData *md, *vmd;
+ VirtualModifierData virtualModifierData;
int i, lastCageIndex, cageIndex;
/* verify we have valid data */
@@ -1039,7 +1042,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0);
/* XXX virtual modifiers are not accesible for python */
- vmd = modifiers_getVirtualModifierList(ob);
+ vmd = modifiers_getVirtualModifierList(ob, &virtualModifierData);
for (i = 0; vmd; i++, vmd = vmd->next) {
if (md == vmd)
@@ -1145,9 +1148,10 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
uiBlockSetEmboss(block, UI_EMBOSSN);
uiItemR(row, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
uiBlockSetEmboss(block, UI_EMBOSS);
-
+
/* name */
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco + 0.5f*UI_UNIT_X, yco, 5 * UI_UNIT_X, 0.9f*UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr,
+ xco + 0.5f * UI_UNIT_X, yco, 5 * UI_UNIT_X, 0.9f * UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "");
if (con->flag & CONSTRAINT_DISABLE)
uiLayoutSetRedAlert(row, TRUE);
@@ -2468,7 +2472,7 @@ void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propnam
static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout,
struct PointerRNA *UNUSED(dataptr), struct PointerRNA *itemptr, int icon,
struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname),
- int UNUSED(index))
+ int UNUSED(index), int UNUSED(flt_flag))
{
char *namebuf;
const char *name;
@@ -2494,30 +2498,245 @@ static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UN
}
}
+static void uilist_draw_filter_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout)
+{
+ PointerRNA listptr;
+ uiLayout *row, *subrow;
+
+ RNA_pointer_create(NULL, &RNA_UIList, ui_list, &listptr);
+
+ row = uiLayoutRow(layout, FALSE);
+
+ subrow = uiLayoutRow(row, TRUE);
+ uiItemR(subrow, &listptr, "filter_name", 0, "", ICON_NONE);
+ uiItemR(subrow, &listptr, "use_filter_invert", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "",
+ (ui_list->filter_flag & UILST_FLT_EXCLUDE) ? ICON_ZOOM_OUT : ICON_ZOOM_IN);
+
+ subrow = uiLayoutRow(row, TRUE);
+ uiItemR(subrow, &listptr, "use_filter_sort_alpha", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ uiItemR(subrow, &listptr, "use_filter_sort_reverse", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "",
+ (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) ? ICON_TRIA_UP : ICON_TRIA_DOWN);
+}
+
+typedef struct {
+ char name[MAX_IDPROP_NAME];
+ int org_idx;
+} StringCmp;
+
+static int cmpstringp(const void *p1, const void *p2)
+{
+ /* Case-insensitive comparison. */
+ return BLI_strcasecmp(((StringCmp *) p1)->name, ((StringCmp *) p2)->name);
+}
+
+static void uilist_filter_items_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct PointerRNA *dataptr,
+ const char *propname)
+{
+ uiListDyn *dyn_data = ui_list->dyn_data;
+ PropertyRNA *prop = RNA_struct_find_property(dataptr, propname);
+
+ const char *filter_raw = ui_list->filter_byname;
+ char *filter = (char *)filter_raw, filter_buff[32], *filter_dyn = NULL;
+ bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0;
+ bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_ALPHA) != 0;
+ int len = RNA_property_collection_length(dataptr, prop);
+
+ dyn_data->items_shown = dyn_data->items_len = len;
+
+ if (len && (order_by_name || filter_raw[0])) {
+ StringCmp *names = NULL;
+ int order_idx = 0, i = 0;
+
+ if (order_by_name) {
+ names = MEM_callocN(sizeof(StringCmp) * len, AT);
+ }
+ if (filter_raw[0]) {
+ size_t idx = 0, slen = strlen(filter_raw);
+
+ dyn_data->items_filter_flags = MEM_callocN(sizeof(int) * len, AT);
+ dyn_data->items_shown = 0;
+
+ /* Implicitly add heading/trailing wildcards if needed. */
+ if (len + 3 <= 32) {
+ filter = filter_buff;
+ }
+ else {
+ filter = filter_dyn = MEM_mallocN((slen + 3) * sizeof(char), AT);
+ }
+ if (filter_raw[idx] != '*') {
+ filter[idx++] = '*';
+ }
+ memcpy(filter + idx, filter_raw, slen);
+ idx += slen;
+ if (filter[idx - 1] != '*') {
+ filter[idx++] = '*';
+ }
+ filter[idx] = '\0';
+ }
+
+ RNA_PROP_BEGIN (dataptr, itemptr, prop)
+ {
+ char *namebuf;
+ const char *name;
+ bool do_order = false;
+
+ namebuf = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL);
+ name = namebuf ? namebuf : "";
+
+ if (filter[0]) {
+ /* Case-insensitive! */
+ if (fnmatch(filter, name, FNM_CASEFOLD) == 0) {
+ dyn_data->items_filter_flags[i] = UILST_FLT_ITEM;
+ if (!filter_exclude) {
+ dyn_data->items_shown++;
+ do_order = order_by_name;
+ }
+ //printf("%s: '%s' matches '%s'\n", __func__, name, filter);
+ }
+ else if (filter_exclude) {
+ dyn_data->items_shown++;
+ do_order = order_by_name;
+ }
+ }
+ else {
+ do_order = order_by_name;
+ }
+
+ if (do_order) {
+ names[order_idx].org_idx = order_idx;
+ BLI_strncpy(names[order_idx++].name, name, MAX_IDPROP_NAME);
+ }
+
+ /* free name */
+ if (namebuf) {
+ MEM_freeN(namebuf);
+ }
+ i++;
+ }
+ RNA_PROP_END;
+
+ if (order_by_name) {
+ int new_idx;
+ /* note: order_idx equals either to ui_list->items_len if no filtering done,
+ * or to ui_list->items_shown if filter is enabled,
+ * or to (ui_list->items_len - ui_list->items_shown) if filtered items are excluded.
+ * This way, we only sort items we actually intend to draw!
+ */
+ qsort(names, order_idx, sizeof(StringCmp), cmpstringp);
+
+ dyn_data->items_filter_neworder = MEM_mallocN(sizeof(int) * order_idx, AT);
+ for (new_idx = 0; new_idx < order_idx; new_idx++) {
+ dyn_data->items_filter_neworder[names[new_idx].org_idx] = new_idx;
+ }
+ }
+
+ if (filter_dyn) {
+ MEM_freeN(filter_dyn);
+ }
+ if (names) {
+ MEM_freeN(names);
+ }
+ }
+}
+
+typedef struct {
+ PointerRNA item;
+ int org_idx;
+ int flt_flag;
+} _uilist_item;
+
+typedef struct {
+ int visual_items; /* Visual number of items (i.e. number of items we have room to display). */
+ int start_idx; /* Index of first item to display. */
+ int end_idx; /* Index of last item to display + 1. */
+} uiListLayoutdata;
+
+static void prepare_list(uiList *ui_list, int len, int activei, int rows, int maxrows, int columns,
+ uiListLayoutdata *layoutdata)
+{
+ uiListDyn *dyn_data = ui_list->dyn_data;
+ int activei_row, max_scroll;
+
+ /* default rows */
+ if (rows == 0)
+ rows = 5;
+ dyn_data->visual_height_min = rows;
+ if (maxrows == 0)
+ maxrows = 5;
+ if (columns == 0)
+ columns = 9;
+
+ if (ui_list->list_grip >= rows) {
+ maxrows = rows = ui_list->list_grip;
+ }
+ else {
+ ui_list->list_grip = 0; /* Reset to auto-size mode. */
+ /* Prevent auto-size mode to take effect while grab-resizing! */
+ if (ui_list->flag & UILST_RESIZING) {
+ maxrows = rows;
+ }
+ }
+
+ if (columns > 1) {
+ dyn_data->height = (int)ceil((double)len / (double)columns);
+ activei_row = (int)floor((double)activei / (double)columns);
+ }
+ else {
+ dyn_data->height = len;
+ activei_row = activei;
+ }
+
+ /* Expand size if needed and possible. */
+ if ((ui_list->list_grip == 0) && (rows != maxrows) && (dyn_data->height > rows)) {
+ rows = min_ii(dyn_data->height, maxrows);
+ }
+
+ /* If list length changes or list is tagged to check this, and active is out of view, scroll to it .*/
+ if (ui_list->list_last_len != len || ui_list->flag & UILST_SCROLL_TO_ACTIVE_ITEM) {
+ if (activei_row < ui_list->list_scroll) {
+ ui_list->list_scroll = activei_row;
+ }
+ else if (activei_row >= ui_list->list_scroll + rows) {
+ ui_list->list_scroll = activei_row - rows + 1;
+ }
+ ui_list->flag &= ~UILST_SCROLL_TO_ACTIVE_ITEM;
+ }
+
+ max_scroll = max_ii(0, dyn_data->height - rows);
+ CLAMP(ui_list->list_scroll, 0, max_scroll);
+ ui_list->list_last_len = len;
+ dyn_data->visual_height = rows;
+ layoutdata->visual_items = rows * columns;
+ layoutdata->start_idx = ui_list->list_scroll * columns;
+ layoutdata->end_idx = min_ii(layoutdata->start_idx + rows * columns, len);
+}
+
void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, const char *list_id,
PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr,
- const char *active_propname, int rows, int maxrows, int layout_type)
+ const char *active_propname, int rows, int maxrows, int layout_type, int columns)
{
uiListType *ui_list_type;
uiList *ui_list = NULL;
+ uiListDyn *dyn_data;
ARegion *ar;
uiListDrawItemFunc draw_item;
+ uiListDrawFilterFunc draw_filter;
+ uiListFilterItemsFunc filter_items;
PropertyRNA *prop = NULL, *activeprop;
PropertyType type, activetype;
+ _uilist_item *items_ptr = NULL;
StructRNA *ptype;
- uiLayout *box, *row, *col, *sub, *overlap;
+ uiLayout *glob = NULL, *box, *row, *col, *subrow, *sub, *overlap;
uiBlock *block, *subblock;
uiBut *but;
+ uiListLayoutdata layoutdata;
char ui_list_id[UI_MAX_NAME_STR];
char numstr[32];
int rnaicon = ICON_NONE, icon = ICON_NONE;
int i = 0, activei = 0;
int len = 0;
- int items;
- int found;
- int min, max;
/* validate arguments */
/* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */
@@ -2580,6 +2799,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
}
draw_item = ui_list_type->draw_item ? ui_list_type->draw_item : uilist_draw_item_default;
+ draw_filter = ui_list_type->draw_filter ? ui_list_type->draw_filter : uilist_draw_filter_default;
+ filter_items = ui_list_type->filter_items ? ui_list_type->filter_items : uilist_filter_items_default;
/* Find or add the uiList to the current Region. */
/* We tag the list id with the list type... */
@@ -2589,146 +2810,211 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
ui_list = BLI_findstring(&ar->ui_lists, ui_list_id, offsetof(uiList, list_id));
if (!ui_list) {
- ui_list = MEM_callocN(sizeof(uiList), __func__);
+ ui_list = MEM_callocN(sizeof(uiList), AT);
BLI_strncpy(ui_list->list_id, ui_list_id, sizeof(ui_list->list_id));
BLI_addtail(&ar->ui_lists, ui_list);
}
+ if (!ui_list->dyn_data) {
+ ui_list->dyn_data = MEM_callocN(sizeof(uiListDyn), AT);
+ }
+ dyn_data = ui_list->dyn_data;
+
/* Because we can't actually pass type across save&load... */
ui_list->type = ui_list_type;
ui_list->layout_type = layout_type;
+ /* Reset filtering data. */
+ if (dyn_data->items_filter_flags) {
+ MEM_freeN(dyn_data->items_filter_flags);
+ dyn_data->items_filter_flags = NULL;
+ }
+ if (dyn_data->items_filter_neworder) {
+ MEM_freeN(dyn_data->items_filter_neworder);
+ dyn_data->items_filter_neworder = NULL;
+ }
+ dyn_data->items_len = dyn_data->items_shown = -1;
+
+ /* Filter list items! (not for compact layout, though) */
+ if (dataptr->data && prop) {
+ int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
+ bool order_reverse = (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0;
+ int items_shown, idx = 0;
+#if 0
+ int prev_ii = -1, prev_i;
+#endif
+
+ if (layout_type == UILST_LAYOUT_COMPACT) {
+ dyn_data->items_len = dyn_data->items_shown = RNA_property_collection_length(dataptr, prop);
+ }
+ else {
+ //printf("%s: filtering...\n", __func__);
+ filter_items(ui_list, C, dataptr, propname);
+ //printf("%s: filtering done.\n", __func__);
+ }
+
+ items_shown = dyn_data->items_shown;
+ if (items_shown >= 0) {
+ items_ptr = MEM_mallocN(sizeof(_uilist_item) * items_shown, AT);
+ //printf("%s: items shown: %d.\n", __func__, items_shown);
+ RNA_PROP_BEGIN (dataptr, itemptr, prop)
+ {
+ if (!dyn_data->items_filter_flags ||
+ ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude))
+ {
+ int ii;
+ if (dyn_data->items_filter_neworder) {
+ ii = dyn_data->items_filter_neworder[idx++];
+ ii = order_reverse ? items_shown - ii - 1 : ii;
+ }
+ else {
+ ii = order_reverse ? items_shown - ++idx : idx++;
+ }
+ //printf("%s: ii: %d\n", __func__, ii);
+ items_ptr[ii].item = itemptr;
+ items_ptr[ii].org_idx = i;
+ items_ptr[ii].flt_flag = dyn_data->items_filter_flags ? dyn_data->items_filter_flags[i] : 0;
+
+ if (activei == i) {
+ activei = ii;
+ }
+# if 0 /* For now, do not alter active element, even if it will be hidden... */
+ else if (activei < i) {
+ /* We do not want an active but invisible item!
+ * Only exception is when all items are filtered out...
+ */
+ if (prev_ii >= 0) {
+ activei = prev_ii;
+ RNA_property_int_set(active_dataptr, activeprop, prev_i);
+ }
+ else {
+ activei = ii;
+ RNA_property_int_set(active_dataptr, activeprop, i);
+ }
+ }
+ prev_i = i;
+ prev_ii = ii;
+#endif
+ }
+ i++;
+ }
+ RNA_PROP_END;
+ }
+ if (dyn_data->items_shown >= 0) {
+ len = dyn_data->items_shown;
+ }
+ else {
+ len = dyn_data->items_len;
+ }
+ }
+
switch (layout_type) {
case UILST_LAYOUT_DEFAULT:
- /* default rows */
- if (rows == 0)
- rows = 5;
- if (maxrows == 0)
- maxrows = 5;
- if (ui_list->list_grip_size != 0)
- rows = ui_list->list_grip_size;
-
/* layout */
box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
- row = uiLayoutRow(box, FALSE);
+ glob = uiLayoutColumn(box, TRUE);
+ row = uiLayoutRow(glob, FALSE);
col = uiLayoutColumn(row, TRUE);
/* init numbers */
- RNA_property_int_range(active_dataptr, activeprop, &min, &max);
-
- if (prop)
- len = RNA_property_collection_length(dataptr, prop);
- items = CLAMPIS(len, rows, MAX2(rows, maxrows));
-
- /* if list length changes and active is out of view, scroll to it */
- if ((ui_list->list_last_len != len) &&
- (activei < ui_list->list_scroll || activei >= ui_list->list_scroll + items))
- {
- ui_list->list_scroll = activei;
- }
-
- ui_list->list_scroll = min_ii(ui_list->list_scroll, len - items);
- ui_list->list_scroll = max_ii(ui_list->list_scroll, 0);
- ui_list->list_size = items;
- ui_list->list_last_len = len;
+ prepare_list(ui_list, len, activei, rows, maxrows, 1, &layoutdata);
if (dataptr->data && prop) {
/* create list items */
- RNA_PROP_BEGIN (dataptr, itemptr, prop)
- {
- if (i >= ui_list->list_scroll && i < ui_list->list_scroll + items) {
- subblock = uiLayoutGetBlock(col);
- overlap = uiLayoutOverlap(col);
+ for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) {
+ PointerRNA *itemptr = &items_ptr[i].item;
+ int org_i = items_ptr[i].org_idx;
+ int flt_flag = items_ptr[i].flt_flag;
+ subblock = uiLayoutGetBlock(col);
+
+ overlap = uiLayoutOverlap(col);
- uiBlockSetFlag(subblock, UI_BLOCK_LIST_ITEM);
+ uiBlockSetFlag(subblock, UI_BLOCK_LIST_ITEM);
- /* list item behind label & other buttons */
- sub = uiLayoutRow(overlap, FALSE);
+ /* list item behind label & other buttons */
+ sub = uiLayoutRow(overlap, FALSE);
- but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
- active_dataptr, activeprop, 0, 0, i, 0, 0, NULL);
- uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
+ but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ active_dataptr, activeprop, 0, 0, org_i, 0, 0, NULL);
+ uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
- sub = uiLayoutRow(overlap, FALSE);
+ sub = uiLayoutRow(overlap, FALSE);
- icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false);
- if (icon == ICON_DOT)
- icon = ICON_NONE;
- draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+ icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false);
+ if (icon == ICON_DOT)
+ icon = ICON_NONE;
+ draw_item(ui_list, C, sub, dataptr, itemptr, icon, active_dataptr, active_propname,
+ org_i, flt_flag);
- /* If we are "drawing" active item, set all labels as active. */
- if (i == activei) {
- ui_layout_list_set_labels_active(sub);
- }
- uiBlockClearFlag(subblock, UI_BLOCK_LIST_ITEM);
+ /* If we are "drawing" active item, set all labels as active. */
+ if (i == activei) {
+ ui_layout_list_set_labels_active(sub);
}
- i++;
+
+ uiBlockClearFlag(subblock, UI_BLOCK_LIST_ITEM);
}
- RNA_PROP_END;
}
/* add dummy buttons to fill space */
- while (i < ui_list->list_scroll + items) {
- if (i >= ui_list->list_scroll)
- uiItemL(col, "", ICON_NONE);
- i++;
+ for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) {
+ uiItemL(col, "", ICON_NONE);
}
/* add scrollbar */
- if (len > items) {
+ if (len > layoutdata.visual_items) {
col = uiLayoutColumn(row, FALSE);
- uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &ui_list->list_scroll,
- 0, len - items, items, 0, "");
+ uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height,
+ &ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height,
+ dyn_data->visual_height, 0, "");
}
break;
case UILST_LAYOUT_COMPACT:
row = uiLayoutRow(layout, TRUE);
- if (dataptr->data && prop) {
- /* create list items */
- RNA_PROP_BEGIN (dataptr, itemptr, prop)
- {
- found = (activei == i);
-
- if (found) {
- icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false);
- if (icon == ICON_DOT)
- icon = ICON_NONE;
- draw_item(ui_list, C, row, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
- }
+ if (dataptr->data && prop && dyn_data->items_shown > 0) {
+ PointerRNA *itemptr = &items_ptr[activei].item;
+ int org_i = items_ptr[activei].org_idx;
- i++;
- }
- RNA_PROP_END;
+ icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false);
+ if (icon == ICON_DOT)
+ icon = ICON_NONE;
+ draw_item(ui_list, C, row, dataptr, itemptr, icon, active_dataptr, active_propname, org_i, 0);
}
-
/* if list is empty, add in dummy button */
- if (i == 0)
+ else {
uiItemL(row, "", ICON_NONE);
+ }
/* next/prev button */
- BLI_snprintf(numstr, sizeof(numstr), "%d :", i);
+ BLI_snprintf(numstr, sizeof(numstr), "%d :", dyn_data->items_shown);
but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y,
active_dataptr, activeprop, 0, 0, 0, 0, 0, "");
- if (i == 0)
+ if (dyn_data->items_shown == 0)
uiButSetFlag(but, UI_BUT_DISABLED);
break;
case UILST_LAYOUT_GRID:
box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
- col = uiLayoutColumn(box, TRUE);
- row = uiLayoutRow(col, FALSE);
+ glob = uiLayoutColumn(box, TRUE);
+ row = uiLayoutRow(glob, FALSE);
+ col = uiLayoutColumn(row, TRUE);
+ subrow = NULL; /* Quite gcc warning! */
+
+ prepare_list(ui_list, len, activei, rows, maxrows, columns, &layoutdata);
if (dataptr->data && prop) {
/* create list items */
- RNA_PROP_BEGIN (dataptr, itemptr, prop)
- {
+ for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) {
+ PointerRNA *itemptr = &items_ptr[i].item;
+ int org_i = items_ptr[i].org_idx;
+ int flt_flag = items_ptr[i].flt_flag;
+
/* create button */
- if (!(i % 9))
- row = uiLayoutRow(col, FALSE);
+ if (!(i % columns))
+ subrow = uiLayoutRow(col, FALSE);
- subblock = uiLayoutGetBlock(row);
- overlap = uiLayoutOverlap(row);
+ subblock = uiLayoutGetBlock(subrow);
+ overlap = uiLayoutOverlap(subrow);
uiBlockSetFlag(subblock, UI_BLOCK_LIST_ITEM);
@@ -2736,13 +3022,14 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
sub = uiLayoutRow(overlap, FALSE);
but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
- active_dataptr, activeprop, 0, 0, i, 0, 0, NULL);
+ active_dataptr, activeprop, 0, 0, org_i, 0, 0, NULL);
uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
sub = uiLayoutRow(overlap, FALSE);
- icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false);
- draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+ icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false);
+ draw_item(ui_list, C, sub, dataptr, itemptr, icon, active_dataptr, active_propname,
+ org_i, flt_flag);
/* If we are "drawing" active item, set all labels as active. */
if (i == activei) {
@@ -2750,13 +3037,67 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
}
uiBlockClearFlag(subblock, UI_BLOCK_LIST_ITEM);
+ }
+ }
- i++;
+ /* add dummy buttons to fill space */
+ for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) {
+ if (!(i % columns)) {
+ subrow = uiLayoutRow(col, FALSE);
}
- RNA_PROP_END;
+ uiItemL(subrow, "", ICON_NONE);
+ }
+
+ /* add scrollbar */
+ if (len > layoutdata.visual_items) {
+ col = uiLayoutColumn(row, FALSE);
+ uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height,
+ &ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height,
+ dyn_data->visual_height, 0, "");
}
break;
}
+
+ if (glob) {
+ row = uiLayoutRow(glob, TRUE);
+ subblock = uiLayoutGetBlock(row);
+ uiBlockSetEmboss(subblock, UI_EMBOSSN);
+
+ if (ui_list->filter_flag & UILST_FLT_SHOW) {
+ but = uiDefIconButBitI(subblock, TOG, UILST_FLT_SHOW, 0, ICON_DISCLOSURE_TRI_DOWN, 0, 0,
+ UI_UNIT_X, UI_UNIT_Y * 0.6f, &(ui_list->filter_flag), 0, 0, 0, 0,
+ TIP_("Hide filtering options"));
+ uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ but = uiDefIconBut(subblock, BUT, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.6f, ui_list,
+ 0.0, 0.0, 0, -1, "");
+ uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ uiBlockSetEmboss(subblock, UI_EMBOSS);
+
+ col = uiLayoutColumn(glob, FALSE);
+ subblock = uiLayoutGetBlock(col);
+ uiDefBut(subblock, SEPR, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y * 0.05f, NULL, 0.0, 0.0, 0, 0, "");
+
+ draw_filter(ui_list, C, col);
+ }
+ else {
+ but = uiDefIconButBitI(subblock, TOG, UILST_FLT_SHOW, 0, ICON_DISCLOSURE_TRI_RIGHT, 0, 0,
+ UI_UNIT_X, UI_UNIT_Y * 0.6f, &(ui_list->filter_flag), 0, 0, 0, 0,
+ TIP_("Show filtering options"));
+ uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ but = uiDefIconBut(subblock, BUT, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.6f, ui_list,
+ 0.0, 0.0, 0, -1, "");
+ uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ uiBlockSetEmboss(subblock, UI_EMBOSS);
+ }
+ }
+
+ if (items_ptr) {
+ MEM_freeN(items_ptr);
+ }
}
/************************* Operator Search Template **************************/
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 594d3e40dcd..b469dc994bc 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -2850,6 +2850,16 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN
rect->xmin += BLI_rcti_size_y(rect) * 0.7 + delta;
}
+/* labels use Editor theme colors for text */
+static void widget_state_label(uiWidgetType *wt, int state)
+{
+ /* call this for option button */
+ widget_state(wt, state);
+ if (state & UI_SELECT)
+ UI_GetThemeColor3ubv(TH_TEXT_HI, (unsigned char *)wt->wcol.text);
+ else
+ UI_GetThemeColor3ubv(TH_TEXT, (unsigned char *)wt->wcol.text);
+}
static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
@@ -2970,9 +2980,12 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
case UI_WTYPE_LISTLABEL:
wt.wcol_theme = &btheme->tui.wcol_list_item;
- /* fall-through */ /* we use usual label code too. */
+ wt.draw = NULL;
+ /* Can't use usual label code. */
+ break;
case UI_WTYPE_LABEL:
wt.draw = NULL;
+ wt.state = widget_state_label;
break;
case UI_WTYPE_TOGGLE:
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 1ef4d43c9f3..ace35f0276e 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -484,6 +484,14 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_STITCH_PREVIEW_ACTIVE:
cp = ts->preview_stitch_active;
break;
+
+ case TH_UV_OTHERS:
+ cp = ts->uv_others;
+ break;
+ case TH_UV_SHADOW:
+ cp = ts->uv_shadow;
+ break;
+
case TH_MARKER_OUTLINE:
cp = ts->marker_outline; break;
case TH_MARKER:
@@ -918,6 +926,9 @@ void ui_theme_init_default(void)
rgba_char_args_set_fl(btheme->tima.preview_stitch_unstitchable, 1.0, 0.0, 0.0, 1.0);
rgba_char_args_set_fl(btheme->tima.preview_stitch_active, 0.886, 0.824, 0.765, 0.140);
+ rgba_char_args_test_set(btheme->tima.uv_others, 96, 96, 96, 255);
+ rgba_char_args_test_set(btheme->tima.uv_shadow, 112, 112, 112, 255);
+
/* space text */
btheme->text = btheme->tv3d;
rgba_char_args_set(btheme->text.back, 153, 153, 153, 255);
@@ -2205,7 +2216,15 @@ void init_userdef_do_versions(void)
}
/* NOTE!! from now on use U.versionfile and U.subversionfile */
-
+
+ if (U.versionfile < 269 || (U.versionfile == 268 && U.subversionfile < 3)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ rgba_char_args_test_set(btheme->tima.uv_others, 96, 96, 96, 255);
+ rgba_char_args_test_set(btheme->tima.uv_shadow, 112, 112, 112, 255);
+ }
+ }
+
if (U.pixelsize == 0.0f)
U.pixelsize = 1.0f;
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index f656d22fc64..037fa7c6a94 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -2029,6 +2029,17 @@ void UI_view2d_to_region_no_clip(View2D *v2d, float x, float y, int *regionx, in
}
}
+void UI_view2d_to_region_float(View2D *v2d, float x, float y, float *regionx, float *regiony)
+{
+ /* express given coordinates as proportional values */
+ x = -v2d->cur.xmin / BLI_rctf_size_x(&v2d->cur);
+ y = -v2d->cur.ymin / BLI_rctf_size_y(&v2d->cur);
+
+ /* convert proportional distances to screen coordinates */
+ *regionx = v2d->mask.xmin + x * BLI_rcti_size_x(&v2d->mask);
+ *regiony = v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask);
+}
+
/* *********************************************************************** */
/* Utilities */
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 929b7ae2a5d..3e9e16b285c 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -128,7 +128,7 @@ static int view_pan_init(bContext *C, wmOperator *op)
}
/* apply transform to view (i.e. adjust 'cur' rect) */
-static void view_pan_apply(wmOperator *op)
+static void view_pan_apply(bContext *C, wmOperator *op)
{
v2dViewPanData *vpd = op->customdata;
View2D *v2d = vpd->v2d;
@@ -153,6 +153,7 @@ static void view_pan_apply(wmOperator *op)
/* request updates to be done... */
ED_region_tag_redraw(vpd->ar);
+ WM_event_add_mousemove(C);
UI_view2d_sync(vpd->sc, vpd->sa, v2d, V2D_LOCK_COPY);
@@ -181,7 +182,7 @@ static int view_pan_exec(bContext *C, wmOperator *op)
if (!view_pan_init(C, op))
return OPERATOR_CANCELLED;
- view_pan_apply(op);
+ view_pan_apply(C, op);
view_pan_exit(op);
return OPERATOR_FINISHED;
}
@@ -209,7 +210,7 @@ static int view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
RNA_int_set(op->ptr, "deltax", event->prevx - event->x);
RNA_int_set(op->ptr, "deltay", event->prevy - event->y);
- view_pan_apply(op);
+ view_pan_apply(C, op);
view_pan_exit(op);
return OPERATOR_FINISHED;
}
@@ -246,7 +247,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
vpd->lastx = event->x;
vpd->lasty = event->y;
- view_pan_apply(op);
+ view_pan_apply(C, op);
break;
}
/* XXX - Mode switching isn't implemented. See comments in 36818.
@@ -333,7 +334,7 @@ static int view_scrollright_exec(bContext *C, wmOperator *op)
RNA_int_set(op->ptr, "deltay", 0);
/* apply movement, then we're done */
- view_pan_apply(op);
+ view_pan_apply(C, op);
view_pan_exit(op);
return OPERATOR_FINISHED;
@@ -377,7 +378,7 @@ static int view_scrollleft_exec(bContext *C, wmOperator *op)
RNA_int_set(op->ptr, "deltay", 0);
/* apply movement, then we're done */
- view_pan_apply(op);
+ view_pan_apply(C, op);
view_pan_exit(op);
return OPERATOR_FINISHED;
@@ -425,7 +426,7 @@ static int view_scrolldown_exec(bContext *C, wmOperator *op)
}
/* apply movement, then we're done */
- view_pan_apply(op);
+ view_pan_apply(C, op);
view_pan_exit(op);
return OPERATOR_FINISHED;
@@ -475,7 +476,7 @@ static int view_scrollup_exec(bContext *C, wmOperator *op)
}
/* apply movement, then we're done */
- view_pan_apply(op);
+ view_pan_apply(C, op);
view_pan_exit(op);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index a1bb7a8ae88..70fa97bebc1 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -106,6 +106,24 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", filepath);
BLI_ensure_extension(filepath, sizeof(filepath), ".dae");
+
+ /* Avoid File write exceptions in Collada */
+ if (!BLI_exists(filepath)) {
+ BLI_make_existing_file(filepath);
+ if (!BLI_file_touch(filepath)) {
+ BKE_report(op->reports, RPT_ERROR, "Can't create export file");
+ fprintf(stdout, "Collada export: Can not create: %s\n", filepath);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else if (!BLI_file_is_writable(filepath)) {
+ BKE_report(op->reports, RPT_ERROR, "Can't overwrite export file");
+ fprintf(stdout, "Collada export: Can not modify: %s\n", filepath);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Now the exporter can create and write the export file */
+
/* Options panel */
apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers");
export_mesh_type = RNA_enum_get(op->ptr, "export_mesh_type_selection");
@@ -129,6 +147,8 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
/* get editmode results */
ED_object_editmode_load(CTX_data_edit_object(C));
+
+
if (collada_export(CTX_data_scene(C),
filepath,
apply_modifiers,
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index 9c270144a0a..4cc9d3b59b1 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -737,3 +737,159 @@ void MASK_OT_add_feather_vertex(wmOperatorType *ot)
RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
"Location", "Location of vertex in normalized space", -1.0f, 1.0f);
}
+
+/******************** common primitive functions *********************/
+
+static int create_primitive_from_points(bContext *C, wmOperator *op, const float (*points)[2],
+ int num_points, char handle_type)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ Scene *scene = CTX_data_scene(C);
+ Mask *mask;
+ MaskLayer *mask_layer;
+ MaskSpline *new_spline;
+ float scale, location[2], frame_size[2];
+ int i, width, height;
+ int size = RNA_float_get(op->ptr, "size");
+
+ ED_mask_get_size(sa, &width, &height);
+ scale = (float)size / max_ii(width, height);
+
+ /* Get location in mask space. */
+ frame_size[0] = width;
+ frame_size[1] = height;
+ RNA_float_get_array(op->ptr, "location", location);
+ location[0] /= width;
+ location[1] /= height;
+ BKE_mask_coord_from_frame(location, location, frame_size);
+
+ /* Make it so new primitive is centered to mouse location. */
+ location[0] -= 0.5f * scale;
+ location[1] -= 0.5f * scale;
+
+ mask_layer = ED_mask_layer_ensure(C);
+ mask = CTX_data_edit_mask(C);
+
+ ED_mask_select_toggle_all(mask, SEL_DESELECT);
+
+ new_spline = BKE_mask_spline_add(mask_layer);
+ new_spline->flag = MASK_SPLINE_CYCLIC | SELECT;
+ new_spline->tot_point = num_points;
+ new_spline->points = MEM_recallocN(new_spline->points,
+ sizeof(MaskSplinePoint) * new_spline->tot_point);
+
+ mask_layer->act_spline = new_spline;
+ mask_layer->act_point = NULL;
+
+ for (i = 0; i < num_points; i++) {
+ MaskSplinePoint *new_point = &new_spline->points[i];
+
+ copy_v2_v2(new_point->bezt.vec[1], points[i]);
+ mul_v2_fl(new_point->bezt.vec[1], scale);
+ add_v2_v2(new_point->bezt.vec[1], location);
+
+ new_point->bezt.h1 = handle_type;
+ new_point->bezt.h2 = handle_type;
+ BKE_mask_point_select_set(new_point, true);
+ }
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+
+ /* TODO: only update this spline */
+ BKE_mask_update_display(mask, CFRA);
+
+ return OPERATOR_FINISHED;
+}
+
+static int primitive_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ ScrArea *sa = CTX_wm_area(C);
+ float cursor[2];
+ int width, height;
+
+ ED_mask_get_size(sa, &width, &height);
+ ED_mask_cursor_location_get(sa, cursor);
+
+ cursor[0] *= width;
+ cursor[1] *= height;
+
+ RNA_float_set_array(op->ptr, "location", cursor);
+
+ return op->type->exec(C, op);
+}
+
+static void define_prinitive_add_properties(wmOperatorType *ot)
+{
+ RNA_def_float(ot->srna, "size", 100, -FLT_MAX, FLT_MAX,
+ "Size", "Size of new circle", -FLT_MAX, FLT_MAX);
+ RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
+ "Location", "Location of new circle", -FLT_MAX, FLT_MAX);
+}
+
+/******************** primitive add circle *********************/
+
+static int primitive_circle_add_exec(bContext *C, wmOperator *op)
+{
+ const float points[4][2] = {{0.0f, 0.5f},
+ {0.5f, 1.0f},
+ {1.0f, 0.5f},
+ {0.5f, 0.0f}};
+ int num_points = sizeof(points) / (2 * sizeof(float));
+
+ create_primitive_from_points(C, op, points, num_points, HD_AUTO);
+
+ return OPERATOR_FINISHED;
+}
+
+void MASK_OT_primitive_circle_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Circle";
+ ot->description = "Add new circle-shaped spline";
+ ot->idname = "MASK_OT_primitive_circle_add";
+
+ /* api callbacks */
+ ot->exec = primitive_circle_add_exec;
+ ot->invoke = primitive_add_invoke;
+ ot->poll = ED_operator_mask;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ define_prinitive_add_properties(ot);
+}
+
+/******************** primitive add suqare *********************/
+
+static int primitive_square_add_exec(bContext *C, wmOperator *op)
+{
+ const float points[4][2] = {{0.0f, 0.0f},
+ {0.0f, 1.0f},
+ {1.0f, 1.0f},
+ {1.0f, 0.0f}};
+ int num_points = sizeof(points) / (2 * sizeof(float));
+
+ create_primitive_from_points(C, op, points, num_points, HD_VECT);
+
+ return OPERATOR_FINISHED;
+}
+
+void MASK_OT_primitive_square_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Square";
+ ot->description = "Add new square-shaped spline";
+ ot->idname = "MASK_OT_primitive_square_add";
+
+ /* api callbacks */
+ ot->exec = primitive_square_add_exec;
+ ot->invoke = primitive_add_invoke;
+ ot->poll = ED_operator_mask;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ define_prinitive_add_properties(ot);
+}
diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c
index 9ae5b436fb3..62eb9cc240a 100644
--- a/source/blender/editors/mask/mask_edit.c
+++ b/source/blender/editors/mask/mask_edit.c
@@ -363,6 +363,40 @@ void ED_mask_pixelspace_factor(ScrArea *sa, ARegion *ar, float *scalex, float *s
}
}
+void ED_mask_cursor_location_get(ScrArea *sa, float cursor[2])
+{
+ if (sa) {
+ switch (sa->spacetype) {
+ case SPACE_CLIP:
+ {
+ SpaceClip *space_clip = sa->spacedata.first;
+ copy_v2_v2(cursor, space_clip->cursor);
+ break;
+ }
+ case SPACE_SEQ:
+ {
+ zero_v2(cursor);
+ break;
+ }
+ case SPACE_IMAGE:
+ {
+ SpaceImage *space_image = sa->spacedata.first;
+ copy_v2_v2(cursor, space_image->cursor);
+ break;
+ }
+ default:
+ /* possible other spaces from which mask editing is available */
+ BLI_assert(0);
+ zero_v2(cursor);
+ break;
+ }
+ }
+ else {
+ BLI_assert(0);
+ zero_v2(cursor);
+ }
+}
+
/********************** registration *********************/
void ED_operatortypes_mask(void)
@@ -376,6 +410,8 @@ void ED_operatortypes_mask(void)
/* add */
WM_operatortype_append(MASK_OT_add_vertex);
WM_operatortype_append(MASK_OT_add_feather_vertex);
+ WM_operatortype_append(MASK_OT_primitive_circle_add);
+ WM_operatortype_append(MASK_OT_primitive_square_add);
/* geometry */
WM_operatortype_append(MASK_OT_switch_direction);
@@ -417,6 +453,9 @@ void ED_operatortypes_mask(void)
/* layers */
WM_operatortype_append(MASK_OT_layer_move);
+
+ /* duplicate */
+ WM_operatortype_append(MASK_OT_duplicate);
}
void ED_keymap_mask(wmKeyConfig *keyconf)
@@ -429,6 +468,9 @@ void ED_keymap_mask(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MASK_OT_new", NKEY, KM_PRESS, KM_ALT, 0);
+ /* add menu */
+ WM_keymap_add_menu(keymap, "MASK_MT_add", AKEY, KM_PRESS, KM_SHIFT, 0);
+
/* mask mode supports PET now */
ED_keymap_proportional_cycle(keyconf, keymap);
ED_keymap_proportional_maskmode(keyconf, keymap);
@@ -500,6 +542,9 @@ void ED_keymap_mask(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MASK_OT_shape_key_insert", IKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "MASK_OT_shape_key_clear", IKEY, KM_PRESS, KM_ALT, 0);
+ /* duplicate */
+ WM_keymap_add_item(keymap, "MASK_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
+
/* for image editor only */
WM_keymap_add_item(keymap, "UV_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0);
@@ -514,7 +559,6 @@ void ED_keymap_mask(wmKeyConfig *keyconf)
void ED_operatormacros_mask(void)
{
- /* XXX: just for sample */
wmOperatorType *ot;
wmOperatorTypeMacro *otmacro;
@@ -531,4 +575,11 @@ void ED_operatormacros_mask(void)
WM_operatortype_macro_define(ot, "MASK_OT_add_feather_vertex");
otmacro = WM_operatortype_macro_define(ot, "MASK_OT_slide_point");
RNA_boolean_set(otmacro->ptr, "slide_feather", TRUE);
+
+ ot = WM_operatortype_append_macro("MASK_OT_duplicate_move", "Add Duplicate", "Duplicate mask and move",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "MASK_OT_duplicate");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
}
diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h
index bd148c48980..51705aa5837 100644
--- a/source/blender/editors/mask/mask_intern.h
+++ b/source/blender/editors/mask/mask_intern.h
@@ -42,9 +42,12 @@ struct wmOperatorType;
/* mask_add.c */
void MASK_OT_add_vertex(struct wmOperatorType *ot);
void MASK_OT_add_feather_vertex(struct wmOperatorType *ot);
+void MASK_OT_primitive_circle_add(struct wmOperatorType *ot);
+void MASK_OT_primitive_square_add(struct wmOperatorType *ot);
/* mask_ops.c */
struct Mask *ED_mask_new(struct bContext *C, const char *name);
+struct MaskLayer *ED_mask_layer_ensure(struct bContext *C);
void MASK_OT_new(struct wmOperatorType *ot);
void MASK_OT_layer_new(struct wmOperatorType *ot);
@@ -75,6 +78,8 @@ struct MaskSplinePoint *ED_mask_point_find_nearest(
void MASK_OT_layer_move(struct wmOperatorType *ot);
+void MASK_OT_duplicate(struct wmOperatorType *ot);
+
/* mask_relationships.c */
void MASK_OT_parent_set(struct wmOperatorType *ot);
void MASK_OT_parent_clear(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index c9d3bd19941..5ca0d133b0e 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -292,6 +292,26 @@ Mask *ED_mask_new(bContext *C, const char *name)
return mask;
}
+/* Get ative layer. Will create mask/layer to be sure there's an active layer. */
+MaskLayer *ED_mask_layer_ensure(bContext *C)
+{
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *mask_layer;
+
+ if (mask == NULL) {
+ /* If there's no active mask, create one. */
+ mask = ED_mask_new(C, NULL);
+ }
+
+ mask_layer = BKE_mask_layer_active(mask);
+ if (mask_layer == NULL) {
+ /* If there's no active mask layer, create one. */
+ mask_layer = BKE_mask_layer_new(mask, "");
+ }
+
+ return mask_layer;
+}
+
static int mask_new_exec(bContext *C, wmOperator *op)
{
char name[MAX_ID_NAME - 2];
@@ -1467,3 +1487,110 @@ void MASK_OT_layer_move(wmOperatorType *ot)
/* properties */
RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move the active layer");
}
+
+/******************** duplicate *********************/
+
+static int mask_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *mask_layer = BKE_mask_layer_active(mask);
+ MaskSpline *spline;
+
+ if (mask_layer == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ for (spline = mask_layer->splines.last;
+ spline;
+ spline = spline->prev)
+ {
+ MaskSplinePoint *point = spline->points;
+ int i = 0;
+ while (i < spline->tot_point) {
+ int start = i, end = -1;
+ /* Find next selected segment. */
+ while (MASKPOINT_ISSEL_ANY(point)) {
+ BKE_mask_point_select_set(point, false);
+ end = i;
+ if (i >= spline->tot_point - 1) {
+ break;
+ }
+ i++;
+ point++;
+ }
+ if (end >= start) {
+ MaskSpline *new_spline = BKE_mask_spline_add(mask_layer);
+ MaskSplinePoint *new_point;
+ int b;
+
+ /* BKE_mask_spline_add might allocate the points, need to free them in this case. */
+ if (new_spline->points) {
+ MEM_freeN(new_spline->points);
+ }
+
+ /* Copy options from old spline. */
+ new_spline->flag = spline->flag;
+ new_spline->offset_mode = spline->offset_mode;
+ new_spline->weight_interp = spline->weight_interp;
+ new_spline->parent = spline->parent;
+
+ /* Allocate new points and copy them from old spline. */
+ new_spline->tot_point = end - start + 1;
+ new_spline->points = MEM_mallocN(sizeof(MaskSplinePoint) * new_spline->tot_point,
+ "duplicated mask points");
+
+ memcpy(new_spline->points, spline->points + start,
+ new_spline->tot_point * sizeof(MaskSplinePoint));
+
+ /* Select points and duplicate their UWs (if needed). */
+ for (b = 0, new_point = new_spline->points;
+ b < new_spline->tot_point;
+ b++, new_point++)
+ {
+ if (new_point->uw) {
+ new_point->uw = MEM_dupallocN(new_point->uw);
+ }
+ BKE_mask_point_select_set(new_point, true);
+ }
+
+ /* Clear cyclic flag if we didn't copy the whole spline. */
+ if (new_spline->flag & MASK_SPLINE_CYCLIC) {
+ if (start != 0 || end != spline->tot_point - 1) {
+ new_spline->flag &= ~MASK_SPLINE_CYCLIC;
+ }
+ }
+
+ /* Flush selection to splines. */
+ new_spline->flag |= SELECT;
+ spline->flag &= ~SELECT;
+
+ mask_layer->act_spline = new_spline;
+ }
+ i++;
+ point++;
+ }
+ }
+
+ /* TODO: only update edited splines */
+ BKE_mask_update_display(mask, CFRA);
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+
+ return OPERATOR_FINISHED;
+}
+
+void MASK_OT_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Duplicate Mask";
+ ot->description = "Duplicate selected control points and segments between them";
+ ot->idname = "MASK_OT_duplicate";
+
+ /* api callbacks */
+ ot->exec = mask_duplicate_exec;
+ ot->poll = ED_maskedit_mask_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c
index 6ced2423074..9cc1702addb 100644
--- a/source/blender/editors/mask/mask_relationships.c
+++ b/source/blender/editors/mask/mask_relationships.c
@@ -137,6 +137,7 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
sub_parent_name = track->name;
parent_type = MASK_PARENT_POINT_TRACK;
+ memset(orig_corners, 0, sizeof(orig_corners));
}
else if ((plane_track = BKE_tracking_plane_track_get_active(tracking)) != NULL) {
MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index 69ef4715df6..8d91b300ff3 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -42,6 +42,7 @@ set(SRC
editface.c
editmesh_add.c
editmesh_bevel.c
+ editmesh_bisect.c
editmesh_extrude.c
editmesh_inset.c
editmesh_knife.c
diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c
new file mode 100644
index 00000000000..5968e0991d1
--- /dev/null
+++ b/source/blender/editors/mesh/editmesh_bisect.c
@@ -0,0 +1,331 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/mesh/editmesh_bisect.c
+ * \ingroup edmesh
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+
+#include "BLI_math.h"
+
+#include "BKE_global.h"
+#include "BKE_context.h"
+#include "BKE_editmesh.h"
+
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+
+#include "mesh_intern.h" /* own include */
+
+static int mesh_bisect_exec(bContext *C, wmOperator *op);
+
+/* -------------------------------------------------------------------- */
+/* Model Helpers */
+
+typedef struct {
+ /* modal only */
+ BMBackup mesh_backup;
+ bool is_first;
+ short twtype;
+} BisectData;
+
+static bool mesh_bisect_interactive_calc(
+ bContext *C, wmOperator *op,
+ BMEditMesh *em,
+ float plane_co[3], float plane_no[3])
+{
+ wmGesture *gesture = op->customdata;
+ BisectData *opdata;
+
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ int x_start = RNA_int_get(op->ptr, "xstart");
+ int y_start = RNA_int_get(op->ptr, "ystart");
+ int x_end = RNA_int_get(op->ptr, "xend");
+ int y_end = RNA_int_get(op->ptr, "yend");
+
+ /* reference location (some point infront of the view) for finding a point on a plane */
+ const float *co_ref = rv3d->ofs;
+ float co_a_ss[2] = {x_start, y_start}, co_b_ss[2] = {x_end, y_end}, co_delta_ss[2];
+ float co_a[3], co_b[3];
+ const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL);
+
+ opdata = gesture->userdata;
+
+ /* view vector */
+ ED_view3d_win_to_vector(ar, co_a_ss, co_a);
+
+ /* view delta */
+ sub_v2_v2v2(co_delta_ss, co_a_ss, co_b_ss);
+ ED_view3d_win_to_delta(ar, co_delta_ss, co_b, zfac);
+
+ /* cross both to get a normal */
+ cross_v3_v3v3(plane_no, co_a, co_b);
+ normalize_v3(plane_no); /* not needed but nicer for user */
+
+ /* point on plane, can use either start or endpoint */
+ ED_view3d_win_to_3d(ar, co_ref, co_a_ss, plane_co);
+
+ if (opdata->is_first == false)
+ EDBM_redo_state_restore(opdata->mesh_backup, em, false);
+
+ opdata->is_first = false;
+
+ return true;
+}
+
+static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int ret;
+
+ /* if the properties are set or there is no rv3d,
+ * skip model and exec immediately */
+
+ if ((CTX_wm_region_view3d(C) == NULL) ||
+ (RNA_struct_property_is_set(op->ptr, "plane_co") &&
+ RNA_struct_property_is_set(op->ptr, "plane_no")))
+ {
+ return mesh_bisect_exec(C, op);
+ }
+
+ ret = WM_gesture_straightline_invoke(C, op, event);
+ if (ret & OPERATOR_RUNNING_MODAL) {
+ View3D *v3d = CTX_wm_view3d(C);
+
+ wmGesture *gesture = op->customdata;
+ BisectData *opdata;
+
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ opdata = MEM_mallocN(sizeof(BisectData), "inset_operator_data");
+ opdata->mesh_backup = EDBM_redo_state_store(em);
+ opdata->is_first = true;
+ gesture->userdata = opdata;
+
+ /* misc other vars */
+ G.moving = G_TRANSFORM_EDIT;
+ opdata->twtype = v3d->twtype;
+ v3d->twtype = 0;
+ }
+ return ret;
+}
+
+static void edbm_bisect_exit(bContext *C, BisectData *opdata)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ EDBM_redo_state_free(&opdata->mesh_backup, NULL, false);
+ v3d->twtype = opdata->twtype;
+ G.moving = 0;
+}
+
+static int mesh_bisect_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ wmGesture *gesture = op->customdata;
+ BisectData *opdata = gesture->userdata;
+ BisectData opdata_back = *opdata; /* annoyance, WM_gesture_straightline_modal, frees */
+ int ret;
+
+ ret = WM_gesture_straightline_modal(C, op, event);
+
+ if (ret & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) {
+ edbm_bisect_exit(C, &opdata_back);
+ }
+
+ return ret;
+}
+
+/* End Model Helpers */
+/* -------------------------------------------------------------------- */
+
+
+
+static int mesh_bisect_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+
+ /* both can be NULL, fallbacks values are used */
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = ED_view3d_context_rv3d(C);
+
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm;
+ BMOperator bmop;
+ float plane_co[3];
+ float plane_no[3];
+ float imat[4][4];
+
+ const float thresh = RNA_float_get(op->ptr, "threshold");
+ const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
+ const bool clear_inner = RNA_boolean_get(op->ptr, "clear_inner");
+ const bool clear_outer = RNA_boolean_get(op->ptr, "clear_outer");
+
+ PropertyRNA *prop_plane_co;
+ PropertyRNA *prop_plane_no;
+
+ prop_plane_co = RNA_struct_find_property(op->ptr, "plane_co");
+ if (RNA_property_is_set(op->ptr, prop_plane_co)) {
+ RNA_property_float_get_array(op->ptr, prop_plane_co, plane_co);
+ }
+ else {
+ copy_v3_v3(plane_co, give_cursor(scene, v3d));
+ RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co);
+ }
+
+ prop_plane_no = RNA_struct_find_property(op->ptr, "plane_no");
+ if (RNA_property_is_set(op->ptr, prop_plane_no)) {
+ RNA_property_float_get_array(op->ptr, prop_plane_no, plane_no);
+ }
+ else {
+ if (rv3d) {
+ copy_v3_v3(plane_no, rv3d->viewinv[1]);
+ }
+ else {
+ /* fallback... */
+ plane_no[0] = plane_no[1] = 0.0f; plane_no[2] = 1.0f;
+ }
+ RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no);
+ }
+
+
+
+ /* -------------------------------------------------------------------- */
+ /* Modal support */
+ /* Note: keep this isolated, exec can work wihout this */
+ if ((op->customdata != NULL) &&
+ mesh_bisect_interactive_calc(C, op, em, plane_co, plane_no))
+ {
+ /* write back to the props */
+ RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no);
+ RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co);
+ }
+ /* End Modal */
+ /* -------------------------------------------------------------------- */
+
+
+
+ bm = em->bm;
+
+ invert_m4_m4(imat, obedit->obmat);
+ mul_m4_v3(imat, plane_co);
+ mul_mat3_m4_v3(imat, plane_no);
+
+ EDBM_op_init(em, &bmop, op,
+ "bisect_plane geom=%hvef plane_co=%v plane_no=%v dist=%f clear_inner=%b clear_outer=%b",
+ BM_ELEM_SELECT, plane_co, plane_no, thresh, clear_inner, clear_outer);
+ BMO_op_exec(bm, &bmop);
+
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
+ if (use_fill) {
+ float normal_fill[3];
+ BMOperator bmop_fill;
+ BMOperator bmop_attr;
+
+ normalize_v3_v3(normal_fill, plane_no);
+ if (clear_outer == true && clear_inner == false) {
+ negate_v3(normal_fill);
+ }
+
+ /* Fill */
+ BMO_op_initf(
+ bm, &bmop_fill, op->flag,
+ "triangle_fill edges=%S normal=%v use_dissolve=%b",
+ &bmop, "geom_cut.out", normal_fill, true);
+ BMO_op_exec(bm, &bmop_fill);
+
+ /* Copy Attributes */
+ BMO_op_initf(bm, &bmop_attr, op->flag,
+ "face_attribute_fill faces=%S use_normals=%b use_data=%b",
+ &bmop_fill, "geom.out", false, true);
+ BMO_op_exec(bm, &bmop_attr);
+
+ BMO_slot_buffer_hflag_enable(bm, bmop_fill.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
+
+ BMO_op_finish(bm, &bmop_attr);
+ BMO_op_finish(bm, &bmop_fill);
+ }
+
+ BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom_cut.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true);
+
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ EDBM_update_generic(em, true, true);
+ EDBM_selectmode_flush(em);
+ return OPERATOR_FINISHED;
+ }
+}
+
+
+void MESH_OT_bisect(struct wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Bisect";
+ ot->description = "Enforce symmetry (both form and topological) across an axis";
+ ot->idname = "MESH_OT_bisect";
+
+ /* api callbacks */
+ ot->exec = mesh_bisect_exec;
+ ot->invoke = mesh_bisect_invoke;
+ ot->modal = mesh_bisect_modal;
+ ot->cancel = WM_gesture_straightline_cancel;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+
+ prop = RNA_def_float_vector(ot->srna, "plane_co", 3, NULL, -FLT_MAX, FLT_MAX,
+ "Plane Point", "A point on the plane", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_float_vector(ot->srna, "plane_no", 3, NULL, -FLT_MAX, FLT_MAX,
+ "Plane Normal", "The direction the plane points", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill in the cut");
+ RNA_def_boolean(ot->srna, "clear_inner", false, "Clear Inner", "Remove geometry behind the plane");
+ RNA_def_boolean(ot->srna, "clear_outer", false, "Clear Outer", "Remove geometry infront of the plane");
+
+ RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Axis Threshold", "", 0.00001, 0.1);
+
+ WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT);
+}
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index dba19ee5da6..3966826a5b2 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -228,10 +228,8 @@ static bool edbm_inset_calc(wmOperator *op)
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
}
else {
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE, BM_ELEM_SELECT, false);
- BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, false);
- /* re-select faces so the verts and edges get selected too */
- BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, BM_ELEM_SELECT);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_in, "faces", BM_FACE, BM_ELEM_SELECT, true);
}
if (!EDBM_op_finish(em, &bmop, op, true)) {
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 2e73cbd02ed..cc3d486c2f3 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -499,10 +499,12 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd)
{
KnifeEdge *kfe = new_knife_edge(kcd), *kfe2 = NULL, *kfe3 = NULL;
- if (kcd->prev.vert && kcd->prev.vert == kcd->curr.vert)
- return;
- if (kcd->prev.edge && kcd->prev.edge == kcd->curr.edge)
+ if ((kcd->prev.vert && kcd->prev.vert == kcd->curr.vert) ||
+ (kcd->prev.edge && kcd->prev.edge == kcd->curr.edge))
+ {
+ kcd->prev = kcd->curr;
return;
+ }
kfe->draw = true;
@@ -573,10 +575,17 @@ static int verge_linehit(const void *vlh1, const void *vlh2)
if (lh1->l < lh2->l) return -1;
else if (lh1->l > lh2->l) return 1;
+ else if (lh1->v && lh2->v) {
+ /* want like verts to sort together; just compare pointers */
+ if (lh1->v < lh2->v) return -1;
+ else if (lh1->v > lh2->v) return 1;
+ else return 0;
+ }
else return 0;
}
/* If there's a linehit connected (same face) as testi in range [firsti, lasti], return the first such, else -1.
+ * It also counts as connected if both linehits are snapped to the same vertex.
* If testi is out of range, look for connection to f instead, if f is non-NULL */
static int find_connected_linehit(KnifeTool_OpData *kcd, int testi, BMFace *f, int firsti, int lasti)
{
@@ -589,6 +598,11 @@ static int find_connected_linehit(KnifeTool_OpData *kcd, int testi, BMFace *f, i
{
return i;
}
+ else if (kcd->linehits[testi].v &&
+ kcd->linehits[testi].v == kcd->linehits[i].v)
+ {
+ return i;
+ }
}
else if (f) {
if (find_ref(&kcd->linehits[i].kfe->faces, f))
@@ -598,13 +612,38 @@ static int find_connected_linehit(KnifeTool_OpData *kcd, int testi, BMFace *f, i
return -1;
}
-/* Sort in order of distance along cut line, but take care when distances are equal */
-static void knife_sort_linehits(KnifeTool_OpData *kcd)
+/* Sort in order of distance along cut line.
+ * Remove any successive linehits that are snapped to the same vertex.
+ * If joinfaces, treat hits at same distance as follows: try to find
+ * ordering so that preceding and succeeding hits will share a face.
+ */
+static void knife_sort_linehits(KnifeTool_OpData *kcd, bool joinfaces)
{
int i, j, k, nexti, nsame;
qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit);
+ /* Remove duplicated linehits snapped to same vertex */
+ i = j = 0; /* loop copies from j to i */
+ while (j < kcd->totlinehit) {
+ nsame = 0;
+ if (kcd->linehits[j].v) {
+ for (k = j + 1; k < kcd->totlinehit; k++) {
+ if (kcd->linehits[k].v != kcd->linehits[j].v)
+ break;
+ nsame++;
+ }
+ }
+ if (i != j)
+ kcd->linehits[i] = kcd->linehits[j];
+ i++;
+ j += 1 + nsame;
+ }
+ kcd->totlinehit = i;
+
+ if (!joinfaces)
+ return;
+
/* for ranges of equal "l", swap if neccesary to make predecessor and
* successor faces connected to the linehits at either end of the range */
for (i = 0; i < kcd->totlinehit - 1; i = nexti) {
@@ -653,6 +692,7 @@ static void knife_add_single_cut_through(KnifeTool_OpData *kcd, KnifeVert *v1, K
knife_edge_append_face(kcd, kfenew, f);
}
+#if 0
static void knife_get_vert_faces(KnifeTool_OpData *kcd, KnifeVert *kfv, BMFace *facef, ListBase *lst)
{
BMIter bmiter;
@@ -685,20 +725,33 @@ static void knife_get_edge_faces(KnifeTool_OpData *kcd, KnifeEdge *kfe, ListBase
}
}
}
+#endif
+
+static void copy_hit_from_posdata(BMEdgeHit *lh, KnifePosData *pos, float lambda)
+{
+ lh->kfe = pos->edge;
+ lh->v = pos->vert;
+ lh->f = pos->bmface;
+ copy_v3_v3(lh->hit, pos->co);
+ copy_v3_v3(lh->cagehit, pos->cage);
+ copy_v3_v3(lh->realhit, pos->co);
+ lh->l = lambda;
+ /* perc and schit not used by callers of this function */
+}
/* BMESH_TODO: add more functionality to cut-through:
* - cutting "in face" (e.g., holes) should cut in all faces, not just visible one
* - perhaps improve O(n^2) algorithm used here */
static void knife_cut_through(KnifeTool_OpData *kcd)
{
- BMEdgeHit *lh, *lh2;
+ BMEdgeHit *lh, *lh2, *linehits;
BMFace *f;
- KnifeEdge *kfe, *kfe2, *kfe3;
- KnifeVert *v1, *v2, *firstv = NULL, *lastv = NULL;
- ListBase firstfaces = {NULL, NULL}, lastfaces = {NULL, NULL};
- Ref *r, *r2;
+ KnifeEdge *kfe, *kfe2;
+ KnifeVert *v1, *v2, *lastv;
+ ListBase *faces1, *faces2;
KnifeEdge **splitkfe;
- int i, j;
+ bool needprev, needcurr;
+ int i, j, n;
if (!kcd->totlinehit) {
/* if no linehits then no interesting back face stuff to do */
@@ -706,93 +759,68 @@ static void knife_cut_through(KnifeTool_OpData *kcd)
return;
}
- /* TODO: probably don't need to sort at all */
- qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit);
- splitkfe = MEM_callocN(kcd->totlinehit * sizeof(KnifeEdge *), "knife_cut_through");
+ /* sort eliminates hits on same vertices */
+ knife_sort_linehits(kcd, false);
- if (kcd->prev.vert) {
- if (kcd->prev.vert == kcd->curr.vert)
- return;
- firstv = kcd->prev.vert;
- knife_get_vert_faces(kcd, firstv, kcd->prev.bmface, &firstfaces);
- }
- else if (kcd->prev.edge) {
- if (kcd->prev.edge == kcd->curr.edge)
- return;
- firstv = knife_split_edge(kcd, kcd->prev.edge, kcd->prev.co, &kfe3);
- knife_get_edge_faces(kcd, kcd->prev.edge, &firstfaces);
+ /* code is cleaner if make prev and curr into hits (if they are on edges or verts) */
+ n = kcd->totlinehit;
+ needprev = ((kcd->prev.vert && kcd->prev.vert != kcd->linehits[0].v) || kcd->prev.edge);
+ needcurr = ((kcd->curr.vert && kcd->curr.vert != kcd->linehits[n - 1].v) || kcd->curr.edge);
+ n += needprev + needcurr;
+ linehits = MEM_callocN(n * sizeof(BMEdgeHit), "knife_cut_through");
+ i = 0;
+ if (needprev) {
+ copy_hit_from_posdata(&linehits[0], &kcd->prev, 0.0f);
+ i++;
}
+ memcpy(linehits + i, kcd->linehits, kcd->totlinehit * sizeof(BMEdgeHit));
+ i += kcd->totlinehit;
+ if (needcurr)
+ copy_hit_from_posdata(&linehits[i], &kcd->curr, 1.0f);
- if (kcd->curr.vert) {
- lastv = kcd->curr.vert;
- knife_get_vert_faces(kcd, lastv, kcd->curr.bmface, &lastfaces);
- }
- else if (kcd->curr.edge) {
- lastv = knife_split_edge(kcd, kcd->curr.edge, kcd->curr.co, &kfe3);
- knife_get_edge_faces(kcd, kcd->curr.edge, &lastfaces);
- }
-
- if (firstv) {
- /* For each face incident to firstv,
- * find the first following linehit (if any) sharing that face and connect */
- for (r = firstfaces.first; r; r = r->next) {
- bool found = false;
- f = r->ref;
- for (j = 0, lh2 = kcd->linehits; j < kcd->totlinehit && !found; j++, lh2++) {
- kfe2 = lh2->kfe;
- for (r2 = kfe2->faces.first; r2; r2 = r2->next) {
- if (r2->ref == f) {
- v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]);
- knife_add_single_cut_through(kcd, firstv, v2, f);
- found = true;
- break;
- }
- }
- }
- if (!found && lastv) {
- for (r2 = lastfaces.first; r2; r2 = r2->next) {
- if (r2->ref == f) {
- knife_add_single_cut_through(kcd, firstv, lastv, f);
- break;
- }
- }
- }
- }
- }
- for (i = 0, lh = kcd->linehits; i < kcd->totlinehit; i++, lh++) {
+ splitkfe = MEM_callocN(n * sizeof(KnifeEdge *), "knife_cut_through");
+
+ lastv = NULL;
+ for (i = 0, lh = linehits; i < n; i++, lh++) {
kfe = lh->kfe;
+ v1 = NULL;
- /* For each face attached to edge for this linehit,
- * find the first following linehit (if any) sharing that face and connect */
- for (r = kfe->faces.first; r; r = r->next) {
- bool found = false;
- f = r->ref;
- for (j = i + 1, lh2 = lh + 1; j < kcd->totlinehit && !found; j++, lh2++) {
- kfe2 = lh2->kfe;
- for (r2 = kfe2->faces.first; r2; r2 = r2->next) {
- if (r2->ref == f) {
- v1 = splitkfe[i] ? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]);
- v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]);
- knife_add_single_cut_through(kcd, v1, v2, f);
- found = true;
- break;
- }
- }
+ /* get faces incident on hit lh */
+ if (lh->v) {
+ v1 = lh->v;
+ faces1 = &v1->faces;
+ }
+ else if (kfe) {
+ faces1 = &kfe->faces;
+ }
+
+ /* For each following hit, connect if lh1 an lh2 share a face */
+ for (j = i + 1, lh2 = lh + 1; j < n; j++, lh2++) {
+ kfe2 = lh2->kfe;
+ v2 = NULL;
+ if (lh2->v) {
+ v2 = lh2->v;
+ faces2 = &v2->faces;
}
- if (!found && lastv) {
- for (r2 = lastfaces.first; r2; r2 = r2->next) {
- if (r2->ref == f) {
- v1 = splitkfe[i] ? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]);
- knife_add_single_cut_through(kcd, v1, lastv, f);
- break;
- }
- }
+ else if (kfe2) {
+ faces2 = &kfe2->faces;
+ }
+
+ f = knife_find_common_face(faces1, faces2);
+ if (f) {
+ if (!v1)
+ v1 = splitkfe[i] ? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]);
+ if (!v2)
+ v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]);
+ knife_add_single_cut_through(kcd, v1, v2, f);
+ lastv = v2;
}
}
}
MEM_freeN(splitkfe);
+ MEM_freeN(linehits);
MEM_freeN(kcd->linehits);
kcd->linehits = NULL;
kcd->totlinehit = 0;
@@ -816,7 +844,7 @@ static void knife_add_cut(KnifeTool_OpData *kcd)
BMEdgeHit *lh, *lastlh, *firstlh;
int i;
- knife_sort_linehits(kcd);
+ knife_sort_linehits(kcd, true);
lh = kcd->linehits;
lastlh = firstlh = NULL;
@@ -848,14 +876,14 @@ static void knife_add_cut(KnifeTool_OpData *kcd)
continue;
/* first linehit may be down face parallel to view */
- if (!lastlh && fabsf(lh->l) < KNIFE_FLT_EPS)
+ if (!lastlh && !lh->v && fabsf(lh->l) < KNIFE_FLT_EPS)
continue;
if (kcd->prev.is_space) {
kcd->prev.is_space = 0;
copy_v3_v3(kcd->prev.co, lh->hit);
copy_v3_v3(kcd->prev.cage, lh->cagehit);
- kcd->prev.vert = NULL;
+ kcd->prev.vert = lh->v;
kcd->prev.edge = lh->kfe;
kcd->prev.bmface = lh->f;
continue;
@@ -1181,9 +1209,9 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
BLI_array_declare(edges);
BVHTreeOverlap *results, *result;
BMLoop **ls;
- float cos[9], lambda;
+ float cos[9], tri_norm[3], tri_plane[4], isects[2][3], lambda;
unsigned int tot = 0;
- int i;
+ int i, j, n_isects;
/* for comparing distances, error of intersection depends on triangle scale.
* need to scale down before squaring for accurate comparison */
@@ -1194,6 +1222,9 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
copy_v3_v3(cos + 3, v2);
copy_v3_v3(cos + 6, v3);
+ normal_tri_v3(tri_norm, v1, v2, v3);
+ plane_from_point_normal_v3(tri_plane, v1, tri_norm);
+
BLI_bvhtree_insert(tree2, 0, cos, 3);
BLI_bvhtree_balance(tree2);
@@ -1217,11 +1248,24 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
continue; /* We already found a hit on this knife edge */
}
- if (isect_line_tri_v3(kfe->v1->cageco, kfe->v2->cageco, v1, v2, v3, &lambda, NULL)) {
+ n_isects = 0;
+ if (fabsf(dist_to_plane_v3(kfe->v1->cageco, tri_plane)) < KNIFE_FLT_EPS &&
+ fabsf(dist_to_plane_v3(kfe->v2->cageco, tri_plane)) < KNIFE_FLT_EPS)
+ {
+ /* both kfe ends are in cutting triangle */
+ copy_v3_v3(isects[0], kfe->v1->cageco);
+ copy_v3_v3(isects[1], kfe->v2->cageco);
+ n_isects = 2;
+ }
+ else if (isect_line_tri_epsilon_v3(kfe->v1->cageco, kfe->v2->cageco, v1, v2, v3, &lambda, NULL, depsilon)) {
+ /* kfe intersects cutting triangle lambda of the way along kfe */
+ interp_v3_v3v3(isects[0], kfe->v1->cageco, kfe->v2->cageco, lambda);
+ n_isects = 1;
+ }
+ for (j = 0; j < n_isects; j++) {
float p[3], no[3], view[3], sp[2];
- interp_v3_v3v3(p, kfe->v1->cageco, kfe->v2->cageco, lambda);
-
+ copy_v3_v3(p, isects[j]);
if (kcd->curr.vert && len_squared_v3v3(kcd->curr.vert->cageco, p) < depsilon_sq) {
continue;
}
@@ -1268,7 +1312,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
add_v3_v3(p1, no);
/* ray cast */
- f_hit = BKE_bmbvh_ray_cast(bmtree, p1, no, NULL, NULL, NULL);
+ f_hit = BKE_bmbvh_ray_cast(bmtree, p1, no, KNIFE_FLT_EPS, NULL, NULL, NULL);
}
/* ok, if visible add the new point */
@@ -1283,6 +1327,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
hit.kfe = kfe;
hit.v = NULL;
+ hit.l = 0.0f;
knife_find_basef(kfe);
hit.f = kfe->basef;
@@ -1292,7 +1337,6 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
interp_v3_v3v3(p, kfe->v1->co, kfe->v2->co, hit.perc);
copy_v3_v3(hit.realhit, p);
- /* BMESH_TODO: should also snap to vertices */
if (kcd->snap_midpoints) {
float perc = hit.perc;
@@ -1310,6 +1354,12 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
interp_v3_v3v3(hit.hit, kfe->v1->co, kfe->v2->co, perc);
interp_v3_v3v3(hit.cagehit, kfe->v1->cageco, kfe->v2->cageco, perc);
}
+ else if (hit.perc < KNIFE_FLT_EPS || hit.perc > 1.0f - KNIFE_FLT_EPS) {
+ /* snap to vert */
+ hit.v = (hit.perc < KNIFE_FLT_EPS) ? kfe->v1 : kfe->v2;
+ copy_v3_v3(hit.hit, hit.v->co);
+ copy_v3_v3(hit.cagehit, hit.v->co);
+ }
else {
copy_v3_v3(hit.hit, p);
}
@@ -1502,7 +1552,7 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float
knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
sub_v3_v3v3(ray, origin_ofs, origin);
- f = BKE_bmbvh_ray_cast(kcd->bmbvh, origin, ray, NULL, co, cageco);
+ f = BKE_bmbvh_ray_cast(kcd->bmbvh, origin, ray, 0.0f, NULL, co, cageco);
if (is_space)
*is_space = !f;
@@ -1652,7 +1702,7 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo
if (fptr)
*fptr = f;
- if (cure && p) {
+ if (cure) {
if (!kcd->ignore_edge_snapping || !(cure->e)) {
KnifeVert *edgesnap = NULL;
@@ -1745,7 +1795,7 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo
if (fptr)
*fptr = f;
- if (curv && p) {
+ if (curv) {
copy_v3_v3(p, curv->co);
copy_v3_v3(cagep, curv->cageco);
@@ -1993,7 +2043,7 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd)
for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
if (!kfv->v) {
/* shouldn't we be at least copying the normal? - if not some comment here should explain why - campbell */
- kfv->v = BM_vert_create(bm, kfv->co, NULL);
+ kfv->v = BM_vert_create(bm, kfv->co, NULL, BM_CREATE_NOP);
kfv->flag = 1;
BMO_elem_flag_enable(bm, kfv->v, DEL);
}
@@ -2683,7 +2733,7 @@ static void knife_make_chain_cut(KnifeTool_OpData *kcd, BMFace *f, ListBase *cha
BM_edge_select_set(bm, l_new->e, true);
}
}
- else {
+ else if (f_new) {
BM_elem_select_copy(bm, bm, f_new, f);
}
diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c
index e7eaa625843..18db21a8726 100644
--- a/source/blender/editors/mesh/editmesh_path.c
+++ b/source/blender/editors/mesh/editmesh_path.c
@@ -52,6 +52,9 @@
#include "WM_types.h"
+#include "bmesh.h"
+#include "bmesh_tools.h"
+
#include "mesh_intern.h" /* own include */
struct UserData {
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index 1360a180b2d..84952297235 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -50,6 +50,9 @@
#include "ED_transform.h"
#include "ED_view3d.h"
+#include "bmesh.h"
+#include "bmesh_tools.h"
+
#include "mesh_intern.h" /* own include */
/**
@@ -60,23 +63,29 @@
* point and would result in the same distance.
*/
#define INSET_DEFAULT 0.00001f
-static float edbm_rip_edgedist(ARegion *ar, float mat[4][4],
- const float co1[3], const float co2[3], const float mvalf[2],
- const float inset)
+static float edbm_rip_edgedist_squared(ARegion *ar, float mat[4][4],
+ const float co1[3], const float co2[3], const float mvalf[2],
+ const float inset)
{
- float vec1[2], vec2[2];
+ float vec1[2], vec2[2], dist_sq;
ED_view3d_project_float_v2_m4(ar, co1, vec1, mat);
ED_view3d_project_float_v2_m4(ar, co2, vec2, mat);
if (inset != 0.0f) {
- const float dist = inset / len_v2v2(vec1, vec2);
- interp_v2_v2v2(vec1, vec1, vec2, dist);
- interp_v2_v2v2(vec2, vec2, vec1, dist);
+ const float dist_2d = len_v2v2(vec1, vec2);
+ if (dist_2d > FLT_EPSILON) {
+ const float dist = inset / dist_2d;
+ BLI_assert(finite(dist));
+ interp_v2_v2v2(vec1, vec1, vec2, dist);
+ interp_v2_v2v2(vec2, vec2, vec1, dist);
+ }
}
- /* TODO: use dist_squared_to_line_segment_v2() looks like we only ever use for comparison */
- return dist_to_line_segment_v2(mvalf, vec1, vec2);
+ dist_sq = dist_squared_to_line_segment_v2(mvalf, vec1, vec2);
+ BLI_assert(finite(dist_sq));
+
+ return dist_sq;
}
#if 0
@@ -488,7 +497,7 @@ static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *u
/* face should never exist */
BLI_assert(BM_face_exists(f_verts, f_verts[3] ? 4 : 3, &f) == false);
- f = BM_face_create_quad_tri_v(bm, f_verts, f_verts[3] ? 4 : 3, f_example, false);
+ f = BM_face_create_verts(bm, f_verts, f_verts[3] ? 4 : 3, f_example, BM_CREATE_NOP, true);
l_iter = BM_FACE_FIRST_LOOP(f);
@@ -525,11 +534,11 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BMIter iter, liter;
BMLoop *l;
BMEdge *e, *e2;
- BMVert *v, *ripvert = NULL;
+ BMVert *v;
const int totvert_orig = bm->totvert;
int i;
float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
- float dist = FLT_MAX;
+ float dist_sq = FLT_MAX;
float d;
bool is_wire;
@@ -562,15 +571,15 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
if (v->e) {
/* find closest edge to mouse cursor */
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- int is_boundary = BM_edge_is_boundary(e);
+ const bool is_boundary = BM_edge_is_boundary(e);
/* consider wire as boundary for this purpose,
* otherwise we can't a face away from a wire edge */
totboundary_edge += (is_boundary != 0 || BM_edge_is_wire(e));
if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
if (is_boundary == false && BM_edge_is_manifold(e)) {
- d = edbm_rip_edgedist(ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT);
- if (d < dist) {
- dist = d;
+ d = edbm_rip_edgedist_squared(ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT);
+ if ((e2 == NULL) || (d < dist_sq)) {
+ dist_sq = d;
e2 = e;
}
}
@@ -596,10 +605,9 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
float l_mid_co[3];
l = l_all[i1];
edbm_calc_loop_co(l, l_mid_co);
- d = edbm_rip_edgedist(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT);
-
- if (d < dist) {
- dist = d;
+ d = edbm_rip_edgedist_squared(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT);
+ if ((e2 == NULL) || (d < dist_sq)) {
+ dist_sq = d;
/* find the edge that is not in this loop */
e2 = NULL;
@@ -647,7 +655,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BM_select_history_remove(bm, ese.ele);
}
- dist = FLT_MAX;
+ dist_sq = FLT_MAX;
/* in the loop below we find the best vertex to drag based on its connected geometry,
* either by its face corner, or connected edge (when no faces are attached) */
@@ -658,12 +666,12 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BM_ITER_ELEM (l, &iter, vout[i], BM_LOOPS_OF_VERT) {
if (!BM_elem_flag_test(l->f, BM_ELEM_HIDDEN)) {
float l_mid_co[3];
- edbm_calc_loop_co(l, l_mid_co);
- d = edbm_rip_edgedist(ar, projectMat, v->co, l_mid_co, fmval, INSET_DEFAULT);
+ edbm_calc_loop_co(l, l_mid_co);
+ d = edbm_rip_edgedist_squared(ar, projectMat, v->co, l_mid_co, fmval, INSET_DEFAULT);
- if (d < dist) {
- dist = d;
+ if (d < dist_sq) {
+ dist_sq = d;
vi_best = i;
}
}
@@ -674,12 +682,12 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BM_ITER_ELEM (e, &iter, vout[i], BM_EDGES_OF_VERT) {
if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
float e_mid_co[3];
- mid_v3_v3v3(e_mid_co, e->v1->co, e->v2->co);
- d = edbm_rip_edgedist(ar, projectMat, v->co, e_mid_co, fmval, INSET_DEFAULT);
+ mid_v3_v3v3(e_mid_co, e->v1->co, e->v2->co);
+ d = edbm_rip_edgedist_squared(ar, projectMat, v->co, e_mid_co, fmval, INSET_DEFAULT);
- if (d < dist) {
- dist = d;
+ if (d < dist_sq) {
+ dist_sq = d;
vi_best = i;
}
}
@@ -730,19 +738,36 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
/* rip two adjacent edges */
if (BM_edge_is_boundary(e2) || BM_vert_face_count(v) == 2) {
/* Don't run the edge split operator in this case */
+ BMVert *v_rip;
- BM_elem_flag_enable(e2, BM_ELEM_TAG); /* only for face-fill (we don't call the operator) */
+ l = BM_edge_vert_share_loop(e2->l, v);
+
+ /* only tag for face-fill (we don't call the operator) */
+ if (BM_edge_is_boundary(e2)) {
+ BM_elem_flag_enable(e2, BM_ELEM_TAG);
+ }
+ else {
+ BM_elem_flag_enable(l->e, BM_ELEM_TAG);
+ BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG);
+ }
/* keep directly before edgesplit */
if (do_fill) {
fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm);
}
- l = e2->l;
- ripvert = BM_face_vert_separate(bm, l->f, v);
+#if 0
+ v_rip = BM_face_vert_separate(bm, l->f, v);
+#else
+ v_rip = BM_face_loop_separate(bm, l);
+#endif
+
+ BLI_assert(v_rip);
- BLI_assert(ripvert);
- if (!ripvert) {
+ if (v_rip) {
+ BM_vert_select_set(bm, v_rip, true);
+ }
+ else {
if (fill_uloop_pairs) MEM_freeN(fill_uloop_pairs);
return OPERATOR_CANCELLED;
}
@@ -769,37 +794,28 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BM_mesh_edgesplit(em->bm, true, true, true);
}
- dist = FLT_MAX;
+ dist_sq = FLT_MAX;
{
/* --- select which vert --- */
BMVert *v_best = NULL;
- float l_prev_co[3], l_next_co[3], l_corner_co[3];
- float scale;
+ float l_corner_co[3];
- dist = FLT_MAX;
+ dist_sq = FLT_MAX;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
/* disable by default, re-enable winner at end */
BM_vert_select_set(bm, v, false);
+ BM_select_history_remove(bm, v);
BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- /* calculate a point in the face, rather then calculate the middle,
- * make a vector pointing between the 2 edges attached to this loop */
- sub_v3_v3v3(l_prev_co, l->prev->v->co, l->v->co);
- sub_v3_v3v3(l_next_co, l->next->v->co, l->v->co);
-
- scale = normalize_v3(l_prev_co) + normalize_v3(l_next_co);
- mul_v3_fl(l_prev_co, scale);
- mul_v3_fl(l_next_co, scale);
-
- add_v3_v3v3(l_corner_co, l_prev_co, l_next_co);
- add_v3_v3(l_corner_co, l->v->co);
- d = edbm_rip_edgedist(ar, projectMat, l->v->co, l_corner_co, fmval, INSET_DEFAULT);
- if (d < dist) {
+ /* check if v_best is null in the _rare_ case there are numeric issues */
+ edbm_calc_loop_co(l, l_corner_co);
+ d = edbm_rip_edgedist_squared(ar, projectMat, l->v->co, l_corner_co, fmval, INSET_DEFAULT);
+ if ((v_best == NULL) || (d < dist_sq)) {
v_best = v;
- dist = d;
+ dist_sq = d;
}
}
}
@@ -965,7 +981,7 @@ static int edbm_rip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
BMesh *bm = em->bm;
BMIter iter;
BMEdge *e;
- int singlesel = (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0);
+ const bool singlesel = (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0);
int ret;
/* running in face mode hardly makes sense, so convert to region loop and rip */
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index f4a55af742c..806ae96cb61 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -2510,7 +2510,7 @@ static int edbm_select_nth_exec(bContext *C, wmOperator *op)
int offset = RNA_int_get(op->ptr, "offset");
/* so input of offset zero ends up being (nth - 1) */
- offset = (offset + (nth - 1)) % nth;
+ offset = mod_i(offset, nth);
if (edbm_deselect_nth(em, nth, offset) == false) {
BKE_report(op->reports, RPT_ERROR, "Mesh has no active vert/edge/face");
@@ -2538,7 +2538,7 @@ void MESH_OT_select_nth(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_int(ot->srna, "nth", 2, 2, INT_MAX, "Nth Selection", "", 2, 100);
- RNA_def_int(ot->srna, "offset", 0, 0, INT_MAX, "Offset", "", 0, 100);
+ RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "", -100, 100);
}
void em_setup_viewcontext(bContext *C, ViewContext *vc)
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 38ce56b4bc7..75ff5256e10 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -29,6 +29,8 @@
* \ingroup edmesh
*/
+#include <stddef.h>
+
#include "MEM_guardedalloc.h"
#include "DNA_key_types.h"
@@ -43,6 +45,7 @@
#include "BLI_noise.h"
#include "BLI_math.h"
#include "BLI_rand.h"
+#include "BLI_sort_utils.h"
#include "BKE_material.h"
#include "BKE_context.h"
@@ -892,14 +895,30 @@ static int edbm_duplicate_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
BMOperator bmop;
+ ListBase bm_selected_store = {NULL, NULL};
+
+ /* de-select all would clear otherwise */
+ SWAP(ListBase, bm->selected, bm_selected_store);
EDBM_op_init(em, &bmop, op, "duplicate geom=%hvef", BM_ELEM_SELECT);
- BMO_op_exec(em->bm, &bmop);
+ BMO_op_exec(bm, &bmop);
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+ BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+
+ /* rebuild editselection */
+ bm->selected = bm_selected_store;
+
+ if (bm->selected.first) {
+ BMOpSlot *slot_vert_map_out = BMO_slot_get(bmop.slots_out, "vert_map.out");
+ BMOpSlot *slot_edge_map_out = BMO_slot_get(bmop.slots_out, "edge_map.out");
+ BMOpSlot *slot_face_map_out = BMO_slot_get(bmop.slots_out, "face_map.out");
+
+ BMO_mesh_selected_remap(bm, slot_vert_map_out, slot_edge_map_out, slot_face_map_out);
+ }
if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
@@ -2292,7 +2311,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
mouse_path = MEM_mallocN(len * sizeof(*mouse_path), __func__);
/* get the cut curve */
- RNA_BEGIN(op->ptr, itemptr, "path")
+ RNA_BEGIN (op->ptr, itemptr, "path")
{
RNA_float_get_array(&itemptr, "loc", (float *)&mouse_path[len]);
}
@@ -2816,6 +2835,146 @@ void MESH_OT_fill(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_beauty", true, "Beauty", "Use best triangulation division");
}
+
+/* -------------------------------------------------------------------- */
+/* Grid Fill (and helper functions) */
+
+static bool bm_edge_test_fill_grid_cb(BMEdge *e, void *UNUSED(bm_v))
+{
+ return BM_elem_flag_test_bool(e, BM_ELEM_TAG);
+}
+
+static float edbm_fill_grid_vert_tag_angle(BMVert *v)
+{
+ BMIter iter;
+ BMEdge *e_iter;
+ BMVert *v_pair[2];
+ int i = 0;
+ BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_iter, BM_ELEM_TAG)) {
+ v_pair[i++] = BM_edge_other_vert(e_iter, v);
+ }
+ }
+ BLI_assert(i == 2);
+
+ return fabsf((float)M_PI - angle_v3v3v3(v_pair[0]->co, v->co, v_pair[1]->co));
+}
+
+/**
+ * non-essential utility function to select 2 open edge loops from a closed loop.
+ */
+static void edbm_fill_grid_prepare(BMesh *bm, int offset, int *r_span, bool span_calc)
+{
+ BMEdge *e;
+ BMIter iter;
+ int count;
+ int span = *r_span;
+
+ ListBase eloops = {NULL};
+ struct BMEdgeLoopStore *el_store;
+ // LinkData *el_store;
+
+ /* select -> tag */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT));
+ }
+
+ count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_fill_grid_cb, bm);
+ el_store = eloops.first;
+
+ if (count == 1 && BM_edgeloop_is_closed(el_store) && (BM_edgeloop_length_get(el_store) & 1) == 0) {
+ /* be clever! detect 2 edge loops from one closed edge loop */
+ const int verts_len = BM_edgeloop_length_get(el_store);
+ ListBase *verts = BM_edgeloop_verts_get(el_store);
+ BMVert *v_act = BM_mesh_active_vert_get(bm);
+ LinkData *v_act_link;
+ BMEdge **edges = MEM_mallocN(sizeof(*edges) * verts_len, __func__);
+ int i;
+
+ if (v_act && (v_act_link = BLI_findptr(verts, v_act, offsetof(LinkData, data)))) {
+ /* pass */
+ }
+ else {
+ /* find the vertex with the best angle (a corner vertex) */
+ LinkData *v_link, *v_link_best = NULL;
+ float angle_best = -1.0f;
+ for (v_link = verts->first; v_link; v_link = v_link->next) {
+ const float angle = edbm_fill_grid_vert_tag_angle(v_link->data);
+ if ((angle > angle_best) || (v_link_best == NULL)) {
+ angle_best = angle;
+ v_link_best = v_link;
+ }
+ }
+
+ v_act_link = v_link_best;
+ v_act = v_act_link->data;
+ }
+
+ if (offset != 0) {
+ v_act_link = BLI_findlink(verts, offset);
+ v_act = v_act_link->data;
+ }
+
+ /* set this vertex first */
+ BLI_rotatelist_first(verts, v_act_link);
+ BM_edgeloop_edges_get(el_store, edges);
+
+
+ if (span_calc) {
+ /* calculate the span by finding the next corner in 'verts'
+ * we dont know what defines a corner exactly so find the 4 verts
+ * in the loop with the greatest angle.
+ * Tag them and use the first tagged vertex to calcualte the span.
+ *
+ * note: we may have already checked 'edbm_fill_grid_vert_tag_angle()' on each
+ * vert, but advantage of de-duplicating is minimal. */
+ struct SortPointerByFloat *ele_sort = MEM_mallocN(sizeof(*ele_sort) * verts_len, __func__);
+ LinkData *v_link;
+ for (v_link = verts->first, i = 0; v_link; v_link = v_link->next, i++) {
+ BMVert *v = v_link->data;
+ const float angle = edbm_fill_grid_vert_tag_angle(v);
+ ele_sort[i].sort_value = angle;
+ ele_sort[i].data = v;
+
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ }
+
+ qsort(ele_sort, verts_len, sizeof(*ele_sort), BLI_sortutil_cmp_float_reverse);
+
+ for (i = 0; i < 4; i++) {
+ BMVert *v = ele_sort[i].data;
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ }
+
+ /* now find the first... */
+ for (v_link = verts->first, i = 0; i < verts_len / 2; v_link = v_link->next, i++) {
+ BMVert *v = v_link->data;
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ if (v != v_act) {
+ span = i;
+ break;
+ }
+ }
+ }
+ MEM_freeN(ele_sort);
+ }
+ /* end span calc */
+
+
+ /* un-flag 'rails' */
+ for (i = 0; i < span; i++) {
+ BM_elem_flag_disable(edges[i], BM_ELEM_TAG);
+ BM_elem_flag_disable(edges[(verts_len / 2) + i], BM_ELEM_TAG);
+ }
+ MEM_freeN(edges);
+ }
+ /* else let the bmesh-operator handle it */
+
+ BM_mesh_edgeloops_free(&eloops);
+
+ *r_span = span;
+}
+
static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
{
BMOperator bmop;
@@ -2824,10 +2983,43 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
const short use_smooth = edbm_add_edge_face__smooth_get(em->bm);
const int totedge_orig = em->bm->totedge;
const int totface_orig = em->bm->totface;
+ const bool use_prepare = true;
+
+
+ if (use_prepare) {
+ /* use when we have a single loop selected */
+ PropertyRNA *prop_span = RNA_struct_find_property(op->ptr, "span");
+ PropertyRNA *prop_offset = RNA_struct_find_property(op->ptr, "offset");
+ bool calc_span;
+
+ const int clamp = em->bm->totvertsel;
+ int span;
+ int offset;
+
+ if (RNA_property_is_set(op->ptr, prop_span)) {
+ span = RNA_property_int_get(op->ptr, prop_span);
+ span = min_ii(span, (clamp / 2) - 1);
+ calc_span = false;
+ }
+ else {
+ span = clamp / 4;
+ calc_span = true;
+ }
+
+ offset = RNA_property_int_get(op->ptr, prop_offset);
+ offset = mod_i(offset, clamp);
+
+ /* in simple cases, move selection for tags, but also support more advanced cases */
+ edbm_fill_grid_prepare(em->bm, offset, &span, calc_span);
+
+ RNA_property_int_set(op->ptr, prop_span, span);
+ }
+ /* end tricky prepare code */
+
if (!EDBM_op_init(em, &bmop, op,
"grid_fill edges=%he mat_nr=%i use_smooth=%b",
- BM_ELEM_SELECT, em->mat_nr, use_smooth))
+ use_prepare ? BM_ELEM_TAG : BM_ELEM_SELECT, em->mat_nr, use_smooth))
{
return OPERATOR_CANCELLED;
}
@@ -2855,6 +3047,8 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
void MESH_OT_fill_grid(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Grid Fill";
ot->description = "Fill grid from two loops";
@@ -2866,6 +3060,12 @@ void MESH_OT_fill_grid(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_int(ot->srna, "span", 1, 1, INT_MAX, "Span", "Number of sides (zero disables)", 1, 100);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "Number of sides (zero disables)", -100, 100);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static int edbm_fill_holes_exec(bContext *C, wmOperator *op)
@@ -4441,10 +4641,17 @@ static int mesh_symmetrize_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMOperator bmop;
- EDBM_op_init(em, &bmop, op, "symmetrize input=%hvef direction=%i",
- BM_ELEM_SELECT, RNA_enum_get(op->ptr, "direction"));
+ const float thresh = RNA_float_get(op->ptr, "threshold");
+
+ EDBM_op_init(em, &bmop, op,
+ "symmetrize input=%hvef direction=%i dist=%f",
+ BM_ELEM_SELECT, RNA_enum_get(op->ptr, "direction"), thresh);
BMO_op_exec(em->bm, &bmop);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+
if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
@@ -4472,6 +4679,7 @@ void MESH_OT_symmetrize(struct wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "direction", symmetrize_direction_items,
BMO_SYMMETRIZE_NEGATIVE_X,
"Direction", "Which sides to copy from and to");
+ RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Threshold", "", 0.00001, 0.1);
}
static int mesh_symmetry_snap_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 46cab3b4416..a64a23a9f4a 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -1481,7 +1481,7 @@ int BMBVH_VertVisible(BMBVHTree *tree, BMEdge *e, RegionView3D *r3d)
static BMFace *edge_ray_cast(struct BMBVHTree *tree, const float co[3], const float dir[3], float *r_hitout, BMEdge *e)
{
- BMFace *f = BKE_bmbvh_ray_cast(tree, co, dir, NULL, r_hitout, NULL);
+ BMFace *f = BKE_bmbvh_ray_cast(tree, co, dir, 0.0f, NULL, r_hitout, NULL);
if (f && BM_edge_in_face(e, f))
return NULL;
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 1dcc0e64183..ed026258e4b 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -95,6 +95,8 @@ void MESH_OT_primitive_ico_sphere_add(struct wmOperatorType *ot);
/* *** editmesh_bevel.c *** */
void MESH_OT_bevel(struct wmOperatorType *ot);
+/* *** editmesh_bisect.c *** */
+void MESH_OT_bisect(struct wmOperatorType *ot);
/* *** editmesh_extrude.c *** */
void MESH_OT_extrude_repeat(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c
index 66e577975b6..d889ed1bc74 100644
--- a/source/blender/editors/mesh/mesh_navmesh.c
+++ b/source/blender/editors/mesh/mesh_navmesh.c
@@ -350,7 +350,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
co[1] = bmin[1] + v[1] * ch;
co[2] = bmin[2] + v[2] * cs;
SWAP(float, co[1], co[2]);
- BM_vert_create(em->bm, co, NULL, 0);
+ BM_vert_create(em->bm, co, NULL, BM_CREATE_NOP);
}
/* create custom data layer to save polygon idx */
@@ -381,7 +381,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
for (j = nv; j < ndv; j++) {
copy_v3_v3(co, &dverts[3 * (vbase + j)]);
SWAP(float, co[1], co[2]);
- BM_vert_create(em->bm, co, NULL, 0);
+ BM_vert_create(em->bm, co, NULL, BM_CREATE_NOP);
}
/* need to rebuild entirely because array size changes */
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index b5352fb35f4..c98ad13acf6 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -175,6 +175,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_convex_hull);
#endif
+ WM_operatortype_append(MESH_OT_bisect);
WM_operatortype_append(MESH_OT_symmetrize);
WM_operatortype_append(MESH_OT_symmetry_snap);
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index d012a8ac656..ce1cacdfb3a 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -178,7 +178,6 @@ int join_mesh_exec(bContext *C, wmOperator *op)
if (kb->data) MEM_freeN(kb->data);
kb->data = MEM_callocN(sizeof(float) * 3 * totvert, "join_shapekey");
kb->totelem = totvert;
- kb->weights = NULL;
}
}
else if (haskey) {
@@ -1136,7 +1135,7 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em)
mesh_octree_table(ob, em, NULL, 'e');
- fhash = BLI_ghash_new(mirror_facehash, mirror_facecmp, "mirror_facehash gh");
+ fhash = BLI_ghash_new_ex(mirror_facehash, mirror_facecmp, "mirror_facehash gh", me->totface);
for (a = 0, mf = mface; a < me->totface; a++, mf++)
BLI_ghash_insert(fhash, mf, mf);
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index de0af1d1bb8..b79eeee49d7 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -112,6 +112,8 @@ MetaElem *add_metaball_primitive(bContext *UNUSED(C), Object *obedit, float mat[
ml = BKE_mball_element_add(mball, type);
ml->rad *= dia;
+ mball->wiresize *= dia;
+ mball->rendersize *= dia;
copy_v3_v3(&ml->x, mat[3]);
ml->flag |= SELECT;
@@ -499,19 +501,13 @@ bool mouse_mball(bContext *C, const int mval[2], bool extend, bool deselect, boo
/* free all MetaElems from ListBase */
static void freeMetaElemlist(ListBase *lb)
{
- MetaElem *ml, *next;
+ MetaElem *ml;
if (lb == NULL) return;
- ml = lb->first;
- while (ml) {
- next = ml->next;
- BLI_remlink(lb, ml);
+ while ((ml = BLI_pophead(lb))) {
MEM_freeN(ml);
- ml = next;
}
-
- lb->first = lb->last = NULL;
}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index ce61b4fce50..b907cba33e2 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1243,7 +1243,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
ob->parent = NULL;
ob->constraints.first = ob->constraints.last = NULL;
- ob->disp.first = ob->disp.last = NULL;
+ ob->curve_cache = NULL;
ob->transflag &= ~OB_DUPLI;
ob->lay = base->lay;
@@ -1385,7 +1385,7 @@ static EnumPropertyItem convert_target_items[] = {
static void curvetomesh(Scene *scene, Object *ob)
{
- if (ob->disp.first == NULL)
+ if (ELEM(NULL, ob->curve_cache, ob->curve_cache->disp.first))
BKE_displist_make_curveTypes(scene, ob, 0); /* force creation */
BKE_mesh_from_nurbs(ob); /* also does users */
@@ -1553,7 +1553,7 @@ static int convert_exec(bContext *C, wmOperator *op)
cu = newob->data;
- if (!newob->disp.first)
+ if ( !newob->curve_cache || !newob->curve_cache->disp.first)
BKE_displist_make_curveTypes(scene, newob, 0);
newob->type = OB_CURVE;
@@ -1595,7 +1595,7 @@ static int convert_exec(bContext *C, wmOperator *op)
curvetomesh(scene, newob);
/* meshes doesn't use displist */
- BKE_displist_free(&newob->disp);
+ BKE_object_free_curve_cache(newob);
}
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
@@ -1616,7 +1616,7 @@ static int convert_exec(bContext *C, wmOperator *op)
newob = ob;
/* meshes doesn't use displist */
- BKE_displist_free(&newob->disp);
+ BKE_object_free_curve_cache(newob);
}
curvetomesh(scene, newob);
@@ -1635,7 +1635,7 @@ static int convert_exec(bContext *C, wmOperator *op)
ob->flag |= OB_DONE;
}
- if (!baseob->disp.first) {
+ if (!baseob->curve_cache || !baseob->curve_cache->disp.first) {
BKE_displist_make_mball(scene, baseob);
}
@@ -1658,7 +1658,7 @@ static int convert_exec(bContext *C, wmOperator *op)
for (a = 0; a < newob->totcol; a++) id_us_plus((ID *)me->mat[a]);
}
- BKE_mesh_from_metaball(&baseob->disp, newob->data);
+ BKE_mesh_from_metaball(&baseob->curve_cache->disp, newob->data);
if (obact->type == OB_MBALL) {
basact = basen;
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 7f7a0777bbf..c69210e2450 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -79,6 +79,7 @@
#include "BKE_softbody.h"
#include "BKE_modifier.h"
#include "BKE_editmesh.h"
+#include "BKE_report.h"
#include "ED_armature.h"
#include "ED_curve.h"
@@ -556,11 +557,20 @@ void ED_object_editmode_enter(bContext *C, int flag)
if (flag & EM_WAITCURSOR) waitcursor(0);
}
-static int editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
+static int editmode_toggle_exec(bContext *C, wmOperator *op)
{
+ const int mode_flag = OB_MODE_EDIT;
+ const bool is_mode_set = CTX_data_edit_object(C);
ToolSettings *toolsettings = CTX_data_tool_settings(C);
- if (!CTX_data_edit_object(C))
+ if (!is_mode_set) {
+ Scene *scene = CTX_data_scene(C);
+ if (!ED_object_mode_compat_set(C, scene->basact->object, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (!is_mode_set)
ED_object_editmode_enter(C, EM_WAITCURSOR);
else
ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */
@@ -582,10 +592,7 @@ static int editmode_toggle_poll(bContext *C)
if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT))
return 0;
- return (ob->type == OB_MESH || ob->type == OB_ARMATURE ||
- ob->type == OB_FONT || ob->type == OB_MBALL ||
- ob->type == OB_LATTICE || ob->type == OB_SURF ||
- ob->type == OB_CURVE);
+ return (ELEM7(ob->type, OB_MESH, OB_ARMATURE, OB_FONT, OB_MBALL, OB_LATTICE, OB_SURF, OB_CURVE));
}
void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
@@ -598,7 +605,6 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
/* api callbacks */
ot->exec = editmode_toggle_exec;
-
ot->poll = editmode_toggle_poll;
/* flags */
@@ -607,16 +613,25 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
/* *************************** */
-static int posemode_exec(bContext *C, wmOperator *UNUSED(op))
+static int posemode_exec(bContext *C, wmOperator *op)
{
Base *base = CTX_data_active_base(C);
+ Object *ob = base->object;
+ const int mode_flag = OB_MODE_POSE;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
- if (base->object->type == OB_ARMATURE) {
- if (base->object == CTX_data_edit_object(C)) {
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (ob->type == OB_ARMATURE) {
+ if (ob == CTX_data_edit_object(C)) {
ED_object_editmode_exit(C, EM_FREEDATA | EM_DO_UNDO);
ED_armature_enter_posemode(C, base);
}
- else if (base->object->mode & OB_MODE_POSE)
+ else if (is_mode_set)
ED_armature_exit_posemode(C, base);
else
ED_armature_enter_posemode(C, base);
@@ -1417,8 +1432,9 @@ static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d)
space = size[0] / size[1];
}
else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
- Curve *cu = ob->data;
- space = cu->size[0] / cu->size[1];
+ float size[3];
+ BKE_curve_texspace_get(ob->data, NULL, NULL, size);
+ space = size[0] / size[1];
}
x = ibuf->x / space;
@@ -1500,19 +1516,21 @@ static const char *object_mode_op_string(int mode)
}
/* checks the mode to be set is compatible with the object
- * should be made into a generic function */
-static bool object_mode_set_compat(bContext *UNUSED(C), wmOperator *op, Object *ob)
+ * should be made into a generic function
+ */
+static bool object_mode_compat_test(Object *ob, ObjectMode mode)
{
- ObjectMode mode = RNA_enum_get(op->ptr, "mode");
-
if (ob) {
if (mode == OB_MODE_OBJECT)
return true;
switch (ob->type) {
case OB_MESH:
- if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT | OB_MODE_PARTICLE_EDIT))
+ if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT |
+ OB_MODE_TEXTURE_PAINT | OB_MODE_PARTICLE_EDIT))
+ {
return true;
+ }
break;
case OB_CURVE:
case OB_SURF:
@@ -1535,6 +1553,30 @@ static bool object_mode_set_compat(bContext *UNUSED(C), wmOperator *op, Object *
return false;
}
+/**
+ * Sets the mode to a compatible state (use before entering the mode).
+ *
+ * This is so each mode's exec function can call
+ */
+bool ED_object_mode_compat_set(bContext *C, Object *ob, int mode, ReportList *reports)
+{
+ bool ok;
+ if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) {
+ const char *opstring = object_mode_op_string(ob->mode);
+ WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
+ ok = ELEM(ob->mode, mode, OB_MODE_OBJECT);
+ if (!ok) {
+ wmOperatorType *ot = WM_operatortype_find(opstring, false);
+ BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name);
+ }
+ }
+ else {
+ ok = true;
+ }
+
+ return ok;
+}
+
static int object_mode_set_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
@@ -1542,25 +1584,31 @@ static int object_mode_set_exec(bContext *C, wmOperator *op)
ObjectMode restore_mode = (ob) ? ob->mode : OB_MODE_OBJECT;
int toggle = RNA_boolean_get(op->ptr, "toggle");
- if (!ob || !object_mode_set_compat(C, op, ob))
+ if (!ob || !object_mode_compat_test(ob, mode))
return OPERATOR_PASS_THROUGH;
- /* Exit current mode if it's not the mode we're setting */
- if (ob->mode != OB_MODE_OBJECT && ob->mode != mode)
- WM_operator_name_call(C, object_mode_op_string(ob->mode), WM_OP_EXEC_REGION_WIN, NULL);
+ if (ob->mode != mode) {
+ /* we should be able to remove this call, each operator calls */
+ ED_object_mode_compat_set(C, ob, mode, op->reports);
+ }
- if (mode != OB_MODE_OBJECT) {
+ /* Exit current mode if it's not the mode we're setting */
+ if (mode != OB_MODE_OBJECT && (ob->mode != mode || toggle)) {
/* Enter new mode */
- if (ob->mode != mode || toggle)
- WM_operator_name_call(C, object_mode_op_string(mode), WM_OP_EXEC_REGION_WIN, NULL);
-
- if (toggle) {
- if (ob->mode == mode)
- /* For toggling, store old mode so we know what to go back to */
- ob->restore_mode = restore_mode;
- else if (ob->restore_mode != OB_MODE_OBJECT && ob->restore_mode != mode) {
- WM_operator_name_call(C, object_mode_op_string(ob->restore_mode), WM_OP_EXEC_REGION_WIN, NULL);
- }
+ WM_operator_name_call(C, object_mode_op_string(mode), WM_OP_EXEC_REGION_WIN, NULL);
+ }
+
+ if (toggle) {
+ /* Special case for Object mode! */
+ if (mode == OB_MODE_OBJECT && restore_mode == OB_MODE_OBJECT && ob->restore_mode != OB_MODE_OBJECT) {
+ WM_operator_name_call(C, object_mode_op_string(ob->restore_mode), WM_OP_EXEC_REGION_WIN, NULL);
+ }
+ else if (ob->mode == mode) {
+ /* For toggling, store old mode so we know what to go back to */
+ ob->restore_mode = restore_mode;
+ }
+ else if (ob->restore_mode != OB_MODE_OBJECT && ob->restore_mode != mode) {
+ WM_operator_name_call(C, object_mode_op_string(ob->restore_mode), WM_OP_EXEC_REGION_WIN, NULL);
}
}
@@ -1569,6 +1617,8 @@ static int object_mode_set_exec(bContext *C, wmOperator *op)
void OBJECT_OT_mode_set(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Set Object Mode";
ot->description = "Sets the object interaction mode";
@@ -1584,14 +1634,20 @@ void OBJECT_OT_mode_set(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "mode", object_mode_items, OB_MODE_OBJECT, "Mode", "");
RNA_def_enum_funcs(ot->prop, object_mode_set_itemsf);
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
- RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
+ prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
void ED_object_toggle_modes(bContext *C, int mode)
{
+ /* Couldn't we use object_mode_op_string() here?
+ * Also, if several bits are set in mode, several toggle ops will be called, is this expected?
+ * If so, would be nice to explain why. ;) --mont29
+ */
if (mode & OB_MODE_SCULPT)
WM_operator_name_call(C, "SCULPT_OT_sculptmode_toggle", WM_OP_EXEC_REGION_WIN, NULL);
if (mode & OB_MODE_VERTEX_PAINT)
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 03d51fcbe82..0ba84e27420 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -637,9 +637,9 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob,
cu = ob->data;
BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices");
- vertexCos = BKE_curve_vertexCos_get(cu, &cu->nurb, &numVerts);
+ vertexCos = BKE_curve_nurbs_vertexCos_get(&cu->nurb, &numVerts);
mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0);
- BK_curve_vertexCos_apply(cu, &cu->nurb, vertexCos);
+ BK_curve_nurbs_vertexCos_apply(&cu->nurb, vertexCos);
MEM_freeN(vertexCos);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 52f51cfcf48..be4948d8a80 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -55,6 +55,7 @@
#include "BLI_listbase.h"
#include "BLI_linklist.h"
#include "BLI_string.h"
+#include "BLI_kdtree.h"
#include "BLI_utildefines.h"
#include "BLF_translation.h"
@@ -584,12 +585,12 @@ EnumPropertyItem prop_make_parent_types[] = {
{PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""},
{PAR_LATTICE, "LATTICE", 0, "Lattice Deform", ""},
{PAR_VERTEX, "VERTEX", 0, "Vertex", ""},
- {PAR_TRIA, "TRIA", 0, "Triangle", ""},
+ {PAR_VERTEX_TRI, "VERTEX_TRI", 0, "Vertex (Triangle)", ""},
{0, NULL, 0, NULL, NULL}
};
int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object *ob, Object *par,
- int partype, int xmirror, int keep_transform)
+ int partype, bool xmirror, bool keep_transform, const int vert_par[3])
{
bPoseChannel *pchan = NULL;
int pararm = ELEM4(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
@@ -718,8 +719,17 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
if (pchan->bone)
pchan->bone->flag |= BONE_RELATIVE_PARENTING;
}
- else
+ else if (partype == PAR_VERTEX) {
+ ob->partype = PARVERT1;
+ ob->par1 = vert_par[0];
+ }
+ else if (partype == PAR_VERTEX_TRI) {
+ ob->partype = PARVERT3;
+ copy_v3_v3_int(&ob->par1, vert_par);
+ }
+ else {
ob->partype = PAROBJECT; /* note, dna define, not operator property */
+ }
/* constraint */
if (partype == PAR_PATH_CONST) {
@@ -766,25 +776,83 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
return 1;
}
+
+
+static void parent_set_vert_find(KDTree *tree, Object *child, int vert_par[3], bool is_tri)
+{
+ const float *co_find = child->obmat[3];
+ if (is_tri) {
+ KDTreeNearest nearest[3];
+ int tot;
+
+ tot = BLI_kdtree_find_nearest_n(tree, co_find, NULL, nearest, 3);
+ BLI_assert(tot == 3);
+
+ vert_par[0] = nearest[0].index;
+ vert_par[1] = nearest[1].index;
+ vert_par[2] = nearest[2].index;
+
+ BLI_assert(min_iii(UNPACK3(vert_par)) >= 0);
+ }
+ else {
+ vert_par[0] = BLI_kdtree_find_nearest(tree, co_find, NULL, NULL);
+ BLI_assert(vert_par[0] >= 0);
+ vert_par[1] = 0;
+ vert_par[2] = 0;
+ }
+}
+
static int parent_set_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *par = ED_object_active_context(C);
int partype = RNA_enum_get(op->ptr, "type");
- int xmirror = RNA_boolean_get(op->ptr, "xmirror");
- int keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
- int ok = 1;
+ bool xmirror = RNA_boolean_get(op->ptr, "xmirror");
+ bool keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
+ bool ok = true;
+
+ /* vertex parent (kdtree) */
+ const bool is_vert_par = ELEM(partype, PAR_VERTEX, PAR_VERTEX_TRI);
+ const bool is_tri = partype == PAR_VERTEX_TRI;
+ int tree_tot;
+ struct KDTree *tree = NULL;
+ int vert_par[3] = {0, 0, 0};
+ int *vert_par_p = is_vert_par ? vert_par : NULL;
+
+
+ if (is_vert_par) {
+ tree = BKE_object_as_kdtree(par, &tree_tot);
+ BLI_assert(tree != NULL);
+
+ if (tree_tot < (is_tri ? 3 : 1)) {
+ BKE_report(op->reports, RPT_ERROR, "Not enough vertices for vertex-parent");
+ ok = false;
+ goto cleanup;
+ }
+ }
+
+ /* Non vertex-parent */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
- if (!ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, xmirror, keep_transform)) {
- ok = 0;
+ if (is_vert_par) {
+ parent_set_vert_find(tree, ob, vert_par, is_tri);
+ }
+
+ if (!ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, xmirror, keep_transform, vert_par_p)) {
+ ok = false;
break;
}
}
CTX_DATA_END;
+
+cleanup:
+ if (is_vert_par) {
+ BLI_kdtree_free(tree);
+ }
+
if (!ok)
return OPERATOR_CANCELLED;
@@ -835,6 +903,12 @@ static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_LATTICE);
}
+ /* vertex parenting */
+ if (OB_TYPE_SUPPORT_PARVERT(ob->type)) {
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX);
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX_TRI);
+ }
+
uiPupMenuEnd(C, pup);
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 366aa72f2b8..36ce72f1cab 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -562,6 +562,21 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
if (apply_scale)
BKE_tracking_reconstruction_scale(&clip->tracking, ob->size);
}
+ else if (ob->type == OB_EMPTY) {
+ /* It's possible for empties too, even though they don't
+ * really have obdata, since we can simply apply the maximum
+ * scaling to the empty's drawsize.
+ *
+ * Core Assumptions:
+ * 1) Most scaled empties have uniform scaling
+ * (i.e. for visibility reasons), AND/OR
+ * 2) Preserving non-uniform scaling is not that important,
+ * and is something that many users would be willing to
+ * sacrifice for having an easy way to do this.
+ */
+ float max_scale = MAX3(ob->size[0], ob->size[1], ob->size[2]);
+ ob->empty_drawsize *= max_scale;
+ }
else {
continue;
}
@@ -589,8 +604,10 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
}
CTX_DATA_END;
- if (!change)
+ if (!change) {
+ BKE_report(reports, RPT_WARNING, "Objects have no data to transform");
return OPERATOR_CANCELLED;
+ }
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
return OPERATOR_FINISHED;
@@ -768,7 +785,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
}
if (ctx_ob_act) {
- BLI_rotatelist(&ctx_data_list, (LinkData *)ctx_ob_act);
+ BLI_rotatelist_first(&ctx_data_list, (LinkData *)ctx_ob_act);
}
for (tob = bmain->object.first; tob; tob = tob->id.next) {
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 294b0632015..b68fa150777 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -1561,9 +1561,12 @@ static void getVerticalAndHorizontalChange(const float norm[3], float d, const f
/* A = Q - ((Q - P).N)N
* D = (a * x0 + b * y0 +c * z0 + d) */
float projA[3], projB[3];
+ float plane[4];
- closest_to_plane_v3(projA, coord, norm, start);
- closest_to_plane_v3(projB, coord, norm, end);
+ plane_from_point_normal_v3(plane, coord, norm);
+
+ closest_to_plane_v3(projA, plane, start);
+ closest_to_plane_v3(projB, plane, end);
/* (vertical and horizontal refer to the plane's y and xz respectively)
* vertical distance */
dists[index] = dot_v3v3(norm, end) + d;
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index d6bb394ff79..1a561efd217 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -69,6 +69,7 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "ED_object.h"
#include "ED_physics.h"
#include "ED_mesh.h"
#include "ED_particle.h"
@@ -2452,7 +2453,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
copy_v3_v3(co, point->keys->co);
mul_m4_v3(mat, co);
- totn= BLI_kdtree_find_n_nearest(tree, 10, co, NULL, nearest);
+ totn = BLI_kdtree_find_nearest_n(tree, co, NULL, nearest, 10);
for (n=0; n<totn; n++) {
/* this needs a custom threshold still */
@@ -3458,7 +3459,7 @@ static int brush_add(PEData *data, short number)
float maxd, totw=0.0, weight[3];
psys_particle_on_dm(psmd->dm, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0, 0);
- maxw= BLI_kdtree_find_n_nearest(tree, 3, co1, NULL, ptn);
+ maxw = BLI_kdtree_find_nearest_n(tree, co1, NULL, ptn, 3);
maxd= ptn[maxw-1].dist;
@@ -4345,23 +4346,36 @@ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache,
static int particle_edit_toggle_poll(bContext *C)
{
- Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (!scene || !ob || ob->id.lib)
+ if (ob == NULL || ob->type != OB_MESH)
return 0;
-
- return (ob->particlesystem.first || modifiers_findByType(ob, eModifierType_Cloth) || modifiers_findByType(ob, eModifierType_Softbody));
+ if (!ob->data || ((ID *)ob->data)->lib)
+ return 0;
+ if (CTX_data_edit_object(C))
+ return 0;
+
+ return (ob->particlesystem.first ||
+ modifiers_findByType(ob, eModifierType_Cloth) ||
+ modifiers_findByType(ob, eModifierType_Softbody));
}
-static int particle_edit_toggle_exec(bContext *C, wmOperator *UNUSED(op))
+static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
{
- Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ const int mode_flag = OB_MODE_PARTICLE_EDIT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
+
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
- if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
+ if (!is_mode_set) {
PTCacheEdit *edit;
- ob->mode |= OB_MODE_PARTICLE_EDIT;
+ ob->mode |= mode_flag;
edit= PE_create_current(scene, ob);
/* mesh may have changed since last entering editmode.
@@ -4373,7 +4387,7 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *UNUSED(op))
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_PARTICLE, NULL);
}
else {
- ob->mode &= ~OB_MODE_PARTICLE_EDIT;
+ ob->mode &= ~mode_flag;
toggle_particle_cursor(C, 0);
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
}
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 3a6bd05df0b..0d6e6fb5ac1 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -164,7 +164,7 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat
IMB_partial_display_buffer_update(ibuf, rectf, NULL, rr->rectx, rxmin, rymin,
&scene->view_settings, &scene->display_settings,
- rxmin, rymin, rxmin + xmax, rymin + ymax, TRUE);
+ rxmin, rymin, rxmin + xmax, rymin + ymax, true);
}
/* ****************************** render invoking ***************** */
@@ -270,6 +270,7 @@ typedef struct RenderJob {
short anim, write_still;
Image *image;
ImageUser iuser;
+ bool image_outdated;
short *stop;
short *do_update;
float *progress;
@@ -409,9 +410,19 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
void *lock;
/* only update if we are displaying the slot being rendered */
- if (ima->render_slot != ima->last_render_slot)
+ if (ima->render_slot != ima->last_render_slot) {
+ rj->image_outdated = true;
return;
+ }
+ else if (rj->image_outdated) {
+ /* update entire render */
+ rj->image_outdated = false;
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE);
+ *(rj->do_update) = TRUE;
+ return;
+ }
+ /* update part of render */
ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
if (ibuf) {
image_buffer_rect_update(rj->scene, rr, ibuf, renrect);
@@ -491,7 +502,9 @@ static void render_endjob(void *rjv)
* engine API, so lets use simple and robust way for now
* - sergey -
*/
- if (rj->scene->r.layers.first != rj->scene->r.layers.last) {
+ if (rj->scene->r.layers.first != rj->scene->r.layers.last ||
+ rj->image_outdated)
+ {
void *lock;
Image *ima = rj->image;
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
@@ -804,6 +817,11 @@ static bool render_view3d_get_rects(ARegion *ar, View3D *v3d, RegionView3D *rv3d
return true;
}
+static bool render_view3d_is_valid(RenderPreview *rp)
+{
+ return (rp->rv3d->render_engine != NULL);
+}
+
/* called by renderer, checks job value */
static int render_view3d_break(void *rpv)
{
@@ -813,8 +831,9 @@ static int render_view3d_break(void *rpv)
return 1;
/* during render, rv3d->engine can get freed */
- if (rp->rv3d->render_engine == NULL)
+ if (render_view3d_is_valid(rp) == false) {
*rp->stop = 1;
+ }
return *(rp->stop);
}
@@ -928,8 +947,11 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda
RE_Database_Preprocess(re);
/* conversion not completed, need to do it again */
- if (!rstats->convertdone)
- rp->engine->job_update_flag |= PR_UPDATE_DATABASE;
+ if (!rstats->convertdone) {
+ if (render_view3d_is_valid(rp)) {
+ rp->engine->job_update_flag |= PR_UPDATE_DATABASE;
+ }
+ }
// printf("dbase update\n");
}
@@ -1116,7 +1138,7 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C)
/* Try using GLSL display transform. */
if (force_fallback == false) {
- if (IMB_colormanagement_setup_glsl_draw(NULL, &scene->display_settings, TRUE)) {
+ if (IMB_colormanagement_setup_glsl_draw(NULL, &scene->display_settings, true, false)) {
glEnable(GL_BLEND);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glaDrawPixelsTex(rres.xof, rres.yof, rres.rectx, rres.recty, GL_RGBA, GL_FLOAT,
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index e21e889d99d..57416a59aa1 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -591,7 +591,7 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op)
ibuf_save = ibuf;
if (is_movie || !BKE_imtype_requires_linear_float(scene->r.im_format.imtype)) {
- ibuf_save = IMB_colormanagement_imbuf_for_write(ibuf, TRUE, TRUE, &scene->view_settings,
+ ibuf_save = IMB_colormanagement_imbuf_for_write(ibuf, true, true, &scene->view_settings,
&scene->display_settings, &scene->r.im_format);
needs_free = TRUE;
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 4bd8a7d426a..2bf8a48edc4 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -587,6 +587,7 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
ID *parent = (ID *)parentp;
MTex *slot = (MTex *)slotp;
SpaceButs *sbuts = sa->spacedata.first;
+ ShaderPreview *sp = WM_jobs_customdata(wm, sa);
rcti newrect;
int ok;
int newx = BLI_rcti_size_x(rect);
@@ -608,9 +609,11 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
*rect = newrect;
/* start a new preview render job if signalled through sbuts->preview,
- * or if no render result was found and no preview render job is running */
+ * if no render result was found and no preview render job is running,
+ * or if the job is running and the size of preview changed */
if ((sbuts->spacetype == SPACE_BUTS && sbuts->preview) ||
- (!ok && !WM_jobs_test(wm, sa, WM_JOB_TYPE_RENDER_PREVIEW)))
+ (!ok && !WM_jobs_test(wm, sa, WM_JOB_TYPE_RENDER_PREVIEW)) ||
+ (sp && (ABS(sp->sizex - newx) >= 2 || ABS(sp->sizey - newy) > 2)))
{
sbuts->preview = 0;
ED_preview_shader_job(C, sa, id, parent, slot, newx, newy, PR_BUTS_RENDER);
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index e805b3f30fc..7cbc8c9b277 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -1806,7 +1806,7 @@ void ED_region_header_init(ARegion *ar)
/* UI_UNIT_Y is defined as U variable now, depending dpi */
int ED_area_headersize(void)
{
- return (int)(1.3f * UI_UNIT_Y);
+ return (int)(HEADERY * UI_DPI_FAC);
}
void ED_region_info_draw(ARegion *ar, const char *text, int block, float fill_color[4])
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 723dce5e226..13befeceee9 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -1091,15 +1091,18 @@ void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter,
if (ibuf->rect_float) {
if (ibuf->float_colorspace) {
ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
- ibuf->float_colorspace, TRUE);
+ ibuf->float_colorspace,
+ true, false);
}
else {
- ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings, TRUE);
+ ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings,
+ true, false);
}
}
else {
ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
- ibuf->rect_colorspace, FALSE);
+ ibuf->rect_colorspace,
+ false, false);
}
if (ok) {
@@ -1178,7 +1181,7 @@ int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int ro
GPU_offscreen_bind(ofs);
- if (!IMB_colormanagement_setup_transform_from_role_glsl(role, TRUE)) {
+ if (!IMB_colormanagement_setup_transform_from_role_glsl(role, true)) {
GPU_offscreen_unbind(ofs);
GPU_offscreen_free(ofs);
return FALSE;
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 498762f1603..10c2ecd6fd9 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -327,10 +327,12 @@ static void screen_delarea(bContext *C, bScreen *sc, ScrArea *sa)
static short testsplitpoint(ScrArea *sa, char dir, float fac)
{
short x, y;
+ const short area_min_x = AREAMINX;
+ const short area_min_y = ED_area_headersize();
// area big enough?
- if (dir == 'v' && (sa->v4->vec.x - sa->v1->vec.x <= 2 * AREAMINX)) return 0;
- if (dir == 'h' && (sa->v2->vec.y - sa->v1->vec.y <= 2 * AREAMINY)) return 0;
+ if (dir == 'v' && (sa->v4->vec.x - sa->v1->vec.x <= 2 * area_min_x)) return 0;
+ if (dir == 'h' && (sa->v2->vec.y - sa->v1->vec.y <= 2 * area_min_y)) return 0;
// to be sure
CLAMP(fac, 0.0f, 1.0f);
@@ -338,10 +340,10 @@ static short testsplitpoint(ScrArea *sa, char dir, float fac)
if (dir == 'h') {
y = sa->v1->vec.y + fac * (sa->v2->vec.y - sa->v1->vec.y);
- if (y - sa->v1->vec.y < AREAMINY)
- y = sa->v1->vec.y + AREAMINY;
- else if (sa->v2->vec.y - y < AREAMINY)
- y = sa->v2->vec.y - AREAMINY;
+ if (y - sa->v1->vec.y < area_min_y)
+ y = sa->v1->vec.y + area_min_y;
+ else if (sa->v2->vec.y - y < area_min_y)
+ y = sa->v2->vec.y - area_min_y;
else y -= (y % AREAGRID);
return y;
@@ -349,10 +351,10 @@ static short testsplitpoint(ScrArea *sa, char dir, float fac)
else {
x = sa->v1->vec.x + fac * (sa->v4->vec.x - sa->v1->vec.x);
- if (x - sa->v1->vec.x < AREAMINX)
- x = sa->v1->vec.x + AREAMINX;
- else if (sa->v4->vec.x - x < AREAMINX)
- x = sa->v4->vec.x - AREAMINX;
+ if (x - sa->v1->vec.x < area_min_x)
+ x = sa->v1->vec.x + area_min_x;
+ else if (sa->v4->vec.x - x < area_min_x)
+ x = sa->v4->vec.x - area_min_x;
else x -= (x % AREAGRID);
return x;
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 3066b733fc5..a02bd1ea391 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -696,28 +696,39 @@ static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
sActionzoneData *sad = op->customdata;
- int deltax, deltay;
- int mindelta = sad->az->type == AZONE_REGION ? 1 : 12;
switch (event->type) {
case MOUSEMOVE:
+ {
+ bool is_gesture;
+
+ const int delta_x = (event->x - sad->x);
+ const int delta_y = (event->y - sad->y);
+
/* calculate gesture direction */
- deltax = (event->x - sad->x);
- deltay = (event->y - sad->y);
-
- if (deltay > ABS(deltax))
+ if (delta_y > ABS(delta_x))
sad->gesture_dir = 'n';
- else if (deltax > ABS(deltay))
+ else if (delta_x > ABS(delta_y))
sad->gesture_dir = 'e';
- else if (deltay < -ABS(deltax))
+ else if (delta_y < -ABS(delta_x))
sad->gesture_dir = 's';
else
sad->gesture_dir = 'w';
+ if (sad->az->type == AZONE_AREA) {
+ /* once we drag outside the actionzone, register a gesture
+ * check we're not on an edge so join finds the other area */
+ is_gesture = ((is_in_area_actionzone(sad->sa1, &event->x) != sad->az) &&
+ (screen_find_active_scredge(CTX_wm_screen(C), event->x, event->y) == NULL));
+ }
+ else {
+ const int delta_min = 1;
+ is_gesture = (ABS(delta_x) > delta_min || ABS(delta_y) > delta_min);
+ }
+
/* gesture is large enough? */
- if (ABS(deltax) > mindelta || ABS(deltay) > mindelta) {
-
- /* second area, for join */
+ if (is_gesture) {
+ /* second area, for join when (sa1 != sa2) */
sad->sa2 = screen_areahascursor(CTX_wm_screen(C), event->x, event->y);
/* apply sends event */
actionzone_apply(C, op, sad->az->type);
@@ -726,6 +737,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_FINISHED;
}
break;
+ }
case ESCKEY:
actionzone_exit(op);
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index db6380e920f..345db7a0ed0 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -71,18 +71,6 @@
#include <assert.h>
-static int planes_contain_v3(float (*planes)[4], int totplane, const float p[3])
-{
- int i;
-
- for (i = 0; i < totplane; i++) {
- if (dot_v3v3(planes[i], p) + planes[i][3] > 0)
- return 0;
- }
-
- return 1;
-}
-
/* return true if the element should be hidden/shown */
static int is_effected(PartialVisArea area,
float planes[4][4],
@@ -95,7 +83,7 @@ static int is_effected(PartialVisArea area,
return mask > 0.5f;
}
else {
- int inside = planes_contain_v3(planes, 4, co);
+ bool inside = isect_point_planes_v3(planes, 4, co);
return ((inside && area == PARTIALVIS_INSIDE) ||
(!inside && area == PARTIALVIS_OUTSIDE));
}
@@ -235,20 +223,20 @@ static void partialvis_update_grids(Object *ob,
}
static void partialvis_update_bmesh_verts(BMesh *bm,
- GHash *verts,
- PartialVisAction action,
- PartialVisArea area,
- float planes[4][4],
- int *any_changed,
- int *any_visible)
+ GSet *verts,
+ PartialVisAction action,
+ PartialVisArea area,
+ float planes[4][4],
+ int *any_changed,
+ int *any_visible)
{
- GHashIterator gh_iter;
+ GSetIterator gs_iter;
- GHASH_ITER (gh_iter, verts) {
- BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ GSET_ITER (gs_iter, verts) {
+ BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
float *vmask = CustomData_bmesh_get(&bm->vdata,
- v->head.data,
- CD_PAINT_MASK);
+ v->head.data,
+ CD_PAINT_MASK);
/* hide vertex if in the hide volume */
if (is_effected(area, planes, v->co, *vmask)) {
@@ -272,7 +260,7 @@ static void partialvis_update_bmesh(Object *ob,
float planes[4][4])
{
BMesh *bm;
- GHash *unique, *other;
+ GSet *unique, *other;
int any_changed = 0, any_visible = 0;
bm = BKE_pbvh_get_bmesh(pbvh);
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index fcf00d4ab2c..feff02fa121 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -82,6 +82,7 @@
#include "UI_view2d.h"
#include "ED_image.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
#include "ED_uvedit.h"
@@ -1006,9 +1007,12 @@ void PAINT_OT_sample_color(wmOperatorType *ot)
static int texture_paint_toggle_poll(bContext *C)
{
- if (CTX_data_edit_object(C))
+ Object *ob = CTX_data_active_object(C);
+ if (ob == NULL || ob->type != OB_MESH)
return 0;
- if (CTX_data_active_object(C) == NULL)
+ if (!ob->data || ((ID *)ob->data)->lib)
+ return 0;
+ if (CTX_data_edit_object(C))
return 0;
return 1;
@@ -1018,25 +1022,20 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
- Mesh *me = NULL;
-
- if (ob == NULL)
- return OPERATOR_CANCELLED;
-
- if (BKE_object_obdata_is_libdata(ob)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot edit external libdata");
- return OPERATOR_CANCELLED;
+ const int mode_flag = OB_MODE_TEXTURE_PAINT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
+ Mesh *me;
+
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
}
me = BKE_mesh_from_object(ob);
- if (!(ob->mode & OB_MODE_TEXTURE_PAINT) && !me) {
- BKE_report(op->reports, RPT_ERROR, "Can only enter texture paint mode for mesh objects");
- return OPERATOR_CANCELLED;
- }
-
- if (ob->mode & OB_MODE_TEXTURE_PAINT) {
- ob->mode &= ~OB_MODE_TEXTURE_PAINT;
+ if (ob->mode & mode_flag) {
+ ob->mode &= ~mode_flag;
if (U.glreslimit != 0)
GPU_free_images();
@@ -1045,7 +1044,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
toggle_paint_cursor(C, 0);
}
else {
- ob->mode |= OB_MODE_TEXTURE_PAINT;
+ ob->mode |= mode_flag;
if (me->mtface == NULL)
me->mtface = CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT,
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index db55dc271f1..dfada683dda 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -3883,7 +3883,7 @@ static void *do_projectpaint_thread(void *ph_v)
float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
straight_uchar_to_premul_float(newColor_f, projPixel->newColor.ch);
- IMB_colormanagement_colorspace_to_scene_linear_v4(newColor_f, TRUE, ps->reproject_ibuf->rect_colorspace);
+ IMB_colormanagement_colorspace_to_scene_linear_v4(newColor_f, true, ps->reproject_ibuf->rect_colorspace);
mul_v4_v4fl(newColor_f, newColor_f, mask);
blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f,
@@ -4279,9 +4279,6 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m
return ps;
}
- /* needed so multiple threads don't try to initialize the brush at once (can leak memory) */
- curvemapping_initialize(ps->brush->curve);
-
paint_brush_init_tex(ps->brush);
ps->source = PROJ_SRC_VIEW;
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index bdf542526ee..0b0607babc1 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -1011,7 +1011,8 @@ typedef enum {
RC_COLOR = 1,
RC_ROTATION = 2,
RC_ZOOM = 4,
- RC_WEIGHT = 8
+ RC_WEIGHT = 8,
+ RC_SECONDARY_ROTATION = 16
} RCFlags;
static void set_brush_rc_path(PointerRNA *ptr, const char *brush_path,
@@ -1043,7 +1044,10 @@ static void set_brush_rc_props(PointerRNA *ptr, const char *paint,
RNA_string_set(ptr, "data_path_secondary", "");
}
set_brush_rc_path(ptr, brush_path, "color_path", "cursor_color_add");
- set_brush_rc_path(ptr, brush_path, "rotation_path", "texture_slot.angle");
+ if (flags & RC_SECONDARY_ROTATION)
+ set_brush_rc_path(ptr, brush_path, "rotation_path", "mask_texture_slot.angle");
+ else
+ set_brush_rc_path(ptr, brush_path, "rotation_path", "texture_slot.angle");
RNA_string_set(ptr, "image_id", brush_path);
if (flags & RC_COLOR)
@@ -1055,6 +1059,11 @@ static void set_brush_rc_props(PointerRNA *ptr, const char *paint,
else
RNA_string_set(ptr, "zoom_path", "");
+ if (flags & RC_SECONDARY_ROTATION)
+ RNA_boolean_set(ptr, "secondary_tex", true);
+ else
+ RNA_boolean_set(ptr, "secondary_tex", false);
+
MEM_freeN(brush_path);
}
@@ -1064,6 +1073,7 @@ static void ed_keymap_paint_brush_radial_control(wmKeyMap *keymap, const char *p
wmKeyMapItem *kmi;
/* only size needs to follow zoom, strength shows fixed size circle */
int flags_nozoom = flags & (~RC_ZOOM);
+ int flags_noradial_secondary = flags & (~(RC_SECONDARY_ROTATION | RC_ZOOM));
kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0);
set_brush_rc_props(kmi->ptr, paint, "size", "use_unified_size", flags);
@@ -1078,7 +1088,12 @@ static void ed_keymap_paint_brush_radial_control(wmKeyMap *keymap, const char *p
if (flags & RC_ROTATION) {
kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0);
- set_brush_rc_props(kmi->ptr, paint, "texture_slot.angle", NULL, flags_nozoom);
+ set_brush_rc_props(kmi->ptr, paint, "texture_slot.angle", NULL, flags_noradial_secondary);
+ }
+
+ if (flags & RC_SECONDARY_ROTATION) {
+ kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
+ set_brush_rc_props(kmi->ptr, paint, "mask_texture_slot.angle", NULL, flags_nozoom);
}
}
@@ -1265,7 +1280,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
ed_keymap_paint_brush_switch(keymap, "image_paint");
ed_keymap_paint_brush_size(keymap, "tool_settings.image_paint.brush.size");
- ed_keymap_paint_brush_radial_control(keymap, "image_paint", RC_COLOR | RC_ZOOM | RC_ROTATION);
+ ed_keymap_paint_brush_radial_control(keymap, "image_paint", RC_COLOR | RC_ZOOM | RC_ROTATION | RC_SECONDARY_ROTATION);
ed_keymap_stencil(keymap);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 36e1b1feb38..e41d4a741ae 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -46,6 +46,7 @@
#include "BKE_context.h"
#include "BKE_paint.h"
#include "BKE_brush.h"
+#include "BKE_colortools.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -477,6 +478,9 @@ PaintStroke *paint_stroke_new(bContext *C,
stroke->redraw = redraw;
stroke->done = done;
stroke->event_type = event_type; /* for modal, return event */
+
+ /* initialize here to avoid initialization conflict with threaded strokes */
+ curvemapping_initialize(br->curve);
BKE_paint_set_overlay_override(br->overlay_flags);
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 2c654507015..538e8394b1f 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -61,6 +61,7 @@
#include "BKE_object_deform.h"
#include "BKE_paint.h"
#include "BKE_report.h"
+#include "BKE_colortools.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -68,12 +69,14 @@
#include "GPU_buffers.h"
#include "ED_armature.h"
+#include "ED_object.h"
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "paint_intern.h" /* own include */
+
/* check if we can do partial updates and have them draw realtime
* (without rebuilding the 'derivedFinal') */
static int vertex_paint_use_fast_update_check(Object *ob)
@@ -916,15 +919,13 @@ static float calc_vp_strength_col_dl(VPaint *vp, ViewContext *vc, const float co
co, co_ss,
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
- float delta[2];
- float dist_squared;
- float factor = 1.0;
+ const float dist_squared = len_squared_v2v2(mval, co_ss);
- sub_v2_v2v2(delta, mval, co_ss);
- dist_squared = dot_v2v2(delta, delta); /* len squared */
if (dist_squared <= brush_size_pressure * brush_size_pressure) {
Brush *brush = BKE_paint_brush(&vp->paint);
const float dist = sqrtf(dist_squared);
+ float factor;
+
if (brush->mtex.tex && rgba) {
if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
BKE_brush_sample_tex_3D(vc->scene, brush, co, rgba, 0, NULL);
@@ -935,6 +936,9 @@ static float calc_vp_strength_col_dl(VPaint *vp, ViewContext *vc, const float co
}
factor = rgba[3];
}
+ else {
+ factor = 1.0f;
+ }
return factor * BKE_brush_curve_strength_clamp(brush, dist, brush_size_pressure);
}
}
@@ -2025,41 +2029,28 @@ static void do_weight_paint_vertex(
/* *************** set wpaint operator ****************** */
-static int wpaint_mode_toggle_exec(bContext *C, wmOperator *UNUSED(op)) /* toggle */
+/**
+ * \note Keep in sync with #vpaint_mode_toggle_exec
+ */
+static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
+ const int mode_flag = OB_MODE_WEIGHT_PAINT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
Scene *scene = CTX_data_scene(C);
VPaint *wp = scene->toolsettings->wpaint;
Mesh *me;
-
- me = BKE_mesh_from_object(ob);
- if (ob->id.lib || me == NULL) return OPERATOR_PASS_THROUGH;
-
- if (ob->mode & OB_MODE_WEIGHT_PAINT) ob->mode &= ~OB_MODE_WEIGHT_PAINT;
- else ob->mode |= OB_MODE_WEIGHT_PAINT;
-
-
- /* Weightpaint works by overriding colors in mesh,
- * so need to make sure we recalc on enter and
- * exit (exit needs doing regardless because we
- * should redeform).
- */
- DAG_id_tag_update(&me->id, 0);
-
- if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- if (wp == NULL)
- wp = scene->toolsettings->wpaint = new_vpaint(1);
- BKE_paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
- paint_cursor_start(C, weight_paint_poll);
-
- mesh_octree_table(ob, NULL, NULL, 's');
-
- ED_vgroup_sync_from_pose(ob);
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
}
- else {
- mesh_octree_table(NULL, NULL, NULL, 'e');
- mesh_mirrtopo_table(NULL, 'e');
+
+ me = BKE_mesh_from_object(ob);
+
+ if (ob->mode & mode_flag) {
+ ob->mode &= ~mode_flag;
if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
BKE_mesh_flush_select_from_verts(me);
@@ -2067,10 +2058,35 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *UNUSED(op)) /* togg
else if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
BKE_mesh_flush_select_from_polys(me);
}
+
+ /* weight paint spesific */
+ mesh_octree_table(NULL, NULL, NULL, 'e');
+ mesh_mirrtopo_table(NULL, 'e');
+ }
+ else {
+ ob->mode |= mode_flag;
+
+ if (wp == NULL)
+ wp = scene->toolsettings->wpaint = new_vpaint(1);
+
+ paint_cursor_start(C, weight_paint_poll);
+
+ BKE_paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
+
+ /* weight paint spesific */
+ mesh_octree_table(ob, NULL, NULL, 's');
+ ED_vgroup_sync_from_pose(ob);
}
+ /* Weightpaint works by overriding colors in mesh,
+ * so need to make sure we recalc on enter and
+ * exit (exit needs doing regardless because we
+ * should redeform).
+ */
+ DAG_id_tag_update(&me->id, 0);
+
WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -2078,12 +2094,12 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *UNUSED(op)) /* togg
static int paint_poll_test(bContext *C)
{
Object *ob = CTX_data_active_object(C);
- if (CTX_data_edit_object(C))
- return 0;
- if (CTX_data_active_object(C) == NULL)
+ if (ob == NULL || ob->type != OB_MESH)
return 0;
if (!ob->data || ((ID *)ob->data)->lib)
return 0;
+ if (CTX_data_edit_object(C))
+ return 0;
return 1;
}
@@ -2633,7 +2649,7 @@ void PAINT_OT_weight_set(wmOperatorType *ot)
/* api callbacks */
ot->exec = weight_paint_set_exec;
- ot->poll = mask_paint_poll; /* it was facemask_paint_poll */
+ ot->poll = mask_paint_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2641,40 +2657,41 @@ void PAINT_OT_weight_set(wmOperatorType *ot)
/* ************ set / clear vertex paint mode ********** */
-
-static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op) /* toggle */
+/**
+ * \note Keep in sync with #wpaint_mode_toggle_exec
+ */
+static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
+ const int mode_flag = OB_MODE_VERTEX_PAINT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
Scene *scene = CTX_data_scene(C);
VPaint *vp = scene->toolsettings->vpaint;
Mesh *me;
-
- me = BKE_mesh_from_object(ob);
-
- if (me == NULL || BKE_object_obdata_is_libdata(ob)) {
- ob->mode &= ~OB_MODE_VERTEX_PAINT;
- return OPERATOR_PASS_THROUGH;
- }
-
- if (me && me->mloopcol == NULL) {
- make_vertexcol(ob);
+
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
}
+
+ me = BKE_mesh_from_object(ob);
/* toggle: end vpaint */
- if (ob->mode & OB_MODE_VERTEX_PAINT) {
-
- ob->mode &= ~OB_MODE_VERTEX_PAINT;
+ if (is_mode_set) {
+ ob->mode &= ~mode_flag;
if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
BKE_mesh_flush_select_from_polys(me);
}
}
else {
- ob->mode |= OB_MODE_VERTEX_PAINT;
- /* Turn off weight painting */
- if (ob->mode & OB_MODE_WEIGHT_PAINT)
- wpaint_mode_toggle_exec(C, op);
-
+ ob->mode |= mode_flag;
+
+ if (me->mloopcol == NULL) {
+ make_vertexcol(ob);
+ }
+
if (vp == NULL)
vp = scene->toolsettings->vpaint = new_vpaint(0);
@@ -3407,6 +3424,9 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
ToolSettings *ts = CTX_data_tool_settings(C);
VPaint *wp = ts->wpaint;
struct Brush *brush = BKE_paint_brush(&wp->paint);
+
+ curvemapping_initialize(brush->curve);
+
data.brush = brush;
data.weightpaint = BKE_brush_weight_get(scene, brush);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 2edd00c015d..9ba4f507b69 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -70,6 +70,7 @@
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_subsurf.h"
+#include "BKE_colortools.h"
#include "BIF_glutil.h"
@@ -77,6 +78,7 @@
#include "WM_types.h"
#include "ED_sculpt.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "ED_util.h" /* for crazyspace correction */
@@ -91,6 +93,7 @@
#include "GPU_buffers.h"
#include "bmesh.h"
+#include "bmesh_tools.h"
#include <math.h>
#include <stdlib.h>
@@ -150,6 +153,7 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob)
{
Mesh *me = (Mesh *)ob->data;
ModifierData *md;
+ VirtualModifierData virtualModifierData;
if (ob->sculpt && ob->sculpt->bm) {
/* can't combine multires and dynamic topology */
@@ -161,7 +165,7 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob)
return NULL;
}
- for (md = modifiers_getVirtualModifierList(ob); md; md = md->next) {
+ for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md; md = md->next) {
if (md->type == eModifierType_Multires) {
MultiresModifierData *mmd = (MultiresModifierData *)md;
@@ -180,8 +184,9 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob)
static int sculpt_has_active_modifiers(Scene *scene, Object *ob)
{
ModifierData *md;
+ VirtualModifierData virtualModifierData;
- md = modifiers_getVirtualModifierList(ob);
+ md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
/* exception for shape keys because we can edit those */
for (; md; md = md->next) {
@@ -198,6 +203,7 @@ static int sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
ModifierData *md;
Mesh *me = (Mesh *)ob->data;
MultiresModifierData *mmd = sculpt_multires_active(scene, ob);
+ VirtualModifierData virtualModifierData;
if (mmd || ob->sculpt->bm)
return 0;
@@ -206,7 +212,7 @@ static int sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
if ((ob->shapeflag & OB_SHAPE_LOCK) == 0 && me->key && ob->shapenr)
return 1;
- md = modifiers_getVirtualModifierList(ob);
+ md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
/* exception for shape keys because we can edit those */
for (; md; md = md->next) {
@@ -327,7 +333,7 @@ typedef struct {
/* Original coordinate, normal, and mask */
const float *co;
float mask;
- short no[3];
+ const short *no;
} SculptOrigVertData;
@@ -378,11 +384,10 @@ static void sculpt_orig_vert_data_update(SculptOrigVertData *orig_data,
}
if (orig_data->normals) {
- copy_v3_v3_short(orig_data->no, orig_data->normals[iter->i]);
+ orig_data->no = orig_data->normals[iter->i];
}
else {
- /* TODO: log doesn't store normals yet */
- normal_float_to_short_v3(orig_data->no, iter->bm_vert->no);
+ orig_data->no = BM_log_original_vert_no(orig_data->bm_log, iter->bm_vert);
}
}
else if (orig_data->unode->type == SCULPT_UNDO_MASK) {
@@ -3422,7 +3427,7 @@ static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss)
/* Need to allocate a bigger buffer for bigger brush size */
ss->texcache_side = 2 * radius;
if (!ss->texcache || ss->texcache_side > ss->texcache_actual) {
- ss->texcache = BKE_brush_gen_texture_cache(brush, radius);
+ ss->texcache = BKE_brush_gen_texture_cache(brush, radius, false);
ss->texcache_actual = ss->texcache_side;
ss->tex_pool = BKE_image_pool_new();
}
@@ -3716,7 +3721,8 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
Brush *brush = BKE_paint_brush(&sd->paint);
ViewContext *vc = paint_stroke_view_context(op->customdata);
Object *ob = CTX_data_active_object(C);
- float rot[3][3], scale[3], loc[3];
+ float mat[3][3];
+ float viewDir[3] = {0.0f, 0.0f, 1.0f};
int i;
int mode;
@@ -3768,6 +3774,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
brush = br;
cache->saved_smooth_size = BKE_brush_size_get(scene, brush);
BKE_brush_size_set(scene, brush, size);
+ curvemapping_initialize(brush->curve);
}
}
}
@@ -3784,12 +3791,13 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
/* cache projection matrix */
ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat);
- mat4_to_loc_rot_size(loc, rot, scale, ob->obmat);
- /* transposing an orthonormal matrix inverts */
- transpose_m3(rot);
- ED_view3d_global_to_vector(cache->vc->rv3d, cache->vc->rv3d->twmat[3], cache->true_view_normal);
- /* This takes care of rotated mesh. Instead of rotating every normal, we inverse rotate view normal. */
- mul_m3_v3(rot, cache->true_view_normal);
+ invert_m4_m4(ob->imat, ob->obmat);
+ copy_m3_m4(mat, cache->vc->rv3d->viewinv);
+ mul_m3_v3(mat, viewDir);
+ copy_m3_m4(mat, ob->imat);
+ mul_m3_v3(mat, viewDir);
+ normalize_v3_v3(cache->true_view_normal, viewDir);
+
/* Initialize layer brush displacements and persistent coords */
if (brush->sculpt_tool == SCULPT_TOOL_LAYER) {
/* not supported yet for multires or dynamic topology */
@@ -4561,7 +4569,9 @@ static void SCULPT_OT_set_persistent_base(wmOperatorType *ot)
static void sculpt_dynamic_topology_triangulate(BMesh *bm)
{
- BM_mesh_triangulate(bm, false, false, NULL, NULL);
+ if (bm->totloop != bm->totface * 3) {
+ BM_mesh_triangulate(bm, false, false, NULL, NULL);
+ }
}
void sculpt_pbvh_clear(Object *ob)
@@ -4800,8 +4810,8 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op))
/* Symmetrize and re-triangulate */
BMO_op_callf(ss->bm, BMO_FLAG_DEFAULTS,
- "symmetrize input=%avef direction=%i",
- sd->symmetrize_direction);
+ "symmetrize input=%avef direction=%i dist=%f",
+ sd->symmetrize_direction, 0.00001f);
sculpt_dynamic_topology_triangulate(ss->bm);
/* Finish undo */
@@ -4907,21 +4917,31 @@ int ED_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd)
return ret;
}
-static int sculpt_mode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
+static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = CTX_data_tool_settings(C);
Object *ob = CTX_data_active_object(C);
- Mesh *me = ob->data;
+ const int mode_flag = OB_MODE_SCULPT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
+ Mesh *me;
MultiresModifierData *mmd = sculpt_multires_active(scene, ob);
int flush_recalc = 0;
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ me = BKE_mesh_from_object(ob);
+
/* multires in sculpt mode could have different from object mode subdivision level */
flush_recalc |= mmd && mmd->sculptlvl != mmd->lvl;
/* if object has got active modifiers, it's dm could be different in sculpt mode */
flush_recalc |= sculpt_has_active_modifiers(scene, ob);
- if (ob->mode & OB_MODE_SCULPT) {
+ if (is_mode_set) {
if (mmd)
multires_force_update(ob);
@@ -4936,13 +4956,13 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
}
/* Leave sculptmode */
- ob->mode &= ~OB_MODE_SCULPT;
+ ob->mode &= ~mode_flag;
free_sculptsession(ob);
}
else {
/* Enter sculptmode */
- ob->mode |= OB_MODE_SCULPT;
+ ob->mode |= mode_flag;
/* Remove dynamic-topology flag; this will be enabled if the
* file was saved with dynamic topology on, but we don't
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 51e740e539f..8508123f942 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -150,20 +150,31 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
bool valid_particles = ED_texture_context_check_particles(C);
bool valid_others = ED_texture_context_check_others(C);
+ /* this is similar to direct user action, no need to keep "better" ctxt in _prev */
if ((sbuts->mainb == BCONTEXT_WORLD) && valid_world) {
- sbuts->texture_context = SB_TEXC_WORLD;
+ sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_WORLD;
}
else if ((sbuts->mainb == BCONTEXT_MATERIAL) && valid_material) {
- sbuts->texture_context = SB_TEXC_MATERIAL;
+ sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_MATERIAL;
}
else if ((sbuts->mainb == BCONTEXT_DATA) && valid_lamp) {
- sbuts->texture_context = SB_TEXC_LAMP;
+ sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_LAMP;
}
else if ((sbuts->mainb == BCONTEXT_PARTICLE) && valid_particles) {
- sbuts->texture_context = SB_TEXC_PARTICLES;
+ sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_PARTICLES;
}
else if ((ELEM(sbuts->mainb, BCONTEXT_MODIFIER, BCONTEXT_PHYSICS)) && valid_others) {
- sbuts->texture_context = SB_TEXC_OTHER;
+ sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_OTHER;
+ }
+ /* Else, try to revive a previous "better" ctxt... */
+ else if ((sbuts->texture_context_prev != sbuts->texture_context) &&
+ (((sbuts->texture_context_prev == SB_TEXC_WORLD) && valid_world) ||
+ ((sbuts->texture_context_prev == SB_TEXC_MATERIAL) && valid_material) ||
+ ((sbuts->texture_context_prev == SB_TEXC_LAMP) && valid_lamp) ||
+ ((sbuts->texture_context_prev == SB_TEXC_PARTICLES) && valid_particles) ||
+ ((sbuts->texture_context_prev == SB_TEXC_OTHER) && valid_others)))
+ {
+ sbuts->texture_context = sbuts->texture_context_prev;
}
/* Else, just be sure that current context is valid! */
else if (((sbuts->texture_context == SB_TEXC_WORLD) && !valid_world) ||
@@ -172,13 +183,9 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
((sbuts->texture_context == SB_TEXC_PARTICLES) && !valid_particles) ||
((sbuts->texture_context == SB_TEXC_OTHER) && !valid_others))
{
- if (valid_others) {
- sbuts->texture_context = SB_TEXC_OTHER;
- }
- else if (valid_world) {
- sbuts->texture_context = SB_TEXC_WORLD;
- }
- else if (valid_material) {
+ /* this is default fallback, do keep "better" ctxt in _prev */
+ sbuts->texture_context_prev = sbuts->texture_context;
+ if (valid_material) {
sbuts->texture_context = SB_TEXC_MATERIAL;
}
else if (valid_lamp) {
@@ -187,6 +194,12 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
else if (valid_particles) {
sbuts->texture_context = SB_TEXC_PARTICLES;
}
+ else if (valid_world) {
+ sbuts->texture_context = SB_TEXC_WORLD;
+ }
+ else if (valid_others) {
+ sbuts->texture_context = SB_TEXC_OTHER;
+ }
}
}
}
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index 18248f4775b..50bb8a0e061 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -238,7 +238,8 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
{
MarkerUpdateCb *cb = (MarkerUpdateCb *) arg_cb;
MovieTrackingMarker *marker;
- int width, height, ok = FALSE;
+ int width, height;
+ bool ok = false;
BKE_movieclip_get_size(cb->clip, cb->user, &width, &height);
@@ -252,7 +253,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
DAG_id_tag_update(&cb->clip->id, 0);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- ok = TRUE;
+ ok = true;
}
else if (event == B_MARKER_PAT_DIM) {
float dim[2], pat_dim[2], pat_min[2], pat_max[2];
@@ -276,7 +277,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
BKE_tracking_marker_clamp(cb->marker, CLAMP_PAT_DIM);
- ok = TRUE;
+ ok = true;
}
else if (event == B_MARKER_SEARCH_POS) {
float delta[2], side[2];
@@ -292,7 +293,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
BKE_tracking_marker_clamp(cb->marker, CLAMP_SEARCH_POS);
- ok = TRUE;
+ ok = true;
}
else if (event == B_MARKER_SEARCH_DIM) {
float dim[2], search_dim[2];
@@ -313,12 +314,12 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
BKE_tracking_marker_clamp(cb->marker, CLAMP_SEARCH_DIM);
- ok = TRUE;
+ ok = true;
}
else if (event == B_MARKER_FLAG) {
marker->flag = cb->marker_flag;
- ok = TRUE;
+ ok = true;
}
else if (event == B_MARKER_OFFSET) {
float offset[2], delta[2];
@@ -337,7 +338,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
DAG_id_tag_update(&cb->clip->id, 0);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- ok = TRUE;
+ ok = true;
}
if (ok)
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index eb58bdc7696..4f3f81e38dc 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -127,9 +127,11 @@ static int generic_track_get_marker_framenr(MovieTrackingTrack *track, MovieTrac
int marker_index)
{
if (track) {
+ BLI_assert(marker_index < track->markersnr);
return track->markers[marker_index].framenr;
}
else if (plane_track) {
+ BLI_assert(marker_index < plane_track->markersnr);
return plane_track->markers[marker_index].framenr;
}
@@ -140,6 +142,7 @@ static bool generic_track_is_marker_enabled(MovieTrackingTrack *track, MovieTrac
int marker_index)
{
if (track) {
+ BLI_assert(marker_index < track->markersnr);
return (track->markers[marker_index].flag & MARKER_DISABLED) == 0;
}
else if (plane_track) {
@@ -153,9 +156,11 @@ static bool generic_track_is_marker_keyframed(MovieTrackingTrack *track, MovieTr
int marker_index)
{
if (track) {
+ BLI_assert(marker_index < track->markersnr);
return (track->markers[marker_index].flag & MARKER_TRACKED) == 0;
}
else if (plane_track) {
+ BLI_assert(marker_index < plane_track->markersnr);
return (plane_track->markers[marker_index].flag & PLANE_MARKER_TRACKED) == 0;
}
@@ -212,6 +217,8 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
a++;
}
+ a = min_ii(a, markersnr - 1);
+
if (generic_track_is_marker_enabled(act_track, act_plane_track, a)) {
framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
@@ -235,11 +242,11 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
glColor4ub(255, 0, 0, 96);
for (i = sfra, a = 0; i <= efra; i++) {
- int ok = FALSE;
+ bool ok = false;
while (a < n) {
if (cameras[a].framenr == i) {
- ok = TRUE;
+ ok = true;
break;
}
else if (cameras[a].framenr > i) {
@@ -280,11 +287,11 @@ static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar)
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
char str[256] = {0};
- int block = FALSE;
+ bool block = false;
if (tracking->stats) {
BLI_strncpy(str, tracking->stats->message, sizeof(str));
- block = TRUE;
+ block = true;
}
else {
if (sc->flag & SC_LOCK_SELECTION)
@@ -490,7 +497,7 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT
float marker_pos[2], int width, int height)
{
int tiny = sc->flag & SC_SHOW_TINY_MARKER;
- int show_search = FALSE;
+ bool show_search = false;
float px[2];
UI_ThemeColor(TH_MARKER_OUTLINE);
@@ -553,8 +560,8 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT
glEnd();
}
- show_search = TRACK_VIEW_SELECTED(sc, track) &&
- ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0);
+ show_search = (TRACK_VIEW_SELECTED(sc, track) &&
+ ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0;
if (sc->flag & SC_SHOW_MARKER_SEARCH && show_search) {
glBegin(GL_LINE_LOOP);
glVertex2f(marker->search_min[0], marker->search_min[1]);
@@ -593,7 +600,7 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
float marker_pos[2], int width, int height, int act, int sel)
{
int tiny = sc->flag & SC_SHOW_TINY_MARKER;
- int show_search = 0;
+ bool show_search = false;
float col[3], scol[3], px[2];
track_colors(track, act, col, scol);
@@ -708,8 +715,8 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
}
/* search */
- show_search = TRACK_VIEW_SELECTED(sc, track) &&
- ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0);
+ show_search = (TRACK_VIEW_SELECTED(sc, track) &&
+ ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0;
if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) {
if (track->flag & TRACK_LOCKED) {
if (act)
@@ -997,17 +1004,6 @@ static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
}
}
-static void view2d_to_region_float(View2D *v2d, float x, float y, float *regionx, float *regiony)
-{
- /* express given coordinates as proportional values */
- x = -v2d->cur.xmin / BLI_rctf_size_x(&v2d->cur);
- y = -v2d->cur.ymin / BLI_rctf_size_y(&v2d->cur);
-
- /* convert proportional distances to screen coordinates */
- *regionx = v2d->mask.xmin + x * BLI_rcti_size_x(&v2d->mask);
- *regiony = v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask);
-}
-
static void plane_track_colors(bool is_active, float color[3], float selected_color[3])
{
UI_GetThemeColor3fv(TH_MARKER, color);
@@ -1071,8 +1067,6 @@ static void draw_plane_marker_ex(SpaceClip *sc, MovieTrackingPlaneTrack *plane_t
else if (tiny) {
glLineStipple(3, 0xaaaa);
glEnable(GL_LINE_STIPPLE);
- glEnable(GL_COLOR_LOGIC_OP);
- glLogicOp(GL_NOR);
}
/* Draw rectangle itself. */
@@ -1120,10 +1114,7 @@ static void draw_plane_marker_ex(SpaceClip *sc, MovieTrackingPlaneTrack *plane_t
}
}
else if (tiny) {
- glDisable(GL_COLOR_LOGIC_OP);
glDisable(GL_LINE_STIPPLE);
- glLineStipple(3, 0xaaaa);
- glEnable(GL_LINE_STIPPLE);
}
}
@@ -1173,7 +1164,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
* to avoid this flickering, calculate base point in the same way as it happens
* in UI_view2d_to_region_no_clip, but do it in floats here */
- view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ UI_view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y);
glPushMatrix();
glTranslatef(x, y, 0);
@@ -1416,7 +1407,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
if ((sc->flag & SC_SHOW_GRID) == 0 && (sc->flag & SC_MANUAL_CALIBRATION) == 0)
return;
- view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ UI_view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y);
glPushMatrix();
glTranslatef(x, y, 0);
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 08d0af817a8..0d64a3ce594 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -262,15 +262,15 @@ ImBuf *ED_space_clip_get_stable_buffer(SpaceClip *sc, float loc[2], float *scale
/* returns color in SRGB */
/* matching ED_space_image_color_sample() */
-int ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_col[3])
+bool ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_col[3])
{
ImBuf *ibuf;
float fx, fy, co[2];
- int ret = FALSE;
+ bool ret = false;
ibuf = ED_space_clip_get_buffer(sc);
if (!ibuf) {
- return FALSE;
+ return false;
}
/* map the mouse coords to the backdrop image space */
@@ -290,12 +290,12 @@ int ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_
if (ibuf->rect_float) {
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
linearrgb_to_srgb_v3_v3(r_col, fp);
- ret = TRUE;
+ ret = true;
}
else if (ibuf->rect) {
cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
rgb_uchar_to_float(r_col, cp);
- ret = TRUE;
+ ret = true;
}
}
@@ -325,11 +325,12 @@ void ED_clip_update_frame(const Main *mainp, int cfra)
}
}
-static int selected_boundbox(SpaceClip *sc, float min[2], float max[2])
+static bool selected_boundbox(SpaceClip *sc, float min[2], float max[2])
{
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTrackingTrack *track;
- int width, height, ok = FALSE;
+ int width, height;
+ bool ok = false;
ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
int framenr = ED_space_clip_get_clip_frame_number(sc);
@@ -362,7 +363,7 @@ static int selected_boundbox(SpaceClip *sc, float min[2], float max[2])
minmax_v2v2_v2(min, max, pos);
- ok = TRUE;
+ ok = true;
}
}
@@ -372,7 +373,7 @@ static int selected_boundbox(SpaceClip *sc, float min[2], float max[2])
return ok;
}
-int ED_clip_view_selection(const bContext *C, ARegion *ar, int fit)
+bool ED_clip_view_selection(const bContext *C, ARegion *ar, bool fit)
{
SpaceClip *sc = CTX_wm_space_clip(C);
int w, h, frame_width, frame_height;
@@ -381,10 +382,10 @@ int ED_clip_view_selection(const bContext *C, ARegion *ar, int fit)
ED_space_clip_get_size(sc, &frame_width, &frame_height);
if ((frame_width == 0) || (frame_height == 0) || (sc->clip == NULL))
- return FALSE;
+ return false;
if (!selected_boundbox(sc, min, max))
- return FALSE;
+ return false;
/* center view */
clip_view_center_to_point(sc, (max[0] + min[0]) / (2 * frame_width),
@@ -412,7 +413,7 @@ int ED_clip_view_selection(const bContext *C, ARegion *ar, int fit)
sc->zoom = newzoom;
}
- return TRUE;
+ return true;
}
void ED_clip_point_undistorted_pos(SpaceClip *sc, const float co[2], float r_co[2])
@@ -500,22 +501,22 @@ void ED_clip_mouse_pos(SpaceClip *sc, ARegion *ar, const int mval[2], float co[2
ED_clip_point_stable_pos(sc, ar, mval[0], mval[1], &co[0], &co[1]);
}
-int ED_space_clip_check_show_trackedit(SpaceClip *sc)
+bool ED_space_clip_check_show_trackedit(SpaceClip *sc)
{
if (sc) {
return ELEM3(sc->mode, SC_MODE_TRACKING, SC_MODE_RECONSTRUCTION, SC_MODE_DISTORTION);
}
- return FALSE;
+ return false;
}
-int ED_space_clip_check_show_maskedit(SpaceClip *sc)
+bool ED_space_clip_check_show_maskedit(SpaceClip *sc)
{
if (sc) {
return sc->mode == SC_MODE_MASKEDIT;
}
- return FALSE;
+ return false;
}
/* ******** clip editing functions ******** */
diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c
index 973200dc340..173d65ee4fc 100644
--- a/source/blender/editors/space_clip/clip_graph_draw.c
+++ b/source/blender/editors/space_clip/clip_graph_draw.c
@@ -126,7 +126,7 @@ static void tracking_segment_end_cb(void *UNUSED(userdata))
static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track,
MovieTrackingMarker *marker, int coord, int scene_framenr, float val)
{
- struct { MovieTrackingTrack *act_track; int sel; float xscale, yscale, hsize; } *data = userdata;
+ struct { MovieTrackingTrack *act_track; bool sel; float xscale, yscale, hsize; } *data = userdata;
int sel = 0, sel_flag;
if (track != data->act_track)
@@ -151,7 +151,7 @@ static void draw_tracks_curves(View2D *v2d, SpaceClip *sc)
MovieTracking *tracking = &clip->tracking;
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
int width, height;
- struct { MovieTrackingTrack *act_track; int sel; float xscale, yscale, hsize; } userdata;
+ struct { MovieTrackingTrack *act_track; bool sel; float xscale, yscale, hsize; } userdata;
BKE_movieclip_get_size(clip, &sc->user, &width, &height);
@@ -160,7 +160,7 @@ static void draw_tracks_curves(View2D *v2d, SpaceClip *sc)
/* non-selected knot handles */
userdata.hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE);
- userdata.sel = FALSE;
+ userdata.sel = false;
userdata.act_track = act_track;
UI_view2d_getscale(v2d, &userdata.xscale, &userdata.yscale);
clip_graph_tracking_values_iterate(sc, sc->flag & SC_SHOW_GRAPH_SEL_ONLY, sc->flag & SC_SHOW_GRAPH_HIDDEN,
diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c
index cdb0fdadebd..393f92f5af5 100644
--- a/source/blender/editors/space_clip/clip_graph_ops.c
+++ b/source/blender/editors/space_clip/clip_graph_ops.c
@@ -96,8 +96,8 @@ static void toggle_selection_cb(void *userdata, MovieTrackingMarker *marker)
/******************** mouse select operator ********************/
typedef struct {
- int coord, /* coordinate index of found entuty (0 = X-axis, 1 = Y-axis) */
- has_prev; /* if there's valid coordinate of previous point of curve segment */
+ int coord; /* coordinate index of found entuty (0 = X-axis, 1 = Y-axis) */
+ bool has_prev; /* if there's valid coordinate of previous point of curve segment */
float min_dist, /* minimal distance between mouse and currently found entuty */
mouse_co[2], /* mouse coordinate */
@@ -134,7 +134,7 @@ static void find_nearest_tracking_segment_end_cb(void *userdata)
{
MouseSelectUserData *data = userdata;
- data->has_prev = FALSE;
+ data->has_prev = false;
}
static void find_nearest_tracking_knot_cb(void *userdata, MovieTrackingTrack *track,
@@ -163,7 +163,7 @@ static void mouse_select_init_data(MouseSelectUserData *userdata, float *co)
copy_v2_v2(userdata->mouse_co, co);
}
-static int mouse_select_knot(bContext *C, float co[2], int extend)
+static bool mouse_select_knot(bContext *C, float co[2], bool extend)
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -200,15 +200,15 @@ static int mouse_select_knot(bContext *C, float co[2], int extend)
else
userdata.marker->flag |= MARKER_GRAPH_SEL_Y;
- return TRUE;
+ return true;
}
}
}
- return FALSE;
+ return false;
}
-static int mouse_select_curve(bContext *C, float co[2], int extend)
+static bool mouse_select_curve(bContext *C, float co[2], bool extend)
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -242,15 +242,15 @@ static int mouse_select_curve(bContext *C, float co[2], int extend)
toggle_selection_cb);
}
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
-static int mouse_select(bContext *C, float co[2], int extend)
+static int mouse_select(bContext *C, float co[2], bool extend)
{
- int sel = FALSE;
+ bool sel = false;
/* first try to select knot on selected curves */
sel = mouse_select_knot(C, co, extend);
@@ -269,7 +269,7 @@ static int mouse_select(bContext *C, float co[2], int extend)
static int select_exec(bContext *C, wmOperator *op)
{
float co[2];
- int extend = RNA_boolean_get(op->ptr, "extend");
+ bool extend = RNA_boolean_get(op->ptr, "extend");
RNA_float_get_array(op->ptr, "location", co);
@@ -313,7 +313,8 @@ void CLIP_OT_graph_select(wmOperatorType *ot)
typedef struct BorderSelectuserData {
rctf rect;
- int change, mode, extend;
+ int mode;
+ bool change, extend;
} BorderSelectuserData;
static void border_select_cb(void *userdata, MovieTrackingTrack *UNUSED(track),
@@ -352,13 +353,17 @@ static int border_select_graph_exec(bContext *C, wmOperator *op)
BorderSelectuserData userdata;
rcti rect;
+ if (act_track == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
/* get rectangle from operator */
WM_operator_properties_border_to_rcti(op, &rect);
UI_view2d_region_to_view(&ar->v2d, rect.xmin, rect.ymin, &userdata.rect.xmin, &userdata.rect.ymin);
UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &userdata.rect.xmax, &userdata.rect.ymax);
- userdata.change = FALSE;
+ userdata.change = false;
userdata.mode = RNA_int_get(op->ptr, "gesture_mode");
userdata.extend = RNA_boolean_get(op->ptr, "extend");
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h
index 8d112b7413c..e6f1813b3a4 100644
--- a/source/blender/editors/space_clip/clip_intern.h
+++ b/source/blender/editors/space_clip/clip_intern.h
@@ -112,6 +112,8 @@ void CLIP_OT_prefetch(struct wmOperatorType *ot);
void CLIP_OT_set_scene_frames(wmOperatorType *ot);
+void CLIP_OT_cursor_set(struct wmOperatorType *ot);
+
/* clip_toolbar.c */
struct ARegion *ED_clip_has_properties_region(struct ScrArea *sa);
void CLIP_OT_tools(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index de19df9abe2..f96a0e71dfc 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -181,7 +181,7 @@ static int open_exec(bContext *C, wmOperator *op)
PointerRNA fileptr;
PropertyRNA *prop;
char dir_only[FILE_MAX], file_only[FILE_MAX];
- int relative = RNA_boolean_get(op->ptr, "relative_path");
+ bool relative = RNA_boolean_get(op->ptr, "relative_path");
RNA_string_get(op->ptr, "directory", dir_only);
if (relative)
@@ -353,7 +353,7 @@ static void view_pan_init(bContext *C, wmOperator *op, const wmEvent *event)
WM_event_add_modal_handler(C, op);
}
-static void view_pan_exit(bContext *C, wmOperator *op, int cancel)
+static void view_pan_exit(bContext *C, wmOperator *op, bool cancel)
{
ViewPanData *vpd = op->customdata;
@@ -502,7 +502,7 @@ static void view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event)
WM_event_add_modal_handler(C, op);
}
-static void view_zoom_exit(bContext *C, wmOperator *op, int cancel)
+static void view_zoom_exit(bContext *C, wmOperator *op, bool cancel)
{
SpaceClip *sc = CTX_wm_space_clip(C);
ViewZoomData *vpd = op->customdata;
@@ -736,7 +736,7 @@ static int view_all_exec(bContext *C, wmOperator *op)
ARegion *ar;
int w, h, width, height;
float aspx, aspy;
- int fit_view = RNA_boolean_get(op->ptr, "fit_view");
+ bool fit_view = RNA_boolean_get(op->ptr, "fit_view");
float zoomx, zoomy;
/* retrieve state */
@@ -782,6 +782,8 @@ static int view_all_exec(bContext *C, wmOperator *op)
void CLIP_OT_view_all(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "View All";
ot->idname = "CLIP_OT_view_all";
@@ -792,7 +794,8 @@ void CLIP_OT_view_all(wmOperatorType *ot)
ot->poll = ED_space_clip_view_clip_poll;
/* properties */
- RNA_def_boolean(ot->srna, "fit_view", 0, "Fit View", "Fit frame to the viewport");
+ prop = RNA_def_boolean(ot->srna, "fit_view", 0, "Fit View", "Fit frame to the viewport");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/********************** view selected operator *********************/
@@ -943,7 +946,8 @@ typedef struct ProxyBuildJob {
Scene *scene;
struct Main *main;
MovieClip *clip;
- int clip_flag, stop;
+ int clip_flag;
+ bool stop;
struct IndexBuildContext *index_context;
} ProxyJob;
@@ -1123,10 +1127,10 @@ static void *do_proxy_thread(void *data_v)
ibuf = IMB_ibImageFromMemory(mem, size, IB_rect | IB_multilayer | IB_alphamode_detect, NULL, "proxy frame");
BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, NULL, cfra,
- data->build_sizes, data->build_count, FALSE);
+ data->build_sizes, data->build_count, false);
BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, data->distortion, cfra,
- data->build_undistort_sizes, data->build_undistort_count, TRUE);
+ data->build_undistort_sizes, data->build_undistort_count, true);
IMB_freeImBuf(ibuf);
@@ -1455,6 +1459,51 @@ void CLIP_OT_set_scene_frames(wmOperatorType *ot)
ot->exec = clip_set_scene_frames_exec;
}
+/******************** set 3d cursor operator ********************/
+
+static int clip_set_2d_cursor_exec(bContext *C, wmOperator *op)
+{
+ SpaceClip *sclip = CTX_wm_space_clip(C);
+
+ RNA_float_get_array(op->ptr, "location", sclip->cursor);
+
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CLIP, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static int clip_set_2d_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SpaceClip *sclip = CTX_wm_space_clip(C);
+ float location[2];
+
+ ED_clip_mouse_pos(sclip, ar, event->mval, location);
+ RNA_float_set_array(op->ptr, "location", location);
+
+ return clip_set_2d_cursor_exec(C, op);
+}
+
+void CLIP_OT_cursor_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Set 2D Cursor";
+ ot->description = "Set 2D cursor location";
+ ot->idname = "CLIP_OT_cursor_set";
+
+ /* api callbacks */
+ ot->exec = clip_set_2d_cursor_exec;
+ ot->invoke = clip_set_2d_cursor_invoke;
+ ot->poll = ED_space_clip_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location",
+ "Cursor location in normalized clip coordinates", -10.0f, 10.0f);
+}
+
/********************** macroses *********************/
void ED_operatormacros_clip(void)
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index 72a3cb98a6a..635aa388541 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -76,7 +76,8 @@ void clip_graph_tracking_values_iterate_track(
BKE_movieclip_get_size(clip, &sc->user, &width, &height);
for (coord = 0; coord < 2; coord++) {
- int i, open = FALSE, prevfra = 0;
+ int i, prevfra = 0;
+ bool open = false;
float prevval = 0.0f;
for (i = 0; i < track->markersnr; i++) {
@@ -88,7 +89,7 @@ void clip_graph_tracking_values_iterate_track(
if (segment_end)
segment_end(userdata);
- open = FALSE;
+ open = false;
}
continue;
@@ -98,7 +99,7 @@ void clip_graph_tracking_values_iterate_track(
if (segment_start)
segment_start(userdata, track, coord);
- open = TRUE;
+ open = true;
prevval = marker->pos[coord];
}
@@ -184,7 +185,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- int has_bundle = FALSE, update_stab = FALSE;
+ bool has_bundle = false, update_stab = false;
if (track == act_track)
tracking->act_track = NULL;
@@ -192,19 +193,19 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
if (track == stab->rot_track) {
stab->rot_track = NULL;
- update_stab = TRUE;
+ update_stab = true;
}
/* handle reconstruction display in 3d viewport */
if (track->flag & TRACK_HAS_BUNDLE)
- has_bundle = TRUE;
+ has_bundle = true;
/* Make sure no plane will use freed track */
for (plane_track = plane_tracks_base->first;
plane_track;
plane_track = next_plane_track)
{
- bool found = false;
+ bool found = false;
int i;
next_plane_track = plane_track->next;
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 8213853c937..8ecf9635af9 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -56,6 +56,7 @@
#include "ED_screen.h"
#include "ED_clip.h"
#include "ED_transform.h"
+#include "ED_uvedit.h" /* just for draw_image_cursor */
#include "IMB_imbuf.h"
@@ -442,6 +443,7 @@ static void clip_operatortypes(void)
WM_operatortype_append(CLIP_OT_view_ndof);
WM_operatortype_append(CLIP_OT_prefetch);
WM_operatortype_append(CLIP_OT_set_scene_frames);
+ WM_operatortype_append(CLIP_OT_cursor_set);
/* ** clip_toolbar.c ** */
WM_operatortype_append(CLIP_OT_tools);
@@ -724,6 +726,9 @@ static void clip_keymap(struct wmKeyConfig *keyconf)
RNA_enum_set(kmi->ptr, "action", TRACK_CLEAR_ALL);
RNA_boolean_set(kmi->ptr, "clear_active", FALSE);
+ /* Cursor */
+ WM_keymap_add_item(keymap, "CLIP_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0);
+
/* ******** Hotkeys avalaible for preview region only ******** */
keymap = WM_keymap_find(keyconf, "Clip Graph Editor", SPACE_CLIP, 0);
@@ -854,36 +859,36 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ARegion *ar_preview = ED_clip_has_preview_region(C, sa);
ARegion *ar_properties = ED_clip_has_properties_region(sa);
ARegion *ar_channels = ED_clip_has_channels_region(sa);
- int main_visible = FALSE, preview_visible = FALSE, tools_visible = FALSE;
- int tool_props_visible = FALSE, properties_visible = FALSE, channels_visible = FALSE;
- int view_changed = FALSE;
+ bool main_visible = false, preview_visible = false, tools_visible = false;
+ bool tool_props_visible = false, properties_visible = false, channels_visible = false;
+ bool view_changed = false;
switch (sc->view) {
case SC_VIEW_CLIP:
- main_visible = TRUE;
- preview_visible = FALSE;
- tools_visible = TRUE;
- tool_props_visible = TRUE;
- properties_visible = TRUE;
- channels_visible = FALSE;
+ main_visible = true;
+ preview_visible = false;
+ tools_visible = true;
+ tool_props_visible = true;
+ properties_visible = true;
+ channels_visible = false;
break;
case SC_VIEW_GRAPH:
- main_visible = FALSE;
- preview_visible = TRUE;
- tools_visible = FALSE;
- tool_props_visible = FALSE;
- properties_visible = FALSE;
- channels_visible = FALSE;
+ main_visible = false;
+ preview_visible = true;
+ tools_visible = false;
+ tool_props_visible = false;
+ properties_visible = false;
+ channels_visible = false;
reinit_preview_region(C, ar_preview);
break;
case SC_VIEW_DOPESHEET:
- main_visible = FALSE;
- preview_visible = TRUE;
- tools_visible = FALSE;
- tool_props_visible = FALSE;
- properties_visible = FALSE;
- channels_visible = TRUE;
+ main_visible = false;
+ preview_visible = true;
+ tools_visible = false;
+ tool_props_visible = false;
+ properties_visible = false;
+ channels_visible = true;
reinit_preview_region(C, ar_preview);
break;
@@ -893,12 +898,12 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
if (ar_main && (ar_main->flag & RGN_FLAG_HIDDEN)) {
ar_main->flag &= ~RGN_FLAG_HIDDEN;
ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
ar_main->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
else {
@@ -906,11 +911,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ar_main->flag |= RGN_FLAG_HIDDEN;
ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
WM_event_remove_handlers((bContext *)C, &ar_main->handlers);
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
ar_main->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
@@ -918,11 +923,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
if (ar_properties && (ar_properties->flag & RGN_FLAG_HIDDEN)) {
ar_properties->flag &= ~RGN_FLAG_HIDDEN;
ar_properties->v2d.flag &= ~V2D_IS_INITIALISED;
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_properties && ar_properties->alignment != RGN_ALIGN_RIGHT) {
ar_properties->alignment = RGN_ALIGN_RIGHT;
- view_changed = TRUE;
+ view_changed = true;
}
}
else {
@@ -930,11 +935,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ar_properties->flag |= RGN_FLAG_HIDDEN;
ar_properties->v2d.flag &= ~V2D_IS_INITIALISED;
WM_event_remove_handlers((bContext *)C, &ar_properties->handlers);
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_properties && ar_properties->alignment != RGN_ALIGN_NONE) {
ar_properties->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
@@ -942,11 +947,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
if (ar_tools && (ar_tools->flag & RGN_FLAG_HIDDEN)) {
ar_tools->flag &= ~RGN_FLAG_HIDDEN;
ar_tools->v2d.flag &= ~V2D_IS_INITIALISED;
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_tools && ar_tools->alignment != RGN_ALIGN_LEFT) {
ar_tools->alignment = RGN_ALIGN_LEFT;
- view_changed = TRUE;
+ view_changed = true;
}
}
else {
@@ -954,11 +959,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ar_tools->flag |= RGN_FLAG_HIDDEN;
ar_tools->v2d.flag &= ~V2D_IS_INITIALISED;
WM_event_remove_handlers((bContext *)C, &ar_tools->handlers);
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_tools && ar_tools->alignment != RGN_ALIGN_NONE) {
ar_tools->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
@@ -966,11 +971,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
if (ar_tool_props && (ar_tool_props->flag & RGN_FLAG_HIDDEN)) {
ar_tool_props->flag &= ~RGN_FLAG_HIDDEN;
ar_tool_props->v2d.flag &= ~V2D_IS_INITIALISED;
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_tool_props && (ar_tool_props->alignment != (RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV))) {
ar_tool_props->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
- view_changed = TRUE;
+ view_changed = true;
}
}
else {
@@ -978,11 +983,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ar_tool_props->flag |= RGN_FLAG_HIDDEN;
ar_tool_props->v2d.flag &= ~V2D_IS_INITIALISED;
WM_event_remove_handlers((bContext *)C, &ar_tool_props->handlers);
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_tool_props && ar_tool_props->alignment != RGN_ALIGN_NONE) {
ar_tool_props->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
@@ -991,11 +996,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ar_preview->flag &= ~RGN_FLAG_HIDDEN;
ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
ar_preview->v2d.cur = ar_preview->v2d.tot;
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
ar_preview->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
else {
@@ -1003,11 +1008,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ar_preview->flag |= RGN_FLAG_HIDDEN;
ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
WM_event_remove_handlers((bContext *)C, &ar_preview->handlers);
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
ar_preview->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
@@ -1015,11 +1020,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
if (ar_channels && (ar_channels->flag & RGN_FLAG_HIDDEN)) {
ar_channels->flag &= ~RGN_FLAG_HIDDEN;
ar_channels->v2d.flag &= ~V2D_IS_INITIALISED;
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_channels && ar_channels->alignment != RGN_ALIGN_LEFT) {
ar_channels->alignment = RGN_ALIGN_LEFT;
- view_changed = TRUE;
+ view_changed = true;
}
}
else {
@@ -1027,11 +1032,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ar_channels->flag |= RGN_FLAG_HIDDEN;
ar_channels->v2d.flag &= ~V2D_IS_INITIALISED;
WM_event_remove_handlers((bContext *)C, &ar_channels->handlers);
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_channels && ar_channels->alignment != RGN_ALIGN_NONE) {
ar_channels->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
@@ -1116,6 +1121,8 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar)
/* draw entirely, view changes should be handled here */
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
+ float aspx, aspy, zoomx, zoomy, x, y;
+ int width, height;
/* if tracking is in progress, we should synchronize framenr from clipuser
* so latest tracked frame would be shown */
@@ -1147,29 +1154,38 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar)
clip_draw_main(C, sc, ar);
- if (sc->mode == SC_MODE_MASKEDIT) {
+ /* TODO(sergey): would be nice to find a way to de-duplicate all this space conversions */
+ UI_view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ ED_space_clip_get_size(sc, &width, &height);
+ ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
+ ED_space_clip_get_aspect(sc, &aspx, &aspy);
+ if (sc->mode == SC_MODE_MASKEDIT) {
Mask *mask = CTX_data_edit_mask(C);
if (mask) {
ScrArea *sa = CTX_wm_area(C);
- int width, height;
- float aspx, aspy;
- ED_mask_get_size(sa, &width, &height);
- ED_space_clip_get_aspect(sc, &aspx, &aspy);
+ int mask_width, mask_height;
+ ED_mask_get_size(sa, &mask_width, &mask_height);
ED_mask_draw_region(mask, ar,
sc->mask_info.draw_flag, sc->mask_info.draw_type,
- width, height,
+ mask_width, mask_height,
aspx, aspy,
TRUE, TRUE,
sc->stabmat, C);
}
-
-
}
+ glPushMatrix();
+ glTranslatef(x, y, 0);
+ glScalef(zoomx, zoomy, 0);
+ glMultMatrixf(sc->stabmat);
+ glScalef(width, height, 0);
+ draw_image_cursor(ar, sc->cursor);
+ glPopMatrix();
+
if (sc->flag & SC_SHOW_GPENCIL) {
/* Grease Pencil */
- clip_draw_grease_pencil((bContext *)C, TRUE);
+ clip_draw_grease_pencil((bContext *)C, true);
}
/* reset view matrix */
@@ -1177,7 +1193,7 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar)
if (sc->flag & SC_SHOW_GPENCIL) {
/* draw Grease Pencil - screen space only */
- clip_draw_grease_pencil((bContext *)C, FALSE);
+ clip_draw_grease_pencil((bContext *)C, false);
}
}
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index e14fc8ad399..8106befcab8 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -593,14 +593,14 @@ static int mouse_on_tilt(SpaceClip *sc, MovieTrackingMarker *marker, float co[2]
return mouse_on_slide_zone(sc, marker, TRACK_AREA_PAT, co, slider, 0.0f, width, height);
}
-static int slide_check_corners(float (*corners)[2])
+static bool slide_check_corners(float (*corners)[2])
{
int i, next, prev;
float cross = 0.0f;
float p[2] = {0.0f, 0.0f};
if (!isect_point_quad_v2(p, corners[0], corners[1], corners[2], corners[3]))
- return FALSE;
+ return false;
for (i = 0; i < 4; i++) {
float v1[2], v2[2], cur_cross;
@@ -618,12 +618,12 @@ static int slide_check_corners(float (*corners)[2])
cross = cur_cross;
}
else if (cross * cur_cross < 0.0f) {
- return FALSE;
+ return false;
}
}
}
- return TRUE;
+ return true;
}
static void hide_cursor(bContext *C)
@@ -664,25 +664,25 @@ MovieTrackingTrack *tracking_marker_check_slide(bContext *C, const wmEvent *even
while (track) {
if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
- int ok = FALSE;
+ bool ok = false;
if ((marker->flag & MARKER_DISABLED) == 0) {
if (mouse_on_offset(sc, track, marker, co, width, height)) {
area = TRACK_AREA_POINT;
action = SLIDE_ACTION_POS;
- ok = TRUE;
+ ok = true;
}
if (!ok && (sc->flag & SC_SHOW_MARKER_SEARCH)) {
if (mouse_on_corner(sc, marker, TRACK_AREA_SEARCH, co, 1, 0.0f, width, height)) {
area = TRACK_AREA_SEARCH;
action = SLIDE_ACTION_OFFSET;
- ok = TRUE;
+ ok = true;
}
else if (mouse_on_corner(sc, marker, TRACK_AREA_SEARCH, co, 0, 0.0f, width, height)) {
area = TRACK_AREA_SEARCH;
action = SLIDE_ACTION_SIZE;
- ok = TRUE;
+ ok = true;
}
}
@@ -693,7 +693,7 @@ MovieTrackingTrack *tracking_marker_check_slide(bContext *C, const wmEvent *even
area = TRACK_AREA_PAT;
action = SLIDE_ACTION_POS;
corner = current_corner;
- ok = TRUE;
+ ok = true;
}
else {
#if 0
@@ -702,18 +702,18 @@ MovieTrackingTrack *tracking_marker_check_slide(bContext *C, const wmEvent *even
if (mouse_on_corner(sc, marker, TRACK_AREA_PAT, co, 1, 12.0f, width, height)) {
area = TRACK_AREA_PAT;
action = SLIDE_ACTION_OFFSET;
- ok = TRUE;
+ ok = true;
}
if (!ok && mouse_on_corner(sc, marker, TRACK_AREA_PAT, co, 0, 12.0f, width, height)) {
area = TRACK_AREA_PAT;
action = SLIDE_ACTION_SIZE;
- ok = TRUE;
+ ok = true;
}
#endif
if (!ok && mouse_on_tilt(sc, marker, co, width, height)) {
area = TRACK_AREA_PAT;
action = SLIDE_ACTION_TILT_SIZE;
- ok = TRUE;
+ ok = true;
}
}
}
@@ -1145,18 +1145,18 @@ static void track_init_markers(SpaceClip *sc, MovieClip *clip, int *frames_limit
*frames_limit_r = frames_limit;
}
-static int track_markers_check_direction(int backwards, int curfra, int efra)
+static bool track_markers_check_direction(int backwards, int curfra, int efra)
{
if (backwards) {
if (curfra < efra)
- return FALSE;
+ return false;
}
else {
if (curfra > efra)
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
static int track_markers_initjob(bContext *C, TrackMarkersJob *tmj, int backwards)
@@ -1960,7 +1960,7 @@ static int count_selected_bundles(bContext *C)
static void object_solver_inverted_matrix(Scene *scene, Object *ob, float invmat[4][4])
{
bConstraint *con;
- int found = FALSE;
+ bool found = false;
for (con = ob->constraints.first; con; con = con->next) {
bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
@@ -1979,7 +1979,7 @@ static void object_solver_inverted_matrix(Scene *scene, Object *ob, float invmat
mul_m4_m4m4(invmat, invmat, data->invmat);
- found = TRUE;
+ found = true;
}
}
@@ -2099,7 +2099,7 @@ static void set_axis(Scene *scene, Object *ob, MovieClip *clip, MovieTrackingOb
{
Object *camera = get_camera_with_movieclip(scene, clip);
int is_camera = tracking_object->flag & TRACKING_OBJECT_CAMERA;
- int flip = FALSE;
+ bool flip = false;
float mat[4][4], vec[3], obmat[4][4], dvec[3];
BKE_object_to_mat4(ob, obmat);
@@ -2127,7 +2127,7 @@ static void set_axis(Scene *scene, Object *ob, MovieClip *clip, MovieTrackingOb
if (axis == 'X') {
if (fabsf(dvec[1]) < 1e-3f) {
- flip = TRUE;
+ flip = true;
mat[0][0] = -1.0f; mat[0][1] = 0.0f; mat[0][2] = 0.0f;
mat[1][0] = 0.0f; mat[1][1] = -1.0f; mat[1][2] = 0.0f;
@@ -2151,7 +2151,7 @@ static void set_axis(Scene *scene, Object *ob, MovieClip *clip, MovieTrackingOb
}
else {
if (fabsf(dvec[0]) < 1e-3f) {
- flip = TRUE;
+ flip = true;
mat[0][0] = -1.0f; mat[0][1] = 0.0f; mat[0][2] = 0.0f;
mat[1][0] = 0.0f; mat[1][1] = -1.0f; mat[1][2] = 0.0f;
diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c
index 6e4d10173fb..7cb5f9b5dc0 100644
--- a/source/blender/editors/space_clip/tracking_select.c
+++ b/source/blender/editors/space_clip/tracking_select.c
@@ -461,7 +461,8 @@ static int border_select_exec(bContext *C, wmOperator *op)
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
rcti rect;
rctf rectf;
- int change = FALSE, mode, extend;
+ bool change = false;
+ int mode, extend;
int framenr = ED_space_clip_get_clip_frame_number(sc);
/* get rectangle from operator */
@@ -490,7 +491,7 @@ static int border_select_exec(bContext *C, wmOperator *op)
BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
}
- change = TRUE;
+ change = true;
}
}
@@ -520,7 +521,7 @@ static int border_select_exec(bContext *C, wmOperator *op)
}
}
- change = TRUE;
+ change = true;
}
}
@@ -569,7 +570,7 @@ static int do_lasso_select_marker(bContext *C, const int mcords[][2], const shor
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
rcti rect;
- int change = FALSE;
+ bool change = false;
int framenr = ED_space_clip_get_clip_frame_number(sc);
/* get rectangle from operator */
@@ -596,7 +597,7 @@ static int do_lasso_select_marker(bContext *C, const int mcords[][2], const shor
BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
}
- change = TRUE;
+ change = true;
}
}
@@ -630,7 +631,7 @@ static int do_lasso_select_marker(bContext *C, const int mcords[][2], const shor
}
}
- change = TRUE;
+ change = true;
}
}
@@ -713,7 +714,8 @@ static int circle_select_exec(bContext *C, wmOperator *op)
MovieTrackingPlaneTrack *plane_track;
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- int x, y, radius, width, height, mode, change = FALSE;
+ int x, y, radius, width, height, mode;
+ bool change = false;
float zoomx, zoomy, offset[2], ellipse[2];
int framenr = ED_space_clip_get_clip_frame_number(sc);
@@ -745,7 +747,7 @@ static int circle_select_exec(bContext *C, wmOperator *op)
else
BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
- change = TRUE;
+ change = true;
}
}
@@ -772,7 +774,7 @@ static int circle_select_exec(bContext *C, wmOperator *op)
}
}
- change = TRUE;
+ change = true;
}
}
@@ -824,7 +826,7 @@ static int select_all_exec(bContext *C, wmOperator *op)
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
int action = RNA_enum_get(op->ptr, "action");
int framenr = ED_space_clip_get_clip_frame_number(sc);
- int has_selection = FALSE;
+ bool has_selection = false;
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
@@ -877,7 +879,7 @@ static int select_all_exec(bContext *C, wmOperator *op)
}
if (TRACK_VIEW_SELECTED(sc, track))
- has_selection = TRUE;
+ has_selection = true;
}
for (plane_track = plane_tracks_base->first;
@@ -899,7 +901,7 @@ static int select_all_exec(bContext *C, wmOperator *op)
}
if (plane_track->flag & SELECT) {
- has_selection = TRUE;
+ has_selection = true;
}
}
@@ -945,7 +947,7 @@ static int select_groped_exec(bContext *C, wmOperator *op)
track = tracksbase->first;
while (track) {
- int ok = FALSE;
+ bool ok = false;
marker = BKE_tracking_marker_get(track, framenr);
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 8f25ac38963..19a6296993d 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -152,17 +152,27 @@ static ImBuf *gSpecialFileImages[SPECIAL_IMG_MAX];
/* ******************* SORT ******************* */
+static bool compare_is_directory(const struct direntry *entry)
+{
+ /* for library browse .blend files may be treated as directories, but
+ * for sorting purposes they should be considered regular files */
+ if (S_ISDIR(entry->type))
+ return !(entry->flags & (BLENDERFILE | BLENDERFILE_BACKUP));
+
+ return false;
+}
+
static int compare_name(const void *a1, const void *a2)
{
const struct direntry *entry1 = a1, *entry2 = a2;
/* type is equal to stat.st_mode */
- if (S_ISDIR(entry1->type)) {
- if (S_ISDIR(entry2->type) == 0) return (-1);
+ if (compare_is_directory(entry1)) {
+ if (compare_is_directory(entry2) == 0) return (-1);
}
else {
- if (S_ISDIR(entry2->type)) return (1);
+ if (compare_is_directory(entry2)) return (1);
}
if (S_ISREG(entry1->type)) {
if (S_ISREG(entry2->type) == 0) return (-1);
@@ -188,11 +198,11 @@ static int compare_date(const void *a1, const void *a2)
/* type is equal to stat.st_mode */
- if (S_ISDIR(entry1->type)) {
- if (S_ISDIR(entry2->type) == 0) return (-1);
+ if (compare_is_directory(entry1)) {
+ if (compare_is_directory(entry2) == 0) return (-1);
}
else {
- if (S_ISDIR(entry2->type)) return (1);
+ if (compare_is_directory(entry2)) return (1);
}
if (S_ISREG(entry1->type)) {
if (S_ISREG(entry2->type) == 0) return (-1);
@@ -221,11 +231,11 @@ static int compare_size(const void *a1, const void *a2)
/* type is equal to stat.st_mode */
- if (S_ISDIR(entry1->type)) {
- if (S_ISDIR(entry2->type) == 0) return (-1);
+ if (compare_is_directory(entry1)) {
+ if (compare_is_directory(entry2) == 0) return (-1);
}
else {
- if (S_ISDIR(entry2->type)) return (1);
+ if (compare_is_directory(entry2)) return (1);
}
if (S_ISREG(entry1->type)) {
if (S_ISREG(entry2->type) == 0) return (-1);
@@ -262,11 +272,11 @@ static int compare_extension(const void *a1, const void *a2)
/* type is equal to stat.st_mode */
- if (S_ISDIR(entry1->type)) {
- if (S_ISDIR(entry2->type) == 0) return (-1);
+ if (compare_is_directory(entry1)) {
+ if (compare_is_directory(entry2) == 0) return (-1);
}
else {
- if (S_ISDIR(entry2->type)) return (1);
+ if (compare_is_directory(entry2)) return (1);
}
if (S_ISREG(entry1->type)) {
if (S_ISREG(entry2->type) == 0) return (-1);
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 85e4d255603..9d762c80405 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -59,6 +59,7 @@
#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
#include "BLI_fileops_types.h"
+#include "BLI_fnmatch.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -81,12 +82,6 @@
#include "file_intern.h"
#include "filelist.h"
-#if defined WIN32 && !defined _LIBC
-# include "BLI_fnmatch.h" /* use fnmatch included in blenlib */
-#else
-# include <fnmatch.h>
-#endif
-
FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile)
{
if (!sfile->params) {
@@ -115,6 +110,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
/* set the parameters from the operator, if it exists */
if (op) {
+ PropertyRNA *prop;
const short is_files = (RNA_struct_find_property(op->ptr, "files") != NULL);
const short is_filepath = (RNA_struct_find_property(op->ptr, "filepath") != NULL);
const short is_filename = (RNA_struct_find_property(op->ptr, "filename") != NULL);
@@ -163,30 +159,30 @@ short ED_fileselect_set_params(SpaceFile *sfile)
}
params->filter = 0;
- if (RNA_struct_find_property(op->ptr, "filter_blender"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_blender") ? BLENDERFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_backup"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_backup") ? BLENDERFILE_BACKUP : 0;
- if (RNA_struct_find_property(op->ptr, "filter_image"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_image") ? IMAGEFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_movie"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_movie") ? MOVIEFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_python"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_python") ? PYSCRIPTFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_font"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_font") ? FTFONTFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_sound"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_sound") ? SOUNDFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_text"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_text") ? TEXTFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_folder"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_folder") ? FOLDERFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_btx"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_btx") ? BTXFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_collada"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_collada") ? COLLADAFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_glob")) {
- RNA_string_get(op->ptr, "filter_glob", params->filter_glob);
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_blender")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BLENDERFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_backup")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BLENDERFILE_BACKUP : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_image")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? IMAGEFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_movie")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? MOVIEFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_python")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? PYSCRIPTFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_font")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FTFONTFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_sound")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? SOUNDFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_text")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? TEXTFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_folder")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FOLDERFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_btx")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BTXFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_collada")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? COLLADAFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_glob"))) {
+ RNA_property_string_get(op->ptr, prop, params->filter_glob);
params->filter |= (OPERATORFILE | FOLDERFILE);
}
else {
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 6f3d0367574..9758e2e9135 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -148,7 +148,6 @@ static void file_free(SpaceLink *sl)
static void file_init(wmWindowManager *UNUSED(wm), ScrArea *sa)
{
SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
- //printf("file_init\n");
/* refresh system directory list */
fsmenu_refresh_system_category(fsmenu_get());
@@ -313,7 +312,6 @@ static void file_main_area_draw(const bContext *C, ARegion *ar)
/* draw entirely, view changes should be handled here */
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
- FileLayout *layout = NULL;
View2D *v2d = &ar->v2d;
View2DScrollers *scrollers;
@@ -323,15 +321,14 @@ static void file_main_area_draw(const bContext *C, ARegion *ar)
if (!sfile->files || filelist_empty(sfile->files))
file_refresh(C, NULL);
- layout = ED_fileselect_get_layout(sfile, ar);
-
/* clear and setup matrix */
UI_GetThemeColor3fv(TH_BACK, col);
glClearColor(col[0], col[1], col[2], 0.0);
glClear(GL_COLOR_BUFFER_BIT);
/* Allow dynamically sliders to be set, saves notifiers etc. */
- if (layout && (layout->flag == FILE_LAYOUT_VER)) {
+
+ if (params->display == FILE_IMGDISPLAY) {
v2d->scroll = V2D_SCROLL_RIGHT;
v2d->keepofs &= ~V2D_LOCKOFS_Y;
v2d->keepofs |= V2D_LOCKOFS_X;
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 9d22d6fcc95..5546682e470 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -882,8 +882,12 @@ static void delete_graph_keys(bAnimContext *ac)
delete_fcurve_keys(fcu);
/* Only delete curve too if it won't be doing anything anymore */
- if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0))
+ if ((fcu->totvert == 0) &&
+ (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) &&
+ (fcu->driver == NULL))
+ {
ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
+ }
}
/* free filtered list */
@@ -1676,7 +1680,7 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
/* FIXME: there are more complicated methods that will be needed to fix more cases than just some */
for (f = 0; f < 3; f++) {
FCurve *fcu = euf->fcurves[f];
- BezTriple *bezt, *prev = NULL;
+ BezTriple *bezt, *prev;
unsigned int i;
/* skip if not enough vets to do a decent analysis of... */
@@ -1684,29 +1688,19 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
continue;
/* prev follows bezt, bezt = "current" point to be fixed */
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, prev = bezt, bezt++) {
- /* our method depends on determining a "difference" from the previous vert */
- if (prev == NULL)
- continue;
+ /* our method depends on determining a "difference" from the previous vert */
+ for (i = 1, prev = fcu->bezt, bezt = fcu->bezt + 1; i < fcu->totvert; i++, prev = bezt++) {
+ const float sign = (prev->vec[1][1] > bezt->vec[1][1]) ? 1.0f : -1.0f;
/* > 180 degree flip? */
- if (fabs(prev->vec[1][1] - bezt->vec[1][1]) >= M_PI) {
+ if ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) {
/* 360 degrees to add/subtract frame value until difference is acceptably small that there's no more flip */
- const float fac = 2.0f * (float)M_PI;
+ const float fac = sign * 2.0f * (float)M_PI;
- if (prev->vec[1][1] > bezt->vec[1][1]) {
- while (fabsf(bezt->vec[1][1] - prev->vec[1][1]) >= (float)M_PI) {
- bezt->vec[0][1] += fac;
- bezt->vec[1][1] += fac;
- bezt->vec[2][1] += fac;
- }
- }
- else { /* if (prev->vec[1][1] < bezt->vec[1][1]) */
- while (fabsf(bezt->vec[1][1] - prev->vec[1][1]) >= (float)M_PI) {
- bezt->vec[0][1] -= fac;
- bezt->vec[1][1] -= fac;
- bezt->vec[2][1] -= fac;
- }
+ while ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) {
+ bezt->vec[0][1] += fac;
+ bezt->vec[1][1] += fac;
+ bezt->vec[2][1] += fac;
}
}
}
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index cbec3072c44..d87bd9a5077 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -149,17 +149,37 @@ static void deselect_graph_keys(bAnimContext *ac, short test, short sel, short d
static int graphkeys_deselectall_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
+ bAnimListElem *ale_active = NULL;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
+ /* find active F-Curve, and preserve this for later
+ * or else it becomes annoying with the current active
+ * curve keeps fading out even while you're editing it
+ */
+ ale_active = get_active_fcurve_channel(&ac);
+
/* 'standard' behavior - check if selected, then apply relevant selection */
if (RNA_boolean_get(op->ptr, "invert"))
deselect_graph_keys(&ac, 0, SELECT_INVERT, TRUE);
else
deselect_graph_keys(&ac, 1, SELECT_ADD, TRUE);
+ /* restore active F-Curve... */
+ if (ale_active) {
+ FCurve *fcu = (FCurve *)ale_active->data;
+
+ /* all others should not be disabled, so we should be able to just set this directly...
+ * - selection needs to be set too, or else this won't work...
+ */
+ fcu->flag |= (FCURVE_SELECTED | FCURVE_ACTIVE);
+
+ MEM_freeN(ale_active);
+ ale_active = NULL;
+ }
+
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@@ -1049,10 +1069,7 @@ static tNearestVertInfo *get_best_nearest_fcurve_vert(ListBase *matches)
/* if list only has 1 item, remove it from the list and return */
if (matches->first == matches->last) {
/* need to remove from the list, otherwise it gets freed and then we can't return it */
- nvi = matches->first;
- BLI_remlink(matches, nvi);
-
- return nvi;
+ return BLI_pophead(matches);
}
/* try to find the first selected F-Curve vert, then take the one after it */
@@ -1075,9 +1092,7 @@ static tNearestVertInfo *get_best_nearest_fcurve_vert(ListBase *matches)
/* if we're still here, this means that we failed to find anything appropriate in the first pass,
* so just take the first item now...
*/
- nvi = matches->first;
- BLI_remlink(matches, nvi);
- return nvi;
+ return BLI_pophead(matches);
}
/* Find the nearest vertices (either a handle or the keyframe) that are nearest to the mouse cursor (in area coordinates)
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 2da3f3adb67..6a3259e030e 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -646,12 +646,13 @@ void IMAGE_OT_view_ndof(wmOperatorType *ot)
* Default behavior is to reset the position of the image and set the zoom to 1
* If the image will not fit within the window rectangle, the zoom is adjusted */
-static int image_view_all_exec(bContext *C, wmOperator *UNUSED(op))
+static int image_view_all_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima;
ARegion *ar;
float aspx, aspy, zoomx, zoomy, w, h;
int width, height;
+ int fit_view = RNA_boolean_get(op->ptr, "fit_view");
/* retrieve state */
sima = CTX_wm_space_image(C);
@@ -667,14 +668,25 @@ static int image_view_all_exec(bContext *C, wmOperator *UNUSED(op))
width = BLI_rcti_size_x(&ar->winrct) + 1;
height = BLI_rcti_size_y(&ar->winrct) + 1;
- if ((w >= width || h >= height) && (width > 0 && height > 0)) {
- /* find the zoom value that will fit the image in the image space */
- zoomx = width / w;
- zoomy = height / h;
- sima_zoom_set(sima, ar, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL);
+ if (fit_view) {
+ const int margin = 5; /* margin from border */
+
+ zoomx = (float) width / (w + 2 * margin);
+ zoomy = (float) height / (h + 2 * margin);
+
+ sima_zoom_set(sima, ar, min_ff(zoomx, zoomy), NULL);
+ }
+ else {
+ if ((w >= width || h >= height) && (width > 0 && height > 0)) {
+ zoomx = (float) width / w;
+ zoomy = (float) height / h;
+
+ /* find the zoom value that will fit the image in the image space */
+ sima_zoom_set(sima, ar, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL);
+ }
+ else
+ sima_zoom_set(sima, ar, 1.0f, NULL);
}
- else
- sima_zoom_set(sima, ar, 1.0f, NULL);
sima->xof = sima->yof = 0.0f;
@@ -685,6 +697,8 @@ static int image_view_all_exec(bContext *C, wmOperator *UNUSED(op))
void IMAGE_OT_view_all(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "View All";
ot->idname = "IMAGE_OT_view_all";
@@ -693,6 +707,10 @@ void IMAGE_OT_view_all(wmOperatorType *ot)
/* api callbacks */
ot->exec = image_view_all_exec;
ot->poll = space_image_main_area_poll;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "fit_view", 0, "Fit View", "Fit frame to the viewport");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/********************** view selected operator *********************/
@@ -1318,7 +1336,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
const char *relbase = ID_BLEND_PATH(CTX_data_main(C), &ima->id);
const short relative = (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path"));
const short save_copy = (RNA_struct_find_property(op->ptr, "copy") && RNA_boolean_get(op->ptr, "copy"));
- const short save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render"));
+ const bool save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render"));
ImageFormatData *imf = &simopts->im_format;
short ok = FALSE;
@@ -1344,7 +1362,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
}
}
- colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, TRUE, &imf->view_settings, &imf->display_settings, imf);
+ colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
if (simopts->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
Scene *scene = CTX_data_scene(C);
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index c0ef59e9e25..5a8292abcab 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -277,6 +277,10 @@ static void image_keymap(struct wmKeyConfig *keyconf)
keymap = WM_keymap_find(keyconf, "Image", SPACE_IMAGE, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
+
+ kmi = WM_keymap_add_item(keymap, "IMAGE_OT_view_all", FKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "fit_view", TRUE);
+
WM_keymap_add_item(keymap, "IMAGE_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MIDDLEMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0);
@@ -670,7 +674,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
}
else if (sima->mode == SI_MODE_MASK) {
mask = ED_space_image_get_mask(sima);
- draw_image_cursor(sima, ar);
+ draw_image_cursor(ar, sima->cursor);
}
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
@@ -719,7 +723,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
ED_mask_draw_frames(mask, ar, CFRA, mask->sfra, mask->efra);
- draw_image_cursor(sima, ar);
+ draw_image_cursor(ar, sima->cursor);
}
/* scrollers? */
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 98c9c8d15fe..c1cddf092aa 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -115,8 +115,8 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
{
int totv = 0, totf = 0, tottri = 0;
- if (ob->disp.first)
- BKE_displist_count(&ob->disp, &totv, &totf, &tottri);
+ if (ob->curve_cache && ob->curve_cache->disp.first)
+ BKE_displist_count(&ob->curve_cache->disp, &totv, &totf, &tottri);
totv *= totob;
totf *= totob;
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index aed5699a9d7..2c89d6f6448 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -427,8 +427,6 @@ static const char *sensor_name(int type)
switch (type) {
case SENS_ALWAYS:
return "Always";
- case SENS_TOUCH:
- return "Touch";
case SENS_NEAR:
return "Near";
case SENS_KEYBOARD:
@@ -1233,11 +1231,6 @@ static void draw_sensor_ray(uiLayout *layout, PointerRNA *ptr, bContext *C)
uiItemR(row, ptr, "use_x_ray", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
}
-static void draw_sensor_touch(uiLayout *layout, PointerRNA *ptr)
-{
- uiItemR(layout, ptr, "material", 0, NULL, ICON_NONE);
-}
-
static void draw_brick_sensor(uiLayout *layout, PointerRNA *ptr, bContext *C)
{
uiLayout *box;
@@ -1292,9 +1285,6 @@ static void draw_brick_sensor(uiLayout *layout, PointerRNA *ptr, bContext *C)
case SENS_RAY:
draw_sensor_ray(box, ptr, C);
break;
- case SENS_TOUCH:
- draw_sensor_touch(box, ptr);
- break;
}
}
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 5cc22b25f72..4e98c9fd894 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -809,9 +809,13 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin
}
static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
-{
+{
+ uiItemR(layout, ptr, "sky_type", 0, "", ICON_NONE);
uiItemR(layout, ptr, "sun_direction", 0, "", ICON_NONE);
uiItemR(layout, ptr, "turbidity", 0, NULL, ICON_NONE);
+
+ if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_NEW)
+ uiItemR(layout, ptr, "ground_albedo", 0, NULL, ICON_NONE);
}
static void node_shader_buts_tex_gradient(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -907,6 +911,11 @@ static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), Point
uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
}
+static void node_shader_buts_subsurface(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "falloff", 0, "", ICON_NONE);
+}
+
static void node_shader_buts_toon(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "component", 0, "", ICON_NONE);
@@ -1039,6 +1048,9 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_BSDF_REFRACTION:
ntype->uifunc = node_shader_buts_glossy;
break;
+ case SH_NODE_SUBSURFACE_SCATTERING:
+ ntype->uifunc = node_shader_buts_subsurface;
+ break;
case SH_NODE_BSDF_TOON:
ntype->uifunc = node_shader_buts_toon;
break;
@@ -1620,12 +1632,14 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C
active_index = RNA_int_get(ptr, "active_input_index");
/* using different collection properties if multilayer format is enabled */
if (multilayer) {
- uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "layer_slots", ptr, "active_input_index", 0, 0, 0);
+ uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "layer_slots", ptr, "active_input_index",
+ 0, 0, 0, 0);
RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "layer_slots"),
active_index, &active_input_ptr);
}
else {
- uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "file_slots", ptr, "active_input_index", 0, 0, 0);
+ uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "file_slots", ptr, "active_input_index",
+ 0, 0, 0, 0);
RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_slots"),
active_index, &active_input_ptr);
}
@@ -3061,7 +3075,16 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa
{
float dist, vec[4][2];
float deltax, deltay;
+ float cursor[2] = {0.0f, 0.0f};
int toreroute, fromreroute;
+
+ /* this function can be called with snode null (via cut_links_intersect) */
+ /* XXX map snode->cursor back to view space */
+ if (snode) {
+ cursor[0] = snode->cursor[0] * UI_DPI_FAC;
+ cursor[1] = snode->cursor[1] * UI_DPI_FAC;
+ }
+
/* in v0 and v3 we put begin/end points */
if (link->fromsock) {
vec[0][0] = link->fromsock->locx;
@@ -3070,7 +3093,7 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa
}
else {
if (snode == NULL) return 0;
- copy_v2_v2(vec[0], snode->cursor);
+ copy_v2_v2(vec[0], cursor);
fromreroute = 0;
}
if (link->tosock) {
@@ -3080,7 +3103,7 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa
}
else {
if (snode == NULL) return 0;
- copy_v2_v2(vec[3], snode->cursor);
+ copy_v2_v2(vec[3], cursor);
toreroute = 0;
}
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index c9618daa7c5..00769975893 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -84,10 +84,6 @@ bNode *node_add_node(const bContext *C, const char *idname, int type, float locx
node->locy = locy + 60.0f; /* arbitrary... so its visible, (0,0) is top of node */
nodeSetSelected(node, TRUE);
- /* node location is mapped */
- locx /= UI_DPI_FAC;
- locy /= UI_DPI_FAC;
-
node->locx = locx;
node->locy = locy + 60.0f;
@@ -215,7 +211,7 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
int i = 0;
/* Get the cut path */
- RNA_BEGIN(op->ptr, itemptr, "path")
+ RNA_BEGIN (op->ptr, itemptr, "path")
{
float loc[2];
@@ -417,9 +413,8 @@ static int node_add_mask_poll(bContext *C)
return ED_operator_node_editable(C) && snode->nodetree->type == NTREE_COMPOSIT;
}
-static int node_add_mask_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int node_add_mask_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
ID *mask = NULL;
@@ -435,9 +430,6 @@ static int node_add_mask_invoke(bContext *C, wmOperator *op, const wmEvent *even
ED_preview_kill_jobs(C);
- /* convert mouse coordinates to v2d space */
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
- &snode->cursor[0], &snode->cursor[1]);
node = node_add_node(C, NULL, CMP_NODE_MASK, snode->cursor[0], snode->cursor[1]);
if (!node) {
@@ -462,7 +454,7 @@ void NODE_OT_add_mask(wmOperatorType *ot)
ot->idname = "NODE_OT_add_mask";
/* callbacks */
- ot->invoke = node_add_mask_invoke;
+ ot->exec = node_add_mask_exec;
ot->poll = node_add_mask_poll;
/* flags */
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index f95e895bef2..53b373e728e 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -145,13 +145,15 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa)
split = uiLayoutRow(row, TRUE);
col = uiLayoutColumn(split, TRUE);
uiItemL(col, IFACE_("Inputs:"), ICON_NONE);
- uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "inputs", &ptr, "inputs", &ptr, "active_input", 0, 0, 0);
+ uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "inputs", &ptr, "inputs", &ptr, "active_input",
+ 0, 0, 0, 0);
opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "in_out", SOCK_IN);
col = uiLayoutColumn(split, TRUE);
uiItemL(col, IFACE_("Outputs:"), ICON_NONE);
- uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "outputs", &ptr, "outputs", &ptr, "active_output", 0, 0, 0);
+ uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "outputs", &ptr, "outputs", &ptr, "active_output",
+ 0, 0, 0, 0);
opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "in_out", SOCK_OUT);
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index dce04bb8c42..b40a7e4702e 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -1075,31 +1075,31 @@ int node_get_resize_cursor(int directions)
return CURSOR_EDIT;
}
-void node_set_cursor(wmWindow *win, SpaceNode *snode)
+void node_set_cursor(wmWindow *win, SpaceNode *snode, float cursor[2])
{
bNodeTree *ntree = snode->edittree;
bNode *node;
bNodeSocket *sock;
- int cursor = CURSOR_STD;
+ int wmcursor = CURSOR_STD;
if (ntree) {
- if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN | SOCK_OUT)) {
+ if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN | SOCK_OUT)) {
/* pass */
}
else {
/* check nodes front to back */
for (node = ntree->nodes.last; node; node = node->prev) {
- if (BLI_rctf_isect_pt(&node->totr, snode->cursor[0], snode->cursor[1]))
+ if (BLI_rctf_isect_pt(&node->totr, cursor[0], cursor[1]))
break; /* first hit on node stops */
}
if (node) {
- int dir = node->typeinfo->resize_area_func(node, snode->cursor[0], snode->cursor[1]);
- cursor = node_get_resize_cursor(dir);
+ int dir = node->typeinfo->resize_area_func(node, cursor[0], cursor[1]);
+ wmcursor = node_get_resize_cursor(dir);
}
}
}
- WM_cursor_set(win, cursor);
+ WM_cursor_set(win, wmcursor);
}
void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
@@ -1251,6 +1251,7 @@ static void draw_group_overlay(const bContext *C, ARegion *ar)
void drawnodespace(const bContext *C, ARegion *ar)
{
+ wmWindow *win = CTX_wm_window(C);
View2DScrollers *scrollers;
SpaceNode *snode = CTX_wm_space_node(C);
View2D *v2d = &ar->v2d;
@@ -1259,7 +1260,13 @@ void drawnodespace(const bContext *C, ARegion *ar)
glClear(GL_COLOR_BUFFER_BIT);
UI_view2d_view_ortho(v2d);
-
+
+ /* XXX snode->cursor set in coordspace for placing new nodes, used for drawing noodles too */
+ UI_view2d_region_to_view(&ar->v2d, win->eventstate->x - ar->winrct.xmin, win->eventstate->y - ar->winrct.ymin,
+ &snode->cursor[0], &snode->cursor[1]);
+ snode->cursor[0] /= UI_DPI_FAC;
+ snode->cursor[1] /= UI_DPI_FAC;
+
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
/* only set once */
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index b7e9cb0268f..3ba749a8eff 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -1056,7 +1056,7 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
/* checks snode->mouse position, and returns found node/socket */
/* type is SOCK_IN and/or SOCK_OUT */
-int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, int in_out)
+int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, float cursor[2], int in_out)
{
bNode *node;
bNodeSocket *sock;
@@ -1068,10 +1068,10 @@ int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **so
/* check if we click in a socket */
for (node = snode->edittree->nodes.first; node; node = node->next) {
- rect.xmin = snode->cursor[0] - (NODE_SOCKSIZE + 4);
- rect.ymin = snode->cursor[1] - (NODE_SOCKSIZE + 4);
- rect.xmax = snode->cursor[0] + (NODE_SOCKSIZE + 4);
- rect.ymax = snode->cursor[1] + (NODE_SOCKSIZE + 4);
+ rect.xmin = cursor[0] - (NODE_SOCKSIZE + 4);
+ rect.ymin = cursor[1] - (NODE_SOCKSIZE + 4);
+ rect.xmax = cursor[0] + (NODE_SOCKSIZE + 4);
+ rect.ymax = cursor[1] + (NODE_SOCKSIZE + 4);
if (!(node->flag & NODE_HIDDEN)) {
/* extra padding inside and out - allow dragging on the text areas too */
@@ -2087,17 +2087,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int node_clipboard_paste_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ARegion *ar = CTX_wm_region(C);
- SpaceNode *snode = CTX_wm_space_node(C);
-
- /* convert mouse coordinates to v2d space */
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]);
-
- return node_clipboard_paste_exec(C, op);
-}
-
void NODE_OT_clipboard_paste(wmOperatorType *ot)
{
/* identifiers */
@@ -2107,7 +2096,6 @@ void NODE_OT_clipboard_paste(wmOperatorType *ot)
/* api callbacks */
ot->exec = node_clipboard_paste_exec;
- ot->invoke = node_clipboard_paste_invoke;
ot->poll = ED_operator_node_editable;
/* flags */
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 1a2e90e5522..9b7b00fba00 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -84,7 +84,7 @@ void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct Spa
struct bNodeTree *ntree, bNodeInstanceKey parent_key);
void drawnodespace(const bContext *C, ARegion *ar);
-void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode);
+void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode, float cursor[2]);
/* DPI scaled coords */
void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry);
void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry);
@@ -129,6 +129,7 @@ void NODE_OT_view_selected(struct wmOperatorType *ot);
void NODE_OT_backimage_move(struct wmOperatorType *ot);
void NODE_OT_backimage_zoom(struct wmOperatorType *ot);
+void NODE_OT_backimage_fit(struct wmOperatorType *ot);
void NODE_OT_backimage_sample(struct wmOperatorType *ot);
/* drawnode.c */
@@ -182,7 +183,7 @@ int composite_node_editable(struct bContext *C);
int node_has_hidden_sockets(bNode *node);
void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set);
int node_render_changed_exec(bContext *, struct wmOperator *);
-int node_find_indicated_socket(struct SpaceNode *snode, struct bNode **nodep, struct bNodeSocket **sockp, int in_out);
+int node_find_indicated_socket(struct SpaceNode *snode, struct bNode **nodep, struct bNodeSocket **sockp, float cursor[2], int in_out);
void NODE_OT_duplicate(struct wmOperatorType *ot);
void NODE_OT_delete(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index 566bb1600cc..f0d3deb24df 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -98,6 +98,7 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_backimage_move);
WM_operatortype_append(NODE_OT_backimage_zoom);
+ WM_operatortype_append(NODE_OT_backimage_fit);
WM_operatortype_append(NODE_OT_backimage_sample);
WM_operatortype_append(NODE_OT_add_file);
@@ -249,6 +250,7 @@ void node_keymap(struct wmKeyConfig *keyconf)
RNA_float_set(kmi->ptr, "factor", 0.83333f);
kmi = WM_keymap_add_item(keymap, "NODE_OT_backimage_zoom", VKEY, KM_PRESS, KM_ALT, 0);
RNA_float_set(kmi->ptr, "factor", 1.2f);
+ WM_keymap_add_item(keymap, "NODE_OT_backimage_fit", HOMEKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "NODE_OT_backimage_sample", ACTIONMOUSE, KM_PRESS, KM_ALT, 0);
kmi = WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 244b222811e..4b5cc9e42b6 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -443,18 +443,19 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
bNodeSocket *tsock = NULL;
bNodeLink *link;
LinkData *linkdata;
+ float cursor[2];
int in_out;
in_out = nldrag->in_out;
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
- &snode->cursor[0], &snode->cursor[1]);
+ &cursor[0], &cursor[1]);
switch (event->type) {
case MOUSEMOVE:
if (in_out == SOCK_OUT) {
- if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) {
+ if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_IN)) {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
@@ -480,7 +481,7 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
else {
- if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) {
+ if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_OUT)) {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
@@ -550,7 +551,7 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* return 1 when socket clicked */
-static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
+static bNodeLinkDrag *node_link_init(SpaceNode *snode, float cursor[2], int detach)
{
bNode *node;
bNodeSocket *sock;
@@ -560,7 +561,7 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
int num_links;
/* output indicated? */
- if (node_find_indicated_socket(snode, &node, &sock, SOCK_OUT)) {
+ if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) {
nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
num_links = nodeCountSocketLinks(snode->edittree, sock);
@@ -596,7 +597,7 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
}
}
/* or an input? */
- else if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN)) {
+ else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) {
nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
num_links = nodeCountSocketLinks(snode->edittree, sock);
@@ -644,14 +645,16 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *ar = CTX_wm_region(C);
bNodeLinkDrag *nldrag;
+ float cursor[2];
+
int detach = RNA_boolean_get(op->ptr, "detach");
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
- &snode->cursor[0], &snode->cursor[1]);
+ &cursor[0], &cursor[1]);
ED_preview_kill_jobs(C);
- nldrag = node_link_init(snode, detach);
+ nldrag = node_link_init(snode, cursor, detach);
if (nldrag) {
op->customdata = nldrag;
@@ -762,7 +765,7 @@ static int cut_links_exec(bContext *C, wmOperator *op)
float mcoords[256][2];
int i = 0;
- RNA_BEGIN(op->ptr, itemptr, "path")
+ RNA_BEGIN (op->ptr, itemptr, "path")
{
float loc[2];
@@ -1065,18 +1068,23 @@ void NODE_OT_join(wmOperatorType *ot)
/* ****************** Attach ******************* */
-static int node_attach_exec(bContext *C, wmOperator *UNUSED(op))
+static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
+ ARegion *ar = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
bNode *frame;
+ float cursor[2];
+
+ /* convert mouse coordinates to v2d space */
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]);
/* check nodes front to back */
for (frame = ntree->nodes.last; frame; frame = frame->prev) {
/* skip selected, those are the nodes we want to attach */
if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT))
continue;
- if (BLI_rctf_isect_pt(&frame->totr, snode->cursor[0], snode->cursor[1]))
+ if (BLI_rctf_isect_pt(&frame->totr, cursor[0], cursor[1]))
break;
}
if (frame) {
@@ -1116,16 +1124,6 @@ static int node_attach_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static int node_attach_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ARegion *ar = CTX_wm_region(C);
- SpaceNode *snode = CTX_wm_space_node(C);
-
- /* convert mouse coordinates to v2d space */
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]);
-
- return node_attach_exec(C, op);
-}
void NODE_OT_attach(wmOperatorType *ot)
{
@@ -1135,7 +1133,7 @@ void NODE_OT_attach(wmOperatorType *ot)
ot->idname = "NODE_OT_attach";
/* api callbacks */
- ot->exec = node_attach_exec;
+
ot->invoke = node_attach_invoke;
ot->poll = ED_operator_node_editable;
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index e17699309ef..6ce31783bff 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -306,24 +306,21 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
{
bNode *node, *tnode;
bNodeSocket *sock, *tsock;
- float mx, my;
+ float cursor[2];
int selected = 0;
/* get mouse coordinates in view2d space */
- UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &mx, &my);
- /* node_find_indicated_socket uses snode->mx/my */
- snode->cursor[0] = mx;
- snode->cursor[1] = my;
+ UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &cursor[0], &cursor[1]);
if (extend) {
/* first do socket selection, these generally overlap with nodes.
* socket selection only in extend mode.
*/
- if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN)) {
+ if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) {
node_socket_toggle(node, sock, 1);
selected = 1;
}
- else if (node_find_indicated_socket(snode, &node, &sock, SOCK_OUT)) {
+ else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) {
if (sock->flag & SELECT) {
node_socket_deselect(node, sock, 1);
}
@@ -341,7 +338,7 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
}
else {
/* find the closest visible node */
- node = node_under_mouse_select(snode->edittree, mx, my);
+ node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]);
if (node) {
if ((node->flag & SELECT) && (node->flag & NODE_ACTIVE) == 0) {
@@ -362,7 +359,7 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
else { /* extend == 0 */
/* find the closest visible node */
- node = node_under_mouse_select(snode->edittree, mx, my);
+ node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]);
if (node) {
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index 9e6e1e628f6..e47a1315663 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -327,6 +327,60 @@ void NODE_OT_backimage_zoom(wmOperatorType *ot)
RNA_def_float(ot->srna, "factor", 1.2f, 0.0f, 10.0f, "Factor", "", 0.0f, 10.0f);
}
+static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ Image *ima;
+ ImBuf *ibuf;
+
+ const float pad = 32.0f;
+
+ void *lock;
+
+ float facx, facy;
+
+ ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+
+ if (ibuf == NULL) {
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ return OPERATOR_CANCELLED;
+ }
+
+ facx = 1.0f * (ar->sizex - pad) / (ibuf->x * snode->zoom);
+ facy = 1.0f * (ar->sizey - pad) / (ibuf->y * snode->zoom);
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+
+ snode->zoom *= min_ff(facx, facy);
+
+ snode->xof = 0;
+ snode->yof = 0;
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_backimage_fit(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name = "Background Image Fit";
+ ot->idname = "NODE_OT_backimage_fit";
+ ot->description = "Zoom in/out the background image";
+
+ /* api callbacks */
+ ot->exec = backimage_fit_exec;
+ ot->poll = composite_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
+
+}
+
/******************** sample backdrop operator ********************/
typedef struct ImageSampleInfo {
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index 922912fa540..a59b2fc21df 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -602,8 +602,14 @@ static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
/* convert mouse coordinates to v2d space */
UI_view2d_region_to_view(&ar->v2d, win->eventstate->x - ar->winrct.xmin, win->eventstate->y - ar->winrct.ymin,
&snode->cursor[0], &snode->cursor[1]);
+
+ /* here snode->cursor is used to detect the node edge for sizing */
+ node_set_cursor(win, snode, snode->cursor);
- node_set_cursor(win, snode);
+ /* XXX snode->cursor is in placing new nodes space */
+ snode->cursor[0] /= UI_DPI_FAC;
+ snode->cursor[1] /= UI_DPI_FAC;
+
}
/* Initialize main area, setting handlers. */
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 44d5672e7da..6200b98350f 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1389,6 +1389,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
tselem_draw_icon_uibut(&arg, ICON_GROUP); break;
case ID_LI:
tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT); break;
+ case ID_LS:
+ tselem_draw_icon_uibut(&arg, ICON_BRUSH_DATA); break; /* FIXME proper icon */
}
}
}
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 1e9b681197c..2de8f52d677 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -1469,7 +1469,7 @@ static int parent_drop_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "child", childname);
ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
- ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE, FALSE);
+ ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, false, false, NULL);
DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
@@ -1525,7 +1525,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) {
- if (ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE, FALSE)) {
+ if (ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, false, false, NULL)) {
DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index c1950e62817..a0af9340fe2 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -57,6 +57,7 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_sequencer.h"
+#include "BKE_treehash.h"
#include "ED_armature.h"
#include "ED_object.h"
@@ -113,7 +114,7 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
case ID_LA: case ID_AR: case ID_CA: case ID_SPK:
case ID_MA: case ID_TE: case ID_IP: case ID_IM:
case ID_SO: case ID_KE: case ID_WO: case ID_AC:
- case ID_NLA: case ID_TXT: case ID_GR:
+ case ID_NLA: case ID_TXT: case ID_GR: case ID_LS:
if (*idlevel == 0) *idlevel = idcode;
else if (*idlevel != idcode) *idlevel = -1;
break;
@@ -299,17 +300,13 @@ static void object_delete_cb(bContext *C, Scene *scene, TreeElement *te,
if (base == NULL)
base = BKE_scene_base_find(scene, (Object *)tselem->id);
if (base) {
- SpaceOops *soops = CTX_wm_space_outliner(C);
-
// check also library later
if (scene->obedit == base->object)
ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
ED_base_object_free_and_unlink(CTX_data_main(C), scene, base);
te->directdata = NULL;
- BLI_ghash_remove(soops->treehash, tselem, NULL, NULL);
tselem->id = NULL;
- BLI_ghash_insert(soops->treehash, tselem, tselem);
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 404821900df..b86fba1398a 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -32,15 +32,6 @@
#include <math.h>
#include <string.h>
-#if defined WIN32 && !defined _LIBC || defined __sun
-# include "BLI_fnmatch.h" /* use fnmatch included in blenlib */
-#else
-# ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-# endif
-# include <fnmatch.h>
-#endif
-
#include "MEM_guardedalloc.h"
#include "DNA_anim_types.h"
@@ -59,12 +50,14 @@
#include "DNA_sequence_types.h"
#include "DNA_speaker_types.h"
#include "DNA_object_types.h"
+#include "DNA_linestyle_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_ghash.h"
#include "BLI_mempool.h"
+#include "BLI_fnmatch.h"
#include "BLF_translation.h"
@@ -74,6 +67,7 @@
#include "BKE_modifier.h"
#include "BKE_sequencer.h"
#include "BKE_idcode.h"
+#include "BKE_treehash.h"
#include "ED_armature.h"
#include "ED_screen.h"
@@ -116,9 +110,8 @@ static void outliner_storage_cleanup(SpaceOops *soops)
if (BLI_mempool_count(ts) == unused) {
BLI_mempool_destroy(ts);
soops->treestore = NULL;
-
if (soops->treehash) {
- BLI_ghash_free(soops->treehash, NULL, NULL);
+ BKE_treehash_free(soops->treehash);
soops->treehash = NULL;
}
}
@@ -135,14 +128,9 @@ static void outliner_storage_cleanup(SpaceOops *soops)
}
BLI_mempool_destroy(ts);
soops->treestore = new_ts;
-
if (soops->treehash) {
/* update hash table to fix broken pointers */
- BLI_ghash_clear(soops->treehash, NULL, NULL);
- BLI_mempool_iternew(soops->treestore, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- BLI_ghash_insert(soops->treehash, tselem, tselem);
- }
+ BKE_treehash_rebuild_from_treestore(soops->treehash, soops->treestore);
}
}
}
@@ -150,63 +138,22 @@ static void outliner_storage_cleanup(SpaceOops *soops)
}
}
-/* This function hashes only by type, nr and id, while cmp function also compares 'used' flag;
- * This is done to skip full treehash rebuild in outliner_storage_cleanup */
-static unsigned int tse_hash(const void *ptr)
-{
- const TreeStoreElem *tse = (const TreeStoreElem *)ptr;
- unsigned int hash;
- BLI_assert(tse->type || !tse->nr);
- hash = BLI_ghashutil_inthash(SET_INT_IN_POINTER((tse->nr << 16) + tse->type));
- hash ^= BLI_ghashutil_inthash(tse->id);
- return hash;
-}
-
-static int tse_cmp(const void *a, const void *b)
-{
- const TreeStoreElem *tse_a = (const TreeStoreElem *)a;
- const TreeStoreElem *tse_b = (const TreeStoreElem *)b;
- return tse_a->type != tse_b->type || tse_a->nr != tse_b->nr ||
- tse_a->id != tse_b->id || tse_a->used != tse_b->used;
-}
-
-static TreeStoreElem *lookup_treehash(GHash *th, short type, short nr, short used, ID *id)
-{
- TreeStoreElem tse_template;
- tse_template.type = type;
- tse_template.nr = type ? nr : 0; // we're picky! :)
- tse_template.id = id;
- tse_template.used = used;
- return BLI_ghash_lookup(th, &tse_template);
-}
-
static void check_persistent(SpaceOops *soops, TreeElement *te, ID *id, short type, short nr)
{
- /* When treestore comes directly from readfile.c, treehash is empty;
- * In this case we don't want to get TSE_CLOSED while adding elements one by one,
- * that is why this function restores treehash */
- bool restore_treehash = (soops->treestore && !soops->treehash);
TreeStoreElem *tselem;
if (soops->treestore == NULL) {
/* if treestore was not created in readfile.c, create it here */
soops->treestore = BLI_mempool_create(sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER);
+
}
if (soops->treehash == NULL) {
- soops->treehash = BLI_ghash_new(tse_hash, tse_cmp, "treehash");
- BLI_ghash_flag_set(soops->treehash, GHASH_FLAG_ALLOW_DUPES);
- }
-
- if (restore_treehash) {
- BLI_mempool_iter iter;
- BLI_mempool_iternew(soops->treestore, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- BLI_ghash_insert(soops->treehash, tselem, tselem);
- }
+ soops->treehash = BKE_treehash_create_from_treestore(soops->treestore);
}
- /* check for unused tree elements is in treestore */
- tselem = lookup_treehash(soops->treehash, type, nr, 0, id);
+ /* find any unused tree element in treestore and mark it as used
+ * (note that there may be multiple unused elements in case of linked objects) */
+ tselem = BKE_treehash_lookup_unused(soops->treehash, type, nr, id);
if (tselem) {
te->store_elem = tselem;
tselem->used = 1;
@@ -221,7 +168,7 @@ static void check_persistent(SpaceOops *soops, TreeElement *te, ID *id, short ty
tselem->used = 0;
tselem->flag = TSE_CLOSED;
te->store_elem = tselem;
- BLI_ghash_insert(soops->treehash, tselem, tselem);
+ BKE_treehash_add_element(soops->treehash, tselem);
}
/* ********************************************************* */
@@ -266,7 +213,7 @@ TreeElement *outliner_find_tse(SpaceOops *soops, TreeStoreElem *tse)
if (tse->id == NULL) return NULL;
/* check if 'tse' is in treestore */
- tselem = lookup_treehash(soops->treehash, tse->type, tse->nr, tse->used, tse->id);
+ tselem = BKE_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id);
if (tselem)
return outliner_find_tree_element(&soops->tree, tselem);
@@ -430,6 +377,28 @@ static bool outliner_animdata_test(AnimData *adt)
return false;
}
+static void outliner_add_line_styles(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te)
+{
+ SceneRenderLayer *srl;
+ FreestyleLineSet *lineset;
+
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ lineset->linestyle->id.flag |= LIB_DOIT;
+ }
+ }
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ FreestyleLineStyle *linestyle = lineset->linestyle;
+
+ if (!(linestyle->id.flag & LIB_DOIT))
+ continue;
+ linestyle->id.flag &= ~LIB_DOIT;
+ outliner_add_element(soops, lb, linestyle, te, 0, 0);
+ }
+ }
+}
+
static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te)
{
SceneRenderLayer *srl;
@@ -455,6 +424,8 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s
outliner_add_element(soops, lb, sce, te, TSE_ANIM_DATA, 0);
outliner_add_element(soops, lb, sce->world, te, 0, 0);
+
+ outliner_add_line_styles(soops, lb, sce, te);
}
// can be inlined if necessary
@@ -813,6 +784,14 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
}
break;
}
+ case ID_LS:
+ {
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)id;
+
+ if (outliner_animdata_test(linestyle->adt))
+ outliner_add_element(soops, &te->subtree, linestyle, te, TSE_ANIM_DATA, 0);
+ break;
+ }
}
}
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 874852ee320..d695ffa46d5 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -43,6 +43,7 @@
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_scene.h"
+#include "BKE_treehash.h"
#include "ED_space_api.h"
#include "ED_screen.h"
@@ -435,7 +436,7 @@ static void outliner_free(SpaceLink *sl)
BLI_mempool_destroy(soutliner->treestore);
}
if (soutliner->treehash) {
- BLI_ghash_free(soutliner->treehash, NULL, NULL);
+ BKE_treehash_free(soutliner->treehash);
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 68fd09f5fb7..ebec818bb36 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -1086,10 +1086,10 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
type = GL_FLOAT;
if (ibuf->float_colorspace) {
- glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->float_colorspace, TRUE);
+ glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->float_colorspace, true);
}
else {
- glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, TRUE);
+ glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, true);
}
}
else if (ibuf->rect) {
@@ -1097,7 +1097,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
format = GL_RGBA;
type = GL_UNSIGNED_BYTE;
- glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, FALSE);
+ glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, false);
}
else {
format = GL_RGBA;
diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c
index 68428cd890f..18733d4e409 100644
--- a/source/blender/editors/space_sequencer/sequencer_view.c
+++ b/source/blender/editors/space_sequencer/sequencer_view.c
@@ -152,7 +152,8 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
info->colfp = info->colf;
/* sequencer's image buffers are in non-linear space, need to make them linear */
- BKE_sequencer_pixel_from_sequencer_space_v4(scene, info->colf);
+ copy_v4_v4(info->linearcol, info->colf);
+ BKE_sequencer_pixel_from_sequencer_space_v4(scene, info->linearcol);
info->color_manage = TRUE;
}
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 04b2a21bf79..84c6329db53 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -491,6 +491,7 @@ static void sequencer_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
case ND_MARKERS:
case ND_RENDER_OPTIONS: /* for FPS and FPS Base */
case ND_SEQUENCER:
+ case ND_RENDER_RESULT:
ED_region_tag_redraw(ar);
break;
}
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 95fd7fce878..e92cab72042 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -1133,23 +1133,23 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc);
- y1 = ar->winy - 2 - (vsell - offl) * lheight;
- y2 = y1 - (lheight * visible_lines + TXT_LINE_SPACING);
+ y1 = ar->winy - (vsell - offl) * lheight;
+ y2 = y1 - (lheight * visible_lines);
}
else {
- y1 = ar->winy - 2 - vsell * lheight;
- y2 = y1 - (lheight + TXT_LINE_SPACING);
+ y1 = ar->winy - vsell * lheight;
+ y2 = y1 - (lheight);
}
if (!(y1 < 0 || y2 > ar->winy)) { /* check we need to draw */
- x1 = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ x1 = 0; // st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
x2 = x1 + ar->winx;
glColor4ub(255, 255, 255, 32);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
- glRecti(x1 - 4, y1, x2, y2 + TXT_LINE_SPACING);
+ glRecti(x1 - 4, y1, x2, y2);
glDisable(GL_BLEND);
}
}
@@ -1317,15 +1317,13 @@ void draw_text_main(SpaceText *st, ARegion *ar)
int wraplinecount = 0, wrap_skip = 0;
int margin_column_x;
- /* dpi controlled line height and font size */
- st->lheight_dpi = (U.widget_unit * st->lheight) / 20;
-
- if (st->lheight_dpi) st->viewlines = (int)ar->winy / (st->lheight_dpi + TXT_LINE_SPACING);
- else st->viewlines = 0;
-
/* if no text, nothing to do */
if (!text)
return;
+
+ /* dpi controlled line height and font size */
+ st->lheight_dpi = (U.widget_unit * st->lheight) / 20;
+ st->viewlines = (st->lheight_dpi) ? (int)ar->winy / (st->lheight_dpi + TXT_LINE_SPACING) : 0;
text_update_drawcache(st, ar);
diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h
index 371ccfd9bd9..b4c2062ab00 100644
--- a/source/blender/editors/space_text/text_intern.h
+++ b/source/blender/editors/space_text/text_intern.h
@@ -54,10 +54,10 @@ void text_scroll_to_cursor(struct SpaceText *st, struct ScrArea *sa);
void text_update_cursor_moved(struct bContext *C);
/* TXT_OFFSET used to be 35 when the scrollbar was on the left... */
-#define TXT_OFFSET ((int)(0.75f * U.widget_unit))
+#define TXT_OFFSET ((int)(0.2f * U.widget_unit))
#define TXT_SCROLL_WIDTH U.widget_unit
#define TXT_SCROLL_SPACE ((int)(0.1f * U.widget_unit))
-#define TXT_LINE_SPACING ((int)(0.2f * U.widget_unit)) /* space between lines */
+#define TXT_LINE_SPACING ((int)(0.3f * st->lheight_dpi)) /* space between lines */
#define TEXTXLOC (st->cwidth * st->linenrs_tot)
#define SUGG_LIST_SIZE 7
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index dec61a0e1ca..2c2a8b255da 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -949,7 +949,7 @@ static int text_indent_exec(bContext *C, wmOperator *UNUSED(op))
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
if (txt_has_sel(text)) {
- txt_order_cursors(text);
+ txt_order_cursors(text, false);
txt_indent(text);
}
else
@@ -983,7 +983,7 @@ static int text_unindent_exec(bContext *C, wmOperator *UNUSED(op))
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- txt_order_cursors(text);
+ txt_order_cursors(text, false);
txt_unindent(text);
text_update_edited(text);
@@ -1063,7 +1063,7 @@ static int text_comment_exec(bContext *C, wmOperator *UNUSED(op))
if (txt_has_sel(text)) {
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- txt_order_cursors(text);
+ txt_order_cursors(text, false);
txt_comment(text);
text_update_edited(text);
@@ -1096,7 +1096,7 @@ static int text_uncomment_exec(bContext *C, wmOperator *UNUSED(op))
if (txt_has_sel(text)) {
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- txt_order_cursors(text);
+ txt_order_cursors(text, false);
txt_uncomment(text);
text_update_edited(text);
@@ -1861,11 +1861,23 @@ static int text_move_cursor(bContext *C, int type, int select)
break;
case PREV_CHAR:
- txt_move_left(text, select);
+ if (txt_has_sel(text) && !select) {
+ txt_order_cursors(text, false);
+ txt_pop_sel(text);
+ }
+ else {
+ txt_move_left(text, select);
+ }
break;
case NEXT_CHAR:
- txt_move_right(text, select);
+ if (txt_has_sel(text) && !select) {
+ txt_order_cursors(text, true);
+ txt_pop_sel(text);
+ }
+ else {
+ txt_move_right(text, select);
+ }
break;
case PREV_LINE:
@@ -2086,10 +2098,17 @@ void TEXT_OT_overwrite_toggle(wmOperatorType *ot)
static void txt_screen_clamp(SpaceText *st, ARegion *ar)
{
- int last;
- last = text_get_total_lines(st, ar);
- last = last - (st->viewlines / 2);
- CLAMP(st->top, 0, last);
+ if (st->top <= 0) {
+ st->top = 0;
+ }
+ else {
+ int last;
+ last = text_get_total_lines(st, ar);
+ last = last - (st->viewlines / 2);
+ if (last > 0 && st->top > last) {
+ st->top = last;
+ }
+ }
}
/* Moves the view vertically by the specified number of lines */
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index d3d8868520d..6961ada462d 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -34,7 +34,6 @@
#include <string.h>
#include <math.h>
-
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
@@ -1099,12 +1098,14 @@ static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, float xwidth,
if ((segments > 1) && (pchan)) {
float dlen = length / (float)segments;
- Mat4 *bbone = b_bone_spline_setup(pchan, 0);
+ Mat4 bbone[MAX_BBONE_SUBDIV];
int a;
-
- for (a = 0; a < segments; a++, bbone++) {
+
+ b_bone_spline_setup(pchan, 0, bbone);
+
+ for (a = 0; a < segments; a++) {
glPushMatrix();
- glMultMatrixf(bbone->mat);
+ glMultMatrixf(bbone[a].mat);
if (dt == OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth);
else drawcube_size(xwidth, dlen, zwidth);
glPopMatrix();
@@ -1235,6 +1236,7 @@ static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float len
static void draw_wire_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id,
bPoseChannel *pchan, EditBone *ebone)
{
+ Mat4 bbones_array[MAX_BBONE_SUBDIV];
Mat4 *bbones = NULL;
int segments = 0;
float length;
@@ -1243,8 +1245,10 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons
segments = pchan->bone->segments;
length = pchan->bone->length;
- if (segments > 1)
- bbones = b_bone_spline_setup(pchan, 0);
+ if (segments > 1) {
+ b_bone_spline_setup(pchan, 0, bbones_array);
+ bbones = bbones_array;
+ }
}
else
length = ebone->length;
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 62e3f8471a3..ac216907c7f 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -1900,9 +1900,9 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
const bool is_edit = (lt->editlatt != NULL);
/* now we default make displist, this will modifiers work for non animated case */
- if (ob->disp.first == NULL)
+ if (ELEM(NULL, ob->curve_cache, ob->curve_cache->disp.first))
BKE_lattice_modifiers_calc(scene, ob);
- dl = BKE_displist_find(&ob->disp, DL_VERTS);
+ dl = BKE_displist_find(&ob->curve_cache->disp, DL_VERTS);
if (is_edit) {
lt = lt->editlatt->latt;
@@ -3094,9 +3094,6 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
BMVert *eve_act = NULL;
bool use_occlude_wire = (v3d->flag2 & V3D_OCCLUDE_WIRE) && (dt > OB_WIRE);
- // BLI_assert(!cageDM || !(cageDM->dirty & DM_DIRTY_NORMALS));
- BLI_assert(!finalDM || !(finalDM->dirty & DM_DIRTY_NORMALS));
-
if (em->bm->selected.last) {
BMEditSelection *ese = em->bm->selected.last;
/* face is handeled above */
@@ -3369,8 +3366,6 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
if (!dm)
return;
- if (dm) BLI_assert(!(dm->dirty & DM_DIRTY_NORMALS));
-
/* Check to draw dynamic paint colors (or weights from WeightVG modifiers).
* Note: Last "preview-active" modifier in stack will win! */
if (DM_get_tessface_data_layer(dm, CD_PREVIEW_MCOL) && modifiers_isPreview(ob))
@@ -3971,7 +3966,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
case OB_CURVE:
cu = ob->data;
- lb = &ob->disp;
+ lb = &ob->curve_cache->disp;
if (solid) {
dl = lb->first;
@@ -4021,7 +4016,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
break;
case OB_SURF:
- lb = &ob->disp;
+ lb = &ob->curve_cache->disp;
if (solid) {
dl = lb->first;
@@ -4049,8 +4044,11 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
case OB_MBALL:
if (BKE_mball_is_basis(ob)) {
- lb = &ob->disp;
- if (lb->first == NULL) BKE_displist_make_mball(scene, ob);
+ lb = ob->curve_cache ? &ob->curve_cache->disp : NULL;
+ if (ELEM(lb, lb->first, NULL)) {
+ BKE_displist_make_mball(scene, ob);
+ lb = &ob->curve_cache->disp;
+ }
if (lb->first == NULL) {
return true;
}
@@ -4566,7 +4564,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
pdd->ma_col = ma_col;
}
- psys->lattice = psys_get_lattice(&sim);
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
/* circles don't use drawdata, so have to add a special case here */
if ((pdd || draw_as == PART_DRAW_CIRC) && draw_as != PART_DRAW_PATH) {
@@ -4892,9 +4890,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED;
}
- if (psys->lattice) {
- end_latt_deform(psys->lattice);
- psys->lattice = NULL;
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
}
if (pdd) {
@@ -5642,7 +5640,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
if ((cu->flag & CU_3D) && (ts->normalsize > 0.0015f) && (cu->drawflag & CU_HIDE_NORMALS) == 0) {
UI_ThemeColor(TH_WIRE_EDIT);
- for (bl = cu->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) {
+ for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) {
BevPoint *bevp = (BevPoint *)(bl + 1);
int nr = bl->nr;
int skip = nu->resolu / 16;
@@ -6065,7 +6063,7 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
}
else if (pd->forcefield == PFIELD_GUIDE && ob->type == OB_CURVE) {
Curve *cu = ob->data;
- if ((cu->flag & CU_PATH) && cu->path && cu->path->data) {
+ if ((cu->flag & CU_PATH) && ob->curve_cache->path && ob->curve_cache->path->data) {
float mindist, guidevec1[4], guidevec2[3];
//if (has_ipo_code(ob->ipo, OB_PD_FSTR))
@@ -6248,7 +6246,7 @@ static void draw_bounding_volume(Scene *scene, Object *ob, char type)
bb = BKE_mesh_boundbox_get(ob);
}
else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- bb = ob->bb ? ob->bb : ( (Curve *)ob->data)->bb;
+ bb = BKE_curve_boundbox_get(ob);
}
else if (ob->type == OB_MBALL) {
if (BKE_mball_is_basis(ob)) {
@@ -6283,9 +6281,7 @@ static void drawtexspace(Object *ob)
BKE_mesh_texspace_get(ob->data, loc, NULL, size);
}
else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- Curve *cu = ob->data;
- copy_v3_v3(size, cu->size);
- copy_v3_v3(loc, cu->loc);
+ BKE_curve_texspace_get(ob->data, loc, NULL, size);
}
else if (ob->type == OB_MBALL) {
MetaBall *mb = ob->data;
@@ -6323,7 +6319,6 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
glDepthMask(0);
if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
- Curve *cu = ob->data;
DerivedMesh *dm = ob->derivedFinal;
bool has_faces = false;
@@ -6331,16 +6326,16 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
has_faces = dm->getNumTessFaces(dm);
}
else {
- has_faces = BKE_displist_has_faces(&ob->disp);
+ has_faces = BKE_displist_has_faces(&ob->curve_cache->disp);
}
- if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+ if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
draw_index_wire = false;
if (dm) {
draw_mesh_object_outline(v3d, ob, dm);
}
else {
- drawDispListwire(&ob->disp);
+ drawDispListwire(&ob->curve_cache->disp);
}
draw_index_wire = true;
}
@@ -6348,7 +6343,7 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
else if (ob->type == OB_MBALL) {
if (BKE_mball_is_basis(ob)) {
if ((base->flag & OB_FROMDUPLI) == 0)
- drawDispListwire(&ob->disp);
+ drawDispListwire(&ob->curve_cache->disp);
}
}
else if (ob->type == OB_ARMATURE) {
@@ -6375,8 +6370,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
- Curve *cu = ob->data;
- if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+ if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
if (ob->type == OB_CURVE)
draw_index_wire = false;
@@ -6384,7 +6378,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
drawCurveDMWired(ob);
}
else {
- drawDispListwire(&ob->disp);
+ drawDispListwire(&ob->curve_cache->disp);
}
if (ob->type == OB_CURVE)
@@ -6393,7 +6387,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
}
else if (ob->type == OB_MBALL) {
if (BKE_mball_is_basis(ob)) {
- drawDispListwire(&ob->disp);
+ drawDispListwire(&ob->curve_cache->disp);
}
}
@@ -6662,23 +6656,17 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* faceselect exception: also draw solid when (dt == wire), except in editmode */
if (is_obact && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
- if (ob->type == OB_MESH) {
-
- if (ob->mode & OB_MODE_EDIT) {
- /* pass */
+ if (ob->type == OB_MESH) {
+ if (dt < OB_SOLID) {
+ zbufoff = 1;
+ dt = OB_SOLID;
}
- else {
- if (dt < OB_SOLID) {
- zbufoff = 1;
- dt = OB_SOLID;
- }
-
- if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
- dt = OB_PAINT;
- }
- glEnable(GL_DEPTH_TEST);
+ if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
+ dt = OB_PAINT;
}
+
+ glEnable(GL_DEPTH_TEST);
}
else {
if (dt < OB_SOLID) {
@@ -6703,7 +6691,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* bad exception, solve this! otherwise outline shows too late */
if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
/* still needed for curves hidden in other layers. depgraph doesnt handle that yet */
- if (ob->disp.first == NULL) BKE_displist_make_curveTypes(scene, ob, 0);
+ if (ELEM(NULL, ob->curve_cache, ob->curve_cache->disp.first)) {
+ BKE_displist_make_curveTypes(scene, ob, 0);
+ }
}
/* draw outline for selected objects, mesh does itself */
@@ -6807,7 +6797,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
draw_bounding_volume(scene, ob, ob->boundtype);
}
}
- else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+ else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
}
@@ -6825,7 +6815,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
draw_bounding_volume(scene, ob, ob->boundtype);
}
}
- else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+ else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
//XXX old animsys if (cu->path)
@@ -7050,6 +7040,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
// get view vector
copy_v3_v3(viewnormal, rv3d->viewinv[2]);
+ invert_m4_m4(ob->imat, ob->obmat);
mul_mat3_m4_v3(ob->imat, viewnormal);
normalize_v3(viewnormal);
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 542ed7af0e6..a7940faa47d 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -83,6 +83,7 @@ struct GPUTexture;
#ifdef DEBUG_DRAW_TIME
# include "PIL_time.h"
+# include "PIL_time_utildefines.h"
#endif
static int intersect_edges(float *points, float a, float b, float c, float d, float edges[12][2][3])
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index bae2134591a..4ebd9706ac9 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -220,10 +220,10 @@ void ED_view3d_clipping_enable(void)
static bool view3d_clipping_test(const float co[3], float clip[6][4])
{
- if (0.0f < clip[0][3] + dot_v3v3(co, clip[0]))
- if (0.0f < clip[1][3] + dot_v3v3(co, clip[1]))
- if (0.0f < clip[2][3] + dot_v3v3(co, clip[2]))
- if (0.0f < clip[3][3] + dot_v3v3(co, clip[3]))
+ if (plane_point_side_v3(clip[0], co) > 0.0f)
+ if (plane_point_side_v3(clip[1], co) > 0.0f)
+ if (plane_point_side_v3(clip[2], co) > 0.0f)
+ if (plane_point_side_v3(clip[3], co) > 0.0f)
return false;
return true;
@@ -2073,7 +2073,7 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
bb = *bb_tmp; /* must make a copy */
/* disable boundbox check for list creation */
- BKE_object_boundbox_flag(dob->ob, OB_BB_DISABLED, 1);
+ BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 1);
/* need this for next part of code */
unit_m4(dob->ob->obmat); /* obmat gets restored */
@@ -2083,7 +2083,7 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
glEndList();
use_displist = true;
- BKE_object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0);
+ BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 0);
}
}
if (use_displist) {
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 7b8c197f3e6..f78d8981400 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -3533,6 +3533,189 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit");
}
+
+/* ************************ viewroll ******************************** */
+
+static void view_roll_angle(ARegion *ar, float quat[4], const float orig_quat[4], const float dvec[3], float angle)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ float quat_mul[4];
+
+ /* camera axis */
+ axis_angle_to_quat(quat_mul, dvec, angle);
+
+ mul_qt_qtqt(quat, orig_quat, quat_mul);
+ rv3d->view = RV3D_VIEW_USER;
+}
+
+static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y))
+{
+ float angle = 0.0;
+
+ {
+ float len1, len2, tot;
+
+ tot = vod->ar->winrct.xmax - vod->ar->winrct.xmin;
+ len1 = (vod->ar->winrct.xmax - x) / tot;
+ len2 = (vod->ar->winrct.xmax - vod->origx) / tot;
+ angle = (len1 - len2) * (float)M_PI * 4.0f;
+ }
+
+ if (angle != 0.0f)
+ view_roll_angle(vod->ar, vod->rv3d->viewquat, vod->oldquat, vod->mousevec, angle);
+
+ if (vod->rv3d->viewlock & RV3D_BOXVIEW)
+ view3d_boxview_sync(vod->sa, vod->ar);
+
+ ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
+
+ ED_region_tag_redraw(vod->ar);
+}
+
+static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ViewOpsData *vod = op->customdata;
+ short event_code = VIEW_PASS;
+
+ /* execute the events */
+ if (event->type == MOUSEMOVE) {
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case VIEW_MODAL_CONFIRM:
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_MOVE:
+ WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_ROTATE:
+ WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ }
+ }
+ else if (event->type == vod->origkey && event->val == KM_RELEASE) {
+ event_code = VIEW_CONFIRM;
+ }
+
+ if (event_code == VIEW_APPLY) {
+ viewroll_apply(vod, event->x, event->y);
+ }
+ else if (event_code == VIEW_CONFIRM) {
+ ED_view3d_depth_tag_update(vod->rv3d);
+ viewops_data_free(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int viewroll_exec(bContext *C, wmOperator *op)
+{
+ View3D *v3d;
+ RegionView3D *rv3d;
+ ARegion *ar;
+ float mousevec[3];
+
+ if (op->customdata) {
+ ViewOpsData *vod = op->customdata;
+ ar = vod->ar;
+ v3d = vod->v3d;
+ }
+ else {
+ ar = CTX_wm_region(C);
+ v3d = CTX_wm_view3d(C);
+ }
+
+ negate_v3_v3(mousevec, ((RegionView3D *)ar->regiondata)->viewinv[2]);
+ normalize_v3(mousevec);
+
+ rv3d = ar->regiondata;
+ if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
+ const float angle = RNA_float_get(op->ptr, "angle");
+ float mousevec[3];
+ float quat_new[4];
+
+ normalize_v3_v3(mousevec, rv3d->viewinv[2]);
+ negate_v3(mousevec);
+ view_roll_angle(ar, quat_new, rv3d->viewquat, mousevec, angle);
+
+ view3d_smooth_view(C, v3d, ar, NULL, NULL, NULL, quat_new, NULL, NULL);
+
+ viewops_data_free(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ viewops_data_free(C, op);
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ViewOpsData *vod;
+
+ /* makes op->customdata */
+ viewops_data_create(C, op, event);
+ vod = op->customdata;
+
+ if (RNA_struct_property_is_set(op->ptr, "angle")) {
+ viewroll_exec(C, op);
+ }
+ else {
+ /* overwrite the mouse vector with the view direction */
+ normalize_v3_v3(vod->mousevec, vod->rv3d->viewinv[2]);
+ negate_v3(vod->mousevec);
+
+ if (event->type == MOUSEROTATE) {
+ vod->origx = vod->oldx = event->x;
+ viewroll_apply(vod, event->prevx, event->prevy);
+ ED_view3d_depth_tag_update(vod->rv3d);
+
+ viewops_data_free(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+ return OPERATOR_FINISHED;
+}
+
+static int viewroll_cancel(bContext *C, wmOperator *op)
+{
+ viewops_data_free(C, op);
+
+ return OPERATOR_CANCELLED;
+}
+
+void VIEW3D_OT_view_roll(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "View Roll";
+ ot->description = "Roll the view";
+ ot->idname = "VIEW3D_OT_view_roll";
+
+ /* api callbacks */
+ ot->invoke = viewroll_invoke;
+ ot->exec = viewroll_exec;
+ ot->modal = viewroll_modal;
+ ot->poll = ED_operator_rv3d_user_region_poll;
+ ot->cancel = viewroll_cancel;
+
+ /* flags */
+ ot->flag = 0;
+
+ /* properties */
+ ot->prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
+}
+
static EnumPropertyItem prop_view_pan_items[] = {
{V3D_VIEW_PANLEFT, "PANLEFT", 0, "Pan Left", "Pan the view to the Left"},
{V3D_VIEW_PANRIGHT, "PANRIGHT", 0, "Pan Right", "Pan the view to the Right"},
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index a1a13130b27..9341ea9d3e6 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -159,6 +159,11 @@ void fly_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_UP);
WM_modalkeymap_add_item(keymap, FKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_DOWN);
+ WM_modalkeymap_add_item(keymap, UPARROWKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_FORWARD);
+ WM_modalkeymap_add_item(keymap, DOWNARROWKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_BACKWARD);
+ WM_modalkeymap_add_item(keymap, LEFTARROWKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_LEFT);
+ WM_modalkeymap_add_item(keymap, RIGHTARROWKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_RIGHT);
+
WM_modalkeymap_add_item(keymap, XKEY, KM_PRESS, 0, 0, FLY_MODAL_AXIS_LOCK_X);
WM_modalkeymap_add_item(keymap, ZKEY, KM_PRESS, 0, 0, FLY_MODAL_AXIS_LOCK_Z);
@@ -580,6 +585,12 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event)
double time_currwheel;
float time_wheel;
+ /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */
+ if (fly->axis == -1) {
+ fly->axis = 2;
+ fly->speed = fabsf(fly->speed);
+ }
+
time_currwheel = PIL_check_seconds_timer();
time_wheel = (float)(time_currwheel - fly->time_lastwheel);
fly->time_lastwheel = time_currwheel;
@@ -599,6 +610,12 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event)
double time_currwheel;
float time_wheel;
+ /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */
+ if (fly->axis == -1) {
+ fly->axis = 2;
+ fly->speed = -fabsf(fly->speed);
+ }
+
time_currwheel = PIL_check_seconds_timer();
time_wheel = (float)(time_currwheel - fly->time_lastwheel);
fly->time_lastwheel = time_currwheel;
@@ -806,9 +823,10 @@ static void flyMoveCamera(bContext *C, RegionView3D *rv3d, FlyInfo *fly,
static int flyApply(bContext *C, FlyInfo *fly)
{
-#define FLY_ROTATE_FAC 2.5f /* more is faster */
+#define FLY_ROTATE_FAC 10.0f /* more is faster */
#define FLY_ZUP_CORRECT_FAC 0.1f /* amount to correct per step */
#define FLY_ZUP_CORRECT_ACCEL 0.05f /* increase upright momentum each step */
+#define FLY_SMOOTH_FAC 20.0f /* higher value less lag */
/* fly mode - Shift+F
* a fly loop where the user can move move the view as if they are flying
@@ -1052,7 +1070,7 @@ static int flyApply(bContext *C, FlyInfo *fly)
}
/* impose a directional lag */
- interp_v3_v3v3(dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * 5.0f))));
+ interp_v3_v3v3(dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * FLY_SMOOTH_FAC))));
if (rv3d->persp == RV3D_CAMOB) {
Object *lock_ob = fly->root_parent ? fly->root_parent : fly->v3d->camera;
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 085af4e5c18..54999b1ae95 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -95,6 +95,7 @@ void VIEW3D_OT_view_persportho(struct wmOperatorType *ot);
void VIEW3D_OT_background_image_add(struct wmOperatorType *ot);
void VIEW3D_OT_background_image_remove(struct wmOperatorType *ot);
void VIEW3D_OT_view_orbit(struct wmOperatorType *ot);
+void VIEW3D_OT_view_roll(struct wmOperatorType *ot);
void VIEW3D_OT_clip_border(struct wmOperatorType *ot);
void VIEW3D_OT_cursor3d(struct wmOperatorType *ot);
void VIEW3D_OT_manipulator(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index d13ab15d837..2023513ad92 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -368,7 +368,7 @@ void lattice_foreachScreenVert(
Object *obedit = vc->obedit;
Lattice *lt = obedit->data;
BPoint *bp = lt->editlatt->latt->def;
- DispList *dl = BKE_displist_find(&obedit->disp, DL_VERTS);
+ DispList *dl = obedit->curve_cache ? BKE_displist_find(&obedit->curve_cache->disp, DL_VERTS) : NULL;
float *co = dl ? dl->verts : NULL;
int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 6780b71c906..e7da921bba2 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -138,6 +138,7 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_view_all);
WM_operatortype_append(VIEW3D_OT_viewnumpad);
WM_operatortype_append(VIEW3D_OT_view_orbit);
+ WM_operatortype_append(VIEW3D_OT_view_roll);
WM_operatortype_append(VIEW3D_OT_view_pan);
WM_operatortype_append(VIEW3D_OT_view_persportho);
WM_operatortype_append(VIEW3D_OT_background_image_add);
@@ -283,7 +284,9 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD4, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANLEFT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD6, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANRIGHT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD8, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANUP);
-
+ RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", PAD4, KM_PRESS, KM_SHIFT, 0)->ptr, "angle", M_PI / -12);
+ RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", PAD6, KM_PRESS, KM_SHIFT, 0)->ptr, "angle", M_PI / 12);
+
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANRIGHT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANLEFT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "type", V3D_VIEW_PANUP);
@@ -294,6 +297,9 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", WHEELUPMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0)->ptr, "type", V3D_VIEW_STEPUP);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0)->ptr, "type", V3D_VIEW_STEPDOWN);
+ RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", WHEELUPMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "angle", M_PI / -12);
+ RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "angle", M_PI / 12);
+
/* active aligned, replaces '*' key in 2.4x */
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD1, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_FRONT);
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index 5e71913ea4a..28ffdea0e6c 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -405,15 +405,15 @@ void ED_view3d_win_to_3d(const ARegion *ar, const float depth_pt[3], const float
float line_end[3];
if (rv3d->is_persp) {
- float mousevec[3];
+ float mousevec[3], lambda;
copy_v3_v3(line_sta, rv3d->viewinv[3]);
ED_view3d_win_to_vector(ar, mval, mousevec);
add_v3_v3v3(line_end, line_sta, mousevec);
- if (isect_line_plane_v3(out, line_sta, line_end, depth_pt, rv3d->viewinv[2], true) == 0) {
- /* highly unlikely to ever happen, mouse vector parallel with view plane */
- zero_v3(out);
- }
+ /* note, we could use isect_line_plane_v3() however we want the intersection to be infront of the
+ * view no matter what, so apply the unsigned factor instead */
+ lambda = line_plane_factor_v3(depth_pt, rv3d->viewinv[2], line_sta, line_end);
+ interp_v3_v3v3(out, line_sta, line_end, fabsf(lambda));
}
else {
float dx = (2.0f * mval[0] / (float)ar->winx) - 1.0f;
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 44c338d22b9..0246e2b75a9 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -40,6 +40,7 @@
#include "BLI_rect.h"
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
+#include "BLI_callbacks.h"
#include "BKE_anim.h"
#include "BKE_action.h"
@@ -617,7 +618,7 @@ bool ED_view3d_boundbox_clip(RegionView3D *rv3d, float obmat[4][4], const BoundB
int a, flag = -1, fl;
if (bb == NULL) return true;
- if (bb->flag & OB_BB_DISABLED) return true;
+ if (bb->flag & BOUNDBOX_DISABLED) return true;
mul_m4_m4m4(mat, rv3d->persmat, obmat);
@@ -1433,6 +1434,7 @@ static int game_engine_exec(bContext *C, wmOperator *op)
{
#ifdef WITH_GAMEENGINE
Scene *startscene = CTX_data_scene(C);
+ Main *bmain = CTX_data_main(C);
ScrArea /* *sa, */ /* UNUSED */ *prevsa = CTX_wm_area(C);
ARegion *ar, *prevar = CTX_wm_region(C);
wmWindow *prevwin = CTX_wm_window(C);
@@ -1449,6 +1451,8 @@ static int game_engine_exec(bContext *C, wmOperator *op)
* the window manager until after this operator exits */
WM_redraw_windows(C);
+ BLI_callback_exec(bmain, &startscene->id, BLI_CB_EVT_GAME_PRE);
+
rv3d = CTX_wm_region_view3d(C);
/* sa = CTX_wm_area(C); */ /* UNUSED */
ar = CTX_wm_region(C);
@@ -1504,6 +1508,8 @@ static int game_engine_exec(bContext *C, wmOperator *op)
BKE_scene_set_background(CTX_data_main(C), startscene);
//XXX BKE_scene_update_for_newframe(bmain, scene, scene->lay);
+ BLI_callback_exec(bmain, &startscene->id, BLI_CB_EVT_GAME_POST);
+
return OPERATOR_FINISHED;
#else
(void)C; /* unused */
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 6d801b86685..82c117a7486 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1749,29 +1749,32 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
// If modal, save settings back in scene if not set as operator argument
if (t->flag & T_MODAL) {
-
/* save settings if not set in operator */
- if ((prop = RNA_struct_find_property(op->ptr, "proportional")) &&
- !RNA_property_is_set(op->ptr, prop))
- {
- if (t->obedit)
- ts->proportional = proportional;
- else if (t->options & CTX_MASK)
- ts->proportional_mask = (proportional != PROP_EDIT_OFF);
- else
- ts->proportional_objects = (proportional != PROP_EDIT_OFF);
- }
- if ((prop = RNA_struct_find_property(op->ptr, "proportional_size")) &&
- !RNA_property_is_set(op->ptr, prop))
- {
- ts->proportional_size = t->prop_size;
- }
+ /* skip saving proportional edit if it was not actually used */
+ if (!(t->options & CTX_NO_PET)) {
+ if ((prop = RNA_struct_find_property(op->ptr, "proportional")) &&
+ !RNA_property_is_set(op->ptr, prop))
+ {
+ if (t->obedit)
+ ts->proportional = proportional;
+ else if (t->options & CTX_MASK)
+ ts->proportional_mask = (proportional != PROP_EDIT_OFF);
+ else
+ ts->proportional_objects = (proportional != PROP_EDIT_OFF);
+ }
- if ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
- !RNA_property_is_set(op->ptr, prop))
- {
- ts->prop_mode = t->prop_mode;
+ if ((prop = RNA_struct_find_property(op->ptr, "proportional_size")) &&
+ !RNA_property_is_set(op->ptr, prop))
+ {
+ ts->proportional_size = t->prop_size;
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
+ !RNA_property_is_set(op->ptr, prop))
+ {
+ ts->prop_mode = t->prop_mode;
+ }
}
/* do we check for parameter? */
@@ -4825,7 +4828,7 @@ static bool bm_loop_calc_opposite_co(BMLoop *l_tmp,
float tvec[3];
if (isect_line_plane_v3(tvec,
l_iter->v->co, l_iter->next->v->co,
- l_tmp->v->co, plane_no, false))
+ l_tmp->v->co, plane_no))
{
const float fac = line_point_factor_v3(tvec, l_iter->v->co, l_iter->next->v->co);
/* allow some overlap to avoid missing the intersection because of float precision */
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 4954f861934..a0550c99988 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -350,6 +350,7 @@ typedef struct TransInfo {
struct ToolSettings *settings;
struct wmTimer *animtimer;
struct wmKeyMap *keymap; /* so we can do lookups for header text */
+ struct ReportList *reports; /* assign from the operator, or can be NULL */
int mval[2]; /* current mouse position */
float zfac; /* use for 3d view */
struct Object *obedit;
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index fd8fba91fc9..a73bf86feb1 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -727,6 +727,7 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
RegionView3D *rv3d = CTX_wm_region_view3d(C);
float tmat[4][4], imat[4][4];
float center[3];
+ int depth_test_enabled;
UI_ThemeColor(TH_GRID);
@@ -759,10 +760,17 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
glScalef(1.0f / aspx, 1.0f / aspy, 1.0);
}
+ depth_test_enabled = glIsEnabled(GL_DEPTH_TEST);
+ if (depth_test_enabled)
+ glDisable(GL_DEPTH_TEST);
+
set_inverted_drawing(1);
drawcircball(GL_LINE_LOOP, center, t->prop_size, imat);
set_inverted_drawing(0);
+ if (depth_test_enabled)
+ glEnable(GL_DEPTH_TEST);
+
glPopMatrix();
}
}
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 1849bfecc51..73c0b3c0ff4 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -275,6 +275,13 @@ static void createTransTexspace(TransInfo *t)
id = ob->data;
if (id == NULL || !ELEM3(GS(id->name), ID_ME, ID_CU, ID_MB)) {
+ BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform");
+ t->total = 0;
+ return;
+ }
+
+ if (BKE_object_obdata_is_libdata(ob)) {
+ BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
t->total = 0;
return;
}
@@ -990,8 +997,7 @@ static void createTransPose(TransInfo *t, Object *ob)
if (arm->flag & ARM_RESTPOS) {
if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE) == 0) {
- // XXX use transform operator reports
- // BKE_report(op->reports, RPT_ERROR, "Cannot select linked when sync selection is enabled");
+ BKE_report(t->reports, RPT_ERROR, "Cannot select linked when sync selection is enabled");
return;
}
}
@@ -1031,8 +1037,7 @@ static void createTransPose(TransInfo *t, Object *ob)
}
if (td != (t->data + t->total)) {
- // XXX use transform operator reports
- // BKE_report(op->reports, RPT_DEBUG, "Bone selection count error");
+ BKE_report(t->reports, RPT_DEBUG, "Bone selection count error");
}
/* initialize initial auto=ik chainlen's? */
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 4c7ac4193b3..359f6425126 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1063,6 +1063,7 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *even
t->ar = ar;
t->obedit = obedit;
t->settings = ts;
+ t->reports = op ? op->reports : NULL;
if (obedit) {
copy_m3_m4(t->obedit_mat, obedit->obmat);
@@ -1522,7 +1523,6 @@ void calculateCenterCursor2D(TransInfo *t)
if (t->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
- /* only space supported right now but may change */
if (t->options & CTX_MASK) {
ED_space_image_get_aspect(sima, &aspx, &aspy);
}
@@ -1531,17 +1531,37 @@ void calculateCenterCursor2D(TransInfo *t)
}
cursor = sima->cursor;
}
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *space_clip = (SpaceClip *) t->sa->spacedata.first;
+ if (t->options & CTX_MOVIECLIP) {
+ ED_space_clip_get_aspect_dimension_aware(space_clip, &aspx, &aspy);
+ }
+ else {
+ ED_space_clip_get_aspect(space_clip, &aspx, &aspy);
+ }
+ cursor = space_clip->cursor;
+ }
if (cursor) {
if (t->options & CTX_MASK) {
float co[2];
float frame_size[2];
- SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
- ED_space_image_get_size_fl(sima, frame_size);
-
- BKE_mask_coord_from_frame(co, cursor, frame_size);
- ED_space_image_get_aspect(sima, &aspx, &aspy);
+ if (t->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
+ ED_space_image_get_size_fl(sima, frame_size);
+ BKE_mask_coord_from_frame(co, cursor, frame_size);
+ ED_space_image_get_aspect(sima, &aspx, &aspy);
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *space_clip = (SpaceClip *) t->sa->spacedata.first;
+ ED_space_clip_get_size_fl(space_clip, frame_size);
+ BKE_mask_coord_from_frame(co, cursor, frame_size);
+ ED_space_clip_get_aspect(space_clip, &aspx, &aspy);
+ }
+ else {
+ BLI_assert(!"Shall not happen");
+ }
t->center[0] = co[0] * aspx;
t->center[1] = co[1] * aspy;
@@ -1620,7 +1640,7 @@ void calculateCenter(TransInfo *t)
calculateCenterMedian(t);
break;
case V3D_CURSOR:
- if (t->spacetype == SPACE_IMAGE)
+ if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP))
calculateCenterCursor2D(t);
else if (t->spacetype == SPACE_IPO)
calculateCenterCursorGraph2D(t);
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 909ca68cc20..86bdcbdb394 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -1147,7 +1147,7 @@ static void TargetSnapClosest(TransInfo *t)
}
}
-static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2no[3], float obmat[4][4], float timat[3][3],
+static bool snapEdge(ARegion *ar, const float v1co[3], const short v1no[3], const float v2co[3], const short v2no[3], float obmat[4][4], float timat[3][3],
const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval_fl[2],
float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth)
{
@@ -1234,7 +1234,7 @@ static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], s
return retval;
}
-static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4], float timat[3][3],
+static bool snapVertex(ARegion *ar, const float vco[3], const short vno[3], float obmat[4][4], float timat[3][3],
const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval_fl[2],
float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth)
{
@@ -1518,6 +1518,45 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
return retval;
}
+/* may extend later (for now just snaps to empty center) */
+static bool snapEmpty(short snap_mode, ARegion *ar, Object *ob, float obmat[4][4],
+ const float ray_start[3], const float ray_normal[3], const float mval[2],
+ float r_loc[3], float *UNUSED(r_no), float *r_dist_px, float *r_depth)
+{
+ float imat[4][4];
+ float ray_start_local[3], ray_normal_local[3];
+ bool retval = false;
+
+ if (ob->transflag & OB_DUPLI) {
+ return retval;
+ }
+ /* for now only vertex supported */
+ if (snap_mode != SCE_SNAP_MODE_VERTEX) {
+ return retval;
+ }
+
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(ray_start_local, ray_start);
+ copy_v3_v3(ray_normal_local, ray_normal);
+
+ mul_m4_v3(imat, ray_start_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
+
+ switch (snap_mode) {
+ case SCE_SNAP_MODE_VERTEX:
+ {
+ const float zero_co[3] = {0.0f};
+ retval |= snapVertex(ar, zero_co, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return retval;
+}
+
static bool snapObject(Scene *scene, short snap_mode, ARegion *ar, Object *ob, float obmat[4][4], bool use_obedit,
Object **r_ob, float r_obmat[4][4],
const float ray_start[3], const float ray_normal[3], const float mval[2],
@@ -1545,6 +1584,9 @@ static bool snapObject(Scene *scene, short snap_mode, ARegion *ar, Object *ob, f
else if (ob->type == OB_ARMATURE) {
retval = snapArmature(snap_mode, ar, ob, ob->data, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, r_depth);
}
+ else if (ob->type == OB_EMPTY) {
+ retval = snapEmpty(snap_mode, ar, ob, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, r_depth);
+ }
if (retval) {
if (r_ob) {
diff --git a/source/blender/editors/util/crazyspace.c b/source/blender/editors/util/crazyspace.c
index bed8aaaddf2..721a7a3b855 100644
--- a/source/blender/editors/util/crazyspace.c
+++ b/source/blender/editors/util/crazyspace.c
@@ -260,11 +260,12 @@ int editbmesh_get_first_deform_matrices(Scene *scene, Object *ob, BMEditMesh *em
int i, a, numleft = 0, numVerts = 0;
int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL;
+ VirtualModifierData virtualModifierData;
modifiers_clearErrors(ob);
dm = NULL;
- md = modifiers_getVirtualModifierList(ob);
+ md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
/* compute the deformation matrices and coordinates for the first
* modifiers with on cage editing that are enabled and support computing
@@ -314,6 +315,7 @@ int sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformma
MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
int has_multires = mmd != NULL && mmd->sculptlvl > 0;
int numleft = 0;
+ VirtualModifierData virtualModifierData;
if (has_multires) {
*deformmats = NULL;
@@ -322,7 +324,7 @@ int sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformma
}
dm = NULL;
- md = modifiers_getVirtualModifierList(ob);
+ md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
for (; md; md = md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -375,7 +377,8 @@ void crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[3][3
float (*origVerts)[3] = MEM_dupallocN(deformedVerts);
float *quats = NULL;
int i, deformed = 0;
- ModifierData *md = modifiers_getVirtualModifierList(ob);
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
Mesh *me = (Mesh *)ob->data;
for (; md; md = md->next) {
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index a873702b5b8..d20ef0e70e0 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -69,7 +69,7 @@
#define USE_EDBM_LOOPTRIS
-void draw_image_cursor(SpaceImage *sima, ARegion *ar)
+void draw_image_cursor(ARegion *ar, const float cursor[2])
{
float zoom[2], x_fac, y_fac;
@@ -80,7 +80,7 @@ void draw_image_cursor(SpaceImage *sima, ARegion *ar)
y_fac = zoom[1];
cpack(0xFFFFFF);
- glTranslatef(sima->cursor[0], sima->cursor[1], 0.0);
+ glTranslatef(cursor[0], cursor[1], 0.0);
fdrawline(-0.05f * x_fac, 0, 0, 0.05f * y_fac);
fdrawline(0, 0.05f * y_fac, 0.05f * x_fac, 0.0f);
fdrawline(0.05f * x_fac, 0.0f, 0.0f, -0.05f * y_fac);
@@ -108,7 +108,7 @@ void draw_image_cursor(SpaceImage *sima, ARegion *ar)
fdrawline(0.0f, -0.020f * y_fac, 0.0f, -0.1f * y_fac);
fdrawline(0.0f, 0.1f * y_fac, 0.0f, 0.020f * y_fac);
- glTranslatef(-sima->cursor[0], -sima->cursor[1], 0.0);
+ glTranslatef(-cursor[0], -cursor[1], 0.0);
setlinestyle(0);
}
@@ -158,7 +158,7 @@ static int draw_uvs_dm_shadow(DerivedMesh *dm)
/* draw shadow mesh - this is the mesh with the modifier applied */
if (dm && dm->drawUVEdges && CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) {
- glColor3ub(112, 112, 112);
+ UI_ThemeColor(TH_UV_SHADOW);
dm->drawUVEdges(dm);
return 1;
}
@@ -362,7 +362,7 @@ static void draw_uvs_other(Scene *scene, Object *obedit, Image *curimage)
{
Base *base;
- glColor3ub(96, 96, 96);
+ UI_ThemeColor(TH_UV_OTHERS);
for (base = scene->base.first; base; base = base->next) {
Object *ob = base->object;
@@ -404,7 +404,7 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
if (sima->flag & SI_DRAW_OTHER)
draw_uvs_other(scene, ob, curimage);
- glColor3ub(112, 112, 112);
+ UI_ThemeColor(TH_UV_SHADOW);
if (me->mtpoly) {
MPoly *mpoly = me->mpoly;
@@ -884,7 +884,7 @@ void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedi
draw_uvs_texpaint(sima, scene, obact);
if (show_uvedit && !(toolsettings->use_uv_sculpt))
- draw_image_cursor(sima, ar);
+ draw_image_cursor(ar, sima->cursor);
}
}
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 0b514e3f6fd..8c299cccbc2 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -3823,6 +3823,12 @@ static void UV_OT_reveal(wmOperatorType *ot)
/******************** set 3d cursor operator ********************/
+static int uv_set_2d_cursor_poll(bContext *C)
+{
+ return ED_operator_uvedit_space_image(C) ||
+ ED_space_image_maskedit_poll(C);
+}
+
static int uv_set_2d_cursor_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima = CTX_wm_space_image(C);
@@ -3858,7 +3864,7 @@ static void UV_OT_cursor_set(wmOperatorType *ot)
/* api callbacks */
ot->exec = uv_set_2d_cursor_exec;
ot->invoke = uv_set_2d_cursor_invoke;
- ot->poll = ED_operator_uvedit_space_image;
+ ot->poll = uv_set_2d_cursor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;