Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * ***** END GPL LICENSE BLOCK ***** 00019 */ 00020 00021 #include <math.h> 00022 #include <stdio.h> 00023 #include <string.h> 00024 00025 #include "BLI_blenlib.h" 00026 #include "BLI_string.h" 00027 #include "BLI_utildefines.h" 00028 00029 #include "DNA_dynamicpaint_types.h" 00030 #include "DNA_modifier_types.h" 00031 #include "DNA_object_types.h" 00032 #include "DNA_scene_types.h" 00033 00034 #include "BKE_blender.h" 00035 #include "BKE_context.h" 00036 #include "BKE_deform.h" 00037 #include "BKE_depsgraph.h" 00038 #include "BKE_dynamicpaint.h" 00039 #include "BKE_global.h" 00040 #include "BKE_modifier.h" 00041 #include "BKE_report.h" 00042 00043 #include "ED_mesh.h" 00044 #include "ED_screen.h" 00045 #include "ED_object.h" 00046 00047 #include "RNA_access.h" 00048 #include "RNA_define.h" 00049 #include "RNA_enum_types.h" 00050 00051 /* Platform independend time */ 00052 #include "PIL_time.h" 00053 00054 #include "WM_types.h" 00055 #include "WM_api.h" 00056 00057 #include "physics_intern.h" /* own include */ 00058 00059 static int surface_slot_add_exec(bContext *C, wmOperator *UNUSED(op)) 00060 { 00061 DynamicPaintModifierData *pmd = NULL; 00062 Object *cObject = ED_object_context(C); 00063 DynamicPaintCanvasSettings *canvas; 00064 DynamicPaintSurface *surface; 00065 00066 /* Make sure we're dealing with a canvas */ 00067 pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint); 00068 if (!pmd || !pmd->canvas) return OPERATOR_CANCELLED; 00069 00070 canvas = pmd->canvas; 00071 surface = dynamicPaint_createNewSurface(canvas, CTX_data_scene(C)); 00072 00073 if (!surface) return OPERATOR_CANCELLED; 00074 00075 /* set preview for this surface only and set active */ 00076 canvas->active_sur = 0; 00077 for(surface=surface->prev; surface; surface=surface->prev) { 00078 surface->flags &= ~MOD_DPAINT_PREVIEW; 00079 canvas->active_sur++; 00080 } 00081 00082 return OPERATOR_FINISHED; 00083 } 00084 00085 /* add surface slot */ 00086 void DPAINT_OT_surface_slot_add(wmOperatorType *ot) 00087 { 00088 /* identifiers */ 00089 ot->name= "Add Surface Slot"; 00090 ot->idname= "DPAINT_OT_surface_slot_add"; 00091 ot->description="Add a new Dynamic Paint surface slot"; 00092 00093 /* api callbacks */ 00094 ot->exec= surface_slot_add_exec; 00095 ot->poll= ED_operator_object_active_editable; 00096 00097 /* flags */ 00098 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00099 } 00100 00101 static int surface_slot_remove_exec(bContext *C, wmOperator *UNUSED(op)) 00102 { 00103 DynamicPaintModifierData *pmd = NULL; 00104 Object *cObject = ED_object_context(C); 00105 DynamicPaintCanvasSettings *canvas; 00106 DynamicPaintSurface *surface; 00107 int id=0; 00108 00109 /* Make sure we're dealing with a canvas */ 00110 pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint); 00111 if (!pmd || !pmd->canvas) return OPERATOR_CANCELLED; 00112 00113 canvas = pmd->canvas; 00114 surface = canvas->surfaces.first; 00115 00116 /* find active surface and remove it */ 00117 for(; surface; surface=surface->next) { 00118 if(id == canvas->active_sur) { 00119 canvas->active_sur -= 1; 00120 dynamicPaint_freeSurface(surface); 00121 break; 00122 } 00123 id++; 00124 } 00125 00126 dynamicPaint_resetPreview(canvas); 00127 DAG_id_tag_update(&cObject->id, OB_RECALC_DATA); 00128 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, cObject); 00129 00130 return OPERATOR_FINISHED; 00131 } 00132 00133 /* remove surface slot */ 00134 void DPAINT_OT_surface_slot_remove(wmOperatorType *ot) 00135 { 00136 /* identifiers */ 00137 ot->name= "Remove Surface Slot"; 00138 ot->idname= "DPAINT_OT_surface_slot_remove"; 00139 ot->description="Remove the selected surface slot"; 00140 00141 /* api callbacks */ 00142 ot->exec= surface_slot_remove_exec; 00143 ot->poll= ED_operator_object_active_editable; 00144 00145 /* flags */ 00146 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00147 } 00148 00149 static int type_toggle_exec(bContext *C, wmOperator *op) 00150 { 00151 00152 Object *cObject = ED_object_context(C); 00153 Scene *scene = CTX_data_scene(C); 00154 DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint); 00155 int type= RNA_enum_get(op->ptr, "type"); 00156 00157 if (!pmd) return OPERATOR_CANCELLED; 00158 00159 /* if type is already enabled, toggle it off */ 00160 if (type == MOD_DYNAMICPAINT_TYPE_CANVAS && pmd->canvas) { 00161 dynamicPaint_freeCanvas(pmd); 00162 } 00163 else if (type == MOD_DYNAMICPAINT_TYPE_BRUSH && pmd->brush) { 00164 dynamicPaint_freeBrush(pmd); 00165 } 00166 /* else create a new type */ 00167 else { 00168 if (!dynamicPaint_createType(pmd, type, scene)) 00169 return OPERATOR_CANCELLED; 00170 } 00171 00172 /* update dependancy */ 00173 DAG_id_tag_update(&cObject->id, OB_RECALC_DATA); 00174 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, cObject); 00175 DAG_scene_sort(CTX_data_main(C), scene); 00176 00177 return OPERATOR_FINISHED; 00178 } 00179 00180 void DPAINT_OT_type_toggle(wmOperatorType *ot) 00181 { 00182 PropertyRNA *prop; 00183 00184 /* identifiers */ 00185 ot->name= "Toggle Type Active"; 00186 ot->idname= "DPAINT_OT_type_toggle"; 00187 ot->description = "Toggle whether given type is active or not"; 00188 00189 /* api callbacks */ 00190 ot->exec= type_toggle_exec; 00191 ot->poll= ED_operator_object_active_editable; 00192 00193 /* flags */ 00194 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00195 00196 /* properties */ 00197 prop= RNA_def_enum(ot->srna, "type", prop_dynamicpaint_type_items, MOD_DYNAMICPAINT_TYPE_CANVAS, "Type", ""); 00198 ot->prop= prop; 00199 } 00200 00201 static int output_toggle_exec(bContext *C, wmOperator *op) 00202 { 00203 Object *ob = ED_object_context(C); 00204 Scene *scene = CTX_data_scene(C); 00205 DynamicPaintSurface *surface; 00206 DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint); 00207 int output= RNA_enum_get(op->ptr, "output"); /* currently only 1/0 */ 00208 00209 if (!pmd || !pmd->canvas) return OPERATOR_CANCELLED; 00210 surface = get_activeSurface(pmd->canvas); 00211 00212 /* if type is already enabled, toggle it off */ 00213 if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { 00214 int exists = dynamicPaint_outputLayerExists(surface, ob, output); 00215 const char *name; 00216 00217 if (output == 0) 00218 name = surface->output_name; 00219 else 00220 name = surface->output_name2; 00221 00222 /* Vertex Color Layer */ 00223 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { 00224 if (!exists) 00225 ED_mesh_color_add(C, scene, ob, ob->data, name, 1); 00226 else 00227 ED_mesh_color_remove_named(C, ob, ob->data, name); 00228 } 00229 /* Vertex Weight Layer */ 00230 else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) { 00231 if (!exists) { 00232 ED_vgroup_add_name(ob, name); 00233 } 00234 else { 00235 bDeformGroup *defgroup = defgroup_find_name(ob, name); 00236 if (defgroup) ED_vgroup_delete(ob, defgroup); 00237 } 00238 } 00239 } 00240 00241 return OPERATOR_FINISHED; 00242 } 00243 00244 void DPAINT_OT_output_toggle(wmOperatorType *ot) 00245 { 00246 static EnumPropertyItem prop_output_toggle_types[] = { 00247 {0, "A", 0, "Output A", ""}, 00248 {1, "B", 0, "Output B", ""}, 00249 {0, NULL, 0, NULL, NULL} 00250 }; 00251 00252 /* identifiers */ 00253 ot->name= "Toggle Output Layer"; 00254 ot->idname= "DPAINT_OT_output_toggle"; 00255 ot->description = "Add or remove Dynamic Paint output data layer"; 00256 00257 /* api callbacks */ 00258 ot->exec= output_toggle_exec; 00259 ot->poll= ED_operator_object_active_editable; 00260 00261 /* flags */ 00262 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00263 00264 /* properties */ 00265 ot->prop= RNA_def_enum(ot->srna, "output", prop_output_toggle_types, 0, "Output Toggle", ""); 00266 } 00267 00268 00269 /***************************** Image Sequence Baking ******************************/ 00270 00271 /* 00272 * Do actual bake operation. Loop through to-be-baked frames. 00273 * Returns 0 on failture. 00274 */ 00275 static int dynamicPaint_bakeImageSequence(bContext *C, DynamicPaintSurface *surface, Object *cObject) 00276 { 00277 DynamicPaintCanvasSettings *canvas = surface->canvas; 00278 Scene *scene= CTX_data_scene(C); 00279 wmWindow *win = CTX_wm_window(C); 00280 int frame = 1; 00281 int frames; 00282 00283 frames = surface->end_frame - surface->start_frame + 1; 00284 if (frames <= 0) {BLI_strncpy(canvas->error, "No frames to bake.", sizeof(canvas->error)); return 0;} 00285 00286 /* Set frame to start point (also inits modifier data) */ 00287 frame = surface->start_frame; 00288 scene->r.cfra = (int)frame; 00289 ED_update_for_newframe(CTX_data_main(C), scene, win->screen, 1); 00290 00291 /* Init surface */ 00292 if (!dynamicPaint_createUVSurface(surface)) return 0; 00293 00294 /* Loop through selected frames */ 00295 for (frame=surface->start_frame; frame<=surface->end_frame; frame++) 00296 { 00297 float progress = (frame - surface->start_frame) / (float)frames * 100; 00298 surface->current_frame = frame; 00299 00300 /* If user requested stop (esc), quit baking */ 00301 if (blender_test_break()) return 0; 00302 00303 /* Update progress bar cursor */ 00304 WM_timecursor(win, (int)progress); 00305 00306 /* calculate a frame */ 00307 scene->r.cfra = (int)frame; 00308 ED_update_for_newframe(CTX_data_main(C), scene, win->screen, 1); 00309 if (!dynamicPaint_calculateFrame(surface, scene, cObject, frame)) return 0; 00310 00311 /* 00312 * Save output images 00313 */ 00314 { 00315 char filename[FILE_MAX]; 00316 00317 /* primary output layer */ 00318 if (surface->flags & MOD_DPAINT_OUT1) { 00319 /* set filepath */ 00320 BLI_join_dirfile(filename, sizeof(filename), surface->image_output_path, surface->output_name); 00321 BLI_path_frame(filename, frame, 4); 00322 00323 /* save image */ 00324 dynamicPaint_outputSurfaceImage(surface, filename, 0); 00325 } 00326 /* secondary output */ 00327 if (surface->flags & MOD_DPAINT_OUT2 && surface->type == MOD_DPAINT_SURFACE_T_PAINT) { 00328 /* set filepath */ 00329 BLI_join_dirfile(filename, sizeof(filename), surface->image_output_path, surface->output_name2); 00330 BLI_path_frame(filename, frame, 4); 00331 00332 /* save image */ 00333 dynamicPaint_outputSurfaceImage(surface, filename, 1); 00334 } 00335 } 00336 } 00337 return 1; 00338 } 00339 00340 00341 /* 00342 * Bake Dynamic Paint image sequence surface 00343 */ 00344 static int dynamicPaint_initBake(struct bContext *C, struct wmOperator *op) 00345 { 00346 DynamicPaintModifierData *pmd = NULL; 00347 DynamicPaintCanvasSettings *canvas; 00348 Object *ob = ED_object_context(C); 00349 int status = 0; 00350 double timer = PIL_check_seconds_timer(); 00351 char result_str[80]; 00352 DynamicPaintSurface *surface; 00353 00354 /* 00355 * Get modifier data 00356 */ 00357 pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint); 00358 if (!pmd) { 00359 BKE_report(op->reports, RPT_ERROR, "Bake Failed: No Dynamic Paint modifier found."); 00360 return 0; 00361 } 00362 00363 /* Make sure we're dealing with a canvas */ 00364 canvas = pmd->canvas; 00365 if (!canvas) { 00366 BKE_report(op->reports, RPT_ERROR, "Bake Failed: Invalid Canvas."); 00367 return 0; 00368 } 00369 surface = get_activeSurface(canvas); 00370 00371 /* Set state to baking and init surface */ 00372 canvas->error[0] = '\0'; 00373 canvas->flags |= MOD_DPAINT_BAKING; 00374 G.afbreek= 0; /* reset blender_test_break*/ 00375 00376 /* Bake Dynamic Paint */ 00377 status = dynamicPaint_bakeImageSequence(C, surface, ob); 00378 /* Clear bake */ 00379 canvas->flags &= ~MOD_DPAINT_BAKING; 00380 WM_cursor_restore(CTX_wm_window(C)); 00381 dynamicPaint_freeSurfaceData(surface); 00382 00383 /* Bake was successful: 00384 * Report for ended bake and how long it took */ 00385 if (status) { 00386 /* Format time string */ 00387 char time_str[30]; 00388 double time = PIL_check_seconds_timer() - timer; 00389 BLI_timestr(time, time_str); 00390 00391 /* Show bake info */ 00392 BLI_snprintf(result_str, sizeof(result_str), "Bake Complete! (%s)", time_str); 00393 BKE_report(op->reports, RPT_INFO, result_str); 00394 } 00395 else { 00396 if (strlen(canvas->error)) { /* If an error occured */ 00397 BLI_snprintf(result_str, sizeof(result_str), "Bake Failed: %s", canvas->error); 00398 BKE_report(op->reports, RPT_ERROR, result_str); 00399 } 00400 else { /* User cancelled the bake */ 00401 BLI_strncpy(result_str, "Baking Cancelled!", sizeof(result_str)); 00402 BKE_report(op->reports, RPT_WARNING, result_str); 00403 } 00404 } 00405 00406 return status; 00407 } 00408 00409 static int dynamicpaint_bake_exec(bContext *C, wmOperator *op) 00410 { 00411 /* Bake dynamic paint */ 00412 if(!dynamicPaint_initBake(C, op)) { 00413 return OPERATOR_CANCELLED;} 00414 00415 return OPERATOR_FINISHED; 00416 } 00417 00418 void DPAINT_OT_bake(wmOperatorType *ot) 00419 { 00420 /* identifiers */ 00421 ot->name= "Dynamic Paint Bake"; 00422 ot->description= "Bake dynamic paint image sequence surface"; 00423 ot->idname= "DPAINT_OT_bake"; 00424 00425 /* api callbacks */ 00426 ot->exec= dynamicpaint_bake_exec; 00427 ot->poll= ED_operator_object_active_editable; 00428 }