~ubuntu-branches/ubuntu/trusty/blender/trusty

« back to all changes in this revision

Viewing changes to source/blender/editors/mesh/editmesh_slide.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-03-06 12:08:47 UTC
  • mfrom: (1.5.1) (14.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20130306120847-frjfaryb2zrotwcg
Tags: 2.66a-1ubuntu1
* Resynchronize with Debian (LP: #1076930, #1089256, #1052743, #999024,
  #1122888, #1147084)
* debian/control:
  - Lower build-depends on libavcodec-dev since we're not
    doing the libav9 transition in Ubuntu yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * ***** BEGIN GPL LICENSE BLOCK *****
3
 
 *
4
 
 * This program is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU General Public License
6
 
 * as published by the Free Software Foundation; either version 2
7
 
 * of the License, or (at your option) any later version.
8
 
 *
9
 
 * This program is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 * GNU General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU General Public License
15
 
 * along with this program; if not, write to the Free Software Foundation,
16
 
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
 
 *
18
 
 * Contributor(s): Francisco De La Cruz
19
 
 *
20
 
 * ***** END GPL LICENSE BLOCK *****
21
 
 */
22
 
 
23
 
/** \file blender/editors/mesh/editmesh_slide.c
24
 
 *  \ingroup edmesh
25
 
 */
26
 
 
27
 
/* Takes heavily from editmesh_loopcut.c */
28
 
 
29
 
#include "DNA_object_types.h"
30
 
 
31
 
#include "MEM_guardedalloc.h"
32
 
 
33
 
#include "BLI_array.h"
34
 
#include "BLI_math.h"
35
 
 
36
 
#include "BKE_context.h"
37
 
#include "BKE_report.h"
38
 
#include "BKE_tessmesh.h"
39
 
 
40
 
#include "BIF_gl.h"
41
 
#include "BIF_glutil.h"
42
 
 
43
 
#include "ED_screen.h"
44
 
#include "ED_view3d.h"
45
 
#include "ED_mesh.h"
46
 
#include "ED_space_api.h"
47
 
 
48
 
#include "UI_resources.h"
49
 
 
50
 
#include "RNA_access.h"
51
 
#include "RNA_define.h"
52
 
 
53
 
#include "WM_api.h"
54
 
#include "WM_types.h"
55
 
 
56
 
#include "mesh_intern.h"
57
 
 
58
 
#define VTX_SLIDE_SNAP_THRSH 15
59
 
 
60
 
/* Cusom VertexSlide Operator data */
61
 
typedef struct VertexSlideOp {
62
 
        /* Starting Vertex */
63
 
        BMVert *start_vtx;
64
 
        BMEdge *sel_edge;
65
 
 
66
 
        ViewContext *view_context;
67
 
        ARegion *active_region;
68
 
 
69
 
        /* Draw callback handle */
70
 
        void *draw_handle;
71
 
 
72
 
        /* Active Object */
73
 
        Object *obj;
74
 
 
75
 
        /* Are we in slide mode */
76
 
        int slide_mode;
77
 
        int snap_n_merge;
78
 
        int snap_to_end_vtx;
79
 
        int snap_to_mid;
80
 
 
81
 
        /* Snap threshold */
82
 
        float snap_threshold;
83
 
 
84
 
        float distance;
85
 
        float interp[3];
86
 
 
87
 
        /* Edge Frame Count */
88
 
        int disk_edges;
89
 
 
90
 
        /* Edges */
91
 
        BMEdge** edge_frame;
92
 
 
93
 
        /* Slide Frame Endpoints */
94
 
        float (*vtx_frame)[3];
95
 
 
96
 
        /* Mouse Click 2d pos */
97
 
        int m_co[2];
98
 
 
99
 
} VertexSlideOp;
100
 
 
101
 
static void vtx_slide_draw(const bContext *C, ARegion *ar, void *arg);
102
 
static int edbm_vertex_slide_exec(bContext *C, wmOperator *op);
103
 
static void vtx_slide_exit(const bContext *C, wmOperator *op);
104
 
static int vtx_slide_set_frame(VertexSlideOp *vso);
105
 
 
106
 
static int vtx_slide_init(bContext *C, wmOperator *op)
107
 
{
108
 
        Object *obedit = CTX_data_edit_object(C);
109
 
        BMEditMesh *em = BMEdit_FromObject(obedit);
110
 
        BMEditSelection *ese;
111
 
 
112
 
        /* Custom data */
113
 
        VertexSlideOp *vso;
114
 
 
115
 
        const char *header_str = "Vertex Slide: Hover over an edge and left-click to select slide edge. "
116
 
                                 "Left-Shift: Midpoint Snap, Left-Alt: Snap, Left-Ctrl: Snap&Merge";
117
 
 
118
 
        if (!obedit) {
119
 
                BKE_report(op->reports, RPT_ERROR, "Vertex Slide Error: Not object in context");
120
 
                return FALSE;
121
 
        }
122
 
 
123
 
        EDBM_selectmode_flush(em);
124
 
        ese = em->bm->selected.last;
125
 
 
126
 
        /* Is there a starting vertex  ? */
127
 
        if (ese == NULL || (ese->htype != BM_VERT && ese->htype != BM_EDGE)) {
128
 
                BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex Slide Error: Select a (single) vertex");
129
 
                return FALSE;
130
 
        }
131
 
 
132
 
        vso = MEM_callocN(sizeof(VertexSlideOp), "Vertex Slide Operator");
133
 
        vso->view_context = MEM_callocN(sizeof(ViewContext), "Vertex Slide View Context");
134
 
 
135
 
        op->customdata = vso;
136
 
 
137
 
        /* Set the start vertex */
138
 
        vso->start_vtx = (BMVert *)ese->ele;
139
 
 
140
 
        vso->sel_edge = NULL;
141
 
 
142
 
        /* Edges */
143
 
        vso->edge_frame = NULL;
144
 
 
145
 
        vso->vtx_frame = NULL;
146
 
 
147
 
        vso->disk_edges = 0;
148
 
 
149
 
        vso->slide_mode = FALSE;
150
 
 
151
 
        vso->snap_n_merge = FALSE;
152
 
 
153
 
        vso->snap_to_end_vtx = FALSE;
154
 
 
155
 
        vso->snap_to_mid = FALSE;
156
 
 
157
 
        vso->distance = 0.0f;
158
 
 
159
 
        vso->snap_threshold = 0.2f;
160
 
 
161
 
        /* Notify the viewport */
162
 
        view3d_operator_needs_opengl(C);
163
 
 
164
 
        /* Set the drawing region */
165
 
        vso->active_region = CTX_wm_region(C);
166
 
 
167
 
        /* Set the draw callback */
168
 
        vso->draw_handle = ED_region_draw_cb_activate(vso->active_region->type, vtx_slide_draw, vso, REGION_DRAW_POST_VIEW);
169
 
 
170
 
        ED_area_headerprint(CTX_wm_area(C), header_str);
171
 
        
172
 
        em_setup_viewcontext(C, vso->view_context);
173
 
 
174
 
        /* Set the object */
175
 
        vso->obj = obedit;
176
 
 
177
 
        /* Init frame */
178
 
        if (!vtx_slide_set_frame(vso)) {
179
 
                BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex Slide: Can't find starting vertex!");
180
 
                vtx_slide_exit(C, op);
181
 
                return FALSE;
182
 
        }
183
 
 
184
 
        /* Add handler for the vertex sliding */
185
 
        WM_event_add_modal_handler(C, op);
186
 
 
187
 
        /* Tag for redraw */
188
 
        ED_region_tag_redraw(vso->active_region);
189
 
 
190
 
        return TRUE;
191
 
}
192
 
 
193
 
static void vtx_slide_confirm(bContext *C, wmOperator *op)
194
 
{
195
 
        VertexSlideOp *vso = op->customdata;
196
 
        BMEditMesh *em = BMEdit_FromObject(vso->obj);
197
 
        BMesh* bm = em->bm;
198
 
 
199
 
        /* Select new edge */
200
 
        BM_edge_select_set(bm, vso->sel_edge, TRUE);
201
 
 
202
 
        /* Invoke operator */
203
 
        edbm_vertex_slide_exec(C, op);
204
 
 
205
 
        if (vso->snap_n_merge) {
206
 
                float other_d;
207
 
                BMVert* other = BM_edge_other_vert(vso->sel_edge, vso->start_vtx);
208
 
                other_d = len_v3v3(vso->interp, other->co);
209
 
 
210
 
                /* Only snap if within threshold */
211
 
                if (other_d < vso->snap_threshold) {
212
 
                        BM_vert_select_set(bm, other, TRUE);
213
 
                        BM_vert_select_set(bm, vso->start_vtx, TRUE);
214
 
                        EDBM_op_callf(em, op, "pointmerge verts=%hv mergeco=%v", BM_ELEM_SELECT, other->co);
215
 
                        EDBM_flag_disable_all(em, BM_ELEM_SELECT);
216
 
                }
217
 
                else {
218
 
                        /* Store in historty if not merging */
219
 
                        BM_select_history_store(em->bm, vso->start_vtx);
220
 
                }
221
 
        }
222
 
        else {
223
 
                /* Store edit selection of the active vertex, allows other
224
 
                 *  ops to run without reselecting */
225
 
                BM_select_history_store(em->bm, vso->start_vtx);
226
 
        }
227
 
 
228
 
        EDBM_selectmode_flush(em);
229
 
        
230
 
        /* NC_GEOM | ND_DATA & Retess */
231
 
        EDBM_update_generic(C, em, TRUE);
232
 
        
233
 
        ED_region_tag_redraw(vso->active_region);
234
 
}
235
 
 
236
 
static void vtx_slide_exit(const bContext *C, wmOperator *op)
237
 
{
238
 
        /* Fetch custom data */
239
 
        VertexSlideOp *vso = op->customdata;
240
 
 
241
 
        /* Clean-up the custom data */
242
 
        ED_region_draw_cb_exit(vso->active_region->type, vso->draw_handle);
243
 
 
244
 
        /* Free Custom Data
245
 
         *
246
 
         */
247
 
        MEM_freeN(vso->view_context);
248
 
 
249
 
        vso->view_context = NULL;
250
 
 
251
 
        if (vso->edge_frame) {
252
 
                MEM_freeN(vso->edge_frame);
253
 
        }
254
 
 
255
 
        if (vso->vtx_frame) {
256
 
                MEM_freeN(vso->vtx_frame);
257
 
        }
258
 
 
259
 
        vso->edge_frame = NULL;
260
 
 
261
 
        vso->vtx_frame = NULL;
262
 
 
263
 
        vso->slide_mode = FALSE;
264
 
 
265
 
        MEM_freeN(vso);
266
 
        vso = NULL;
267
 
        op->customdata = NULL;
268
 
 
269
 
        /* Clear the header */
270
 
        ED_area_headerprint(CTX_wm_area(C), NULL);
271
 
}
272
 
 
273
 
static void vtx_slide_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
274
 
{
275
 
        VertexSlideOp *vso = arg;
276
 
 
277
 
        /* Have an edge to draw */
278
 
        if (vso && vso->sel_edge) {
279
 
                /* Get 3d view */
280
 
                View3D *view3d = CTX_wm_view3d(C);
281
 
                const float outline_w = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.8f;
282
 
                const float pt_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5;
283
 
 
284
 
                int i = 0;
285
 
 
286
 
                if (view3d && view3d->zbuf)
287
 
                        glDisable(GL_DEPTH_TEST);
288
 
 
289
 
                glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT);
290
 
 
291
 
                glPushMatrix();
292
 
                glMultMatrixf(vso->obj->obmat);
293
 
 
294
 
                glEnable(GL_BLEND);
295
 
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
296
 
                        
297
 
 
298
 
                if (vso->slide_mode && vso->disk_edges > 0) {
299
 
                        /* Draw intermediate edge frame */
300
 
                        UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 50, -50);
301
 
 
302
 
                        for (i = 0; i < vso->disk_edges; i++) {
303
 
                                glBegin(GL_LINES);
304
 
                                glVertex3fv(vso->vtx_frame[i]);
305
 
                                glVertex3fv(vso->interp);
306
 
                                glEnd();
307
 
                        }
308
 
                }
309
 
 
310
 
                /* Draw selected edge
311
 
                 * Add color offset and reduce alpha */
312
 
                UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 40, -50);
313
 
 
314
 
                glLineWidth(outline_w);
315
 
 
316
 
                glBegin(GL_LINES);
317
 
                bglVertex3fv(vso->sel_edge->v1->co);
318
 
                bglVertex3fv(vso->sel_edge->v2->co);
319
 
                glEnd();
320
 
 
321
 
                if (vso->slide_mode) {
322
 
                        /* Draw interpolated vertex */
323
 
                        
324
 
                        UI_ThemeColorShadeAlpha(TH_FACE_DOT, -80, -50);
325
 
 
326
 
                        glPointSize(pt_size);
327
 
 
328
 
                        bglBegin(GL_POINTS);
329
 
                        bglVertex3fv(vso->interp);
330
 
                        bglEnd();
331
 
                }
332
 
 
333
 
                glDisable(GL_BLEND);
334
 
                glPopMatrix();
335
 
                glPopAttrib();
336
 
 
337
 
                if (view3d && view3d->zbuf)
338
 
                        glEnable(GL_DEPTH_TEST);
339
 
        }
