Blender V2.61 - r43446

render_shading.c

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