|
Blender
V2.59
|
00001 /* 00002 * $Id: render_shading.c 38596 2011-07-22 00:31:24Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * The Original Code is Copyright (C) 2009 Blender Foundation. 00020 * All rights reserved. 00021 * 00022 * Contributor(s): Blender Foundation 00023 * 00024 * ***** END GPL LICENSE BLOCK ***** 00025 */ 00026 00032 #include <stdlib.h> 00033 #include <string.h> 00034 00035 #include "MEM_guardedalloc.h" 00036 00037 #include "DNA_curve_types.h" 00038 #include "DNA_lamp_types.h" 00039 #include "DNA_material_types.h" 00040 #include "DNA_node_types.h" 00041 #include "DNA_object_types.h" 00042 #include "DNA_particle_types.h" 00043 #include "DNA_scene_types.h" 00044 #include "DNA_space_types.h" 00045 #include "DNA_world_types.h" 00046 00047 #include "BLI_blenlib.h" 00048 #include "BLI_math.h" 00049 #include "BLI_editVert.h" 00050 #include "BLI_listbase.h" 00051 #include "BLI_utildefines.h" 00052 00053 #include "BKE_animsys.h" 00054 #include "BKE_context.h" 00055 #include "BKE_depsgraph.h" 00056 #include "BKE_font.h" 00057 #include "BKE_global.h" 00058 #include "BKE_icons.h" 00059 #include "BKE_image.h" 00060 #include "BKE_library.h" 00061 #include "BKE_main.h" 00062 #include "BKE_material.h" 00063 #include "BKE_node.h" 00064 #include "BKE_report.h" 00065 #include "BKE_scene.h" 00066 #include "BKE_texture.h" 00067 #include "BKE_world.h" 00068 00069 #include "IMB_imbuf.h" 00070 #include "IMB_imbuf_types.h" 00071 00072 #include "GPU_material.h" 00073 00074 #include "RNA_access.h" 00075 00076 #include "WM_api.h" 00077 #include "WM_types.h" 00078 00079 #include "ED_curve.h" 00080 #include "ED_mesh.h" 00081 #include "ED_render.h" 00082 #include "ED_screen.h" 00083 00084 #include "RNA_define.h" 00085 00086 #include "UI_interface.h" 00087 00088 #include "render_intern.h" // own include 00089 00090 /********************** material slot operators *********************/ 00091 00092 static int material_slot_add_exec(bContext *C, wmOperator *UNUSED(op)) 00093 { 00094 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 00095 00096 if(!ob) 00097 return OPERATOR_CANCELLED; 00098 00099 object_add_material_slot(ob); 00100 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); 00101 WM_event_add_notifier(C, NC_OBJECT|ND_OB_SHADING, ob); 00102 00103 return OPERATOR_FINISHED; 00104 } 00105 00106 void OBJECT_OT_material_slot_add(wmOperatorType *ot) 00107 { 00108 /* identifiers */ 00109 ot->name= "Add Material Slot"; 00110 ot->idname= "OBJECT_OT_material_slot_add"; 00111 ot->description="Add a new material slot"; 00112 00113 /* api callbacks */ 00114 ot->exec= material_slot_add_exec; 00115 ot->poll= ED_operator_object_active_editable; 00116 00117 /* flags */ 00118 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00119 } 00120 00121 static int material_slot_remove_exec(bContext *C, wmOperator *op) 00122 { 00123 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 00124 00125 if(!ob) 00126 return OPERATOR_CANCELLED; 00127 00128 /* Removing material slots in edit mode screws things up, see bug #21822.*/ 00129 if(ob == CTX_data_edit_object(C)) { 00130 BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode."); 00131 return OPERATOR_CANCELLED; 00132 } 00133 00134 object_remove_material_slot(ob); 00135 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 00136 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); 00137 WM_event_add_notifier(C, NC_OBJECT|ND_OB_SHADING, ob); 00138 00139 return OPERATOR_FINISHED; 00140 } 00141 00142 void OBJECT_OT_material_slot_remove(wmOperatorType *ot) 00143 { 00144 /* identifiers */ 00145 ot->name= "Remove Material Slot"; 00146 ot->idname= "OBJECT_OT_material_slot_remove"; 00147 ot->description="Remove the selected material slot"; 00148 00149 /* api callbacks */ 00150 ot->exec= material_slot_remove_exec; 00151 ot->poll= ED_operator_object_active_editable; 00152 00153 /* flags */ 00154 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00155 } 00156 00157 static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op)) 00158 { 00159 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 00160 00161 if(!ob) 00162 return OPERATOR_CANCELLED; 00163 00164 if(ob && ob->actcol>0) { 00165 if(ob->type == OB_MESH) { 00166 EditMesh *em= ((Mesh*)ob->data)->edit_mesh; 00167 EditFace *efa; 00168 00169 if(em) { 00170 for(efa= em->faces.first; efa; efa=efa->next) 00171 if(efa->f & SELECT) 00172 efa->mat_nr= ob->actcol-1; 00173 } 00174 } 00175 else if(ELEM(ob->type, OB_CURVE, OB_SURF)) { 00176 Nurb *nu; 00177 ListBase *nurbs= ED_curve_editnurbs((Curve*)ob->data); 00178 00179 if(nurbs) { 00180 for(nu= nurbs->first; nu; nu= nu->next) 00181 if(isNurbsel(nu)) 00182 nu->mat_nr= nu->charidx= ob->actcol-1; 00183 } 00184 } 00185 else if(ob->type == OB_FONT) { 00186 EditFont *ef= ((Curve*)ob->data)->editfont; 00187 int i, selstart, selend; 00188 00189 if(ef && BKE_font_getselection(ob, &selstart, &selend)) { 00190 for(i=selstart; i<=selend; i++) 00191 ef->textbufinfo[i].mat_nr = ob->actcol; 00192 } 00193 } 00194 } 00195 00196 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 00197 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data); 00198 00199 return OPERATOR_FINISHED; 00200 } 00201 00202 void OBJECT_OT_material_slot_assign(wmOperatorType *ot) 00203 { 00204 /* identifiers */ 00205 ot->name= "Assign Material Slot"; 00206 ot->idname= "OBJECT_OT_material_slot_assign"; 00207 ot->description="Assign the material in the selected material slot to the selected vertices"; 00208 00209 /* api callbacks */ 00210 ot->exec= material_slot_assign_exec; 00211 ot->poll= ED_operator_object_active_editable; 00212 00213 /* flags */ 00214 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00215 } 00216 00217 static int material_slot_de_select(bContext *C, int select) 00218 { 00219 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 00220 00221 if(!ob) 00222 return OPERATOR_CANCELLED; 00223 00224 if(ob->type == OB_MESH) { 00225 EditMesh *em= ((Mesh*)ob->data)->edit_mesh; 00226 00227 if(em) { 00228 if(select) 00229 EM_select_by_material(em, ob->actcol-1); 00230 else 00231 EM_deselect_by_material(em, ob->actcol-1); 00232 } 00233 } 00234 else if ELEM(ob->type, OB_CURVE, OB_SURF) { 00235 ListBase *nurbs= ED_curve_editnurbs((Curve*)ob->data); 00236 Nurb *nu; 00237 BPoint *bp; 00238 BezTriple *bezt; 00239 int a; 00240 00241 if(nurbs) { 00242 for(nu= nurbs->first; nu; nu=nu->next) { 00243 if(nu->mat_nr==ob->actcol-1) { 00244 if(nu->bezt) { 00245 a= nu->pntsu; 00246 bezt= nu->bezt; 00247 while(a--) { 00248 if(bezt->hide==0) { 00249 if(select) { 00250 bezt->f1 |= SELECT; 00251 bezt->f2 |= SELECT; 00252 bezt->f3 |= SELECT; 00253 } 00254 else { 00255 bezt->f1 &= ~SELECT; 00256 bezt->f2 &= ~SELECT; 00257 bezt->f3 &= ~SELECT; 00258 } 00259 } 00260 bezt++; 00261 } 00262 } 00263 else if(nu->bp) { 00264 a= nu->pntsu*nu->pntsv; 00265 bp= nu->bp; 00266 while(a--) { 00267 if(bp->hide==0) { 00268 if(select) bp->f1 |= SELECT; 00269 else bp->f1 &= ~SELECT; 00270 } 00271 bp++; 00272 } 00273 } 00274 } 00275 } 00276 } 00277 } 00278 00279 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data); 00280 00281 return OPERATOR_FINISHED; 00282 } 00283 00284 static int material_slot_select_exec(bContext *C, wmOperator *UNUSED(op)) 00285 { 00286 return material_slot_de_select(C, 1); 00287 } 00288 00289 void OBJECT_OT_material_slot_select(wmOperatorType *ot) 00290 { 00291 /* identifiers */ 00292 ot->name= "Select Material Slot"; 00293 ot->idname= "OBJECT_OT_material_slot_select"; 00294 ot->description="Select vertices assigned to the selected material slot"; 00295 00296 /* api callbacks */ 00297 ot->exec= material_slot_select_exec; 00298 00299 /* flags */ 00300 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00301 } 00302 00303 static int material_slot_deselect_exec(bContext *C, wmOperator *UNUSED(op)) 00304 { 00305 return material_slot_de_select(C, 0); 00306 } 00307 00308 void OBJECT_OT_material_slot_deselect(wmOperatorType *ot) 00309 { 00310 /* identifiers */ 00311 ot->name= "Deselect Material Slot"; 00312 ot->idname= "OBJECT_OT_material_slot_deselect"; 00313 ot->description="Deselect vertices assigned to the selected material slot"; 00314 00315 /* api callbacks */ 00316 ot->exec= material_slot_deselect_exec; 00317 00318 /* flags */ 00319 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00320 } 00321 00322 00323 static int material_slot_copy_exec(bContext *C, wmOperator *UNUSED(op)) 00324 { 00325 Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; 00326 Material ***matar; 00327 00328 if(!ob || !(matar= give_matarar(ob))) 00329 return OPERATOR_CANCELLED; 00330 00331 CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) { 00332 if(ob != ob_iter && give_matarar(ob_iter)) { 00333 if (ob->data != ob_iter->data) 00334 assign_matarar(ob_iter, matar, ob->totcol); 00335 00336 if(ob_iter->totcol==ob->totcol) { 00337 ob_iter->actcol= ob->actcol; 00338 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob_iter); 00339 } 00340 } 00341 } 00342 CTX_DATA_END; 00343 00344 return OPERATOR_FINISHED; 00345 } 00346 00347 00348 void OBJECT_OT_material_slot_copy(wmOperatorType *ot) 00349 { 00350 /* identifiers */ 00351 ot->name= "Copy Material to Others"; 00352 ot->idname= "OBJECT_OT_material_slot_copy"; 00353 ot->description="Copies materials to other selected objects"; 00354 00355 /* api callbacks */ 00356 ot->exec= material_slot_copy_exec; 00357 00358 /* flags */ 00359 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00360 } 00361 00362 /********************** new material operator *********************/ 00363 00364 static int new_material_exec(bContext *C, wmOperator *UNUSED(op)) 00365 { 00366 Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data; 00367 PointerRNA ptr, idptr; 00368 PropertyRNA *prop; 00369 00370 /* add or copy material */ 00371 if(ma) 00372 ma= copy_material(ma); 00373 else 00374 ma= add_material("Material"); 00375 00376 /* hook into UI */ 00377 uiIDContextProperty(C, &ptr, &prop); 00378 00379 if(prop) { 00380 /* when creating new ID blocks, use is already 1, but RNA 00381 * pointer se also increases user, so this compensates it */ 00382 ma->id.us--; 00383 00384 RNA_id_pointer_create(&ma->id, &idptr); 00385 RNA_property_pointer_set(&ptr, prop, idptr); 00386 RNA_property_update(C, &ptr, prop); 00387 } 00388 00389 WM_event_add_notifier(C, NC_MATERIAL|NA_ADDED, ma); 00390 00391 return OPERATOR_FINISHED; 00392 } 00393 00394 void MATERIAL_OT_new(wmOperatorType *ot) 00395 { 00396 /* identifiers */ 00397 ot->name= "New Material"; 00398 ot->idname= "MATERIAL_OT_new"; 00399 ot->description="Add a new material"; 00400 00401 /* api callbacks */ 00402 ot->exec= new_material_exec; 00403 00404 /* flags */ 00405 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00406 } 00407 00408 /********************** new texture operator *********************/ 00409 00410 static int new_texture_exec(bContext *C, wmOperator *UNUSED(op)) 00411 { 00412 Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data; 00413 PointerRNA ptr, idptr; 00414 PropertyRNA *prop; 00415 00416 /* add or copy texture */ 00417 if(tex) 00418 tex= copy_texture(tex); 00419 else 00420 tex= add_texture("Texture"); 00421 00422 /* hook into UI */ 00423 uiIDContextProperty(C, &ptr, &prop); 00424 00425 if(prop) { 00426 /* when creating new ID blocks, use is already 1, but RNA 00427 * pointer se also increases user, so this compensates it */ 00428 tex->id.us--; 00429 00430 RNA_id_pointer_create(&tex->id, &idptr); 00431 RNA_property_pointer_set(&ptr, prop, idptr); 00432 RNA_property_update(C, &ptr, prop); 00433 } 00434 00435 WM_event_add_notifier(C, NC_TEXTURE|NA_ADDED, tex); 00436 00437 return OPERATOR_FINISHED; 00438 } 00439 00440 void TEXTURE_OT_new(wmOperatorType *ot) 00441 { 00442 /* identifiers */ 00443 ot->name= "New Texture"; 00444 ot->idname= "TEXTURE_OT_new"; 00445 ot->description="Add a new texture"; 00446 00447 /* api callbacks */ 00448 ot->exec= new_texture_exec; 00449 00450 /* flags */ 00451 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00452 } 00453 00454 /********************** new world operator *********************/ 00455 00456 static int new_world_exec(bContext *C, wmOperator *UNUSED(op)) 00457 { 00458 World *wo= CTX_data_pointer_get_type(C, "world", &RNA_World).data; 00459 PointerRNA ptr, idptr; 00460 PropertyRNA *prop; 00461 00462 /* add or copy world */ 00463 if(wo) 00464 wo= copy_world(wo); 00465 else 00466 wo= add_world("World"); 00467 00468 /* hook into UI */ 00469 uiIDContextProperty(C, &ptr, &prop); 00470 00471 if(prop) { 00472 /* when creating new ID blocks, use is already 1, but RNA 00473 * pointer se also increases user, so this compensates it */ 00474 wo->id.us--; 00475 00476 RNA_id_pointer_create(&wo->id, &idptr); 00477 RNA_property_pointer_set(&ptr, prop, idptr); 00478 RNA_property_update(C, &ptr, prop); 00479 } 00480 00481 WM_event_add_notifier(C, NC_WORLD|NA_ADDED, wo); 00482 00483 return OPERATOR_FINISHED; 00484 } 00485 00486 void WORLD_OT_new(wmOperatorType *ot) 00487 { 00488 /* identifiers */ 00489 ot->name= "New World"; 00490 ot->idname= "WORLD_OT_new"; 00491 ot->description= "Add a new world"; 00492 00493 /* api callbacks */ 00494 ot->exec= new_world_exec; 00495 00496 /* flags */ 00497 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00498 } 00499 00500 /********************** render layer operators *********************/ 00501 00502 static int render_layer_add_exec(bContext *C, wmOperator *UNUSED(op)) 00503 { 00504 Scene *scene= CTX_data_scene(C); 00505 00506 scene_add_render_layer(scene); 00507 scene->r.actlay= BLI_countlist(&scene->r.layers) - 1; 00508 00509 WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene); 00510 00511 return OPERATOR_FINISHED; 00512 } 00513 00514 void SCENE_OT_render_layer_add(wmOperatorType *ot) 00515 { 00516 /* identifiers */ 00517 ot->name= "Add Render Layer"; 00518 ot->idname= "SCENE_OT_render_layer_add"; 00519 ot->description="Add a render layer"; 00520 00521 /* api callbacks */ 00522 ot->exec= render_layer_add_exec; 00523 00524 /* flags */ 00525 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00526 } 00527 00528 static int render_layer_remove_exec(bContext *C, wmOperator *UNUSED(op)) 00529 { 00530 Scene *scene= CTX_data_scene(C); 00531 SceneRenderLayer *rl; 00532 int act= scene->r.actlay; 00533 00534 if(BLI_countlist(&scene->r.layers) <= 1) 00535 return OPERATOR_CANCELLED; 00536 00537 rl= BLI_findlink(&scene->r.layers, scene->r.actlay); 00538 BLI_remlink(&scene->r.layers, rl); 00539 MEM_freeN(rl); 00540 00541 scene->r.actlay= 0; 00542 00543 if(scene->nodetree) { 00544 bNode *node; 00545 for(node= scene->nodetree->nodes.first; node; node= node->next) { 00546 if(node->type==CMP_NODE_R_LAYERS && node->id==NULL) { 00547 if(node->custom1==act) 00548 node->custom1= 0; 00549 else if(node->custom1>act) 00550 node->custom1--; 00551 } 00552 } 00553 } 00554 00555 WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene); 00556 00557 return OPERATOR_FINISHED; 00558 } 00559 00560 void SCENE_OT_render_layer_remove(wmOperatorType *ot) 00561 { 00562 /* identifiers */ 00563 ot->name= "Remove Render Layer"; 00564 ot->idname= "SCENE_OT_render_layer_remove"; 00565 ot->description="Remove the selected render layer"; 00566 00567 /* api callbacks */ 00568 ot->exec= render_layer_remove_exec; 00569 00570 /* flags */ 00571 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00572 } 00573 00574 static int texture_slot_move(bContext *C, wmOperator *op) 00575 { 00576 ID *id= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; 00577 00578 if(id) { 00579 MTex **mtex_ar, *mtexswap; 00580 short act; 00581 int type= RNA_enum_get(op->ptr, "type"); 00582 struct AnimData *adt= BKE_animdata_from_id(id); 00583 00584 give_active_mtex(id, &mtex_ar, &act); 00585 00586 if(type == -1) { /* Up */ 00587 if(act > 0) { 00588 mtexswap = mtex_ar[act]; 00589 mtex_ar[act] = mtex_ar[act-1]; 00590 mtex_ar[act-1] = mtexswap; 00591 00592 BKE_animdata_fix_paths_rename(id, adt, "texture_slots", NULL, NULL, act-1, -1, 0); 00593 BKE_animdata_fix_paths_rename(id, adt, "texture_slots", NULL, NULL, act, act-1, 0); 00594 BKE_animdata_fix_paths_rename(id, adt, "texture_slots", NULL, NULL, -1, act, 0); 00595 00596 if(GS(id->name)==ID_MA) { 00597 Material *ma= (Material *)id; 00598 int mtexuse = ma->septex & (1<<act); 00599 ma->septex &= ~(1<<act); 00600 ma->septex |= (ma->septex & (1<<(act-1))) << 1; 00601 ma->septex &= ~(1<<(act-1)); 00602 ma->septex |= mtexuse >> 1; 00603 } 00604 00605 set_active_mtex(id, act-1); 00606 } 00607 } 00608 else { /* Down */ 00609 if(act < MAX_MTEX-1) { 00610 mtexswap = mtex_ar[act]; 00611 mtex_ar[act] = mtex_ar[act+1]; 00612 mtex_ar[act+1] = mtexswap; 00613 00614 BKE_animdata_fix_paths_rename(id, adt, "texture_slots", NULL, NULL, act+1, -1, 0); 00615 BKE_animdata_fix_paths_rename(id, adt, "texture_slots", NULL, NULL, act, act+1, 0); 00616 BKE_animdata_fix_paths_rename(id, adt, "texture_slots", NULL, NULL, -1, act, 0); 00617 00618 if(GS(id->name)==ID_MA) { 00619 Material *ma= (Material *)id; 00620 int mtexuse = ma->septex & (1<<act); 00621 ma->septex &= ~(1<<act); 00622 ma->septex |= (ma->septex & (1<<(act+1))) >> 1; 00623 ma->septex &= ~(1<<(act+1)); 00624 ma->septex |= mtexuse << 1; 00625 } 00626 00627 set_active_mtex(id, act+1); 00628 } 00629 } 00630 00631 DAG_id_tag_update(id, 0); 00632 WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C)); 00633 } 00634 00635 return OPERATOR_FINISHED; 00636 } 00637 00638 void TEXTURE_OT_slot_move(wmOperatorType *ot) 00639 { 00640 static EnumPropertyItem slot_move[] = { 00641 {-1, "UP", 0, "Up", ""}, 00642 {1, "DOWN", 0, "Down", ""}, 00643 {0, NULL, 0, NULL, NULL} 00644 }; 00645 00646 /* identifiers */ 00647 ot->name= "Move Texture Slot"; 00648 ot->idname= "TEXTURE_OT_slot_move"; 00649 ot->description="Move texture slots up and down"; 00650 00651 /* api callbacks */ 00652 ot->exec= texture_slot_move; 00653 00654 /* flags */ 00655 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00656 00657 RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", ""); 00658 } 00659 00660 00661 00662 /********************** environment map operators *********************/ 00663 00664 static int save_envmap(wmOperator *op, Scene *scene, EnvMap *env, char *str, int imtype) 00665 { 00666 ImBuf *ibuf=NULL; 00667 int dx; 00668 int retval; 00669 int relative= (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path")); 00670 00671 if(env->cube[1]==NULL) { 00672 BKE_report(op->reports, RPT_ERROR, "There is no generated environment map available to save"); 00673 return OPERATOR_CANCELLED; 00674 } 00675 00676 dx= env->cube[1]->x; 00677 00678 if (env->type == ENV_CUBE) { 00679 ibuf = IMB_allocImBuf(3*dx, 2*dx, 24, IB_rectfloat); 00680 00681 IMB_rectcpy(ibuf, env->cube[0], 0, 0, 0, 0, dx, dx); 00682 IMB_rectcpy(ibuf, env->cube[1], dx, 0, 0, 0, dx, dx); 00683 IMB_rectcpy(ibuf, env->cube[2], 2*dx, 0, 0, 0, dx, dx); 00684 IMB_rectcpy(ibuf, env->cube[3], 0, dx, 0, 0, dx, dx); 00685 IMB_rectcpy(ibuf, env->cube[4], dx, dx, 0, 0, dx, dx); 00686 IMB_rectcpy(ibuf, env->cube[5], 2*dx, dx, 0, 0, dx, dx); 00687 } 00688 else if (env->type == ENV_PLANE) { 00689 ibuf = IMB_allocImBuf(dx, dx, 24, IB_rectfloat); 00690 IMB_rectcpy(ibuf, env->cube[1], 0, 0, 0, 0, dx, dx); 00691 } 00692 else { 00693 BKE_report(op->reports, RPT_ERROR, "Invalid environment map type"); 00694 return OPERATOR_CANCELLED; 00695 } 00696 00697 if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) 00698 ibuf->profile = IB_PROFILE_LINEAR_RGB; 00699 00700 /* to save, we first get absolute path */ 00701 BLI_path_abs(str, G.main->name); 00702 00703 if (BKE_write_ibuf(ibuf, str, imtype, scene->r.subimtype, scene->r.quality)) { 00704 retval = OPERATOR_FINISHED; 00705 } 00706 else { 00707 BKE_reportf(op->reports, RPT_ERROR, "Error saving environment map to %s.", str); 00708 retval = OPERATOR_CANCELLED; 00709 } 00710 /* in case we were saving with relative paths, change back again */ 00711 if(relative) 00712 BLI_path_rel(str, G.main->name); 00713 00714 IMB_freeImBuf(ibuf); 00715 ibuf = NULL; 00716 00717 return retval; 00718 } 00719 00720 static int envmap_save_exec(bContext *C, wmOperator *op) 00721 { 00722 Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data; 00723 Scene *scene = CTX_data_scene(C); 00724 //int imtype = RNA_enum_get(op->ptr, "file_type"); 00725 int imtype = scene->r.imtype; 00726 char path[FILE_MAX]; 00727 00728 RNA_string_get(op->ptr, "filepath", path); 00729 00730 if(scene->r.scemode & R_EXTENSION) { 00731 BKE_add_image_extension(path, imtype); 00732 } 00733 00734 WM_cursor_wait(1); 00735 00736 save_envmap(op, scene, tex->env, path, imtype); 00737 00738 WM_cursor_wait(0); 00739 00740 WM_event_add_notifier(C, NC_TEXTURE, tex); 00741 00742 return OPERATOR_FINISHED; 00743 } 00744 00745 static int envmap_save_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 00746 { 00747 //Scene *scene= CTX_data_scene(C); 00748 00749 if(!RNA_property_is_set(op->ptr, "relative_path")) 00750 RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS); 00751 00752 if(RNA_property_is_set(op->ptr, "filepath")) 00753 return envmap_save_exec(C, op); 00754 00755 //RNA_enum_set(op->ptr, "file_type", scene->r.imtype); 00756 00757 RNA_string_set(op->ptr, "filepath", G.main->name); 00758 WM_event_add_fileselect(C, op); 00759 00760 return OPERATOR_RUNNING_MODAL; 00761 } 00762 00763 static int envmap_save_poll(bContext *C) 00764 { 00765 Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data; 00766 00767 if (!tex) 00768 return 0; 00769 if (!tex->env || !tex->env->ok) 00770 return 0; 00771 if (tex->env->cube[1]==NULL) 00772 return 0; 00773 00774 return 1; 00775 } 00776 00777 void TEXTURE_OT_envmap_save(wmOperatorType *ot) 00778 { 00779 /* identifiers */ 00780 ot->name= "Save Environment Map"; 00781 ot->idname= "TEXTURE_OT_envmap_save"; 00782 ot->description="Save the current generated Environment map to an image file"; 00783 00784 /* api callbacks */ 00785 ot->exec= envmap_save_exec; 00786 ot->invoke= envmap_save_invoke; 00787 ot->poll= envmap_save_poll; 00788 00789 /* flags */ 00790 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00791 00792 /* properties */ 00793 //RNA_def_enum(ot->srna, "file_type", image_file_type_items, R_PNG, "File Type", "File type to save image as."); 00794 WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE|MOVIEFILE, FILE_SPECIAL, FILE_SAVE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH); 00795 } 00796 00797 static int envmap_clear_exec(bContext *C, wmOperator *UNUSED(op)) 00798 { 00799 Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data; 00800 00801 BKE_free_envmapdata(tex->env); 00802 00803 WM_event_add_notifier(C, NC_TEXTURE|NA_EDITED, tex); 00804 00805 return OPERATOR_FINISHED; 00806 } 00807 00808 static int envmap_clear_poll(bContext *C) 00809 { 00810 Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data; 00811 00812 if (!tex) 00813 return 0; 00814 if (!tex->env || !tex->env->ok) 00815 return 0; 00816 if (tex->env->cube[1]==NULL) 00817 return 0; 00818 00819 return 1; 00820 } 00821 00822 void TEXTURE_OT_envmap_clear(wmOperatorType *ot) 00823 { 00824 /* identifiers */ 00825 ot->name= "Clear Environment Map"; 00826 ot->idname= "TEXTURE_OT_envmap_clear"; 00827 ot->description="Discard the environment map and free it from memory"; 00828 00829 /* api callbacks */ 00830 ot->exec= envmap_clear_exec; 00831 ot->poll= envmap_clear_poll; 00832 00833 /* flags */ 00834 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00835 } 00836 00837 static int envmap_clear_all_exec(bContext *C, wmOperator *UNUSED(op)) 00838 { 00839 Main *bmain = CTX_data_main(C); 00840 Tex *tex; 00841 00842 for (tex=bmain->tex.first; tex; tex=tex->id.next) 00843 if (tex->env) 00844 BKE_free_envmapdata(tex->env); 00845 00846 WM_event_add_notifier(C, NC_TEXTURE|NA_EDITED, tex); 00847 00848 return OPERATOR_FINISHED; 00849 } 00850 00851 void TEXTURE_OT_envmap_clear_all(wmOperatorType *ot) 00852 { 00853 /* identifiers */ 00854 ot->name= "Clear All Environment Maps"; 00855 ot->idname= "TEXTURE_OT_envmap_clear_all"; 00856 ot->description="Discard all environment maps in the .blend file and free them from memory"; 00857 00858 /* api callbacks */ 00859 ot->exec= envmap_clear_all_exec; 00860 ot->poll= envmap_clear_poll; 00861 00862 /* flags */ 00863 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00864 } 00865 00866 /********************** material operators *********************/ 00867 00868 /* material copy/paste */ 00869 static int copy_material_exec(bContext *C, wmOperator *UNUSED(op)) 00870 { 00871 Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data; 00872 00873 if(ma==NULL) 00874 return OPERATOR_CANCELLED; 00875 00876 copy_matcopybuf(ma); 00877 00878 WM_event_add_notifier(C, NC_MATERIAL, ma); 00879 00880 return OPERATOR_FINISHED; 00881 } 00882 00883 void MATERIAL_OT_copy(wmOperatorType *ot) 00884 { 00885 /* identifiers */ 00886 ot->name= "Copy Material"; 00887 ot->idname= "MATERIAL_OT_copy"; 00888 ot->description="Copy the material settings and nodes"; 00889 00890 /* api callbacks */ 00891 ot->exec= copy_material_exec; 00892 00893 /* flags */ 00894 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00895 } 00896 00897 static int paste_material_exec(bContext *C, wmOperator *UNUSED(op)) 00898 { 00899 Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data; 00900 00901 if(ma==NULL) 00902 return OPERATOR_CANCELLED; 00903 00904 paste_matcopybuf(ma); 00905 00906 WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING_DRAW, ma); 00907 00908 return OPERATOR_FINISHED; 00909 } 00910 00911 void MATERIAL_OT_paste(wmOperatorType *ot) 00912 { 00913 /* identifiers */ 00914 ot->name= "Paste Material"; 00915 ot->idname= "MATERIAL_OT_paste"; 00916 ot->description="Paste the material settings and nodes"; 00917 00918 /* api callbacks */ 00919 ot->exec= paste_material_exec; 00920 00921 /* flags */ 00922 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00923 } 00924 00925 00926 static short mtexcopied=0; /* must be reset on file load */ 00927 static MTex mtexcopybuf; 00928 00929 void ED_render_clear_mtex_copybuf(void) 00930 { /* use for file reload */ 00931 mtexcopied= 0; 00932 } 00933 00934 static void copy_mtex_copybuf(ID *id) 00935 { 00936 MTex **mtex= NULL; 00937 00938 switch(GS(id->name)) { 00939 case ID_MA: 00940 mtex= &(((Material *)id)->mtex[(int)((Material *)id)->texact]); 00941 break; 00942 case ID_LA: 00943 mtex= &(((Lamp *)id)->mtex[(int)((Lamp *)id)->texact]); 00944 // la->mtex[(int)la->texact] // TODO 00945 break; 00946 case ID_WO: 00947 mtex= &(((World *)id)->mtex[(int)((World *)id)->texact]); 00948 // mtex= wrld->mtex[(int)wrld->texact]; // TODO 00949 break; 00950 case ID_PA: 00951 mtex= &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]); 00952 break; 00953 } 00954 00955 if(mtex && *mtex) { 00956 memcpy(&mtexcopybuf, *mtex, sizeof(MTex)); 00957 mtexcopied= 1; 00958 } 00959 else { 00960 mtexcopied= 0; 00961 } 00962 } 00963 00964 static void paste_mtex_copybuf(ID *id) 00965 { 00966 MTex **mtex= NULL; 00967 00968 if(mtexcopied == 0 || mtexcopybuf.tex==NULL) 00969 return; 00970 00971 switch(GS(id->name)) { 00972 case ID_MA: 00973 mtex= &(((Material *)id)->mtex[(int)((Material *)id)->texact]); 00974 break; 00975 case ID_LA: 00976 mtex= &(((Lamp *)id)->mtex[(int)((Lamp *)id)->texact]); 00977 // la->mtex[(int)la->texact] // TODO 00978 break; 00979 case ID_WO: 00980 mtex= &(((World *)id)->mtex[(int)((World *)id)->texact]); 00981 // mtex= wrld->mtex[(int)wrld->texact]; // TODO 00982 break; 00983 case ID_PA: 00984 mtex= &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]); 00985 break; 00986 default: 00987 BLI_assert("invalid id type"); 00988 return; 00989 } 00990 00991 if(mtex) { 00992 if(*mtex==NULL) { 00993 *mtex= MEM_mallocN(sizeof(MTex), "mtex copy"); 00994 } 00995 else if((*mtex)->tex) { 00996 (*mtex)->tex->id.us--; 00997 } 00998 00999 memcpy(*mtex, &mtexcopybuf, sizeof(MTex)); 01000 01001 id_us_plus((ID *)mtexcopybuf.tex); 01002 } 01003 } 01004 01005 01006 static int copy_mtex_exec(bContext *C, wmOperator *UNUSED(op)) 01007 { 01008 ID *id= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; 01009 01010 if(id==NULL) { 01011 /* copying empty slot */ 01012 ED_render_clear_mtex_copybuf(); 01013 return OPERATOR_CANCELLED; 01014 } 01015 01016 copy_mtex_copybuf(id); 01017 01018 WM_event_add_notifier(C, NC_TEXTURE, NULL); 01019 01020 return OPERATOR_FINISHED; 01021 } 01022 01023 static int copy_mtex_poll(bContext *C) 01024 { 01025 ID *id= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; 01026 01027 return (id != NULL); 01028 } 01029 01030 void TEXTURE_OT_slot_copy(wmOperatorType *ot) 01031 { 01032 /* identifiers */ 01033 ot->name= "Copy Texture Slot Settings"; 01034 ot->idname= "TEXTURE_OT_slot_copy"; 01035 ot->description="Copy the material texture settings and nodes"; 01036 01037 /* api callbacks */ 01038 ot->exec= copy_mtex_exec; 01039 ot->poll= copy_mtex_poll; 01040 01041 /* flags */ 01042 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01043 } 01044 01045 static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op)) 01046 { 01047 ID *id= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; 01048 01049 if(id==NULL) { 01050 Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data; 01051 Lamp *la= CTX_data_pointer_get_type(C, "lamp", &RNA_Lamp).data; 01052 World *wo= CTX_data_pointer_get_type(C, "world", &RNA_World).data; 01053 ParticleSystem *psys= CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data; 01054 01055 if (ma) 01056 id = &ma->id; 01057 else if (la) 01058 id = &la->id; 01059 else if (wo) 01060 id = &wo->id; 01061 else if (psys) 01062 id = &psys->part->id; 01063 01064 if (id==NULL) 01065 return OPERATOR_CANCELLED; 01066 } 01067 01068 paste_mtex_copybuf(id); 01069 01070 WM_event_add_notifier(C, NC_TEXTURE|ND_SHADING_DRAW, NULL); 01071 01072 return OPERATOR_FINISHED; 01073 } 01074 01075 void TEXTURE_OT_slot_paste(wmOperatorType *ot) 01076 { 01077 /* identifiers */ 01078 ot->name= "Paste Texture Slot Settings"; 01079 ot->idname= "TEXTURE_OT_slot_paste"; 01080 ot->description="Copy the texture settings and nodes"; 01081 01082 /* api callbacks */ 01083 ot->exec= paste_mtex_exec; 01084 01085 /* flags */ 01086 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01087 } 01088