340
 
}
341
 
 
342
 
static BMEdge* vtx_slide_nrst_in_frame(VertexSlideOp *vso, const float mval[2])
343
 
{
344
 
        BMEdge* cl_edge = NULL;
345
 
        if (vso->disk_edges > 0) {
346
 
                int i = 0;
347
 
                BMEdge* edge = NULL;
348
 
                
349
 
                float v1_proj[3], v2_proj[3];
350
 
                float dist = 0;
351
 
                float min_dist = FLT_MAX;
352
 
 
353
 
                for (i = 0; i < vso->disk_edges; i++) {
354
 
                        edge = vso->edge_frame[i];
355
 
 
356
 
                        mul_v3_m4v3(v1_proj, vso->obj->obmat, edge->v1->co);
357
 
                        project_float_noclip(vso->active_region, v1_proj, v1_proj);
358
 
 
359
 
                        mul_v3_m4v3(v2_proj, vso->obj->obmat, edge->v2->co);
360
 
                        project_float_noclip(vso->active_region, v2_proj, v2_proj);
361
 
 
362
 
                        dist = dist_to_line_segment_v2(mval, v1_proj, v2_proj);
363
 
                        if (dist < min_dist) {
364
 
                                min_dist = dist;
365
 
                                cl_edge = edge;
366
 
                        }
367
 
                }
368
 
        }
369
 
        return cl_edge;
370
 
}
371
 
 
372
 
