~siretart/ubuntu/utopic/blender/libav10

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2014-02-19 11:24:23 UTC
  • mfrom: (14.2.23 sid)
  • Revision ID: package-import@ubuntu.com-20140219112423-rkmaz2m7ha06d4tk
Tags: 2.69-3ubuntu1
* Merge with Debian; remaining changes:
  - Configure without OpenImageIO on armhf, as it is not available on
    Ubuntu.

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
 * The Original Code is Copyright (C) 2013 by Blender Foundation.
 
19
 * All rights reserved.
 
20
 *
 
21
 * Contributor(s): Campbell Barton
 
22
 *
 
23
 * ***** END GPL LICENSE BLOCK *****
 
24
 */
 
25
 
 
26
/** \file blender/editors/mesh/editmesh_bisect.c
 
27
 *  \ingroup edmesh
 
28
 */
 
29
 
 
30
#include "MEM_guardedalloc.h"
 
31
 
 
32
#include "DNA_object_types.h"
 
33
 
 
34
#include "BLI_math.h"
 
35
 
 
36
#include "BKE_global.h"
 
37
#include "BKE_context.h"
 
38
#include "BKE_editmesh.h"
 
39
 
 
40
#include "RNA_define.h"
 
41
#include "RNA_access.h"
 
42
 
 
43
#include "WM_api.h"
 
44
#include "WM_types.h"
 
45
 
 
46
#include "ED_mesh.h"
 
47
#include "ED_screen.h"
 
48
#include "ED_view3d.h"
 
49
 
 
50
 
 
51
#include "mesh_intern.h"  /* own include */
 
52
 
 
53
static int mesh_bisect_exec(bContext *C, wmOperator *op);
 
54
 
 
55
/* -------------------------------------------------------------------- */
 
56
/* Model Helpers */
 
57
 
 
58
typedef struct {
 
59
        /* modal only */
 
60
        BMBackup mesh_backup;
 
61
        bool is_first;
 
62
        short twtype;
 
63
} BisectData;
 
64
 
 
65
static bool mesh_bisect_interactive_calc(
 
66
        bContext *C, wmOperator *op,
 
67
        BMEditMesh *em,
 
68
        float plane_co[3], float plane_no[3])
 
69
{
 
70
        wmGesture *gesture = op->customdata;
 
71
        BisectData *opdata;
 
72
 
 
73
        ARegion *ar = CTX_wm_region(C);
 
74
        RegionView3D *rv3d = ar->regiondata;
 
75
 
 
76
        int x_start = RNA_int_get(op->ptr, "xstart");
 
77
        int y_start = RNA_int_get(op->ptr, "ystart");
 
78
        int x_end = RNA_int_get(op->ptr, "xend");
 
79
        int y_end = RNA_int_get(op->ptr, "yend");
 
80
 
 
81
        /* reference location (some point in front of the view) for finding a point on a plane */
 
82
        const float *co_ref = rv3d->ofs;
 
83
        float co_a_ss[2] = {x_start, y_start}, co_b_ss[2] = {x_end, y_end}, co_delta_ss[2];
 
84
        float co_a[3], co_b[3];
 
85
        const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL);
 
86
 
 
87
        opdata = gesture->userdata;
 
88
 
 
89
        /* view vector */
 
90
        ED_view3d_win_to_vector(ar, co_a_ss, co_a);
 
91
 
 
92
        /* view delta */
 
93
        sub_v2_v2v2(co_delta_ss, co_a_ss, co_b_ss);
 
94
        ED_view3d_win_to_delta(ar, co_delta_ss, co_b, zfac);
 
95
 
 
96
        /* cross both to get a normal */
 
97
        cross_v3_v3v3(plane_no, co_a, co_b);
 
98
        normalize_v3(plane_no);  /* not needed but nicer for user */
 
99
 
 
100
        /* point on plane, can use either start or endpoint */
 
101
        ED_view3d_win_to_3d(ar, co_ref, co_a_ss, plane_co);
 
102
 
 
103
        if (opdata->is_first == false)
 
104
                EDBM_redo_state_restore(opdata->mesh_backup, em, false);
 
105
 
 
106
        opdata->is_first = false;
 
107
 
 
108
        return true;
 
109
}
 
110
 
 
111
static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
 
