~diresu/blender/blender-command-port-002

« back to all changes in this revision

Viewing changes to source/blender/editors/sculpt_paint/sculpt_undo.c

  • Committer: Dietrich Bollmann
  • Date: 2010-07-23 08:21:44 UTC
  • mfrom: (15474.1.5025)
  • Revision ID: dietrich@formgames.org-20100723082144-24nrn8oku0115pwh
Update to state of blender repository from 2010-07-23 revision 30644.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id$
 
3
 *
 
4
 * ***** BEGIN GPL LICENSE BLOCK *****
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version 2
 
9
 * of the License, or (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software  Foundation,
 
18
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
19
 *
 
20
 * The Original Code is Copyright (C) 2006 by Nicholas Bishop
 
21
 * All rights reserved.
 
22
 *
 
23
 * The Original Code is: all of this file.
 
24
 *
 
25
 * Contributor(s): none yet.
 
26
 *
 
27
 * ***** END GPL LICENSE BLOCK *****
 
28
 *
 
29
 * Implements the Sculpt Mode tools
 
30
 *
 
31
 */
 
32
 
 
33
#include "BLI_math.h"
 
34
#include "BLI_ghash.h"
 
35
#include "BLI_threads.h"
 
36
 
 
37
#include "DNA_meshdata_types.h"
 
38
#include "DNA_object_types.h"
 
39
#include "DNA_scene_types.h"
 
40
#include "DNA_mesh_types.h"
 
41
#include "DNA_key_types.h"
 
42
 
 
43
#include "BKE_cdderivedmesh.h"
 
44
#include "BKE_context.h"
 
45
#include "BKE_depsgraph.h"
 
46
#include "BKE_modifier.h"
 
47
#include "BKE_multires.h"
 
48
#include "BKE_paint.h"
 
49
#include "BKE_mesh.h"
 
50
#include "BKE_key.h"
 
51
 
 
52
#include "WM_api.h"
 
53
#include "WM_types.h"
 
54
 
 
55
#include "ED_sculpt.h"
 
56
#include "paint_intern.h"
 
57
#include "sculpt_intern.h"
 
58
 
 
59
/************************** Undo *************************/
 
60
 
 
61
static void update_cb(PBVHNode *node, void *unused)
 
62
{
 
63
        (void)unused;
 
64
        BLI_pbvh_node_mark_update(node);
 
65
}
 
66
 
 
67
static void sculpt_undo_restore(bContext *C, ListBase *lb)
 
68
{
 
69
        Scene *scene = CTX_data_scene(C);
 
70
        Object *ob = CTX_data_active_object(C);
 
71
        DerivedMesh *dm = mesh_get_derived_final(scene, ob, 0);
 
72
        SculptSession *ss = ob->sculpt;
 
73
        SculptUndoNode *unode;
 
74
        MVert *mvert;
 
75
        MultiresModifierData *mmd;
 
76
        int *index;
 
77
        int i, j, update= 0;
 
78
 
 
79
        sculpt_update_mesh_elements(scene, ob, 0);
 
80
 
 
81
        for(unode=lb->first; unode; unode=unode->next) {
 
82
                if(!(strcmp(unode->idname, ob->id.name)==0))
 
83
                        continue;
 
84
 
 
85
                if(unode->maxvert) {
 
86
                        char *shapeName= (char*)unode->shapeName;
 
87
 
 
88
                        /* regular mesh restore */
 
89
                        if(ss->totvert != unode->maxvert)
 
90
                                continue;
 
91
 
 
92
                        if (ss->kb && strcmp(ss->kb->name, shapeName)) {
 
93
                                /* shape key has been changed before calling undo operator */
 
94
 
 
95
                                Key *key= ob_get_key(ob);
 
96
                                KeyBlock *kb= key_get_named_keyblock(key, shapeName);
 
97
 
 
98
                                if (kb) {
 
99
                                        ob->shapenr= BLI_findindex(&key->block, kb) + 1;
 
100
                                        ob->shapeflag|= OB_SHAPE_LOCK;
 
101
 
 
102
                                        sculpt_update_mesh_elements(scene, ob, 0);
 
103
                                        WM_event_add_notifier(C, NC_OBJECT|ND_DATA, ob);
 
104
                                } else {
 
105
                                        /* key has been removed -- skip this undo node */
 
106
                                        continue;
 
107
                                }
 
108
                        }
 
109
 
 
110
                        index= unode->index;
 
111
                        mvert= ss->mvert;
 
112
 
 
113
                        if (ss->kb) {
 
114
                                float (*vertCos)[3];
 
115
                                vertCos= key_to_vertcos(ob, ss->kb);
 
116
 
 
117
                                for(i=0; i<unode->totvert; i++)
 
118
                                        swap_v3_v3(vertCos[index[i]], unode->co[i]);
 
119
 
 
120
                                /* propagate new coords to keyblock */
 
121
                                sculpt_vertcos_to_key(ob, ss->kb, vertCos);
 
122
 
 
123
                                /* pbvh uses it's own mvert array, so coords should be */
 
124
                                /* propagated to pbvh here */
 
125
                                BLI_pbvh_apply_vertCos(ss->pbvh, vertCos);
 
126
 
 
127
                                MEM_freeN(vertCos);
 
128
                        } else {
 
129
                                for(i=0; i<unode->totvert; i++) {
 
130
                                        swap_v3_v3(mvert[index[i]].co, unode->co[i]);
 
131
                                        mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
 
132
                                }
 
133
                        }
 
134
                }
 
135
                else if(unode->maxgrid && dm->getGridData) {
 
136
                        /* multires restore */
 
137
                        DMGridData **grids, *grid;
 
138
                        float (*co)[3];
 
139
                        int gridsize;
 
140
 
 
141
                        if(dm->getNumGrids(dm) != unode->maxgrid)
 
142
                                continue;
 
143
                        if(dm->getGridSize(dm) != unode->gridsize)
 
144
                                continue;
 
145
 
 
146
                        grids= dm->getGridData(dm);
 
147
                        gridsize= dm->getGridSize(dm);
 
148
 
 
149
                        co = unode->co;
 
150
                        for(j=0; j<unode->totgrid; j++) {
 
151
                                grid= grids[unode->grids[j]];
 
152
 
 
153
                                for(i=0; i<gridsize*gridsize; i++, co++)
 
154
                                        swap_v3_v3(grid[i].co, co[0]);
 
155
                        }
 
156
                }
 
157
 
 
158
                update= 1;
 
159
        }
 
160
 
 
161
        if(update) {
 
162
                /* we update all nodes still, should be more clever, but also
 
163
                   needs to work correct when exiting/entering sculpt mode and
 
164
                   the nodes get recreated, though in that case it could do all */
 
165
                BLI_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, NULL);
 
166
                BLI_pbvh_update(ss->pbvh, PBVH_UpdateBB|PBVH_UpdateOriginalBB|PBVH_UpdateRedraw, NULL);
 
167
 
 
168
                if((mmd=sculpt_multires_active(scene, ob)))
 
169
                        multires_mark_as_modified(ob);
 
170
 
 
171
                if(ss->modifiers_active || ((Mesh*)ob->data)->id.us > 1)
 
172
                        DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
 
173
        }
 
174
}
 
