Blender  V2.59
render_shading.c
Go to the documentation of this file.
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