112
{
 
113
        int ret;
 
114
 
 
115
        /* if the properties are set or there is no rv3d,
 
116
         * skip model and exec immediately */
 
117
 
 
118
        if ((CTX_wm_region_view3d(C) == NULL) ||
 
119
            (RNA_struct_property_is_set(op->ptr, "plane_co") &&
 
120
             RNA_struct_property_is_set(op->ptr, "plane_no")))
 
121
        {
 
122
                return mesh_bisect_exec(C, op);
 
123
        }
 
124
 
 
125
        ret = WM_gesture_straightline_invoke(C, op, event);
 
126
        if (ret & OPERATOR_RUNNING_MODAL) {
 
127
                View3D *v3d = CTX_wm_view3d(C);
 
128
 
 
129
                wmGesture *gesture = op->customdata;
 
130
                BisectData *opdata;
 
131
 
 
132
                Object *obedit = CTX_data_edit_object(C);
 
133
                BMEditMesh *em = BKE_editmesh_from_object(obedit);
 
134
 
 
135
                opdata = MEM_mallocN(sizeof(BisectData), "inset_operator_data");
 
136
                opdata->mesh_backup = EDBM_redo_state_store(em);
 
137
                opdata->is_first = true;
 
138
                gesture->userdata = opdata;
 
139
 
 
140
                /* misc other vars */
 
141
                G.moving = G_TRANSFORM_EDIT;
 
142
                opdata->twtype = v3d->twtype;
 
143
                v3d->twtype = 0;
 
144
        }
 
145
        return ret;
 
146
}
 
147
 
 
148
static void edbm_bisect_exit(bContext *C, BisectData *opdata)
 
149
{
 
150
        View3D *v3d = CTX_wm_view3d(C);
 
151
        EDBM_redo_state_free(&opdata->mesh_backup, NULL, false);
 
152
        v3d->twtype = opdata->twtype;
 
153
        G.moving = 0;
 
154
}
 
155
 
 
156
static int mesh_bisect_modal(bContext *C, wmOperator *op, const wmEvent *event)
 
157
{
 
158
        wmGesture *gesture = op->customdata;
 
159
        BisectData *opdata = gesture->userdata;
 
160
        BisectData opdata_back = *opdata;  /* annoyance, WM_gesture_straightline_modal, frees */
 
161
        int ret;
 
162
 
 
163
        ret = WM_gesture_straightline_modal(C, op, event);
 
164
 
 
165
        if (ret & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) {
 
166
                edbm_bisect_exit(C, &opdata_back);
 
167
        }
 
168
 
 
169
        return ret;
 
170
}
 
171
 
 
172
/* End Model Helpers */
 
173
/* -------------------------------------------------------------------- */
 
174
 
 
175
 
 
176
 
 
177
static int mesh_bisect_exec(bContext *C, wmOperator *op)
 
178
{
 
179
        Scene *scene = CTX_data_scene(C);
 
180
 
 
181
        /* both can be NULL, fallbacks values are used */
 
182
        View3D *v3d = CTX_wm_view3d(C);
 
183
        RegionView3D *rv3d = ED_view3d_context_rv3d(C);
 
184
 
 
185
        Object *obedit = CTX_data_edit_object(C);
 
186
        BMEditMesh *em = BKE_editmesh_from_object(obedit);
 
187
        BMesh *bm;
 
188
        BMOperator bmop;
 
189
        float plane_co[3];
 
190
        float plane_no[3];
 
191
        float imat[4][4];
 
192
 
 
193
        const float thresh = RNA_float_get(op->ptr, "threshold");
 
194
        const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
 
195
        const bool clear_inner = RNA_boolean_get(op->ptr, "clear_inner");
 
196
        const bool clear_outer = RNA_boolean_get(op->ptr, "clear_outer");
 
197
 
 
198
        PropertyRNA *prop_plane_co;
 
199
        PropertyRNA *prop_plane_no;
 
200
 
 
201
        prop_plane_co = RNA_struct_find_property(op->ptr, "plane_co");
 
202
        if (RNA_property_is_set(op->ptr, prop_plane_co)) {
 
203
                RNA_property_float_get_array(op->ptr, prop_plane_co, plane_co);
 
204
        }
 
205
        else {
 
206
                copy_v3_v3(plane_co, give_cursor(scene, v3d));
 
207
                RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co);
 
208
        }
 
209
 
 
210
        prop_plane_no = RNA_struct_find_property(op->ptr, "plane_no");
 
211
        if (RNA_property_is_set(op->ptr, prop_plane_no)) {
 
212
                RNA_property_float_get_array(op->ptr, prop_plane_no, plane_no);
 
213
        }
 
214
        else {
 
215
                if (rv3d) {
 
216
                        copy_v3_v3(plane_no, rv3d->viewinv[1]);
 
217
                }
 
218
                else {
 
219
                        /* fallback... */
 
220
                        plane_no[0] = plane_no[1] = 0.0f; plane_no[2] = 1.0f;
 
221
                }
 
222
                RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no);
 
223
        }
 
224
 
 
225
 
 
226
 
 
227
        /* -------------------------------------------------------------------- */
 
228
        /* Modal support */
 
229
        /* Note: keep this isolated, exec can work wihout this */
 