static void vtx_slide_find_edge(VertexSlideOp *vso, wmEvent *event)
373
 
{
374
 
        /* Nearest edge */
375
 
        BMEdge *nst_edge = NULL;
376
 
 
377
 
        const float mval_float[] = { (float)event->mval[0], (float)event->mval[1]};
378
 
 
379
 
        /* Set mouse coords */
380
 
        copy_v2_v2_int(vso->view_context->mval, event->mval);
381
 
 
382
 
        /* Find nearest edge */
383
 
        nst_edge = vtx_slide_nrst_in_frame(vso, mval_float);
384
 
 
385
 
        if (nst_edge) {
386
 
                /* Find a connected edge */
387
 
                if (BM_vert_in_edge(nst_edge, vso->start_vtx)) {
388
 
 
389
 
                        /* Save mouse coords */
390
 
                        copy_v2_v2_int(vso->m_co, event->mval);
391
 
 
392
 
                        /* Set edge */
393
 
                        vso->sel_edge = nst_edge;
394
 
                }
395
 
        }
396
 
}
397
 
 
398
 
/* Updates the status of the operator - Invoked on mouse movement */
399
 
static void vtx_slide_update(VertexSlideOp *vso, wmEvent *event)
400
 
{
401
 
        BMEdge *edge;
402
 
 
403
 
        /* Find nearest edge */
404
 
        edge = vso->sel_edge;
405
 
 
406
 
        if (edge) {
407
 
                float edge_other_proj[3];
408
 
                float start_vtx_proj[3];
409
 
                float edge_len;
410
 
                BMVert *other;
411
 
 
412
 
                float interp[3];
413
 
 
414
 
                /* Calculate interpolation value for preview */
415
 
                float t_val;
416
 
 
417
 
                float mval_float[] = { (float)event->mval[0], (float)event->mval[1]};
418
 
                float closest_2d[2];
419
 
 
420
 
                other = BM_edge_other_vert(edge, vso->start_vtx);
421
 
 
422
 
                /* Project points onto screen and do interpolation in 2D */
423
 
                mul_v3_m4v3(start_vtx_proj, vso->obj->obmat, vso->start_vtx->co);
424
 
                project_float_noclip(vso->active_region, start_vtx_proj, start_vtx_proj);
425
 
 
426
 
                mul_v3_m4v3(edge_other_proj, vso->obj->obmat, other->co);
427
 
                project_float_noclip(vso->active_region, edge_other_proj, edge_other_proj);
428
 
 
429
 
                closest_to_line_v2(closest_2d, mval_float, start_vtx_proj, edge_other_proj);
430
 
 
431
 
                t_val = line_point_factor_v2(closest_2d, start_vtx_proj, edge_other_proj);
432
 
 
433
 
                /* Set snap threshold to be proportional to edge length */
434
 
                edge_len = len_v3v3(start_vtx_proj, edge_other_proj);
435
 
                
436
 
                if (edge_len <= 0.0f)
437
 
                        edge_len = VTX_SLIDE_SNAP_THRSH;
438
 
 
439
 
                edge_len =  (len_v3v3(edge->v1->co, edge->v2->co) * VTX_SLIDE_SNAP_THRSH) / edge_len;
440
 
 
441
 
                vso->snap_threshold =  edge_len;
442
 
 
443
 
                /* Snap to mid */
444
 
                if (vso->snap_to_mid) {
445
 
                        t_val = 0.5f;
446
 
                }
447
 
 
448
 
                /* Interpolate preview vertex 3D */
449
 
                interp_v3_v3v3(interp, vso->start_vtx->co, other->co, t_val);
450
 
                copy_v3_v3(vso->interp, interp);
451
 
 
452
 
                vso->distance = t_val;
453
 
 
454
 
                /* If snapping */
455
 
                if (vso->snap_to_end_vtx) {
456
 
                        int start_at_v1 = edge->v1 == vso->start_vtx;
457
 
                        float v1_d = len_v3v3(vso->interp, edge->v1->co);
458
 
                        float v2_d = len_v3v3(vso->interp, edge->v2->co);
459
 
 
460
 
                        if (v1_d > v2_d && v2_d < vso->snap_threshold) {
461
 
                                copy_v3_v3(vso->interp, edge->v2->co);
462
 
 
463
 
                                if (start_at_v1)
464
 
                                        vso->distance = 1.0f;
465
 
                                else
466
 
                                        vso->distance = 0.0f;
467
 
                        }
468
 
                        if (v2_d > v1_d && v1_d < vso->snap_threshold) {
469
 
                                copy_v3_v3(vso->interp, edge->v1->co);
470
 
                                if (start_at_v1)
471
 
                                        vso->distance = 0.0f;
472
 
                                else
473
 
                                        vso->distance = 1.0f;
474
 
                        }
475
 
                }
476
 
        }
477
 
}
478
 
 
479
 