175
 
 
176
static void sculpt_undo_free(ListBase *lb)
 
177
{
 
178
        SculptUndoNode *unode;
 
179
 
 
180
        for(unode=lb->first; unode; unode=unode->next) {
 
181
                if(unode->co)
 
182
                        MEM_freeN(unode->co);
 
183
                if(unode->no)
 
184
                        MEM_freeN(unode->no);
 
185
                if(unode->index)
 
186
                        MEM_freeN(unode->index);
 
187
                if(unode->grids)
 
188
                        MEM_freeN(unode->grids);
 
189
                if(unode->layer_disp)
 
190
                        MEM_freeN(unode->layer_disp);
 
191
        }
 
192
}
 
193
 
 
194
SculptUndoNode *sculpt_undo_get_node(PBVHNode *node)
 
195
{
 
196
        ListBase *lb= undo_paint_push_get_list(UNDO_PAINT_MESH);
 
197
        SculptUndoNode *unode;
 
198
 
 
199
        if(!lb)
 
200
                return NULL;
 
201
 
 
202
        for(unode=lb->first; unode; unode=unode->next)
 
203
                if(unode->node == node)
 
204
                        return unode;
 
205
 
 
206
        return NULL;
 
207
}
 
208
 
 
209
SculptUndoNode *sculpt_undo_push_node(SculptSession *ss, PBVHNode *node)
 
