Big commit in orange: Interface icons for materials, textures
[blender-staging.git] / source / blender / blenkernel / intern / material.c
1
2 /*  material.c
3  *
4  * 
5  * $Id$
6  *
7  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version. The Blender
13  * Foundation also sells licenses for use in proprietary software under
14  * the Blender License.  See http://www.blender.org/BL/ for information
15  * about this.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  *
26  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
27  * All rights reserved.
28  *
29  * The Original Code is: all of this file.
30  *
31  * Contributor(s): none yet.
32  *
33  * ***** END GPL/BL DUAL LICENSE BLOCK *****
34  */
35
36 #include <string.h>
37 #include "MEM_guardedalloc.h"
38
39 #include "DNA_curve_types.h"
40 #include "DNA_material_types.h"
41 #include "DNA_mesh_types.h"
42 #include "DNA_meta_types.h"
43 #include "DNA_object_types.h"
44 #include "DNA_scene_types.h"
45 #include "DNA_texture_types.h"
46
47 #include "BLI_blenlib.h"
48
49 #include "BKE_bad_level_calls.h"
50 #include "BKE_blender.h"
51 #include "BKE_displist.h"
52 #include "BKE_global.h"
53 #include "BKE_icons.h"
54 #include "BKE_library.h"
55 #include "BKE_main.h"
56 #include "BKE_material.h"
57 #include "BKE_mesh.h"
58 #include "BKE_utildefines.h"
59
60 #include "BPY_extern.h"
61
62 /* not material itself */
63 void free_material(Material *ma)
64 {
65         MaterialLayer *ml;
66         MTex *mtex;
67         int a;
68
69         BPY_free_scriptlink(&ma->scriptlink);
70         
71         for(a=0; a<MAX_MTEX; a++) {
72                 mtex= ma->mtex[a];
73                 if(mtex && mtex->tex) mtex->tex->id.us--;
74                 if(mtex) MEM_freeN(mtex);
75         }
76         
77         if(ma->ramp_col) MEM_freeN(ma->ramp_col);
78         if(ma->ramp_spec) MEM_freeN(ma->ramp_spec);
79         
80         BKE_icon_delete((struct ID*)ma);
81         ma->id.icon_id = 0;
82
83         for(ml= ma->layers.first; ml; ml= ml->next)
84                 if(ml->mat) ml->mat->id.us--;
85         
86         BLI_freelistN(&ma->layers);
87 }
88
89 void init_material(Material *ma)
90 {
91         ma->lay= 1;
92         ma->r= ma->g= ma->b= ma->ref= 0.8;
93         ma->specr= ma->specg= ma->specb= 1.0;
94         ma->mirr= ma->mirg= ma->mirb= 1.0;
95         ma->spectra= 1.0;
96         ma->amb= 0.5;
97         ma->alpha= 1.0;
98         ma->spec= ma->hasize= 0.5;
99         ma->har= 50;
100         ma->starc= ma->ringc= 4;
101         ma->linec= 12;
102         ma->flarec= 1;
103         ma->flaresize= ma->subsize= 1.0;
104         ma->flareboost= 1;
105         ma->seed2= 6;
106         ma->friction= 0.5;
107         ma->refrac= 4.0;
108         ma->roughness= 0.5;
109         ma->param[0]= 0.5;
110         ma->param[1]= 0.1;
111         ma->param[2]= 0.5;
112         ma->param[3]= 0.1;
113         ma->rms= 0.1;
114         ma->darkness= 1.0;      
115         
116         ma->strand_sta= ma->strand_end= 1.0f;
117         
118         ma->ang= 1.0;
119         ma->ray_depth= 2;
120         ma->ray_depth_tra= 2;
121         ma->fresnel_mir= 0.0;
122         ma->fresnel_tra= 0.0;
123         ma->fresnel_tra_i= 1.25;
124         ma->fresnel_mir_i= 1.25;
125         
126         ma->rampfac_col= 1.0;
127         ma->rampfac_spec= 1.0;
128         ma->pr_lamp= 3;                 /* two lamps, is bits */
129         ma->ml_flag= ML_RENDER; /* default render base material for layers */
130
131         ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RADIO|MA_RAYBIAS|MA_TANGENT_STR;
132 }
133
134 Material *add_material(char *name)
135 {
136         Material *ma;
137
138         ma= alloc_libblock(&G.main->mat, ID_MA, name);
139         
140         init_material(ma);
141         
142         return ma;      
143 }
144
145 Material *copy_material(Material *ma)
146 {
147         Material *man;
148         MaterialLayer *ml;
149         int a;
150         
151         man= copy_libblock(ma);
152         
153         id_us_plus((ID *)man->ipo);
154         
155         for(a=0; a<MAX_MTEX; a++) {
156                 if(ma->mtex[a]) {
157                         man->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial");
158                         memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex));
159                         id_us_plus((ID *)man->mtex[a]->tex);
160                 }
161         }
162         
163         BPY_copy_scriptlink(&ma->scriptlink);
164         
165         if(ma->ramp_col) man->ramp_col= MEM_dupallocN(ma->ramp_col);
166         if(ma->ramp_spec) man->ramp_spec= MEM_dupallocN(ma->ramp_spec);
167         
168         duplicatelist(&man->layers, &ma->layers);
169         for(ml= man->layers.first; ml; ml= ml->next)
170                 id_us_plus((ID *)ml->mat);
171
172         return man;
173 }
174
175 void make_local_material(Material *ma)
176 {
177         Object *ob;
178         Mesh *me;
179         Curve *cu;
180         MetaBall *mb;
181         Material *man;
182         int a, local=0, lib=0;
183
184         /* - only lib users: do nothing
185             * - only local users: set flag
186             * - mixed: make copy
187             */
188         
189         if(ma->id.lib==0) return;
190         if(ma->id.us==1) {
191                 ma->id.lib= 0;
192                 ma->id.flag= LIB_LOCAL;
193                 new_id(0, (ID *)ma, 0);
194                 for(a=0; a<MAX_MTEX; a++) {
195                         if(ma->mtex[a]) id_lib_extern((ID *)ma->mtex[a]->tex);
196                 }
197                 
198                 return;
199         }
200         
201         /* test objects */
202         ob= G.main->object.first;
203         while(ob) {
204                 if(ob->mat) {
205                         for(a=0; a<ob->totcol; a++) {
206                                 if(ob->mat[a]==ma) {
207                                         if(ob->id.lib) lib= 1;
208                                         else local= 1;
209                                 }
210                         }
211                 }
212                 ob= ob->id.next;
213         }
214         /* test meshes */
215         me= G.main->mesh.first;
216         while(me) {
217                 if(me->mat) {
218                         for(a=0; a<me->totcol; a++) {
219                                 if(me->mat[a]==ma) {
220                                         if(me->id.lib) lib= 1;
221                                         else local= 1;
222                                 }
223                         }
224                 }
225                 me= me->id.next;
226         }
227         /* test curves */
228         cu= G.main->curve.first;
229         while(cu) {
230                 if(cu->mat) {
231                         for(a=0; a<cu->totcol; a++) {
232                                 if(cu->mat[a]==ma) {
233                                         if(cu->id.lib) lib= 1;
234                                         else local= 1;
235                                 }
236                         }
237                 }
238                 cu= cu->id.next;
239         }
240         /* test mballs */
241         mb= G.main->mball.first;
242         while(mb) {
243                 if(mb->mat) {
244                         for(a=0; a<mb->totcol; a++) {
245                                 if(mb->mat[a]==ma) {
246                                         if(mb->id.lib) lib= 1;
247                                         else local= 1;
248                                 }
249                         }
250                 }
251                 mb= mb->id.next;
252         }
253         
254         if(local && lib==0) {
255                 ma->id.lib= 0;
256                 ma->id.flag= LIB_LOCAL;
257                 
258                 for(a=0; a<MAX_MTEX; a++) {
259                         if(ma->mtex[a]) id_lib_extern((ID *)ma->mtex[a]->tex);
260                 }
261                 
262                 new_id(0, (ID *)ma, 0);
263         }
264         else if(local && lib) {
265                 Material *mat;
266                 MaterialLayer *ml;
267                 
268                 man= copy_material(ma);
269                 man->id.us= 0;
270                 
271                 /* do material layers */
272                 for(mat= G.main->mat.first; mat; mat= mat->id.next) {
273                         if(mat->id.lib==NULL) {
274                                 for(ml= mat->layers.first; ml; ml= ml->next) {
275                                         if(ml->mat==ma) {
276                                                 ml->mat= man;
277                                                 man->id.us++;
278                                                 ma->id.us--;
279                                         }
280                                 }
281                         }
282                 }
283                 
284                 /* do objects */
285                 ob= G.main->object.first;
286                 while(ob) {
287                         if(ob->mat) {
288                                 for(a=0; a<ob->totcol; a++) {
289                                         if(ob->mat[a]==ma) {
290                                                 if(ob->id.lib==0) {
291                                                         ob->mat[a]= man;
292                                                         man->id.us++;
293                                                         ma->id.us--;
294                                                 }
295                                         }
296                                 }
297                         }
298                         ob= ob->id.next;
299                 }
300                 /* do meshes */
301                 me= G.main->mesh.first;
302                 while(me) {
303                         if(me->mat) {
304                                 for(a=0; a<me->totcol; a++) {
305                                         if(me->mat[a]==ma) {
306                                                 if(me->id.lib==0) {
307                                                         me->mat[a]= man;
308                                                         man->id.us++;
309                                                         ma->id.us--;
310                                                 }
311                                         }
312                                 }
313                         }
314                         me= me->id.next;
315                 }
316                 /* do curves */
317                 cu= G.main->curve.first;
318                 while(cu) {
319                         if(cu->mat) {
320                                 for(a=0; a<cu->totcol; a++) {
321                                         if(cu->mat[a]==ma) {
322                                                 if(cu->id.lib==0) {
323                                                         cu->mat[a]= man;
324                                                         man->id.us++;
325                                                         ma->id.us--;
326                                                 }
327                                         }
328                                 }
329                         }
330                         cu= cu->id.next;
331                 }
332                 /* do mballs */
333                 mb= G.main->mball.first;
334                 while(mb) {
335                         if(mb->mat) {
336                                 for(a=0; a<mb->totcol; a++) {
337                                         if(mb->mat[a]==ma) {
338                                                 if(mb->id.lib==0) {
339                                                         mb->mat[a]= man;
340                                                         man->id.us++;
341                                                         ma->id.us--;
342                                                 }
343                                         }
344                                 }
345                         }
346                         mb= mb->id.next;
347                 }
348         }
349 }
350
351 Material ***give_matarar(Object *ob)
352 {
353         Mesh *me;
354         Curve *cu;
355         MetaBall *mb;
356         
357         if(ob->type==OB_MESH) {
358                 me= ob->data;
359                 return &(me->mat);
360         }
361         else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) {
362                 cu= ob->data;
363                 return &(cu->mat);
364         }
365         else if(ob->type==OB_MBALL) {
366                 mb= ob->data;
367                 return &(mb->mat);
368         }
369         return 0;
370 }
371
372 short *give_totcolp(Object *ob)
373 {
374         Mesh *me;
375         Curve *cu;
376         MetaBall *mb;
377         
378         if(ob->type==OB_MESH) {
379                 me= ob->data;
380                 return &(me->totcol);
381         }
382         else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) {
383                 cu= ob->data;
384                 return &(cu->totcol);
385         }
386         else if(ob->type==OB_MBALL) {
387                 mb= ob->data;
388                 return &(mb->totcol);
389         }
390         return 0;
391 }
392
393 Material *give_current_material(Object *ob, int act)
394 {
395         Material ***matarar, *ma;
396         
397         if(ob==0) return 0;
398         if(ob->totcol==0) return 0;
399         
400         if(act>ob->totcol) act= ob->totcol;
401         else if(act==0) act= 1;
402
403         if( BTST(ob->colbits, act-1) ) {        /* in object */
404                 ma= ob->mat[act-1];
405         }
406         else {                                                          /* in data */
407                 matarar= give_matarar(ob);
408                 
409                 if(matarar && *matarar) ma= (*matarar)[act-1];
410                 else ma= 0;
411                 
412         }
413         
414         return ma;
415 }
416
417 ID *material_from(Object *ob, int act)
418 {
419
420         if(ob==0) return 0;
421
422         if(ob->totcol==0) return ob->data;
423         if(act==0) act= 1;
424
425         if( BTST(ob->colbits, act-1) ) return (ID *)ob;
426         else return ob->data;
427 }
428
429 /* GS reads the memory pointed at in a specific ordering. There are,
430  * however two definitions for it. I have jotted them down here, both,
431  * but I think the first one is actually used. The thing is that
432  * big-endian systems might read this the wrong way round. OTOH, we
433  * constructed the IDs that are read out with this macro explicitly as
434  * well. I expect we'll sort it out soon... */
435
436 /* from blendef: */
437 #define GS(a)   (*((short *)(a)))
438
439 /* from misc_util: flip the bytes from x  */
440 /*  #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
441
442 void test_object_materials(ID *id)
443 {
444         /* make the ob mat-array same size as 'ob->data' mat-array */
445         Object *ob;
446         Mesh *me;
447         Curve *cu;
448         MetaBall *mb;
449         Material **newmatar;
450         int totcol=0;
451
452         if(id==0) return;
453
454         if( GS(id->name)==ID_ME ) {
455                 me= (Mesh *)id;
456                 totcol= me->totcol;
457         }
458         else if( GS(id->name)==ID_CU ) {
459                 cu= (Curve *)id;
460                 totcol= cu->totcol;
461         }
462         else if( GS(id->name)==ID_MB ) {
463                 mb= (MetaBall *)id;
464                 totcol= mb->totcol;
465         }
466         else return;
467
468         ob= G.main->object.first;
469         while(ob) {
470                 
471                 if(ob->data==id) {
472                 
473                         if(totcol==0) {
474                                 if(ob->totcol) {
475                                         MEM_freeN(ob->mat);
476                                         ob->mat= 0;
477                                 }
478                         }
479                         else if(ob->totcol<totcol) {
480                                 newmatar= MEM_callocN(sizeof(void *)*totcol, "newmatar");
481                                 if(ob->totcol) {
482                                         memcpy(newmatar, ob->mat, sizeof(void *)*ob->totcol);
483                                         MEM_freeN(ob->mat);
484                                 }
485                                 ob->mat= newmatar;
486                         }
487                         ob->totcol= totcol;
488                         if(ob->totcol && ob->actcol==0) ob->actcol= 1;
489                         if(ob->actcol>ob->totcol) ob->actcol= ob->totcol;
490                 }
491                 ob= ob->id.next;
492         }
493 }
494
495
496 void assign_material(Object *ob, Material *ma, int act)
497 {
498         Material *mao, **matar, ***matarar;
499         short *totcolp;
500
501         if(act>MAXMAT) return;
502         if(act<1) act= 1;
503         
504         /* test arraylens */
505         
506         totcolp= give_totcolp(ob);
507         matarar= give_matarar(ob);
508         
509         if(totcolp==0 || matarar==0) return;
510         
511         if( act > *totcolp) {
512                 matar= MEM_callocN(sizeof(void *)*act, "matarray1");
513                 if( *totcolp) {
514                         memcpy(matar, *matarar, sizeof(void *)*( *totcolp ));
515                         MEM_freeN(*matarar);
516                 }
517                 *matarar= matar;
518                 *totcolp= act;
519         }
520         
521         if(act > ob->totcol) {
522                 matar= MEM_callocN(sizeof(void *)*act, "matarray2");
523                 if( ob->totcol) {
524                         memcpy(matar, ob->mat, sizeof(void *)*( ob->totcol ));
525                         MEM_freeN(ob->mat);
526                 }
527                 ob->mat= matar;
528                 ob->totcol= act;
529         }
530         
531         /* do it */
532
533         if( BTST(ob->colbits, act-1) ) {        /* in object */
534                 mao= ob->mat[act-1];
535                 if(mao) mao->id.us--;
536                 ob->mat[act-1]= ma;
537         }
538         else {  /* in data */
539                 mao= (*matarar)[act-1];
540                 if(mao) mao->id.us--;
541                 (*matarar)[act-1]= ma;
542         }
543         id_us_plus((ID *)ma);
544         test_object_materials(ob->data);
545 }
546
547 void new_material_to_objectdata(Object *ob)
548 {
549         Material *ma;
550         
551         if(ob==0) return;
552         if(ob->totcol>=MAXMAT) return;
553         
554         ma= give_current_material(ob, ob->actcol);
555         if(ma==0) {
556                 ma= add_material("Material");
557                 ma->id.us= 0;
558         }
559         
560         if(ob->actcol) {
561                 if( BTST(ob->colbits, ob->actcol-1) ) {
562                         ob->colbits= BSET(ob->colbits, ob->totcol);
563                 }
564         }
565         
566         assign_material(ob, ma, ob->totcol+1);
567         ob->actcol= ob->totcol;
568 }
569
570 Material *get_active_matlayer(Material *ma)
571 {
572         MaterialLayer *ml;
573         
574         if(ma==NULL) return NULL;
575         
576         for(ml= ma->layers.first; ml; ml= ml->next)
577                 if(ml->flag & ML_ACTIVE) break;
578         if(ml)
579                 return ml->mat;
580         return ma;
581 }
582
583 void init_render_material(Material *ma)
584 {
585         MTex *mtex;
586         int a, needuv=0;
587         
588         if(ma->flarec==0) ma->flarec= 1;
589
590         /* add all texcoflags from mtex */
591         ma->texco= 0;
592         ma->mapto= 0;
593         for(a=0; a<MAX_MTEX; a++) {
594                 mtex= ma->mtex[a];
595                 if(mtex && mtex->tex) {
596                         
597                         ma->texco |= mtex->texco;
598                         ma->mapto |= mtex->mapto;
599                         if(R.osa) {
600                                 if ELEM3(mtex->tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) ma->texco |= TEXCO_OSA;
601                         }
602                         
603                         if(ma->texco & (TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM|TEXCO_STRAND|TEXCO_STRESS)) needuv= 1;
604                         else if(ma->texco & (TEXCO_GLOB|TEXCO_UV|TEXCO_OBJECT)) needuv= 1;
605                         else if(ma->texco & (TEXCO_LAVECTOR|TEXCO_VIEW|TEXCO_STICKY)) needuv= 1;
606                         
607                         if(mtex->object) mtex->object->flag |= OB_DO_IMAT;
608                         
609                 }
610         }
611         if(ma->mode & MA_ZTRA) {
612                 /* if(ma->alpha==0.0 || ma->alpha==1.0) */
613                 if(R.flag & R_RENDERING) R.flag |= R_ZTRA;
614         }
615         
616         if(ma->mode & MA_RADIO) needuv= 1;
617         
618         if(ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE)) {
619                 needuv= 1;
620                 if(R.osa) ma->texco |= TEXCO_OSA;               /* for texfaces */
621         }
622         if(needuv) ma->texco |= NEED_UV;
623         
624         // since the raytracer doesnt recalc O structs for each ray, we have to preset them all
625         if(ma->mode & (MA_RAYMIRROR|MA_RAYTRANSP|MA_SHADOW_TRA)) { 
626                 ma->texco |= NEED_UV|TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM;
627                 if(R.osa) ma->texco |= TEXCO_OSA;
628         }
629
630         ma->ambr= ma->amb*R.wrld.ambr;
631         ma->ambg= ma->amb*R.wrld.ambg;
632         ma->ambb= ma->amb*R.wrld.ambb;
633         
634         /* will become or-ed result of all layer modes */
635         ma->mode_l= ma->mode;
636 }
637
638 void init_render_materials()
639 {
640         Material *ma;
641         MaterialLayer *ml;
642         
643         /* two steps, first initialize, then or the flags for layers */
644         for(ma= G.main->mat.first; ma; ma= ma->id.next) {
645                 if(ma->id.us) init_render_material(ma);
646         }
647         
648         for(ma= G.main->mat.first; ma; ma= ma->id.next) {
649                 for(ml= ma->layers.first; ml; ml= ml->next) {
650                         if(ml->mat) {
651                                 ma->texco |= ml->mat->texco;
652                                 ma->mode_l |= ml->mat->mode;
653                         }
654                 }
655         }       
656 }
657
658 /* ****************** */
659
660 char colname_array[125][20]= {
661 "Black","DarkRed","HalveRed","Red","Red",
662 "DarkGreen","DarkOlive","Brown","Chocolate","OrangeRed",
663 "HalveGreen","GreenOlive","DryOlive","Goldenrod","DarkOrange",
664 "LightGreen","Chartreuse","YellowGreen","Yellow","Gold",
665 "Green","LawnGreen","GreenYellow","LightOlive","Yellow",
666 "DarkBlue","DarkPurple","HotPink","VioletPink","RedPink",
667 "SlateGray","DarkGrey","PalePurple","IndianRed","Tomato",
668 "SeaGreen","PaleGreen","GreenKhaki","LightBrown","LightSalmon",
669 "SpringGreen","PaleGreen","MediumOlive","YellowBrown","LightGold",
670 "LightGreen","LightGreen","LightGreen","GreenYellow","PaleYellow",
671 "HalveBlue","DarkSky","HalveMagenta","VioletRed","DeepPink",
672 "SteelBlue","SkyBlue","Orchid","LightHotPink","HotPink",
673 "SeaGreen","SlateGray","MediumGrey","Burlywood","LightPink",
674 "SpringGreen","Aquamarine","PaleGreen","Khaki","PaleOrange",
675 "SpringGreen","SeaGreen","PaleGreen","PaleWhite","YellowWhite",
676 "LightBlue","Purple","MediumOrchid","Magenta","Magenta",
677 "RoyalBlue","SlateBlue","MediumOrchid","Orchid","Magenta",
678 "DeepSkyBlue","LightSteelBlue","LightSkyBlue","Violet","LightPink",
679 "Cyaan","DarkTurquoise","SkyBlue","Grey","Snow",
680 "Mint","Mint","Aquamarine","MintCream","Ivory",
681 "Blue","Blue","DarkMagenta","DarkOrchid","Magenta",
682 "SkyBlue","RoyalBlue","LightSlateBlue","MediumOrchid","Magenta",
683 "DodgerBlue","SteelBlue","MediumPurple","PalePurple","Plum",
684 "DeepSkyBlue","PaleBlue","LightSkyBlue","PalePurple","Thistle",
685 "Cyan","ColdBlue","PaleTurquoise","GhostWhite","White"
686 };
687
688 void automatname(Material *ma)
689 {
690         int nr, r, g, b;
691         float ref;
692         
693         if(ma==0) return;
694         if(ma->mode & MA_SHLESS) ref= 1.0;
695         else ref= ma->ref;
696         
697         r= (int)(4.99*(ref*ma->r));
698         g= (int)(4.99*(ref*ma->g));
699         b= (int)(4.99*(ref*ma->b));
700         nr= r + 5*g + 25*b;
701         if(nr>124) nr= 124;
702         new_id(&G.main->mat, (ID *)ma, colname_array[nr]);
703         
704 }
705
706
707 void delete_material_index()
708 {
709         Material *mao, ***matarar;
710         Object *ob, *obt;
711         Curve *cu;
712         Nurb *nu;
713         short *totcolp;
714         int a, actcol;
715         
716         if(G.obedit) {
717                 error("Unable to perform function in EditMode");
718                 return;
719         }
720         ob= ((G.scene->basact)? (G.scene->basact->object) : 0) ;
721         if(ob==0 || ob->totcol==0) return;
722         
723         /* take a mesh/curve/mball as starting point, remove 1 index,
724          * AND with all objects that share the ob->data
725          * 
726          * after that check indices in mesh/curve/mball!!!
727          */
728         
729         totcolp= give_totcolp(ob);
730         matarar= give_matarar(ob);
731
732         /* we delete the actcol */
733         if(ob->totcol) {
734                 mao= (*matarar)[ob->actcol-1];
735                 if(mao) mao->id.us--;
736         }
737         
738         for(a=ob->actcol; a<ob->totcol; a++) {
739                 (*matarar)[a-1]= (*matarar)[a];
740         }
741         (*totcolp)--;
742         
743         if(*totcolp==0) {
744                 MEM_freeN(*matarar);
745                 *matarar= 0;
746         }
747         
748         actcol= ob->actcol;
749         obt= G.main->object.first;
750         while(obt) {
751         
752                 if(obt->data==ob->data) {
753                         
754                         /* WATCH IT: do not use actcol from ob or from obt (can become zero) */
755                         mao= obt->mat[actcol-1];
756                         if(mao) mao->id.us--;
757                 
758                         for(a=actcol; a<obt->totcol; a++) obt->mat[a-1]= obt->mat[a];
759                         obt->totcol--;
760                         if(obt->actcol > obt->totcol) obt->actcol= obt->totcol;
761                         
762                         if(obt->totcol==0) {
763                                 MEM_freeN(obt->mat);
764                                 obt->mat= 0;
765                         }
766                 }
767                 obt= obt->id.next;
768         }
769
770         /* check indices from mesh */
771
772         if(ob->type==OB_MESH) {
773                 Mesh *me= get_mesh(ob);
774                 mesh_delete_material_index(me, actcol-1);
775                 freedisplist(&ob->disp);
776         }
777         else if ELEM(ob->type, OB_CURVE, OB_SURF) {
778                 cu= ob->data;
779                 nu= cu->nurb.first;
780                 
781                 while(nu) {
782                         if(nu->mat_nr && nu->mat_nr>=actcol-1) {
783                                 nu->mat_nr--;
784                                 if (ob->type == OB_CURVE) nu->charidx--;
785                         }
786                         nu= nu->next;
787                 }
788                 freedisplist(&ob->disp);
789         }
790 }