/* Sets the outline frame */
480
 
static int vtx_slide_set_frame(VertexSlideOp *vso)
481
 
{
482
 
        BMEdge *edge;
483
 
        float (*vtx_frame)[3] = NULL;
484
 
        BMEdge** edge_frame = NULL;
485
 
        BMVert *curr_vert = NULL;
486
 
        BLI_array_declare(vtx_frame);
487
 
        BLI_array_declare(edge_frame);
488
 
        BMIter iter;
489
 
        BMVert *sel_vtx = vso->start_vtx;
490
 
        int idx = 0;
491
 
 
492
 
        vso->disk_edges = 0;
493
 
 
494
 
        if (vso->edge_frame) {
495
 
                MEM_freeN(vso->edge_frame);
496
 
                vso->edge_frame = NULL;
497
 
        }
498
 
 
499
 
        if (vso->vtx_frame) {
500
 
                MEM_freeN(vso->vtx_frame);
501
 
                vso->vtx_frame = NULL;
502
 
        }
503
 
 
504
 
        /* Iterate over edges of vertex and copy them */
505
 
        BM_ITER_ELEM_INDEX (edge, &iter, sel_vtx, BM_EDGES_OF_VERT, idx) {
506
 
                curr_vert = BM_edge_other_vert(edge, sel_vtx);
507
 
                if (curr_vert) {
508
 
                        BLI_array_growone(vtx_frame);
509
 
 
510
 
                        copy_v3_v3(vtx_frame[idx], curr_vert->co);
511
 
 
512
 
                        BLI_array_append(edge_frame, edge);
513
 
                        vso->disk_edges++;
514
 
                }
515
 
        }
516
 
 
517
 
        vso->edge_frame = edge_frame;
518
 
        vso->vtx_frame = vtx_frame;
519
 
 
520
 
        /* Set the interp at starting vtx */
521
 
        copy_v3_v3(vso->interp, sel_vtx->co);
522
 
 
523
 
        return vso->disk_edges > 0;
524
 
}
525
 
 
526
 