230
        if ((op->customdata != NULL) &&
 
231
            mesh_bisect_interactive_calc(C, op, em, plane_co, plane_no))
 
232
        {
 
233
                /* write back to the props */
 
234
                RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no);
 
235
                RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co);
 
236
        }
 
237
        /* End Modal */
 
238
        /* -------------------------------------------------------------------- */
 
239
 
 
240
 
 
241
 
 
242
        bm = em->bm;
 
243
 
 
244
        invert_m4_m4(imat, obedit->obmat);
 
245
        mul_m4_v3(imat, plane_co);
 
246
        mul_mat3_m4_v3(imat, plane_no);
 
247
 
 
248
        EDBM_op_init(em, &bmop, op,
 
249
                     "bisect_plane geom=%hvef plane_co=%v plane_no=%v dist=%f clear_inner=%b clear_outer=%b",
 
250
                     BM_ELEM_SELECT, plane_co, plane_no, thresh, clear_inner, clear_outer);
 
251
        BMO_op_exec(bm, &bmop);
 
252
 
 
253
        EDBM_flag_disable_all(em, BM_ELEM_SELECT);
 
254
 
 
255
        if (use_fill) {
 
256
                float normal_fill[3];
 
257
                BMOperator bmop_fill;
 
258
                BMOperator bmop_attr;
 
259
 
 
260
                normalize_v3_v3(normal_fill, plane_no);
 
261
                if (clear_outer == true && clear_inner == false) {
 
262
                        negate_v3(normal_fill);
 
263
                }
 
264
 
 
265
                /* Fill */
 
266
                BMO_op_initf(
 
267
                        bm, &bmop_fill, op->flag,
 
268
                        "triangle_fill edges=%S normal=%v use_dissolve=%b",
 
269
                        &bmop, "geom_cut.out", normal_fill, true);
 
270
                BMO_op_exec(bm, &bmop_fill);
 
271
 
 
272
                /* Copy Attributes */
 
273
                BMO_op_initf(bm, &bmop_attr, op->flag,
 
274
                             "face_attribute_fill faces=%S use_normals=%b use_data=%b",
 
275
                             &bmop_fill, "geom.out", false, true);
 
276
                BMO_op_exec(bm, &bmop_attr);
 
277
 
 
278
                BMO_slot_buffer_hflag_enable(bm, bmop_fill.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
 
279
 
 
280
                BMO_op_finish(bm, &bmop_attr);
 
281
                BMO_op_finish(bm, &bmop_fill);
 
282
        }
 
283
 
 
284
        BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom_cut.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true);
 
285
 
 
286
        if (!EDBM_op_finish(em, &bmop, op, true)) {
 
287
                return OPERATOR_CANCELLED;
 
288
        }
 
289
        else {
 
290
                EDBM_update_generic(em, true, true);
 
291
                EDBM_selectmode_flush(em);
 
292
                return OPERATOR_FINISHED;
 
293
        }
 
294
}
 
295
 
 
296
 
 
297
void MESH_OT_bisect(struct wmOperatorType *ot)
 
298
{
 
299
        PropertyRNA *prop;
 
300
 
 
301
        /* identifiers */
 
302
        ot->name = "Bisect";
 
303
        ot->description = "Cut geometry along a plane";
 
304
        ot->idname = "MESH_OT_bisect";
 
305
 
 
306
        /* api callbacks */
 
307
        ot->exec = mesh_bisect_exec;
 
308
        ot->invoke = mesh_bisect_invoke;
 
309
        ot->modal = mesh_bisect_modal;
 
310
        ot->cancel = WM_gesture_straightline_cancel;
 
311
        ot->poll = ED_operator_editmesh;
 
312
 
 
313
        /* flags */
 
314
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
315
 
 
316
 
 
317
        prop = RNA_def_float_vector(ot->srna, "plane_co", 3, NULL, -FLT_MAX, FLT_MAX,
 
318
                                    "Plane Point", "A point on the plane", -FLT_MAX, FLT_MAX);
 
319
        RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 
320
        prop = RNA_def_float_vector(ot->srna, "plane_no", 3, NULL, -FLT_MAX, FLT_MAX,
 
321
                                    "Plane Normal", "The direction the plane points", -FLT_MAX, FLT_MAX);
 
322
        RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 
323
 
 
324
        RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill in the cut");
 
325
        RNA_def_boolean(ot->srna, "clear_inner", false, "Clear Inner", "Remove geometry behind the plane");
 
326
        RNA_def_boolean(ot->srna, "clear_outer", false, "Clear Outer", "Remove geometry in front of the plane");
 
327
 
 
328
        RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Axis Threshold", "", 0.00001, 0.1);
 
329
 
 
330
        WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT);
 
331
}