210
{
 
211
        ListBase *lb= undo_paint_push_get_list(UNDO_PAINT_MESH);
 
212
        Object *ob= ss->ob;
 
213
        SculptUndoNode *unode;
 
214
        int totvert, allvert, totgrid, maxgrid, gridsize, *grids;
 
215
 
 
216
        /* list is manipulated by multiple threads, so we lock */
 
217
        BLI_lock_thread(LOCK_CUSTOM1);
 
218
 
 
219
        if((unode= sculpt_undo_get_node(node))) {
 
220
                BLI_unlock_thread(LOCK_CUSTOM1);
 
221
                return unode;
 
222
        }
 
223
 
 
224
        unode= MEM_callocN(sizeof(SculptUndoNode), "SculptUndoNode");
 
225
        strcpy(unode->idname, ob->id.name);
 
226
        unode->node= node;
 
227
 
 
228
        BLI_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert);
 
229
        BLI_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
 
230
                &maxgrid, &gridsize, NULL, NULL);
 
231
 
 
232
        unode->totvert= totvert;
 
233
        /* we will use this while sculpting, is mapalloc slow to access then? */
 
234
        unode->co= MEM_mapallocN(sizeof(float)*3*allvert, "SculptUndoNode.co");
 
235
        unode->no= MEM_mapallocN(sizeof(short)*3*allvert, "SculptUndoNode.no");
 
236
        undo_paint_push_count_alloc(UNDO_PAINT_MESH, (sizeof(float)*3 + sizeof(short)*3 + sizeof(int))*allvert);
 
237
        BLI_addtail(lb, unode);
 
238
 
 
239
        if(maxgrid) {
 
240
                /* multires */
 
241
                unode->maxgrid= maxgrid;
 
242
                unode->totgrid= totgrid;
 
243
                unode->gridsize= gridsize;
 
244
                unode->grids= MEM_mapallocN(sizeof(int)*totgrid, "SculptUndoNode.grids");
 
245
        }
 
246
        else {
 
247
                /* regular mesh */
 
248
                unode->maxvert= ss->totvert;
 
249
                unode->index= MEM_mapallocN(sizeof(int)*allvert, "SculptUndoNode.index");
 
250
        }
 
251
 
 
252
        BLI_unlock_thread(LOCK_CUSTOM1);
 
253
 
 
254
        /* copy threaded, hopefully this is the performance critical part */
 
255
        {
 
256
                PBVHVertexIter vd;
 
257
 
 
258
                BLI_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL) {
 
259
                        copy_v3_v3(unode->co[vd.i], vd.co);
 
260
                        if(vd.no) VECCOPY(unode->no[vd.i], vd.no)
 
261
                        else normal_float_to_short_v3(unode->no[vd.i], vd.fno);
 
262
                        if(vd.vert_indices) unode->index[vd.i]= vd.vert_indices[vd.i];
 
263
                }
 
264
                BLI_pbvh_vertex_iter_end;
 
265
        }
 
266
 
 
267
        if(unode->grids)
 
268
                memcpy(unode->grids, grids, sizeof(int)*totgrid);
 
269
 
 
270
        /* store active shape key */
 
271
        if(ss->kb) BLI_strncpy((char*)unode->shapeName, ss->kb->name, sizeof(ss->kb->name));
 
272
        else unode->shapeName[0]= '\0';
 
273
 
 
274
        return unode;
 
275
}
 
276
 
 
277
void sculpt_undo_push_begin(char *name)
 
278
{
 
279
        undo_paint_push_begin(UNDO_PAINT_MESH, name,
 
280
                sculpt_undo_restore, sculpt_undo_free);
 
281
}
 
282
 
 
283
void sculpt_undo_push_end(void)
 
284
{
 
285
        ListBase *lb= undo_paint_push_get_list(UNDO_PAINT_MESH);
 
286
        SculptUndoNode *unode;
 
287
 
 
288
        /* we don't need normals in the undo stack */
 
289
        for(unode=lb->first; unode; unode=unode->next) {
 
290
                if(unode->no) {
 
291
                        MEM_freeN(unode->no);
 
292
                        unode->no= NULL;
 
293
                }
 
294
 
 
295
                if(unode->layer_disp) {
 
296
                        MEM_freeN(unode->layer_disp);
 
297
                        unode->layer_disp= NULL;
 
298
                }
 
299
        }
 
300
 
 
301
        undo_paint_push_end(UNDO_PAINT_MESH);
 
302
}