static int edbm_vertex_slide_modal(bContext *C, wmOperator *op, wmEvent *event)
527
 
{
528
 
        VertexSlideOp *vso = op->customdata;
529
 
        char buff[128];
530
 
 
531
 
        if (!vso)
532
 
                return OPERATOR_CANCELLED;
533
 
 
534
 
        /* Notify the viewport */
535
 
        view3d_operator_needs_opengl(C);
536
 
 
537
 
        switch (event->type) {
538
 
                case LEFTSHIFTKEY:
539
 
                {
540
 
                        switch (event->val) {
541
 
                                case KM_PRESS:
542
 
                                        vso->snap_to_mid = TRUE;
543
 
                                        break;
544
 
                                case KM_RELEASE:
545
 
                                        vso->snap_to_mid = FALSE;
546
 
                                        break;
547
 
                        }
548
 
 
549
 
                        break;
550
 
                }
551
 
                case LEFTCTRLKEY:
552
 
                {
553
 
                        switch (event->val) {
554
 
                                case KM_PRESS:
555
 
                                        vso->snap_n_merge = TRUE;
556
 
                                        vso->snap_to_end_vtx = TRUE;
557
 
                                        break;
558
 
                                case KM_RELEASE:
559
 
                                        vso->snap_n_merge = FALSE;
560
 
                                        vso->snap_to_end_vtx = FALSE;
561
 
                                        break;
562
 
                        }
563
 
 
564
 
                        break;
565
 
                }
566
 
                case LEFTALTKEY:
567
 
                {
568
 
                        switch (event->val) {
569
 
                                case KM_PRESS:
570
 
                                        vso->snap_to_end_vtx = TRUE;
571
 
                                        break;
572
 
                                case KM_RELEASE:
573
 
                                        vso->snap_to_end_vtx = FALSE;
574
 
                                        break;
575
 
                        }
576
 
 
577
 
                        break;
578
 
                }
579
 
                case RIGHTMOUSE:
580
 
                {
581
 
                        /* Enforce redraw */
582
 
                        ED_region_tag_redraw(vso->active_region);
583
 
 
584
 
                        /* Clean-up */
585
 
                        vtx_slide_exit(C, op);
586
 
 
587
 
                        return OPERATOR_CANCELLED;
588
 
                }
589
 
                case LEFTMOUSE:
590
 
                {
591
 
                        if (event->val == KM_PRESS) {
592
 
                                /* Update mouse coords */
593
 
                                copy_v2_v2_int(vso->m_co, event->mval);
594
 
 
595
 
                                if (vso->slide_mode) {
596
 
                                        vtx_slide_confirm(C, op);
597
 
                                        /* Clean-up */
598
 
                                        vtx_slide_exit(C, op);
599
 
                                        return OPERATOR_FINISHED;
600
 
                                }
601
 
                                else if (vso->sel_edge) {
602
 
                                        vso->slide_mode = TRUE;
603
 
                                }
604
 
                        }
605
 
 
606
 
                        ED_region_tag_redraw(vso->active_region);
607
 
                        break;
608
 
 
609
 
                }
610
 
                case MOUSEMOVE:
611
 
                {
612
 
                        sprintf(buff, "Vertex Slide: %f", vso->distance);
613
 
                        if (!vso->slide_mode) {
614
 
                                vtx_slide_find_edge(vso, event);
615
 
                        }
616
 
                        else {
617
 
                                vtx_slide_update(vso, event);
618
 
                        }
619
 
                        ED_area_headerprint(CTX_wm_area(C), buff);
620
 
                        ED_region_tag_redraw(vso->active_region);
621
 
                        break;
622
 
                }
623
 
        }
624
 
 
625
 
        return OPERATOR_RUNNING_MODAL;
626
 
}
627
 
 
628
 
static int edbm_vertex_slide_cancel(bContext *C, wmOperator *op)
629
 
{
630
 
        /* Exit the modal */
631
 
        vtx_slide_exit(C, op);
632
 
 
633
 
        return OPERATOR_CANCELLED;
634
 
}
635
 
 
636
 
static int edbm_vertex_slide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
637
 
{
638
 
        /* Initialize the operator */
639
 
        if (vtx_slide_init(C, op))
640
 
                return OPERATOR_RUNNING_MODAL;
641
 
        else
642
 
                return OPERATOR_CANCELLED;
643
 
}
644
 
 
645
 
/* Vertex Slide */
646
 
static int edbm_vertex_slide_exec(bContext *C, wmOperator *op)
647
 
{
648
 
        Object *obedit = CTX_data_edit_object(C);
649
 
        BMEditMesh *em = BMEdit_FromObject(obedit);
650
 
        BMesh *bm = em->bm;
651
 
        BMVert *start_vert;
652
 
        BMOperator bmop;
653
 
        BMEditSelection *ese = (BMEditSelection *)em->bm->selected.last;
654
 
 
655
 
        float distance_t = 0.0f;
656
 
 
657
 
        /* Invoked modally? */
658
 
        if (op->type->modal == edbm_vertex_slide_modal && op->customdata) {
659
 
                VertexSlideOp *vso = (VertexSlideOp *)op->customdata;
660
 
 
661
 
                if (bm->totedgesel > 1) {
662
 
                        /* Reset selections */
663
 
                        EDBM_flag_disable_all(em, BM_ELEM_SELECT);
664
 
                        BM_edge_select_set(bm, vso->sel_edge, TRUE);
665
 
                        BM_vert_select_set(bm, vso->start_vtx, TRUE);
666
 
 
667
 
                        BM_select_history_store(em->bm, vso->sel_edge);
668
 
                        BM_select_history_store(em->bm, vso->start_vtx);
669
 
                        ese = (BMEditSelection *)em->bm->selected.last;
670
 
                }
671
 
                distance_t = vso->distance;
672
 
                RNA_float_set(op->ptr, "distance_t", distance_t);
673
 
        }
674
 
        else {
675
 
                /* Get Properties */
676
 
                distance_t = RNA_float_get(op->ptr, "distance_t");
677
 
        }
678
 
 
679
 
        /* Is there a starting vertex  ? */
680
 
        if ((ese == NULL) || (ese->htype != BM_VERT && ese->htype != BM_EDGE)) {
681
 
                BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex Slide Error: Select a (single) vertex");
682
 
                return OPERATOR_CANCELLED;
683
 
        }
684
 
 
685
 
        start_vert = (BMVert *)ese->ele;
686
 
 
687
 
        /* Prepare operator */
688
 
        if (!EDBM_op_init(em, &bmop, op,
689
 
                          "vertex_slide vert=%e edge=%hev distance_t=%f",
690
 
                          start_vert, BM_ELEM_SELECT, distance_t))
691
 
        {
692
 
                return OPERATOR_CANCELLED;
693
 
        }
694
 
        /* Execute operator */
695
 
        BMO_op_exec(bm, &bmop);
696
 
 
697
 
        /* Deselect the input edges */
698
 
        BMO_slot_buffer_hflag_disable(bm, &bmop, "edge", BM_ALL, BM_ELEM_SELECT, TRUE);
699
 
 
700
 
        /* Select the output vert */
701
 
        BMO_slot_buffer_hflag_enable(bm, &bmop, "vertout", BM_ALL, BM_ELEM_SELECT, TRUE);
702
 
 
703
 
        /* Flush the select buffers */
704
 
        EDBM_selectmode_flush(em);
705
 
 
706
 
        if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
707
 
                return OPERATOR_CANCELLED;
708
 
        }
709
 
 
710
 
        /* Update Geometry */
711
 
        EDBM_update_generic(C, em, TRUE);
712
 
 
713
 
        return OPERATOR_FINISHED;
714
 
}
715
 
 
716
 
void MESH_OT_vert_slide(wmOperatorType *ot)
717
 
{
718
 
        PropertyRNA *prop;
719
 
 
720
 
        /* identifiers */
721
 
        ot->name = "Vertex Slide";
722
 
        ot->idname = "MESH_OT_vert_slide";
723
 
        ot->description = "Vertex slide";
724
 
 
725
 
        /* api callback */
726
 
        ot->invoke = edbm_vertex_slide_invoke;
727
 
        ot->modal = edbm_vertex_slide_modal;
728
 
        ot->cancel = edbm_vertex_slide_cancel;
729
 
        ot->poll = ED_operator_editmesh_region_view3d;
730
 
 
731
 
        /* ot->exec = edbm_vertex_slide_exec;
732
 
         * ot->poll = ED_operator_editmesh; */
733
 
 
734
 
        /* flags */
735
 
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
736
 
 
737
 
        /* Properties for vertex slide */
738
 
        prop = RNA_def_float(ot->srna, "distance_t", 0.0f, -FLT_MAX, FLT_MAX, "Distance", "Distance", -5.0f, 5.0f);
739
 
        RNA_def_property_ui_range(prop, -5.0f, 5.0f, 0.1, 4);
740
 
        RNA_def_property_flag(prop, PROP_SKIP_SAVE);
741
 
}