diff options
Diffstat (limited to 'source/blender')
81 files changed, 4588 insertions, 1504 deletions
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index 16e8b5652aa..e4cd8e39aca 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -43,9 +43,6 @@ void free_path(struct Path *path); void calc_curvepath(struct Object *ob); int interval_test(int min, int max, int p1, int cycl); int where_on_path(struct Object *ob, float ctime, float *vec, float *dir); -void frames_duplilist(struct Object *ob); -void vertex_duplilist(struct Scene *sce, struct Object *par); -void particle_duplilist(struct Scene *sce, struct Object *par, struct PartEff *paf); void free_duplilist(void); void make_duplilist(struct Scene *sce, struct Object *ob); int count_duplilist(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h index 905b6d3bf74..8a86e88406f 100644 --- a/source/blender/blenkernel/BKE_bad_level_calls.h +++ b/source/blender/blenkernel/BKE_bad_level_calls.h @@ -88,6 +88,7 @@ float WardIso_Spec(float *n, float *l, float *v, float a, int); float Toon_Diff(float *n, float *l, float *v, float a, float b); float OrenNayar_Diff(float *n, float *l, float *v, float rough); float Minnaert_Diff(float nl, float *n, float *v, float a); +float Fresnel_Diff(float *vn, float *lv, float *view, float ior, float fac); void add_to_diffuse(float *, ShadeInput *, float, float, float, float); void ramp_diffuse_result(float *diff, ShadeInput *shi); @@ -158,7 +159,6 @@ void do_material_tex(ShadeInput *shi); void externtex(struct MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *tb, float *ta); void init_render_textures(void); -void end_render_textures(void); void RE_free_envmap(struct EnvMap *env); void RE_free_envmapdata(struct EnvMap *env); diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index c68d4b8b10e..d149d2b6e7c 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -38,10 +38,8 @@ struct Effect; struct ListBase; struct Object; struct PartEff; -struct MTex; -struct Mesh; -struct WaveEff; struct Particle; +struct Group; struct Effect *add_effect(int type); void free_effect(struct Effect *eff); @@ -57,7 +55,7 @@ void build_particle_system(struct Object *ob); /* particle deflector */ #define PE_WIND_AS_SPEED 0x00000001 -struct ListBase *pdInitEffectors(struct Object *ob); +struct ListBase *pdInitEffectors(struct Object *obsrc, struct Group *group); void pdEndEffectors(struct ListBase *lb); void pdDoEffectors(struct ListBase *lb, float *opco, float *force, float *speed, float cur_time, float loc_time, unsigned int flags); diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index 265d16579c2..4e69f18a238 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -35,26 +35,16 @@ #define BKE_GROUP_H struct Group; -struct GroupKey; struct GroupObject; -struct ObjectKey; struct Object; -void free_object_key(struct ObjectKey *ok); void free_group_object(struct GroupObject *go); void free_group(struct Group *group); struct Group *add_group(void); -void object_to_obkey(struct Object *ob, struct ObjectKey *ok); -void obkey_to_object(struct ObjectKey *ok, struct Object *ob); -void add_object_key(struct GroupObject *go, struct GroupKey *gk); void add_to_group(struct Group *group, struct Object *ob); void rem_from_group(struct Group *group, struct Object *ob); -void add_group_key(struct Group *group); -void set_object_key(struct Object *ob, struct ObjectKey *ok); -void set_group_key(struct Group *group); struct Group *find_group(struct Object *ob); -void set_group_key_name(struct Group *group, char *name); -void set_group_key_frame(struct Group *group, float frame); +int object_in_group(struct Object *ob, struct Group *group); #endif diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index fcdbed10ffa..16a320010ec 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -48,16 +48,18 @@ void init_material(struct Material *ma); struct Material *add_material(char *name); struct Material *copy_material(struct Material *ma); void make_local_material(struct Material *ma); + struct Material ***give_matarar(struct Object *ob); short *give_totcolp(struct Object *ob); struct Material *give_current_material(struct Object *ob, int act); ID *material_from(struct Object *ob, int act); void assign_material(struct Object *ob, struct Material *ma, int act); void new_material_to_objectdata(struct Object *ob); + +struct Material *get_active_matlayer(struct Material *ma); void init_render_material(struct Material *ma); void init_render_materials(void); -void end_render_material(struct Material *ma); -void end_render_materials(void); + void automatname(struct Material *ma); void delete_material_index(void); diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 1313ad251e7..a7eea6f6393 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -60,7 +60,7 @@ void free_qtcodecdata(struct QuicktimeCodecData *acd); void free_scene(struct Scene *me); struct Scene *add_scene(char *name); -int object_in_scene(struct Object *ob, struct Scene *sce); +struct Base *object_in_scene(struct Object *ob, struct Scene *sce); void set_scene_bg(struct Scene *sce); void set_scene_name(char *name); diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index a18a43fb7b8..f0b05802e97 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -58,11 +58,6 @@ #define ELEM7(a, b, c, d, e, f, g, h) ( ELEM3(a, b, c, d) || ELEM4(a, e, f, g, h) ) #define ELEM8(a, b, c, d, e, f, g, h, i) ( ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) ) -/* pointer magic, only to be used for the max 16 Gig mem period */ -/* note that int is signed! */ -#define POINTER_TO_INT(poin) (int)( ((long)(poin))>>3 ) -#define INT_TO_POINTER(int) (void *)( ((long)(int))<<3 ) - /* string compare */ #define STREQ(str, a) ( strcmp((str), (a))==0 ) #define STREQ2(str, a, b) ( STREQ(str, a) || STREQ(str, b) ) diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index 457c6a2d7e5..44997480779 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -116,6 +116,7 @@ float WardIso_Spec(float *n, float *l, float *v, float a, int tangent){return 0; float Toon_Diff(float *n, float *l, float *v, float a, float b){return 0;} float OrenNayar_Diff(float *n, float *l, float *v, float rough){return 0;} float Minnaert_Diff(float nl, float *n, float *v, float a){return 0;} +float Fresnel_Diff(float *vn, float *lv, float *view, float ior, float fac){return 0;} void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, float g, float b){} void ramp_diffuse_result(float *diff, ShadeInput *shi){} @@ -206,12 +207,11 @@ int BPY_call_importloader(char *name) void do_material_tex(ShadeInput *shi){} void externtex(struct MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *tb, float *ta){} -void init_render_textures(void){} -void end_render_textures(void){} void RE_free_envmap(struct EnvMap *env){} struct EnvMap *RE_copy_envmap(struct EnvMap *env){ return env;} void RE_free_envmapdata(struct EnvMap *env){} +void init_render_textures(void){} int RE_envmaptex(struct Tex *tex, float *texvec, float *dxt, float *dyt){ return 0; diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index b8178dd98cd..b448816589f 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -40,14 +40,15 @@ #include "BLI_arithb.h" #include "DNA_listBase.h" -#include "DNA_object_types.h" #include "DNA_curve_types.h" -#include "DNA_key_types.h" -#include "DNA_view3d_types.h" #include "DNA_effect_types.h" +#include "DNA_group_types.h" +#include "DNA_key_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_view3d_types.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" @@ -271,7 +272,7 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK return 1; } -static Object *new_dupli_object(ListBase *lb, Object *ob, Object *par) +static Object *new_dupli_object(ListBase *lb, Object *ob, Object *par, int clearpar) { Object *newob; @@ -284,7 +285,7 @@ static Object *new_dupli_object(ListBase *lb, Object *ob, Object *par) /* only basis-ball gets displist */ if(newob->type==OB_MBALL) newob->disp.first= newob->disp.last= NULL; - if(ob!=par) { // dupliverts, particle + if(clearpar) { // dupliverts, particle newob->parent= NULL; newob->track= NULL; } @@ -293,7 +294,22 @@ static Object *new_dupli_object(ListBase *lb, Object *ob, Object *par) return newob; } -void frames_duplilist(Object *ob) +static void group_duplilist(Object *ob) +{ + Object *newob; + GroupObject *go; + float mat[4][4]; + + if(ob->dup_group==NULL) return; + + for(go= ob->dup_group->gobject.first; go; go= go->next) { + newob= new_dupli_object(&duplilist, go->ob, ob, 0); + Mat4CpyMat4(mat, newob->obmat); + Mat4MulMat4(newob->obmat, mat, ob->obmat); + } +} + +static void frames_duplilist(Object *ob) { extern int enable_cu_speed; /* object.c */ Object *newob, copyob; @@ -315,7 +331,7 @@ void frames_duplilist(Object *ob) else ok= 0; } if(ok) { - newob= new_dupli_object(&duplilist, ob, ob); + newob= new_dupli_object(&duplilist, ob, ob, 0); do_ob_ipo(newob); where_is_object_time(newob, (float)G.scene->r.cfra); @@ -343,7 +359,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n VecSubf(vec, vec, vdd->pmat[3]); VecAddf(vec, vec, vdd->ob->obmat[3]); - newob= new_dupli_object(&duplilist, vdd->ob, vdd->par); + newob= new_dupli_object(&duplilist, vdd->ob, vdd->par, 1); VECCOPY(newob->obmat[3], vec); if(vdd->par->transflag & OB_DUPLIROT) { @@ -359,7 +375,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n } -void vertex_duplilist(Scene *sce, Object *par) +static void vertex_duplilist(Scene *sce, Object *par) { Object *ob; Base *base; @@ -420,8 +436,7 @@ void vertex_duplilist(Scene *sce, Object *par) dm->release(dm); } - -void particle_duplilist(Scene *sce, Object *par, PartEff *paf) +static void particle_duplilist(Scene *sce, Object *par, PartEff *paf) { Object *ob, *newob; Base *base; @@ -462,7 +477,7 @@ void particle_duplilist(Scene *sce, Object *par, PartEff *paf) mtime= pa->time+pa->lifetime; for(ctime= pa->time; ctime<mtime; ctime+=paf->staticstep) { - newob= new_dupli_object(&duplilist, ob, par); + newob= new_dupli_object(&duplilist, ob, par, 1); /* make sure hair grows until the end.. */ if(ctime>pa->time+pa->lifetime) ctime= pa->time+pa->lifetime; @@ -494,7 +509,7 @@ void particle_duplilist(Scene *sce, Object *par, PartEff *paf) if((paf->flag & PAF_DIED)==0 && ctime > pa->time+pa->lifetime) continue; //if(ctime < pa->time+pa->lifetime) { - newob= new_dupli_object(&duplilist, ob, par); + newob= new_dupli_object(&duplilist, ob, par, 1); /* to give ipos in object correct offset */ where_is_object_time(newob, ctime-pa->time); @@ -523,7 +538,6 @@ void particle_duplilist(Scene *sce, Object *par, PartEff *paf) } } - void free_duplilist() { Object *ob; @@ -551,7 +565,10 @@ void make_duplilist(Scene *sce, Object *ob) font_duplilist(ob); } } - else if(ob->transflag & OB_DUPLIFRAMES) frames_duplilist(ob); + else if(ob->transflag & OB_DUPLIFRAMES) + frames_duplilist(ob); + else if(ob->transflag & OB_DUPLIGROUP) + group_duplilist(ob); } } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 9273bd8eb71..f7cf3d6d931 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -537,6 +537,7 @@ static void fastshade(float *co, float *nor, float *orco, Material *ma, char *co if(ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(nor, lv, shi.view, ma->roughness); else if(ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(nor, lv, shi.view, ma->param[0], ma->param[1]); else if(ma->diff_shader==MA_DIFF_MINNAERT) is= Minnaert_Diff(is, nor, shi.view, ma->darkness); + else if(ma->diff_shader==MA_DIFF_FRESNEL) is= Fresnel_Diff(nor, lv, shi.view, ma->param[0], ma->param[1]); } back= 0; @@ -726,15 +727,6 @@ static void init_fastshade_for_ob(Object *ob, int *need_orco_r, float mat[4][4], } } } -static void end_fastshade_for_ob(Object *ob) -{ - int a; - - for(a=0; a<ob->totcol; a++) { - Material *ma= give_current_material(ob, a+1); - if(ma) end_render_material(ma); - } -} void mesh_create_shadedColors(Object *ob, int onlyForMesh, unsigned int **col1_r, unsigned int **col2_r) { @@ -846,7 +838,6 @@ void mesh_create_shadedColors(Object *ob, int onlyForMesh, unsigned int **col1_r if (dmNeedsFree) dm->release(dm); - end_fastshade_for_ob(ob); } void shadeDispList(Object *ob) @@ -986,8 +977,6 @@ void shadeDispList(Object *ob) dl= dl->next; } } - - end_fastshade_for_ob(ob); } void reshadeall_displist(void) @@ -1999,8 +1988,6 @@ void imagestodisplist(void) base= base->next; } - end_render_textures(); - allqueue(REDRAWVIEW3D, 0); } diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index acff6d80024..17dbae4c0af 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -36,19 +36,21 @@ #include <stdlib.h> #include "MEM_guardedalloc.h" -#include "DNA_listBase.h" + +#include "DNA_curve_types.h" #include "DNA_effect_types.h" -#include "DNA_object_types.h" -#include "DNA_object_force.h" +#include "DNA_group_types.h" +#include "DNA_ipo_types.h" +#include "DNA_key_types.h" +#include "DNA_lattice_types.h" +#include "DNA_listBase.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_material_types.h" -#include "DNA_curve_types.h" -#include "DNA_key_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" #include "DNA_texture_types.h" #include "DNA_scene_types.h" -#include "DNA_lattice_types.h" -#include "DNA_ipo_types.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -326,42 +328,57 @@ typedef struct pEffectorCache { Object obcopy; /* for restoring transformation data */ } pEffectorCache; +static void add_to_effectorcache(ListBase *lb, Object *ob, Object *obsrc) +{ + pEffectorCache *ec; + PartDeflect *pd= ob->pd; + + if(pd->forcefield == PFIELD_GUIDE) { + if(ob->type==OB_CURVE && obsrc->type==OB_MESH) { /* guides only do mesh particles */ + Curve *cu= ob->data; + if(cu->flag & CU_PATH) { + if(cu->path==NULL || cu->path->data==NULL) + makeDispListCurveTypes(ob, 0); + if(cu->path && cu->path->data) { + ec= MEM_callocN(sizeof(pEffectorCache), "effector cache"); + ec->ob= ob; + BLI_addtail(lb, ec); + } + } + } + } + else if(pd->forcefield) { + ec= MEM_callocN(sizeof(pEffectorCache), "effector cache"); + ec->ob= ob; + BLI_addtail(lb, ec); + } +} /* returns ListBase handle with objects taking part in the effecting */ -ListBase *pdInitEffectors(Object *obsrc) +ListBase *pdInitEffectors(Object *obsrc, Group *group) { static ListBase listb={NULL, NULL}; pEffectorCache *ec; - unsigned int layer= obsrc->lay; Base *base; - - for(base = G.scene->base.first; base; base= base->next) { - if( (base->lay & layer) && base->object->pd && base->object!=obsrc) { - Object *ob= base->object; - PartDeflect *pd= ob->pd; - - if(pd->forcefield == PFIELD_GUIDE) { - if(ob->type==OB_CURVE && obsrc->type==OB_MESH) { /* guides only do mesh particles */ - Curve *cu= ob->data; - if(cu->flag & CU_PATH) { - if(cu->path==NULL || cu->path->data==NULL) - makeDispListCurveTypes(ob, 0); - if(cu->path && cu->path->data) { - ec= MEM_callocN(sizeof(pEffectorCache), "effector cache"); - ec->ob= ob; - BLI_addtail(&listb, ec); - } - } - } + unsigned int layer= obsrc->lay; + + if(group) { + GroupObject *go; + + for(go= group->gobject.first; go; go= go->next) { + if( (go->ob->lay & layer) && go->ob->pd && go->ob!=obsrc) { + add_to_effectorcache(&listb, go->ob, obsrc); } - else if(pd->forcefield) { - ec= MEM_callocN(sizeof(pEffectorCache), "effector cache"); - ec->ob= ob; - BLI_addtail(&listb, ec); + } + } + else { + for(base = G.scene->base.first; base; base= base->next) { + if( (base->lay & layer) && base->object->pd && base->object!=obsrc) { + add_to_effectorcache(&listb, base->object, obsrc); } } } - + /* make a full copy */ for(ec= listb.first; ec; ec= ec->next) { ec->obcopy= *(ec->ob); @@ -1663,7 +1680,7 @@ void build_particle_system(Object *ob) } /* get the effectors */ - effectorbase= pdInitEffectors(ob); + effectorbase= pdInitEffectors(ob, paf->group); /* init geometry, return is 6 x float * me->totvert in size */ vertexcosnos= (VeNoCo *)mesh_get_mapped_verts_nors(ob); diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 65c4ed42e03..7405f16d9c0 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -1,19 +1,12 @@ -/* group.c sept 2000 - * - cleaned up mar-01 nzc - * - * - * ton roosendaal +/* * $Id$ * - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,7 +24,7 @@ * * Contributor(s): none yet. * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * ***** END GPL LICENSE BLOCK ***** */ #include <stdio.h> @@ -57,22 +50,8 @@ #include <config.h> #endif -void free_object_key(ObjectKey *ok) -{ - if(ok->ipo) ok->ipo->id.us--; - - MEM_freeN(ok); -} - void free_group_object(GroupObject *go) { - ObjectKey *ok; - - while(go->okey.first) { - ok= go->okey.first; - BLI_remlink(&go->okey, ok); - free_object_key(ok); - } MEM_freeN(go); } @@ -82,14 +61,11 @@ void free_group(Group *group) /* don't free group itself */ GroupObject *go; - BLI_freelistN(&group->gkey); - while(group->gobject.first) { go= group->gobject.first; BLI_remlink(&group->gobject, go); free_group_object(go); } - } Group *add_group() @@ -100,97 +76,16 @@ Group *add_group() return group; } -/* assumes 'ok' is unitialized */ -void object_to_obkey(Object *ob, ObjectKey *ok) -{ - ok->partype= ob->partype; - ok->par1= ob->par1; - ok->par2= ob->par2; - ok->par3= ob->par3; - - ok->parent= ob->parent; - ok->track= ob->track; - - ok->ipo= copy_ipo(ob->ipo); - - memcpy(ok->loc, ob->loc, 7*3*sizeof(float)); - memcpy(ok->quat, ob->quat, 2*4*sizeof(float)); - memcpy(ok->obmat, ob->obmat, 3*4*4*sizeof(float)); - - ok->lay= ob->lay; - ok->transflag= ob->transflag; - ok->trackflag= ob->transflag; - ok->upflag= ob->upflag; - ok->sf= ob->sf; - ok->ctime= ob->ctime; - - -} - -void obkey_to_object(ObjectKey *ok, Object *ob) -{ - ob->partype= ok->partype; - ob->par1= ok->par1; - ob->par2= ok->par2; - ob->par3= ok->par3; - - ob->parent= ok->parent; - ob->track= ok->track; - - /* pretty tricky, this makes ob->ipo blocks with users 'hanging around' */ - if(ob->ipo) { - free_libblock_us(&G.main->ipo, ob->ipo); - } - ob->ipo= copy_ipo(ok->ipo); - - memcpy(ob->loc, ok->loc, 7*3*sizeof(float)); - memcpy(ob->quat, ok->quat, 2*4*sizeof(float)); - memcpy(ob->obmat, ok->obmat, 3*4*4*sizeof(float)); - - ob->lay= ok->lay; - ob->transflag= ok->transflag; - ob->trackflag= ok->transflag; - ob->upflag= ok->upflag; - ob->sf= ok->sf; - ob->ctime= ok->ctime; -} - -/* current ob position */ -void add_object_key(GroupObject *go, GroupKey *gk) -{ - ObjectKey *ok; - - /* check if there already is a key */ - ok= go->okey.first; - while(ok) { - if(ok->gkey == gk) break; - ok= ok->next; - } - - if(ok) { - BLI_remlink(&go->okey, ok); - free_object_key(ok); - } - ok= MEM_mallocN(sizeof(ObjectKey), "objectkey"); - ok->gkey= gk; - - object_to_obkey(go->ob, ok); - - BLI_addtail(&go->okey, ok); - -} - /* external */ void add_to_group(Group *group, Object *ob) { GroupObject *go; - GroupKey *gk; + + if(group==NULL || ob==NULL) return; /* check if the object has been added already */ - go= group->gobject.first; - while(go) { + for(go= group->gobject.first; go; go= go->next) { if(go->ob==ob) return; - go= go->next; } go= MEM_callocN(sizeof(GroupObject), "groupobject"); @@ -198,18 +93,13 @@ void add_to_group(Group *group, Object *ob) go->ob= ob; - /* keys? */ - gk= group->gkey.first; - while(gk) { - add_object_key(go, gk); - gk= gk->next; - } } void rem_from_group(Group *group, Object *ob) { GroupObject *go, *gon; - ObjectKey *ok; + + if(group==NULL || ob==NULL) return; go= group->gobject.first; while(go) { @@ -218,116 +108,31 @@ void rem_from_group(Group *group, Object *ob) BLI_remlink(&group->gobject, go); free_group_object(go); } - else { - ok= go->okey.first; - while(ok) { - if(ok->parent==ob) ok->parent= NULL; - if(ok->track==ob) ok->track= NULL; - ok= ok->next; - } - } go= gon; } } -void add_group_key(Group *group) +int object_in_group(Object *ob, Group *group) { GroupObject *go; - GroupKey *gk; - int nr=10; - extern char colname_array[][20]; /* material.c */ - - gk= group->gkey.first; - while(gk) { - nr++; - gk= gk->next; - } - - gk= MEM_callocN(sizeof(GroupKey), "groupkey"); - BLI_addtail(&group->gkey, gk); - strcpy(gk->name, colname_array[ nr % 120 ]); - - go= group->gobject.first; - while(go) { - add_object_key(go, gk); - go= go->next; - } - - group->active= gk; -} - -void set_object_key(Object *ob, ObjectKey *ok) -{ - obkey_to_object(ok, ob); -} - -void set_group_key(Group *group) -{ - /* sets active */ - GroupObject *go; - ObjectKey *ok; - if(group->active==NULL) return; + if(group==NULL || ob==NULL) return 0; - go= group->gobject.first; - while(go) { - ok= go->okey.first; - while(ok) { - if(ok->gkey==group->active) { - set_object_key(go->ob, ok); - break; - } - ok= ok->next; - } - go= go->next; + for(go= group->gobject.first; go; go= go->next) { + if(go->ob==ob) + return 1; } - + return 0; } Group *find_group(Object *ob) { Group *group= G.main->group.first; - GroupObject *go; while(group) { - - go= group->gobject.first; - while(go) { - if(go->ob==ob) return group; - go= go->next; - } + if(object_in_group(ob, group)) + return group; group= group->id.next; } return NULL; } - -void set_group_key_name(Group *group, char *name) -{ - GroupKey *gk; - - if(group==NULL) return; - - gk= group->gkey.first; - while(gk) { - if(strcmp(name, gk->name)==0) break; - gk= gk->next; - } - - if(gk) { - group->active= gk; - set_group_key(group); - } -} - -void set_group_key_frame(Group *group, float frame) -{ - GroupObject *go; - - if(group==NULL) return; - - go= group->gobject.first; - while(go) { - where_is_object_time(go->ob, frame); - go= go->next; - } -} diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index d303a7ed5bd..c9c1b4fa98d 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -36,33 +36,34 @@ #include <string.h> #include "MEM_guardedalloc.h" +#include "DNA_curve_types.h" #include "DNA_material_types.h" -#include "DNA_texture_types.h" #include "DNA_mesh_types.h" -#include "DNA_object_types.h" -#include "DNA_curve_types.h" #include "DNA_meta_types.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_texture_types.h" #include "BLI_blenlib.h" #include "BKE_bad_level_calls.h" -#include "BKE_utildefines.h" - +#include "BKE_blender.h" +#include "BKE_displist.h" #include "BKE_global.h" -#include "BKE_main.h" - -#include "BKE_mesh.h" #include "BKE_library.h" -#include "BKE_displist.h" +#include "BKE_main.h" #include "BKE_material.h" +#include "BKE_mesh.h" +#include "BKE_utildefines.h" #include "BPY_extern.h" +/* not material itself */ void free_material(Material *ma) { - int a; + MaterialLayer *ml; MTex *mtex; + int a; BPY_free_scriptlink(&ma->scriptlink); @@ -74,6 +75,11 @@ void free_material(Material *ma) if(ma->ramp_col) MEM_freeN(ma->ramp_col); if(ma->ramp_spec) MEM_freeN(ma->ramp_spec); + + for(ml= ma->layers.first; ml; ml= ml->next) + if(ml->mat) ml->mat->id.us--; + + BLI_freelistN(&ma->layers); } void init_material(Material *ma) @@ -115,9 +121,10 @@ void init_material(Material *ma) ma->rampfac_col= 1.0; ma->rampfac_spec= 1.0; - ma->pr_lamp= 3; // two lamps, is bits - - ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RADIO|MA_TANGENT_STR; + ma->pr_lamp= 3; /* two lamps, is bits */ + ma->ml_flag= ML_RENDER; /* default render base material for layers */ + + ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RADIO|MA_RAYBIAS|MA_TANGENT_STR; } Material *add_material(char *name) @@ -134,6 +141,7 @@ Material *add_material(char *name) Material *copy_material(Material *ma) { Material *man; + MaterialLayer *ml; int a; man= copy_libblock(ma); @@ -149,9 +157,14 @@ Material *copy_material(Material *ma) } BPY_copy_scriptlink(&ma->scriptlink); + if(ma->ramp_col) man->ramp_col= MEM_dupallocN(ma->ramp_col); if(ma->ramp_spec) man->ramp_spec= MEM_dupallocN(ma->ramp_spec); + duplicatelist(&man->layers, &ma->layers); + for(ml= man->layers.first; ml; ml= ml->next) + id_us_plus((ID *)ml->mat); + return man; } @@ -245,9 +258,25 @@ void make_local_material(Material *ma) new_id(0, (ID *)ma, 0); } else if(local && lib) { + Material *mat; + MaterialLayer *ml; + man= copy_material(ma); man->id.us= 0; + /* do material layers */ + for(mat= G.main->mat.first; mat; mat= mat->id.next) { + if(mat->id.lib==NULL) { + for(ml= mat->layers.first; ml; ml= ml->next) { + if(ml->mat==ma) { + ml->mat= man; + man->id.us++; + ma->id.us--; + } + } + } + } + /* do objects */ ob= G.main->object.first; while(ob) { @@ -534,6 +563,18 @@ void new_material_to_objectdata(Object *ob) ob->actcol= ob->totcol; } +Material *get_active_matlayer(Material *ma) +{ + MaterialLayer *ml; + + if(ma==NULL) return NULL; + + for(ml= ma->layers.first; ml; ml= ml->next) + if(ml->flag & ML_ACTIVE) break; + if(ml) + return ml->mat; + return ma; +} void init_render_material(Material *ma) { @@ -586,43 +627,30 @@ void init_render_material(Material *ma) ma->ambg= ma->amb*R.wrld.ambg; ma->ambb= ma->amb*R.wrld.ambb; + /* will become or-ed result of all layer modes */ + ma->mode_l= ma->mode; } void init_render_materials() { Material *ma; + MaterialLayer *ml; - ma= G.main->mat.first; - while(ma) { + /* two steps, first initialize, then or the flags for layers */ + for(ma= G.main->mat.first; ma; ma= ma->id.next) { if(ma->id.us) init_render_material(ma); - ma= ma->id.next; } -} - -void end_render_material(Material *ma) -{ - /* XXXX obsolete? check! */ - if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) { - if( !(ma->mode & MA_HALO) ) { - ma->r= ma->g= ma->b= 1.0; + for(ma= G.main->mat.first; ma; ma= ma->id.next) { + for(ml= ma->layers.first; ml; ml= ml->next) { + if(ml->mat) { + ma->texco |= ml->mat->texco; + ma->mode_l |= ml->mat->mode; + } } - } -} - -void end_render_materials() -{ - Material *ma; - - ma= G.main->mat.first; - while(ma) { - if(ma->id.us) end_render_material(ma); - ma= ma->id.next; - } - + } } - /* ****************** */ char colname_array[125][20]= { diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 957d76d786b..7c19f48e2e0 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -55,6 +55,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" +#include "DNA_nla_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_object_fluidsim.h" @@ -888,6 +889,7 @@ Object *copy_object(Object *ob) void expand_local_object(Object *ob) { + bActionStrip *strip; int a; id_lib_extern((ID *)ob->action); @@ -897,6 +899,10 @@ void expand_local_object(Object *ob) for(a=0; a<ob->totcol; a++) { id_lib_extern((ID *)ob->mat[a]); } + for (strip=ob->nlastrips.first; strip; strip=strip->next) { + id_lib_extern((ID *)strip->act); + } + } void make_local_object(Object *ob) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 53b4a09d89b..2cd387d7d93 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -220,16 +220,16 @@ Scene *add_scene(char *name) return sce; } -int object_in_scene(Object *ob, Scene *sce) +Base *object_in_scene(Object *ob, Scene *sce) { Base *base; base= sce->base.first; while(base) { - if(base->object == ob) return 1; + if(base->object == ob) return base; base= base->next; } - return 0; + return NULL; } void set_scene_bg(Scene *sce) diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 5b98a3bf794..d81c0e94944 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -546,7 +546,7 @@ static void softbody_calc_forces(Object *ob, float forcetime) /* check! */ do_deflector= is_there_deflection(ob->lay); - do_effector= pdInitEffectors(ob); + do_effector= pdInitEffectors(ob, NULL); iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */ bproot= sb->bpoint; /* need this for proper spring addressing */ diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index ceb226f67fb..8c7fd8de053 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -83,7 +83,7 @@ static IDType idtypes[]= { { ID_AR, "Armature", IDTYPE_FLAGS_ISLINKABLE}, { ID_CA, "Camera", IDTYPE_FLAGS_ISLINKABLE}, { ID_CU, "Curve", IDTYPE_FLAGS_ISLINKABLE}, - { ID_GR, "Group", 0}, + { ID_GR, "Group", IDTYPE_FLAGS_ISLINKABLE}, { ID_ID, "ID", 0}, { ID_IM, "Image", IDTYPE_FLAGS_ISLINKABLE}, { ID_IP, "Ipo", IDTYPE_FLAGS_ISLINKABLE}, diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 1fb00163644..bd9709edb5e 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1,19 +1,12 @@ /* - * readfile.c - * - * .blend file reading - * * $Id$ * - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,7 +24,7 @@ * * Contributor(s): none yet. * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * ***** END GPL LICENSE BLOCK ***** * */ @@ -1983,6 +1976,7 @@ static void direct_link_texture(FileData *fd, Tex *tex) static void lib_link_material(FileData *fd, Main *main) { Material *ma; + MaterialLayer *ml; MTex *mtex; int a; @@ -2000,6 +1994,10 @@ static void lib_link_material(FileData *fd, Main *main) } } lib_link_scriptlink(fd, &ma->id, &ma->scriptlink); + + for (ml=ma->layers.first; ml; ml=ml->next) + ml->mat= newlibadr_us(fd, ma->id.lib, ml->mat); + ma->id.flag -= LIB_NEEDLINK; } ma= ma->id.next; @@ -2010,8 +2008,6 @@ static void direct_link_material(FileData *fd, Material *ma) { int a; - direct_link_scriptlink(fd, &ma->scriptlink); - for(a=0; a<MAX_MTEX; a++) { ma->mtex[a]= newdataadr(fd, ma->mtex[a]); } @@ -2019,6 +2015,10 @@ static void direct_link_material(FileData *fd, Material *ma) ma->ramp_col= newdataadr(fd, ma->ramp_col); ma->ramp_spec= newdataadr(fd, ma->ramp_spec); + direct_link_scriptlink(fd, &ma->scriptlink); + + link_list(fd, &ma->layers); + } /* ************ READ MESH ***************** */ @@ -2129,6 +2129,7 @@ static void lib_link_modifiers(FileData *fd, Object *ob) static void lib_link_object(FileData *fd, Main *main) { Object *ob; + PartEff *paf; bSensor *sens; bController *cont; bActuator *act; @@ -2143,7 +2144,8 @@ static void lib_link_object(FileData *fd, Main *main) ob->track= newlibadr(fd, ob->id.lib, ob->track); ob->ipo= newlibadr_us(fd, ob->id.lib, ob->ipo); ob->action = newlibadr_us(fd, ob->id.lib, ob->action); - + ob->dup_group= newlibadr_us(fd, ob->id.lib, ob->dup_group); + poin= ob->data; ob->data= newlibadr_us(fd, ob->id.lib, ob->data); @@ -2164,6 +2166,11 @@ static void lib_link_object(FileData *fd, Main *main) lib_link_nlastrips(fd, &ob->id, &ob->nlastrips); lib_link_constraint_channels(fd, &ob->id, &ob->constraintChannels); + for(paf= ob->effect.first; paf; paf= paf->next) { + if(paf->type==EFF_PARTICLE) { + paf->group= newlibadr_us(fd, ob->id.lib, paf->group); + } + } sens= ob->sensors.first; while(sens) { @@ -2337,7 +2344,7 @@ static void direct_link_object(FileData *fd, Object *ob) paf= ob->effect.first; while(paf) { if(paf->type==EFF_PARTICLE) { - paf->keys= 0; + paf->keys= NULL; } if(paf->type==EFF_WAVE) { WaveEff *wav = (WaveEff*) paf; @@ -2496,7 +2503,6 @@ static void lib_link_scene(FileData *fd, Main *main) sce->world= newlibadr_us(fd, sce->id.lib, sce->world); sce->set= newlibadr(fd, sce->id.lib, sce->set); sce->ima= newlibadr_us(fd, sce->id.lib, sce->ima); - sce->group= newlibadr_us(fd, sce->id.lib, sce->group); base= sce->base.first; while(base) { @@ -3140,30 +3146,13 @@ static void lib_link_sound(FileData *fd, Main *main) static void direct_link_group(FileData *fd, Group *group) { - GroupObject *go; - ObjectKey *ok; - link_list(fd, &group->gobject); - link_list(fd, &group->gkey); - group->active= newdataadr(fd, group->active); - - go= group->gobject.first; - while(go) { - link_list(fd, &go->okey); - ok= go->okey.first; - while(ok) { - ok->gkey= newdataadr(fd, ok->gkey); - ok= ok->next; - } - go= go->next; - } } static void lib_link_group(FileData *fd, Main *main) { Group *group= main->group.first; GroupObject *go; - ObjectKey *ok; while(group) { if(group->id.flag & LIB_NEEDLINK) { @@ -3172,15 +3161,12 @@ static void lib_link_group(FileData *fd, Main *main) go= group->gobject.first; while(go) { go->ob= newlibadr(fd, group->id.lib, go->ob); - ok= go->okey.first; - while(ok) { - ok->parent= newlibadr(fd, group->id.lib, ok->parent); - ok->track= newlibadr(fd, group->id.lib, ok->track); - ok->ipo= newlibadr_us(fd, group->id.lib, ok->ipo); - ok= ok->next; - } + /* groups have inverse users... */ + if(go->ob && group->id.us==0) + group->id.us= 1; go= go->next; } + rem_from_group(group, NULL); /* removes NULL entries */ } group= group->id.next; } @@ -5082,6 +5068,10 @@ static void do_versions(FileData *fd, Library *lib, Main *main) if(ma->mode & MA_TRACEBLE) ma->mode |= MA_SHADBUF; ma->pad= 1; } + /* orange stuff, so should be done for 2.40 too */ + if(ma->layers.first==NULL) { + ma->ml_flag= ML_RENDER; + } } } @@ -5287,6 +5277,15 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old) } } +static void expand_group(FileData *fd, Main *mainvar, Group *group) +{ + GroupObject *go; + + for(go= group->gobject.first; go; go= go->next) { + expand_doit(fd, mainvar, go->ob); + } +} + static void expand_key(FileData *fd, Main *mainvar, Key *key) { expand_doit(fd, mainvar, key->ipo); @@ -5301,6 +5300,7 @@ static void expand_texture(FileData *fd, Main *mainvar, Tex *tex) static void expand_material(FileData *fd, Main *mainvar, Material *ma) { + MaterialLayer *ml; int a; for(a=0; a<MAX_MTEX; a++) { @@ -5309,7 +5309,13 @@ static void expand_material(FileData *fd, Main *mainvar, Material *ma) expand_doit(fd, mainvar, ma->mtex[a]->object); } } + expand_doit(fd, mainvar, ma->ipo); + + for (ml=ma->layers.first; ml; ml=ml->next) { + if(ml->mat) + expand_doit(fd, mainvar, ml->mat); + } } static void expand_lamp(FileData *fd, Main *mainvar, Lamp *la) @@ -5718,6 +5724,9 @@ static void expand_main(FileData *fd, Main *mainvar) case ID_AC: expand_action(fd, mainvar, (bAction *)id); break; + case ID_GR: + expand_group(fd, mainvar, (Group *)id); + break; } doit= 1; @@ -5747,8 +5756,9 @@ static void give_base_to_objects(Scene *sce, ListBase *lb) BLI_addtail(&(sce->base), base); base->lay= ob->lay; base->object= ob; + base->flag= ob->flag; ob->id.us= 1; - + ob->id.flag -= LIB_INDIRECT; ob->id.flag |= LIB_EXTERN; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index f941b5f77d2..d2e1d7e2c6c 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -994,6 +994,7 @@ static void write_textures(WriteData *wd, ListBase *idbase) static void write_materials(WriteData *wd, ListBase *idbase) { Material *ma; + MaterialLayer *ml; int a; ma= idbase->first; @@ -1010,6 +1011,10 @@ static void write_materials(WriteData *wd, ListBase *idbase) if(ma->ramp_spec) writestruct(wd, DATA, "ColorBand", 1, ma->ramp_spec); write_scriptlink(wd, &ma->scriptlink); + + for (ml=ma->layers.first; ml; ml=ml->next) + writestruct(wd, DATA, "MaterialLayer", 1, ml); + } ma= ma->id.next; } @@ -1487,9 +1492,7 @@ static void write_sounds(WriteData *wd, ListBase *idbase) static void write_groups(WriteData *wd, ListBase *idbase) { Group *group; - GroupKey *gk; GroupObject *go; - ObjectKey *ok; group= idbase->first; while(group) { @@ -1497,27 +1500,11 @@ static void write_groups(WriteData *wd, ListBase *idbase) /* write LibData */ writestruct(wd, ID_GR, "Group", 1, group); - gk= group->gkey.first; - while(gk) { - writestruct(wd, DATA, "GroupKey", 1, gk); - gk= gk->next; - } - go= group->gobject.first; while(go) { writestruct(wd, DATA, "GroupObject", 1, go); go= go->next; } - go= group->gobject.first; - while(go) { - ok= go->okey.first; - while(ok) { - writestruct(wd, DATA, "ObjectKey", 1, ok); - ok= ok->next; - } - go= go->next; - } - } group= group->id.next; } diff --git a/source/blender/include/BDR_unwrapper.h b/source/blender/include/BDR_unwrapper.h index 176bf8c8e68..f8c73dfdea2 100644 --- a/source/blender/include/BDR_unwrapper.h +++ b/source/blender/include/BDR_unwrapper.h @@ -34,9 +34,16 @@ #define BDR_UNWRAPPER_H void set_seamtface(void); /* set TF_SEAM flags in tfaces */ -void unwrap_lscm(void); /* unwrap selected tfaces */ -void unwrap_lscm_live(void); /* unwrap selected tfaces (for live mode, with no undo pushes) */ void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index); +void unwrap_lscm(void); /* unwrap faces selected in 3d view */ +void unwrap_lscm_new(void); +void minimize_stretch_tface_uv(void); /* optimize faces selected in uv editor */ + +/* for live mode: no undo pushes, caching for quicky re-unwrap */ +void unwrap_lscm_live_begin(void); +void unwrap_lscm_live_re_solve(void); +void unwrap_lscm_live_end(void); + #endif /* BDR_UNWRAPPER_H */ diff --git a/source/blender/include/BIF_editgroup.h b/source/blender/include/BIF_editgroup.h index 01102649fd6..e86bd962a6c 100644 --- a/source/blender/include/BIF_editgroup.h +++ b/source/blender/include/BIF_editgroup.h @@ -31,10 +31,8 @@ */ struct Group; -void set_active_group(void); -void add_selected_to_group(void); + +void add_selected_to_group(struct Group *group); void rem_selected_from_group(void); -void prev_group_key(struct Group *group); -void next_group_key(struct Group *group); -void select_group_menu(void); -void select_group(short nr); +void group_operation_with_menu(void); + diff --git a/source/blender/include/BIF_meshtools.h b/source/blender/include/BIF_meshtools.h index b5f5a91c50c..8df5e7255a5 100644 --- a/source/blender/include/BIF_meshtools.h +++ b/source/blender/include/BIF_meshtools.h @@ -34,6 +34,7 @@ #define BIF_MESHTOOLS_H struct Object; +struct EditVert; extern void join_mesh(void); @@ -42,8 +43,9 @@ extern void slowerdraw(void); extern void sort_faces(void); -extern int mesh_octree_table(struct Object *ob, float *co, char mode); +extern long mesh_octree_table(struct Object *ob, float *co, char mode); extern int mesh_get_x_mirror_vert(struct Object *ob, int index); +extern struct EditVert *editmesh_get_x_mirror_vert(struct Object *ob, float *co); #endif diff --git a/source/blender/include/BIF_resources.h b/source/blender/include/BIF_resources.h index 8c05d96ec72..b9b1d1f63bf 100644 --- a/source/blender/include/BIF_resources.h +++ b/source/blender/include/BIF_resources.h @@ -117,8 +117,8 @@ typedef enum { ICON_ENVMAP, ICON_TRANSP_HLT, ICON_TRANSP_DEHLT, - ICON_RADIO_DEHLT, - ICON_RADIO_HLT, + ICON_CIRCLE_DEHLT, + ICON_CIRCLE_HLT, ICON_TPAINT_DEHLT, ICON_TPAINT_HLT, ICON_WPAINT_DEHLT, diff --git a/source/blender/include/BIF_space.h b/source/blender/include/BIF_space.h index b51d844403c..7970ed5e41d 100644 --- a/source/blender/include/BIF_space.h +++ b/source/blender/include/BIF_space.h @@ -114,8 +114,7 @@ extern void newspace(struct ScrArea *sa, int type); extern void set_rects_butspace(struct SpaceButs *buts); extern void test_butspace(void); extern void start_game(void); -extern void select_group_menu(void); -extern void select_group(short nr); +extern void select_grouped(short nr); extern void BIF_undo_push(char *str); extern void BIF_undo(void); diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h index ab36972ea18..05e06afca4e 100644 --- a/source/blender/include/blendef.h +++ b/source/blender/include/blendef.h @@ -388,7 +388,7 @@ #define B_AUTOFGON 32 #define B_KNIFE 0x80 #define B_PERCENTSUBD 0x40 - +#define B_MESH_X_MIRROR 0x100 /* DISPLAYMODE */ #define R_DISPLAYVIEW 0 diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index 33a074ba46d..8e72198da52 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -121,6 +121,8 @@ void test_scenepoin_but(char *name, struct ID **idpp); void test_matpoin_but(char *name, struct ID **idpp); void test_scriptpoin_but(char *name, struct ID **idpp); void test_actionpoin_but(char *name, ID **idpp); +void test_grouppoin_but(char *name, ID **idpp); + void test_idbutton_cb(void *namev, void *arg2_unused); /* -------------- internal event defines ------------ */ @@ -155,6 +157,8 @@ void test_idbutton_cb(void *namev, void *arg2_unused); #define B_SBUFF 1104 #define B_SHADBUF 1105 #define B_SHADRAY 1106 +#define B_LMTEXPASTE 1107 +#define B_LMTEXCOPY 1108 /* *********************** */ #define B_MATBUTS 1300 @@ -178,6 +182,8 @@ void test_idbutton_cb(void *namev, void *arg2_unused); /* yafray: material preset menu event */ #define B_MAT_YF_PRESET 1217 +#define B_MAT_LAYERBROWSE 1218 + /* *********************** */ #define B_TEXBUTS 1400 @@ -218,7 +224,7 @@ void test_idbutton_cb(void *namev, void *arg2_unused); #define B_ENV_FREE_ALL 1357 #define B_UNLINKIMA 1358 -/* *********************** */ +/* **************** animbuts = object buttons ******* */ #define B_ANIMBUTS 1500 #define B_RECALCPATH 1401 @@ -234,21 +240,22 @@ void test_idbutton_cb(void *namev, void *arg2_unused); #define B_SOFTBODY_BAKE 1422 #define B_SOFTBODY_BAKE_FREE 1423 - /* this has MAX_EFFECT settings! Next free define is 1450... */ -#define B_SELEFFECT 1430 +/* this has MAX_EFFECT settings! Next free define is 1450... */ +#define B_SELEFFECT 1430 /* Fluidsim button defines */ #define B_FLUIDSIM_BAKE 1450 -#define B_FLUIDSIM_SELDIR 1451 +#define B_FLUIDSIM_SELDIR 1451 #define B_FLUIDSIM_FORCEREDRAW 1452 - /* *********************** */ #define B_WORLDBUTS 1600 #define B_TEXCLEARWORLD 1501 #define B_COLHOR 1502 #define B_COLZEN 1503 +#define B_WMTEXPASTE 1504 +#define B_WMTEXCOPY 1505 /* *********************** */ diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 463fceaa0a1..c8781a75e2e 100755 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -125,6 +125,7 @@ typedef struct TransData { struct Object *ob; TransDataExtension *ext; /* for objects, poses. 1 single malloc per TransInfo! */ TransDataIpokey *tdi; /* for objects, ipo keys. per transdata a malloc */ + void *tdmir; /* mirrored element pointer, in editmode mesh to EditVert */ short flag; /* Various flags */ short protectflag; /* If set, copy of Object or PoseChannel protection */ } TransData; diff --git a/source/blender/makesdna/DNA_effect_types.h b/source/blender/makesdna/DNA_effect_types.h index 46ce9b7d017..86ffb0fc4ad 100644 --- a/source/blender/makesdna/DNA_effect_types.h +++ b/source/blender/makesdna/DNA_effect_types.h @@ -104,6 +104,7 @@ typedef struct Particle { short mat_nr, rt; } Particle; +struct Group; typedef struct PartEff { struct PartEff *next, *prev; @@ -125,7 +126,9 @@ typedef struct PartEff { short disp, vertgroup_v; char vgroupname[32], vgroupname_v[32]; + Particle *keys; + struct Group *group; } PartEff; diff --git a/source/blender/makesdna/DNA_group_types.h b/source/blender/makesdna/DNA_group_types.h index f7139101476..2ee699839ed 100644 --- a/source/blender/makesdna/DNA_group_types.h +++ b/source/blender/makesdna/DNA_group_types.h @@ -38,50 +38,11 @@ #include "DNA_ID.h" struct Object; -struct Ipo; - -typedef struct GroupKey { - struct GroupKey *next, *prev; - short sfra, efra; - float cfra; - char name[32]; -} GroupKey; - -typedef struct ObjectKey { - struct ObjectKey *next, *prev; - GroupKey *gkey; /* for reference */ - - /* copy of relevant data */ - short partype, pad; - int par1, par2, par3; - - struct Object *parent, *track; - struct Ipo *ipo; - - /* this block identical to object */ - float loc[3], dloc[3], orig[3]; - float size[3], dsize[3]; - float rot[3], drot[3]; - float quat[4], dquat[4]; - float obmat[4][4]; - float parentinv[4][4]; - float imat[4][4]; /* voor bij render, tijdens simulate, tijdelijk: ipokeys van transform */ - - unsigned int lay; /* kopie van Base */ - - char transflag, ipoflag; - char trackflag, upflag; - - float sf, ctime, padf; - - -} ObjectKey; typedef struct GroupObject { struct GroupObject *next, *prev; struct Object *ob; - ListBase okey; /* ObjectKey */ - + void *lampren; /* used while render */ } GroupObject; @@ -89,11 +50,9 @@ typedef struct Group { ID id; ListBase gobject; /* GroupObject */ - ListBase gkey; /* GroupKey */ - - GroupKey *active; } Group; + #endif diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 5ef327502e1..bbe7d0f8125 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -34,10 +34,9 @@ #ifndef DNA_MATERIAL_TYPES_H #define DNA_MATERIAL_TYPES_H -/* #include "BLI_listBase.h" */ - #include "DNA_ID.h" #include "DNA_scriptlink_types.h" +#include "DNA_listBase.h" #ifndef MAX_MTEX #define MAX_MTEX 10 @@ -47,6 +46,17 @@ struct MTex; struct Ipo; struct Material; struct ColorBand; +struct Group; + +typedef struct MaterialLayer { + struct MaterialLayer *next, *prev; + + struct Material *mat; + float blendfac; + short flag, blendmethod, menunr, pad; + int pad2; + +} MaterialLayer; /* WATCH IT: change type? also make changes in ipo.h */ @@ -54,14 +64,16 @@ typedef struct Material { ID id; short colormodel, lay; /* lay: for dynamics (old engine, until 2.04) */ + /* note, keep this below synced with render_types.h */ float r, g, b; float specr, specg, specb; float mirr, mirg, mirb; float ambr, ambb, ambg; - float amb, emit, ang, spectra, ray_mirror; float alpha, ref, spec, zoffs, add; float translucency; + /* end synced with render_types.h */ + float fresnel_mir, fresnel_mir_i; float fresnel_tra, fresnel_tra_i; float filter; /* filter added, for raytrace transparency */ @@ -69,16 +81,15 @@ typedef struct Material { short har; char seed1, seed2; - int mode; - int mode2; /* even more material settings :) */ + int mode, mode_l; /* mode_l is the or-ed result of all layer modes */ short flarec, starc, linec, ringc; float hasize, flaresize, subsize, flareboost; float strand_sta, strand_end, strand_ease; + float pad1; /* for buttons and render*/ char rgbsel, texact, pr_type, pad; - short pr_back, pr_lamp, septex, pad4; - int pad5; + short pr_back, pr_lamp, septex, ml_flag; /* ml_flag is for disable base material */ /* shaders */ short diff_shader, spec_shader; @@ -97,7 +108,9 @@ typedef struct Material { float rampfac_col, rampfac_spec; struct MTex *mtex[10]; + ListBase layers; struct Ipo *ipo; + struct Group *group; /* dynamic properties */ float friction, fh, reflect; @@ -107,7 +120,7 @@ typedef struct Material { /* yafray: absorption color, dispersion parameters and material preset menu */ float YF_ar, YF_ag, YF_ab, YF_dscale, YF_dpwr; int YF_dsmp, YF_preset, YF_djit; - + ScriptLink scriptlink; } Material; @@ -161,7 +174,8 @@ typedef struct Material { #define MA_DIFF_LAMBERT 0 #define MA_DIFF_ORENNAYAR 1 #define MA_DIFF_TOON 2 -#define MA_DIFF_MINNAERT 3 +#define MA_DIFF_MINNAERT 3 +#define MA_DIFF_FRESNEL 4 /* spec_shader */ #define MA_SPEC_COOKTORR 0 @@ -224,6 +238,7 @@ typedef struct Material { #define MAP_AMB 2048 #define MAP_DISPLACE 4096 #define MAP_WARP 8192 +#define MAP_LAYER 16384 /* pr_type */ #define MA_FLAT 0 @@ -233,5 +248,13 @@ typedef struct Material { /* pr_back */ #define MA_DARK 1 +/* MaterialLayer flag */ +#define ML_ACTIVE 1 +#define ML_RENDER 2 +#define ML_NEG_NORMAL 4 +#define ML_DIFFUSE 8 +#define ML_SPECULAR 16 +#define ML_ALPHA 32 + #endif diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 1d16015a628..88075e718de 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -188,10 +188,7 @@ typedef struct Object { struct PartDeflect *pd; /* particle deflector/attractor/collision data */ struct SoftBody *soft; /* if exists, saved in file */ - struct Life *life; - - LBuf lbuf; - LBuf port; + struct Group *dup_group; /* object duplicator for group */ short fluidsimFlag; /* NT toggle fluidsim participation on/off */ char shapenr, shapeflag; /* current shape key for menu or pinned, flag for pinning */ @@ -262,13 +259,13 @@ extern Object workob; #define OB_OFFS_LOCAL 1 #define OB_QUAT 2 #define OB_NEG_SCALE 4 -#define OB_DUPLI (8+16) +#define OB_DUPLI (8+16+256) #define OB_DUPLIFRAMES 8 #define OB_DUPLIVERTS 16 #define OB_DUPLIROT 32 #define OB_DUPLINOSPEED 64 - #define OB_POWERTRACK 128 +#define OB_DUPLIGROUP 256 /* (short) ipoflag */ #define OB_DRAWKEY 1 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index fe54a631bdd..968aa6abe56 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -289,7 +289,6 @@ typedef struct Scene { ListBase base; struct Base *basact; - struct Group *group; float cursor[3]; float twcent[3]; /* center for transform widget */ @@ -407,33 +406,6 @@ typedef struct Scene { #define R_RADHDR 21 #define R_TIFF 22 -/* **************** RENDER ********************* */ -/* mode flag is same as for renderdata */ -/* flag */ -#define R_ZTRA 1 -#define R_HALO 2 -#define R_SEC_FIELD 4 -#define R_LAMPHALO 8 -#define R_RENDERING 16 -#define R_ANIMRENDER 32 -#define R_REDRAW_PRV 64 - -/* vlakren->flag (vlak = face in dutch) char!!! */ -#define R_SMOOTH 1 -#define R_VISIBLE 2 - /* strand flag, means special handling */ -#define R_STRAND 4 -#define R_NOPUNOFLIP 8 -#define R_FULL_OSA 16 -#define R_FACE_SPLIT 32 - /* Tells render to divide face other way. */ -#define R_DIVIDE_24 64 - /* vertex normals are tangent or view-corrected vector, for hair strands */ -#define R_TANGENT 128 - -/* vertren->texofs (texcoordinate offset relative to vertren->orco */ -#define R_UVOFS3 1 - /* **************** SCENE ********************* */ #define RAD_PHASE_PATCHES 1 #define RAD_PHASE_FACES 2 diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 7007981ff64..5a7e84c62ef 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -483,6 +483,7 @@ typedef struct SpaceImaSel { #define SO_SELECTED 3 #define SO_ACTIVE 4 #define SO_SAME_TYPE 5 +#define SO_GROUPS 6 /* SpaceOops->storeflag */ #define SO_TREESTORE_CLEANUP 1 diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h index e284044a633..edc621ba758 100644 --- a/source/blender/makesdna/DNA_world_types.h +++ b/source/blender/makesdna/DNA_world_types.h @@ -152,12 +152,13 @@ typedef struct World { #define WOMAP_HORIZ 2 #define WOMAP_ZENUP 4 #define WOMAP_ZENDOWN 8 +#define WOMAP_MIST 16 /* physicsEngine */ #define WOPHY_NONE 0 #define WOPHY_ENJI 1 #define WOPHY_SUMO 2 -#define WOPHY_DYNAMO 3 +#define WOPHY_DYNAMO 3 #define WOPHY_ODE 4 #define WOPHY_BULLET 5 diff --git a/source/blender/render/extern/include/render.h b/source/blender/render/extern/include/render.h index e3eb926192c..ec724b55846 100644 --- a/source/blender/render/extern/include/render.h +++ b/source/blender/render/extern/include/render.h @@ -148,9 +148,7 @@ struct MTex; struct Tex; void init_render_textures(void); -void end_render_textures(void); void init_render_texture(struct Tex *tex); -void end_render_texture(struct Tex *tex); void do_material_tex(ShadeInput *shi); void do_lamp_tex(struct LampRen *la, float *lavec, ShadeInput *shi, float *fcol); @@ -162,7 +160,6 @@ void externtex(struct MTex *mtex, float *vec, float *tin, float *tr, float *tg, /* envmap (4) */ /* ------------------------------------------------------------------------- */ struct EnvMap; -struct Tex; void RE_free_envmapdata(struct EnvMap *env); void RE_free_envmap(struct EnvMap *env); @@ -173,6 +170,9 @@ struct EnvMap *RE_copy_envmap(struct EnvMap *env); /* --------------------------------------------------------------------- */ /* rendercore (12) */ /* --------------------------------------------------------------------- */ +struct MaterialLayer; +struct ShadeResult; + float Phong_Spec(float *n, float *l, float *v, int hard, int tangent); float CookTorr_Spec(float *n, float *l, float *v, int hard, int tangent); float Blinn_Spec(float *n, float *l, float *v, float refrac, float spec_power, int tangent); @@ -182,12 +182,14 @@ float WardIso_Spec(float *n, float *l, float *v, float rms, int tangent); float OrenNayar_Diff(float *n, float *l, float *v, float rough); float Toon_Diff( float *n, float *l, float *v, float size, float smooth); float Minnaert_Diff( float nl, float *n, float *v, float darkness); +float Fresnel_Diff(float *vn, float *lv, float *view, float ior, float fac); void add_to_diffuse(float *diff, ShadeInput *shi, float is, float r, float g, float b); void ramp_diffuse_result(float *diff, ShadeInput *shi); void do_specular_ramp(ShadeInput *shi, float is, float t, float *spec); void ramp_spec_result(float *specr, float *specg, float *specb, ShadeInput *shi); +void matlayer_blend(struct MaterialLayer *ml, float blendfac, struct ShadeResult *target, struct ShadeResult *src); /* --------------------------------------------------------------------- */ /* ray.c (2) */ diff --git a/source/blender/render/extern/include/render_types.h b/source/blender/render/extern/include/render_types.h index 3a09ba133ef..531a7fc5ceb 100644 --- a/source/blender/render/extern/include/render_types.h +++ b/source/blender/render/extern/include/render_types.h @@ -1,15 +1,12 @@ /** * $Id$ * - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -27,7 +24,7 @@ * * Contributor(s): none yet. * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * ***** END GPL LICENSE BLOCK ***** */ #ifndef RENDER_TYPES_H @@ -58,6 +55,15 @@ typedef struct TexResult { float *nor; } TexResult; +/* localized shade result data */ +typedef struct ShadeResult +{ + float diff[3]; + float spec[3]; + float alpha; + +} ShadeResult; + /* localized renderloop data */ typedef struct ShadeInput { @@ -79,10 +85,11 @@ typedef struct ShadeInput /* individual copies: */ int har; + float layerfac; /* texture coordinates */ float lo[3], gl[3], uv[3], ref[3], orn[3], winco[3], sticky[3], vcol[3], rad[3]; - float vn[3], facenor[3], view[3], refcol[4], displace[3], strand, tang[3]; + float vn[3], vno[3], facenor[3], view[3], refcol[4], displace[3], strand, tang[3]; /* dx/dy OSA coordinates */ float dxco[3], dyco[3]; @@ -139,6 +146,7 @@ typedef struct RE_Render int totvlak, totvert, tothalo, totlamp; /* internal, fortunately */ + ListBase lights; struct LampRen **la; struct VlakRen **blovl; struct VertRen **blove; @@ -194,9 +202,9 @@ typedef struct VertRen float *orco; float *sticky; void *svert; /* smooth vert, only used during initrender */ - short clip, texofs; /* texofs= flag */ - float accum; /* accum for radio weighting, and for strand texco static particles */ + short clip; short flag; /* in use for clipping ztra parts */ + float accum; /* accum for radio weighting, and for strand texco static particles */ } VertRen; /* ------------------------------------------------------------------------- */ @@ -313,6 +321,34 @@ typedef struct LampRen struct MTex *mtex[MAX_MTEX]; } LampRen; +/* **************** defines ********************* */ + +/* mode flag is same as for renderdata */ +/* flag */ +#define R_ZTRA 1 +#define R_HALO 2 +#define R_SEC_FIELD 4 +#define R_LAMPHALO 8 +#define R_RENDERING 16 +#define R_ANIMRENDER 32 +#define R_REDRAW_PRV 64 + +/* vlakren->flag (vlak = face in dutch) char!!! */ +#define R_SMOOTH 1 +#define R_VISIBLE 2 +/* strand flag, means special handling */ +#define R_STRAND 4 +#define R_NOPUNOFLIP 8 +#define R_FULL_OSA 16 +#define R_FACE_SPLIT 32 +/* Tells render to divide face other way. */ +#define R_DIVIDE_24 64 +/* vertex normals are tangent or view-corrected vector, for hair strands */ +#define R_TANGENT 128 + + + + #endif /* RENDER_TYPES_H */ diff --git a/source/blender/render/intern/include/pixelshading.h b/source/blender/render/intern/include/pixelshading.h index 6b9e13c069f..9f4600209b5 100644 --- a/source/blender/render/intern/include/pixelshading.h +++ b/source/blender/render/intern/include/pixelshading.h @@ -68,12 +68,11 @@ enum RE_SkyAlphaBlendingType getSkyBlendingMode(void); /** * Render the sky at pixel (x, y). */ -void renderSkyPixelFloat(RE_COLBUFTYPE *collector, float x, float y); +void renderSkyPixelFloat(RE_COLBUFTYPE *collector, float x, float y, float *rco); +void shadeSkyPixel(RE_COLBUFTYPE *collector, float fx, float fy, float *rco); +void shadeSkyPixelFloat(float *colf, float *rco, float *view, float *dxyview); -/* used by shadeSkyPixel: */ -void shadeSkyPixelFloat(float *colf, float *view, float *dxyview); void renderSpotHaloPixel(float x, float y, float *target); -void shadeSkyPixel(RE_COLBUFTYPE *collector, float fx, float fy); void fillBackgroundImage(RE_COLBUFTYPE *collector, float x, float y); void fillBackgroundImageChar(char *col, float x, float y); diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h index 5163b85d8c0..8f236c502f4 100644 --- a/source/blender/render/intern/include/rendercore.h +++ b/source/blender/render/intern/include/rendercore.h @@ -46,14 +46,6 @@ struct HaloRen; struct ShadeInput; -typedef struct ShadeResult -{ - float diff[3]; - float spec[3]; - float alpha; - -} ShadeResult; - typedef struct PixStr { struct PixStr *next; @@ -103,7 +95,7 @@ void zbufshadeDA(void); /* Delta Accum Pixel Struct */ /** * Also called in: zbuf.c */ -void *shadepixel(float x, float y, int z, int facenr, int mask, float *col); +void *shadepixel(float x, float y, int z, int facenr, int mask, float *col, float *rco); /** * A cryptic but very efficient way of counting the number of bits that diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h index 525f8455aa2..4b7ac102d80 100644 --- a/source/blender/render/intern/include/texture.h +++ b/source/blender/render/intern/include/texture.h @@ -55,7 +55,7 @@ struct Image; /* texture.h */ void do_halo_tex(struct HaloRen *har, float xn, float yn, float *colf); -void do_sky_tex(float *lo, float *dxyview, float *hor, float *zen, float *blend); +void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, float *blend); void render_realtime_texture(struct ShadeInput *shi); /* imagetexture.h */ diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index f3d8ef94d8e..f7c31fa099a 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -50,7 +50,7 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" /* for rectcpy */ -#include "DNA_texture_types.h" +#include "DNA_group_types.h" #include "DNA_image_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -271,6 +271,7 @@ static void envmap_transmatrix(float mat[][4], int part) static void env_rotate_scene(float mat[][4], int mode) { + GroupObject *go; VlakRen *vlr = NULL; VertRen *ver = NULL; LampRen *lar = NULL; @@ -326,8 +327,8 @@ static void env_rotate_scene(float mat[][4], int mode) set_normalflags(); - for(a=0; a<R.totlamp; a++) { - lar= R.la[a]; + for(go=R.lights.first; go; go= go->next) { + lar= go->lampren; /* removed here some horrible code of someone in NaN who tried to fix prototypes... just solved by introducing a correct cmat[3][3] instead diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c index 84eb9d9dfca..1f1ffc20cf5 100644 --- a/source/blender/render/intern/source/initrender.c +++ b/source/blender/render/intern/source/initrender.c @@ -466,33 +466,8 @@ static void free_filt_mask() MEM_freeN(centmask); } -/* unused */ - -#if 0 -void defaultlamp() -{ - LampRen *lar; - - lar= (LampRen *)MEM_callocN(sizeof(LampRen),"lampren"); - R.la[R.totlamp++]=lar; - - lar->type= LA_SUN; - lar->vec[0]= -R.viewmat[2][0]; - lar->vec[1]= -R.viewmat[2][1]; - lar->vec[2]= -R.viewmat[2][2]; - Normalise(lar->vec); - lar->r= 1.0; - lar->g= 1.0; - lar->b= 1.0; - lar->lay= 65535; -} -#endif - - - /* ********************* init calls *********************** */ - static void init_def_material(void) { Material *ma; @@ -511,7 +486,6 @@ void RE_init_render_data(void) R.blove= (VertRen **)MEM_callocN(sizeof(void *)*(TABLEINITSIZE),"Blove"); R.blovl= (VlakRen **)MEM_callocN(sizeof(void *)*(TABLEINITSIZE),"Blovl"); R.bloha= (HaloRen **)MEM_callocN(sizeof(void *)*(TABLEINITSIZE),"Bloha"); - R.la= (LampRen **)MEM_mallocN(LAMPINITSIZE*sizeof(void *),"renderlamparray"); init_def_material(); init_filt_mask(); @@ -525,8 +499,7 @@ void RE_free_render_data() R.blovl= NULL; MEM_freeN(R.bloha); R.bloha= NULL; - MEM_freeN(R.la); - R.la= NULL; + if(R.rectot) MEM_freeN(R.rectot); if(R.rectftot) MEM_freeN(R.rectftot); if(R.rectz) MEM_freeN(R.rectz); @@ -536,7 +509,6 @@ void RE_free_render_data() R.rectz= NULL; R.rectspare= NULL; - end_render_material(&defmaterial); free_filt_mask(); } diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c index d0c23f6daf3..6bb0ce04533 100644 --- a/source/blender/render/intern/source/pixelshading.c +++ b/source/blender/render/intern/source/pixelshading.c @@ -45,6 +45,7 @@ #include "MTC_vectorops.h" #include "DNA_camera_types.h" +#include "DNA_group_types.h" #include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_image_types.h" @@ -127,10 +128,11 @@ static void *renderHaloPixel(RE_COLBUFTYPE *collector, float x, float y, int hal void *renderPixel(RE_COLBUFTYPE *collector, float x, float y, int *obdata, int mask) { - void* data = NULL; + void *data = NULL; + float rco[3]; /* not used (yet?) */ if (obdata[3] & RE_POLY) { - data = shadepixel(x, y, obdata[0], obdata[1], mask, collector); + data = shadepixel(x, y, obdata[0], obdata[1], mask, collector, rco); } else if (obdata[3] & RE_HALO) { data = renderHaloPixel(collector, x, y, obdata[1]); @@ -138,7 +140,7 @@ void *renderPixel(RE_COLBUFTYPE *collector, float x, float y, int *obdata, int m else if( obdata[1] == 0 ) { /* for lamphalo, but doesn't seem to be called? Actually it is, and */ /* it returns NULL pointers. */ - data = shadepixel(x, y, obdata[0], obdata[1], mask, collector); + data = shadepixel(x, y, obdata[0], obdata[1], mask, collector, rco); } return data; @@ -148,7 +150,8 @@ void *renderPixel(RE_COLBUFTYPE *collector, float x, float y, int *obdata, int m void renderSpotHaloPixel(float x, float y, float* fcol) { - shadepixel(x, y, 0, 0, 0, fcol); + float rco[3]; /* unused */ + shadepixel(x, y, 0, 0, 0, fcol, rco); } @@ -158,10 +161,10 @@ extern float hashvectf[]; static void render_lighting_halo(HaloRen *har, float *colf) { + GroupObject *go; LampRen *lar; float i, inp, inpr, rco[3], dco[3], lv[3], lampdist, ld, t, *vn; float ir, ig, ib, shadfac, soft, lacol[3]; - int a; ir= ig= ib= 0.0; @@ -170,8 +173,8 @@ static void render_lighting_halo(HaloRen *har, float *colf) vn= har->no; - for(a=0; a<R.totlamp; a++) { - lar= R.la[a]; + for(go=R.lights.first; go; go= go->next) { + lar= go->lampren; /* test for lamplayer */ if(lar->mode & LA_LAYER) if((lar->lay & har->lay)==0) continue; @@ -494,7 +497,7 @@ void shadeHaloFloat(HaloRen *har, float *col, int zz, if(har->mat) { if(har->mat->mode & MA_HALO_SHADE) { /* we test for lights because of preview... */ - if(R.totlamp) render_lighting_halo(har, col); + if(R.lights.first) render_lighting_halo(har, col); } /* Next, we do the line and ring factor modifications. */ @@ -551,7 +554,7 @@ enum RE_SkyAlphaBlendingType getSkyBlendingMode() { } /* This one renders into collector, as always. */ -void renderSkyPixelFloat(RE_COLBUFTYPE *collector, float x, float y) +void renderSkyPixelFloat(RE_COLBUFTYPE *collector, float x, float y, float *rco) { switch (keyingType) { @@ -566,7 +569,7 @@ void renderSkyPixelFloat(RE_COLBUFTYPE *collector, float x, float y) break; case RE_ALPHA_SKY: /* Fill in the sky as if it were a normal face. */ - shadeSkyPixel(collector, x, y); + shadeSkyPixel(collector, x, y, rco); collector[3]= 0.0; break; default: @@ -579,7 +582,7 @@ void renderSkyPixelFloat(RE_COLBUFTYPE *collector, float x, float y) /* Stuff the sky colour into the collector. */ -void shadeSkyPixel(RE_COLBUFTYPE *collector, float fx, float fy) +void shadeSkyPixel(RE_COLBUFTYPE *collector, float fx, float fy, float *rco) { float view[3], dxyview[2]; @@ -655,13 +658,13 @@ void shadeSkyPixel(RE_COLBUFTYPE *collector, float fx, float fy) } /* get sky colour in the collector */ - shadeSkyPixelFloat(collector, view, dxyview); + shadeSkyPixelFloat(collector, rco, view, dxyview); collector[3] = 1.0f; } } /* Only view vector is important here. Result goes to colf[3] */ -void shadeSkyPixelFloat(float *colf, float *view, float *dxyview) +void shadeSkyPixelFloat(float *colf, float *rco, float *view, float *dxyview) { float lo[3], zen[3], hor[3], blend, blendm; @@ -698,7 +701,7 @@ void shadeSkyPixelFloat(float *colf, float *view, float *dxyview) SWAP(float, lo[1], lo[2]); } - do_sky_tex(lo, dxyview, hor, zen, &blend); + do_sky_tex(rco, lo, dxyview, hor, zen, &blend); } if(blend>1.0) blend= 1.0; diff --git a/source/blender/render/intern/source/ray.c b/source/blender/render/intern/source/ray.c index d9f94c0be60..30973b0891b 100644 --- a/source/blender/render/intern/source/ray.c +++ b/source/blender/render/intern/source/ray.c @@ -1623,7 +1623,7 @@ static void traceray(short depth, float *start, float *vec, float *col, VlakRen VECCOPY(shi.view, vec); Normalise(shi.view); - shadeSkyPixelFloat(col, shi.view, NULL); + shadeSkyPixelFloat(col, NULL, shi.view, isec.start); } } @@ -2118,7 +2118,7 @@ void ray_ao(ShadeInput *shi, World *wrld, float *shadfac) shadfac[2]+= (1.0-fac)*R.wrld.horb + fac*R.wrld.zenb; } else { - shadeSkyPixelFloat(skycol, view, NULL); + shadeSkyPixelFloat(skycol, NULL, view, isec.start); shadfac[0]+= skycol[0]; shadfac[1]+= skycol[1]; shadfac[2]+= skycol[2]; @@ -2272,3 +2272,44 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) } +/* only when face points away from lamp, in direction of lamp, trace ray and find first exit point */ +void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float *co) +{ + Isect isec; + float lampco[3]; + + /* setup isec */ + isec.mode= DDA_SHADOW_TRA; + + if(lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1; + + if(lar->type==LA_SUN || lar->type==LA_HEMI) { + lampco[0]= shi->co[0] - g_oc.ocsize*lar->vec[0]; + lampco[1]= shi->co[1] - g_oc.ocsize*lar->vec[1]; + lampco[2]= shi->co[2] - g_oc.ocsize*lar->vec[2]; + } + else { + VECCOPY(lampco, lar->co); + } + + isec.vlrorig= shi->vlr; + + /* set up isec vec */ + VECCOPY(isec.start, shi->co); + VECCOPY(isec.end, lampco); + + if( d3dda(&isec)) { + /* we got a face */ + + /* render co */ + co[0]= isec.start[0]+isec.labda*(isec.vec[0]); + co[1]= isec.start[1]+isec.labda*(isec.vec[1]); + co[2]= isec.start[2]+isec.labda*(isec.vec[2]); + + *distfac= VecLength(isec.vec); + } + else + *distfac= 0.0f; +} + + diff --git a/source/blender/render/intern/source/renderPreAndPost.c b/source/blender/render/intern/source/renderPreAndPost.c index defb6b97ff6..0753a73276b 100644 --- a/source/blender/render/intern/source/renderPreAndPost.c +++ b/source/blender/render/intern/source/renderPreAndPost.c @@ -34,6 +34,8 @@ #include "MEM_guardedalloc.h" +#include "DNA_group_types.h" + #include "render.h" #include "renderPreAndPost.h" #include "RE_callbacks.h" @@ -52,15 +54,16 @@ */ void prepareScene() { - int a; + GroupObject *go; extern void makeoctree(void); RE_local_get_renderdata(); /* SHADOW BUFFER */ - for(a=0; a<R.totlamp; a++) { + for(go=R.lights.first; go; go= go->next) { + LampRen *lar= go->lampren; + if(lar->shb) makeshadowbuf(lar); if(RE_local_test_break()) break; - if(R.la[a]->shb) makeshadowbuf(R.la[a]); } /* yafray: 'direct' radiosity, environment maps and octree init not needed for yafray render */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 73d57e453b8..99e9384f5b8 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -42,12 +42,13 @@ #include "BKE_utildefines.h" +#include "DNA_camera_types.h" +#include "DNA_group_types.h" +#include "DNA_image_types.h" +#include "DNA_lamp_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" -#include "DNA_image_types.h" #include "DNA_object_types.h" -#include "DNA_camera_types.h" -#include "DNA_lamp_types.h" #include "DNA_texture_types.h" #include "BKE_global.h" @@ -113,6 +114,48 @@ void calc_view_vector(float *view, float x, float y) } } +#if 0 +static void fogcolor(float *colf, float *rco, float *view) +{ + float alpha, stepsize, startdist, dist, hor[4], zen[3], vec[3], dview[3]; + float div=0.0f, distfac; + + hor[0]= R.wrld.horr; hor[1]= R.wrld.horg; hor[2]= R.wrld.horb; + zen[0]= R.wrld.zenr; zen[1]= R.wrld.zeng; zen[2]= R.wrld.zenb; + + VECCOPY(vec, rco); + + /* we loop from cur coord to mist start in steps */ + stepsize= 1.0f; + + div= ABS(view[2]); + dview[0]= view[0]/(stepsize*div); + dview[1]= view[1]/(stepsize*div); + dview[2]= -stepsize; + + startdist= -rco[2] + BLI_frand(); + for(dist= startdist; dist>R.wrld.miststa; dist-= stepsize) { + + hor[0]= R.wrld.horr; hor[1]= R.wrld.horg; hor[2]= R.wrld.horb; + alpha= 1.0f; + do_sky_tex(vec, vec, NULL, hor, zen, &alpha); + + distfac= (dist-R.wrld.miststa)/R.wrld.mistdist; + + hor[3]= hor[0]*distfac*distfac; + + /* premul! */ + alpha= hor[3]; + hor[0]= hor[0]*alpha; + hor[1]= hor[1]*alpha; + hor[2]= hor[2]*alpha; + addAlphaOverFloat(colf, hor); + + VECSUB(vec, vec, dview); + } +} +#endif + float mistfactor(float zcor, float *co) /* dist en height, return alpha */ { float fac, hi; @@ -158,7 +201,7 @@ void RE_sky_char(float *view, char *col) dither_value = ( (BLI_frand()-0.5)*R.r.dither_intensity)/256.0; - shadeSkyPixelFloat(colf, view, NULL); + shadeSkyPixelFloat(colf, view, view, NULL); f= 255.0*(colf[0]+dither_value); if(f<=0.0) col[0]= 0; else if(f>255.0) col[0]= 255; @@ -364,14 +407,15 @@ static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens) static void renderspothalo(ShadeInput *shi, float *col, float alpha) { + GroupObject *go; LampRen *lar; float i; - int a; if(alpha==0.0f) return; - for(a=0; a<R.totlamp; a++) { - lar= R.la[a]; + for(go=R.lights.first; go; go= go->next) { + lar= go->lampren; + if(lar->type==LA_SPOT && (lar->mode & LA_HALO) && lar->haint>0) { spothalo(lar, shi, &i); @@ -607,6 +651,23 @@ static double Normalise_d(double *n) return d; } +/* mix of 'real' fresnel and allowing control. grad defines blending gradient */ +float fresnel_fac(float *view, float *vn, float grad, float fac) +{ + float t1, t2; + + if(fac==0.0) return 1.0; + + t1= (view[0]*vn[0] + view[1]*vn[1] + view[2]*vn[2]); + if(t1>0.0) t2= 1.0+t1; + else t2= 1.0-t1; + + t2= grad + (1.0-grad)*pow(t2, fac); + + if(t2<0.0) return 0.0; + else if(t2>1.0) return 1.0; + return t2; +} static double saacos_d(double fac) { @@ -968,6 +1029,11 @@ float Minnaert_Diff(float nl, float *n, float *v, float darkness) return i; } +float Fresnel_Diff(float *vn, float *lv, float *view, float fac_i, float fac) +{ + return fresnel_fac(lv, vn, fac_i, fac); +} + /* --------------------------------------------- */ /* also called from texture.c */ void calc_R_ref(ShadeInput *shi) @@ -1017,24 +1083,6 @@ void calc_R_ref(ShadeInput *shi) } -/* mix of 'real' fresnel and allowing control. grad defines blending gradient */ -float fresnel_fac(float *view, float *vn, float grad, float fac) -{ - float t1, t2; - - if(fac==0.0) return 1.0; - - t1= (view[0]*vn[0] + view[1]*vn[1] + view[2]*vn[2]); - if(t1>0.0) t2= 1.0+t1; - else t2= 1.0-t1; - - t2= grad + (1.0-grad)*pow(t2, fac); - - if(t2<0.0) return 0.0; - else if(t2>1.0) return 1.0; - return t2; -} - void shade_color(ShadeInput *shi, ShadeResult *shr) { Material *ma= shi->mat; @@ -1065,65 +1113,84 @@ void shade_color(ShadeInput *shi, ShadeResult *shr) shr->alpha= shi->alpha; } -/* r g b = 1 value, col = vector */ -static void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col) +/* r g b = current value, col = new value, fac==0 is no change */ +/* if g==NULL, it only does r channel */ +void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col) { float tmp, facm= 1.0-fac; switch (type) { case MA_RAMP_BLEND: *r = facm*(*r) + fac*col[0]; - *g = facm*(*g) + fac*col[1]; - *b = facm*(*b) + fac*col[2]; + if(g) { + *g = facm*(*g) + fac*col[1]; + *b = facm*(*b) + fac*col[2]; + } break; case MA_RAMP_ADD: *r += fac*col[0]; - *g += fac*col[1]; - *b += fac*col[2]; + if(g) { + *g += fac*col[1]; + *b += fac*col[2]; + } break; case MA_RAMP_MULT: *r *= (facm + fac*col[0]); - *g *= (facm + fac*col[1]); - *b *= (facm + fac*col[2]); + if(g) { + *g *= (facm + fac*col[1]); + *b *= (facm + fac*col[2]); + } break; case MA_RAMP_SCREEN: - *r = 1.0-(facm + (1.0 - col[0]))*(1.0 - *r); - *g = 1.0-(facm + (1.0 - col[1]))*(1.0 - *g); - *b = 1.0-(facm + (1.0 - col[2]))*(1.0 - *b); + *r = 1.0 - (facm + fac*(1.0 - col[0])) * (1.0 - *r); + if(g) { + *g = 1.0 - (facm + fac*(1.0 - col[1])) * (1.0 - *g); + *b = 1.0 - (facm + fac*(1.0 - col[2])) * (1.0 - *b); + } break; case MA_RAMP_SUB: *r -= fac*col[0]; - *g -= fac*col[1]; - *b -= fac*col[2]; + if(g) { + *g -= fac*col[1]; + *b -= fac*col[2]; + } break; case MA_RAMP_DIV: if(col[0]!=0.0) *r = facm*(*r) + fac*(*r)/col[0]; - if(col[1]!=0.0) - *g = facm*(*g) + fac*(*g)/col[1]; - if(col[2]!=0.0) - *b = facm*(*b) + fac*(*b)/col[2]; + if(g) { + if(col[1]!=0.0) + *g = facm*(*g) + fac*(*g)/col[1]; + if(col[2]!=0.0) + *b = facm*(*b) + fac*(*b)/col[2]; + } break; case MA_RAMP_DIFF: *r = facm*(*r) + fac*fabs(*r-col[0]); - *g = facm*(*g) + fac*fabs(*g-col[1]); - *b = facm*(*b) + fac*fabs(*b-col[2]); + if(g) { + *g = facm*(*g) + fac*fabs(*g-col[1]); + *b = facm*(*b) + fac*fabs(*b-col[2]); + } break; case MA_RAMP_DARK: tmp= fac*col[0]; if(tmp < *r) *r= tmp; - tmp= fac*col[1]; - if(tmp < *g) *g= tmp; - tmp= fac*col[2]; - if(tmp < *b) *b= tmp; + if(g) { + tmp= fac*col[1]; + if(tmp < *g) *g= tmp; + tmp= fac*col[2]; + if(tmp < *b) *b= tmp; + } break; case MA_RAMP_LIGHT: tmp= fac*col[0]; if(tmp > *r) *r= tmp; - tmp= fac*col[1]; - if(tmp > *g) *g= tmp; - tmp= fac*col[2]; - if(tmp > *b) *b= tmp; + if(g) { + tmp= fac*col[1]; + if(tmp > *g) *g= tmp; + tmp= fac*col[2]; + if(tmp > *b) *b= tmp; + } break; } @@ -1289,17 +1356,30 @@ static void ambient_occlusion(World *wrld, ShadeInput *shi, ShadeResult *shr) void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) { LampRen *lar; + GroupObject *go; Material *ma= shi->mat; VlakRen *vlr= shi->vlr; + ListBase *lights; float i, inp, inpr, is, t, lv[3], vnor[3], lacol[3], lampdist, ld = 0; float lvrot[3], *vn, *view, shadfac[4], soft, phongcorr; // shadfac = rgba - int a; vn= shi->vn; view= shi->view; memset(shr, 0, sizeof(ShadeResult)); + /* copy all relevant material vars, note, keep this synced with render_types.h */ + memcpy(&shi->r, &ma->r, 23*sizeof(float)); + /* set special cases */ + shi->har= ma->har; + if((ma->mode & MA_RAYMIRROR)==0) shi->ray_mirror= 0.0; + + /* lights */ + if(ma->group) + lights= &ma->group->gobject; + else + lights= &R.lights; + /* separate loop */ if(ma->mode & MA_ONLYSHADOW) { float ir; @@ -1307,8 +1387,10 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) if(R.r.mode & R_SHADOW) { shadfac[3]= ir= 0.0; - for(a=0; a<R.totlamp; a++) { - lar= R.la[a]; + for(go=lights->first; go; go= go->next) { + lar= go->lampren; + if(lar==NULL) continue; + /* yafray: ignore shading by photonlights, not used in Blender */ if (lar->type==LA_YF_PHOTON) continue; @@ -1434,8 +1516,10 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) ambient_occlusion(&R.wrld, shi, shr); - for(a=0; a<R.totlamp; a++) { - lar= R.la[a]; + for(go=lights->first; go; go= go->next) { + lar= go->lampren; + if(lar==NULL) continue; + /* yafray: ignore shading by photonlights, not used in Blender */ if (lar->type==LA_YF_PHOTON) continue; @@ -1590,6 +1674,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) if(ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff_i(inp, vn, lv, view, ma->roughness); else if(ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(vn, lv, view, ma->param[0], ma->param[1]); else if(ma->diff_shader==MA_DIFF_MINNAERT) is= Minnaert_Diff(inp, vn, view, ma->darkness); + else if(ma->diff_shader==MA_DIFF_FRESNEL) is= Fresnel_Diff(vn, lv, view, ma->param[0], ma->param[1]); else is= inp; // Lambert } @@ -1632,6 +1717,22 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) } } } + + if(R.r.mode & R_RAYTRACE) { + extern void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float *co); + float co[3], distfac; + + ray_translucent(shi, lar, &distfac, co); + + if(distfac<0.01f*G.rt) { + // printf("distfac %f\n", distfac); + distfac= 1.0f - distfac/(0.01f*G.rt); + shr->diff[0]+= distfac; + shr->diff[1]+= distfac; + shr->diff[2]+= distfac; + } + } + /* specularity */ if(shadfac[3]>0.0 && shi->spec!=0.0 && !(lar->mode & LA_NO_SPEC)) { @@ -1718,21 +1819,14 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) shr->alpha= shi->alpha; - if(shr->spec[0]<0.0) shr->spec[0]= 0.0; - if(shr->spec[1]<0.0) shr->spec[1]= 0.0; - if(shr->spec[2]<0.0) shr->spec[2]= 0.0; - shr->diff[0]+= shi->r*shi->amb*shi->rad[0]; shr->diff[0]+= shi->ambr; - if(shr->diff[0]<0.0) shr->diff[0]= 0.0; shr->diff[1]+= shi->g*shi->amb*shi->rad[1]; shr->diff[1]+= shi->ambg; - if(shr->diff[1]<0.0) shr->diff[1]= 0.0; shr->diff[2]+= shi->b*shi->amb*shi->rad[2]; shr->diff[2]+= shi->ambb; - if(shr->diff[2]<0.0) shr->diff[2]= 0.0; if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(shr->diff, shi); if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(shr->spec, shr->spec+1, shr->spec+2, shi); @@ -1754,7 +1848,7 @@ void shade_input_set_coords(ShadeInput *shi, float u, float v, int i1, int i2, i VlakRen *vlr= shi->vlr; float l, dl; short texco= shi->mat->texco; - int mode= shi->mat->mode; + int mode= shi->mat->mode_l; /* or-ed result for all layers */ char p1, p2, p3; /* for rendering of quads, the following values are used to denote vertices: @@ -2006,7 +2100,20 @@ void shade_input_set_coords(ShadeInput *shi, float u, float v, int i1, int i2, i shi->dyuv[0]= 2.0*(dl*uv3[0]-duv[0]*uv1[0]-duv[1]*uv2[0]); shi->dyuv[1]= 2.0*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]); } - +#if 0 + { /* tangent derived from UV, comes back later! (ton) */ + //float s1= uv2[0] - uv1[0]; + //float s2= uv3[0] - uv1[0]; + float t1= uv2[1] - uv1[1]; + float t2= uv3[1] - uv1[1]; + + shi->vn[0]= (t2 * (v2->co[0]-v1->co[0]) - t1 * (v3->co[0]-v1->co[0])); + shi->vn[1]= (t2 * (v2->co[1]-v1->co[1]) - t1 * (v3->co[1]-v1->co[1])); + shi->vn[2]= (t2 * (v2->co[2]-v1->co[2]) - t1 * (v3->co[2]-v1->co[2])); + Normalise(shi->vn); + vlr->flag |= R_TANGENT; + } +#endif if(mode & MA_FACETEXTURE) { if((mode & (MA_VERTEXCOL|MA_VERTEXCOLP))==0) { shi->vcol[0]= 1.0; @@ -2080,10 +2187,23 @@ static float isec_view_line(float *view, float *v3, float *v4) } #endif - +void matlayer_blend(MaterialLayer *ml, float blendfac, ShadeResult *target, ShadeResult *src) +{ + + if(ml->flag & ML_DIFFUSE) + ramp_blend(ml->blendmethod, target->diff, target->diff+1, target->diff+2, blendfac*src->alpha, src->diff); + + if(ml->flag & ML_SPECULAR) + ramp_blend(ml->blendmethod, target->spec, target->spec+1, target->spec+2, blendfac*src->alpha, src->spec); + + if(ml->flag & ML_ALPHA) + ramp_blend(ml->blendmethod, &target->alpha, NULL, NULL, blendfac, &src->alpha); +} + + /* x,y: window coordinate from 0 to rectx,y */ /* return pointer to rendered face */ -void *shadepixel(float x, float y, int z, int facenr, int mask, float *col) +void *shadepixel(float x, float y, int z, int facenr, int mask, float *col, float *rco) { ShadeResult shr; ShadeInput shi; @@ -2102,21 +2222,19 @@ void *shadepixel(float x, float y, int z, int facenr, int mask, float *col) if(facenr==0) { /* sky */ col[0]= 0.0; col[1]= 0.0; col[2]= 0.0; col[3]= 0.0; + VECCOPY(rco, col); } else if( (facenr & 0x7FFFFF) <= R.totvlak) { VertRen *v1, *v2, *v3; + Material *mat; + MaterialLayer *ml; float alpha, fac, zcor; vlr= RE_findOrAddVlak( (facenr-1) & 0x7FFFFF); shi.vlr= vlr; - shi.mat= vlr->mat; + mat= shi.mat= vlr->mat; - // copy all relevant material vars, note, keep this synced with render_types.h - memcpy(&shi.r, &shi.mat->r, 23*sizeof(float)); - // set special cases: - shi.har= shi.mat->har; - if((shi.mat->mode & MA_RAYMIRROR)==0) shi.ray_mirror= 0.0; shi.osatex= (shi.mat->texco & TEXCO_OSA); /* copy the face normal (needed because it gets flipped for tracing */ @@ -2197,6 +2315,8 @@ void *shadepixel(float x, float y, int z, int facenr, int mask, float *col) } } } + /* rco might be used for sky texture */ + VECCOPY(rco, shi.co); /* cannot normalise earlier, code above needs it at pixel level */ fac= Normalise(shi.view); @@ -2280,32 +2400,79 @@ void *shadepixel(float x, float y, int z, int facenr, int mask, float *col) } } - /* ------ main shading loop */ - shade_lamp_loop(&shi, &shr); + /* ------ main shading loop -------- */ + VECCOPY(shi.vno, shi.vn); + + if(shi.mat->ml_flag & ML_RENDER) { - if(shi.translucency!=0.0) { - ShadeResult shr_t; + shade_lamp_loop(&shi, &shr); /* clears shr */ + + if(shi.translucency!=0.0) { + ShadeResult shr_t; + + VECCOPY(shi.vn, shi.vno); + VecMulf(shi.vn, -1.0); + VecMulf(shi.facenor, -1.0); + shade_lamp_loop(&shi, &shr_t); + + shr.diff[0]+= shi.translucency*shr_t.diff[0]; + shr.diff[1]+= shi.translucency*shr_t.diff[1]; + shr.diff[2]+= shi.translucency*shr_t.diff[2]; + VecMulf(shi.vn, -1.0); + VecMulf(shi.facenor, -1.0); + } - VecMulf(shi.vn, -1.0); - VecMulf(shi.facenor, -1.0); - shade_lamp_loop(&shi, &shr_t); - shr.diff[0]+= shi.translucency*shr_t.diff[0]; - shr.diff[1]+= shi.translucency*shr_t.diff[1]; - shr.diff[2]+= shi.translucency*shr_t.diff[2]; - VecMulf(shi.vn, -1.0); - VecMulf(shi.facenor, -1.0); - } - - if(R.r.mode & R_RAYTRACE) { - if(shi.ray_mirror!=0.0 || ((shi.mat->mode & MA_RAYTRANSP) && shr.alpha!=1.0)) { - ray_trace(&shi, &shr); + if(R.r.mode & R_RAYTRACE) { + if(shi.ray_mirror!=0.0 || ((shi.mat->mode & MA_RAYTRANSP) && shr.alpha!=1.0)) { + ray_trace(&shi, &shr); + } + } + else { + /* doesnt look 'correct', but is better for preview, plus envmaps dont raytrace this */ + if(shi.mat->mode & MA_RAYTRANSP) shr.alpha= 1.0; } } else { - // doesnt look 'correct', but is better for preview, plus envmaps dont raytrace this - if(shi.mat->mode & MA_RAYTRANSP) shr.alpha= 1.0; + memset(&shr, 0, sizeof(ShadeResult)); + shr.alpha= 1.0f; } + for(ml= shi.mat->layers.first; ml; ml= ml->next) { + if(ml->mat && (ml->flag & ML_RENDER)) { + ShadeResult shrlay; + + shi.mat= ml->mat; + shi.layerfac= ml->blendfac; + VECCOPY(shi.vn, shi.vno); + if(ml->flag & ML_NEG_NORMAL) + VecMulf(shi.vn, -1.0); + + shade_lamp_loop(&shi, &shrlay); /* clears shrlay */ + + if(R.r.mode & R_RAYTRACE) { + if(shi.ray_mirror!=0.0 || ((shi.mat->mode & MA_RAYTRANSP) && shr.alpha!=1.0)) { + ray_trace(&shi, &shr); + } + } + else { + /* doesnt look 'correct', but is better for preview, plus envmaps dont raytrace this */ + if(shi.mat->mode & MA_RAYTRANSP) shr.alpha= 1.0; + } + + matlayer_blend(ml, shi.layerfac, &shr, &shrlay); + } + } + shi.mat= mat; + + /* after shading and composit layers */ + if(shr.spec[0]<0.0f) shr.spec[0]= 0.0f; + if(shr.spec[1]<0.0f) shr.spec[1]= 0.0f; + if(shr.spec[2]<0.0f) shr.spec[2]= 0.0f; + + if(shr.diff[0]<0.0f) shr.diff[0]= 0.0f; + if(shr.diff[1]<0.0f) shr.diff[1]= 0.0f; + if(shr.diff[2]<0.0f) shr.diff[2]= 0.0f; + VECADD(col, shr.diff, shr.spec); /* exposure correction */ @@ -2318,7 +2485,7 @@ void *shadepixel(float x, float y, int z, int facenr, int mask, float *col) } /* MIST */ - if( (R.wrld.mode & WO_MIST) && (shi.mat->mode & MA_NOMIST)==0 ) { + if((R.wrld.mode & WO_MIST) && (shi.mat->mode & MA_NOMIST)==0 ) { if(R.r.mode & R_ORTHO) alpha= mistfactor(-shi.co[2], shi.co); else @@ -2369,15 +2536,15 @@ void *shadepixel(float x, float y, int z, int facenr, int mask, float *col) static void shadepixel_sky(float x, float y, int z, int facenr, int mask, float *colf) { VlakRen *vlr; - float collector[4]; + float collector[4], rco[3]; - vlr= shadepixel(x, y, z, facenr, mask, colf); + vlr= shadepixel(x, y, z, facenr, mask, colf, rco); if(colf[3] != 1.0) { /* bail out when raytrace transparency (sky included already) */ if(vlr && (R.r.mode & R_RAYTRACE)) if(vlr->mat->mode & MA_RAYTRANSP) return; - - renderSkyPixelFloat(collector, x, y); + + renderSkyPixelFloat(collector, x, y, vlr?rco:NULL); addAlphaOverFloat(collector, colf); QUATCOPY(colf, collector); } diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index ee003964764..b2f7cdfca48 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -74,6 +74,35 @@ /* ------------------------------------------------------------------------- */ +#if 0 +/* proposal for more dynamic allocation of options for render vertices, so we dont + have to reserve this space inside vertices */ +typedef struct VertTableNode { + VertRen *vert; + float *rad; + float *sticky; + float *strand; + float *tangent; + float *stress; +} VertTableNode; + +#define RE_STICKY_ELEMS 3 +float *RE_vertren_get_sticky(VertRen *ver, int verify) +{ + float *sticky; + int a= ver->index>>8; + + sticky= R.blove[a].sticky; + if(sticky==NULL) { + if(verify) + sticky= R.blove[a].sticky= MEM_mallocN(RE_STICKY_ELEMS*sizeof(float), "sticky table"); + else + return NULL; + } + sticky+= (nr & 255)*RE_STICKY_ELEMS; +} +#endif + VertRen *RE_findOrAddVert(int nr) { VertRen *v, **temp; diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index 55e546a89f9..344957608fe 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -218,27 +218,6 @@ void init_render_textures() /* ------------------------------------------------------------------------- */ -void end_render_texture(Tex *tex) -{ - - -} - -/* ------------------------------------------------------------------------- */ - -void end_render_textures() -{ - Tex *tex; - - tex= G.main->tex.first; - while(tex) { - if(tex->id.us) end_render_texture(tex); - tex= tex->id.next; - } - -} - -/* ------------------------------------------------------------------------- */ /* this allows colorbanded textures to control normals as well */ static void tex_normal_derivate(Tex *tex, TexResult *texres) @@ -1292,9 +1271,9 @@ static void texture_rgb_blend(float *in, float *tex, float *out, float fact, flo case MTEX_SCREEN: fact*= facg; facm= 1.0-facg; - in[0]= 1.0-(facm+fact*(1.0-tex[0]))*(1.0-out[0]); - in[1]= 1.0-(facm+fact*(1.0-tex[1]))*(1.0-out[1]); - in[2]= 1.0-(facm+fact*(1.0-tex[2]))*(1.0-out[2]); + in[0]= 1.0 - (facm+fact*(1.0-tex[0])) * (1.0-out[0]); + in[1]= 1.0 - (facm+fact*(1.0-tex[1])) * (1.0-out[1]); + in[2]= 1.0 - (facm+fact*(1.0-tex[2])) * (1.0-out[2]); break; case MTEX_SUB: @@ -1825,6 +1804,13 @@ void do_material_tex(ShadeInput *shi) if(shi->translucency<0.0) shi->translucency= 0.0; else if(shi->translucency>1.0) shi->translucency= 1.0; } + if(mtex->mapto & MAP_LAYER) { + int flip= mtex->maptoneg & MAP_LAYER; + + shi->layerfac= texture_value_blend(mtex->def_var, shi->layerfac, texres.tin, varfac, mtex->blendtype, flip); + if(shi->layerfac<0.0) shi->layerfac= 0.0; + else if(shi->layerfac>1.0) shi->layerfac= 1.0; + } if(mtex->mapto & MAP_AMB) { int flip= mtex->maptoneg & MAP_AMB; @@ -1965,7 +1951,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float *colf) /* ------------------------------------------------------------------------- */ /* hor and zen are RGB vectors, blend is 1 float, should all be initialized */ -void do_sky_tex(float *lo, float *dxyview, float *hor, float *zen, float *blend) +void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, float *blend) { MTex *mtex; TexResult texres; @@ -2033,6 +2019,22 @@ void do_sky_tex(float *lo, float *dxyview, float *hor, float *zen, float *blend) MTC_Mat4MulVecfl(mtex->object->imat, tempvec); co= tempvec; } + break; + + case TEXCO_GLOB: + if(rco) { + VECCOPY(tempvec, rco); + MTC_Mat4MulVecfl(R.viewinv, tempvec); + co= tempvec; + } + else + co= lo; + +// VECCOPY(shi->dxgl, shi->dxco); +// MTC_Mat3MulVecfl(R.imat, shi->dxco); +// VECCOPY(shi->dygl, shi->dyco); +// MTC_Mat3MulVecfl(R.imat, shi->dyco); + break; } /* placement */ diff --git a/source/blender/render/intern/source/vanillaRenderPipe.c b/source/blender/render/intern/source/vanillaRenderPipe.c index b5b70aa0e0d..5ab38b589e8 100644 --- a/source/blender/render/intern/source/vanillaRenderPipe.c +++ b/source/blender/render/intern/source/vanillaRenderPipe.c @@ -594,7 +594,6 @@ static int composeStack(int zrow[][RE_PIXELFIELDSIZE], RE_COLBUFTYPE *collector, VlakRen *vlr= NULL; float xs = 0.0; float ys = 0.0; /* coordinates for the render-spot */ - float alphathreshold[RE_MAX_OSA_COUNT]; float colbuf[4]; int inconflict = 0; @@ -714,7 +713,7 @@ static int composeStack(int zrow[][RE_PIXELFIELDSIZE], RE_COLBUFTYPE *collector, ys= (float)y; /* code identical for rendering empty sky pixel */ - renderSkyPixelFloat(collector, xs, ys); + renderSkyPixelFloat(collector, xs, ys, NULL); cpFloatColV(collector, colbuf); if(R.flag & R_LAMPHALO) { @@ -1011,7 +1010,7 @@ static zbufline zb1, zb2; static void renderZBufLine(int y, RE_COLBUFTYPE *colbuf1, RE_COLBUFTYPE *colbuf2, RE_COLBUFTYPE *colbuf3) { - RE_APixstrExt *ap; /* iterator for the face-lists */ + RE_APixstrExt *ap; /* iterator for the face-lists */ RE_COLBUFTYPE collector[4]; RE_COLBUFTYPE sampcol[RE_MAX_OSA_COUNT * 4]; RE_COLBUFTYPE *j = NULL; /* generic pixel pointer */ @@ -1057,7 +1056,7 @@ static void renderZBufLine(int y, RE_COLBUFTYPE *colbuf1, RE_COLBUFTYPE *colbuf2 /* This is a bit dirty. Depending on sky-mode, the pixel is */ /* blended in differently. */ - renderSkyPixelFloat(collector, x, y); + renderSkyPixelFloat(collector, x, y, NULL); j = sampcol; for(i = 0; i < osaNr; i++, j+=4) { diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index b99f4d8e768..f7480c4cb2f 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -2695,6 +2695,7 @@ int vergzvlak(const void *a1, const void *a2) */ static void shadetrapixel(float x, float y, int z, int facenr, int mask, float *fcol) { + float rco[3]; if( (facenr & 0x7FFFFF) > R.totvlak) { printf("error in shadetrapixel nr: %d\n", (facenr & 0x7FFFFF)); @@ -2708,7 +2709,7 @@ static void shadetrapixel(float x, float y, int z, int facenr, int mask, float * if(vlr->flag & R_FULL_OSA) { for(a=0; a<R.osa; a++) { if(mask & (1<<a)) { - shadepixel(x+jit[a][0], y+jit[a][1], z, facenr, 1<<a, fcol); + shadepixel(x+jit[a][0], y+jit[a][1], z, facenr, 1<<a, fcol, rco); accumcol[0]+= fcol[0]; accumcol[1]+= fcol[1]; accumcol[2]+= fcol[2]; @@ -2729,11 +2730,11 @@ static void shadetrapixel(float x, float y, int z, int facenr, int mask, float * int b= centmask[mask]; x= x+centLut[b & 15]; y= y+centLut[b>>4]; - shadepixel(x, y, z, facenr, mask, fcol); + shadepixel(x, y, z, facenr, mask, fcol, rco); } } - else shadepixel(x, y, z, facenr, mask, fcol); + else shadepixel(x, y, z, facenr, mask, fcol, rco); } static int addtosampcol(float *sampcol, float *fcol, int mask) diff --git a/source/blender/renderconverter/intern/convertBlenderScene.c b/source/blender/renderconverter/intern/convertBlenderScene.c index e1fc8556d73..a4dbad1000a 100644 --- a/source/blender/renderconverter/intern/convertBlenderScene.c +++ b/source/blender/renderconverter/intern/convertBlenderScene.c @@ -53,6 +53,7 @@ #include "DNA_material_types.h" #include "DNA_curve_types.h" #include "DNA_effect_types.h" +#include "DNA_group_types.h" #include "DNA_lamp_types.h" #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" @@ -74,6 +75,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_group.h" #include "BKE_key.h" #include "BKE_ipo.h" #include "BKE_lattice.h" @@ -1669,23 +1671,10 @@ static void area_lamp_vectors(LampRen *lar) void RE_add_render_lamp(Object *ob, int actual_render) { Lamp *la; - LampRen *lar, **temp; + LampRen *lar; + GroupObject *go; float mat[4][4], hoek, xn, yn; int c; - static int rlalen=LAMPINITSIZE; /*number of currently allocated lampren pointers*/ - - if(R.totlamp>=rlalen) { /* Need more Lamp pointers....*/ - printf("Alocating %i more lamp groups, %i total.\n", - LAMPINITSIZE, rlalen+LAMPINITSIZE); - temp=R.la; - R.la=(LampRen**)MEM_callocN(sizeof(void*)*(rlalen+LAMPINITSIZE) , "renderlamparray"); - memcpy(R.la, temp, rlalen*sizeof(void*)); - memset(&(R.la[R.totlamp]), 0, LAMPINITSIZE*sizeof(void*)); - rlalen+=LAMPINITSIZE; - MEM_freeN(temp); - } - - la= ob->data; /* prevent only shadow from rendering light, but only return on render, not preview */ if(actual_render) { @@ -1693,9 +1682,13 @@ void RE_add_render_lamp(Object *ob, int actual_render) if((R.r.mode & R_SHADOW)==0) return; } - + + go= MEM_callocN(sizeof(GroupObject), "groupobject"); + BLI_addtail(&R.lights, go); + R.totlamp++; lar= (LampRen *)MEM_callocN(sizeof(LampRen),"lampren"); - R.la[R.totlamp++]= lar; + go->lampren= lar; + go->ob= ob; MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat); MTC_Mat4Invert(ob->imat, mat); @@ -1703,6 +1696,8 @@ void RE_add_render_lamp(Object *ob, int actual_render) MTC_Mat3CpyMat4(lar->mat, mat); MTC_Mat3CpyMat4(lar->imat, ob->imat); + la= ob->data; + lar->bufsize = la->bufsize; lar->samp = la->samp; lar->soft = la->soft; @@ -2371,6 +2366,7 @@ void RE_freeRotateBlenderScene(void) { ShadBuf *shb; Object *ob = NULL; + GroupObject *go; unsigned long *ztile; int a, b, v; char *ctile; @@ -2379,10 +2375,11 @@ void RE_freeRotateBlenderScene(void) BLI_memarena_free(R.memArena); R.memArena = NULL; - - for(a=0; a<R.totlamp; a++) { - if(R.la[a]->shb) { - shb= R.la[a]->shb; + + for(go= R.lights.first; go; go= go->next) { + struct LampRen *lar= go->lampren; + if(lar->shb) { + shb= lar->shb; v= (shb->size*shb->size)/256; ztile= shb->zbuf; ctile= shb->cbuf; @@ -2392,11 +2389,13 @@ void RE_freeRotateBlenderScene(void) MEM_freeN(shb->zbuf); MEM_freeN(shb->cbuf); - MEM_freeN(R.la[a]->shb); + MEM_freeN(lar->shb); } - if(R.la[a]->jitter) MEM_freeN(R.la[a]->jitter); - MEM_freeN(R.la[a]); + if(lar->jitter) MEM_freeN(lar->jitter); + MEM_freeN(lar); } + + BLI_freelistN(&R.lights); /* note; these pointer arrays were allocated, with last element NULL to stop loop */ a=0; @@ -2435,8 +2434,6 @@ void RE_freeRotateBlenderScene(void) free_mesh_orco_hash(); - end_render_textures(); - end_render_materials(); end_radio_render(); if(R.wrld.aosphere) { MEM_freeN(R.wrld.aosphere); @@ -2586,7 +2583,25 @@ static void check_non_flat_quads(void) } } - +static void set_material_lightgroups(void) +{ + GroupObject *go, *gol; + Material *ma; + + /* it's a bit too many loops in loops... but will survive */ + for(ma= G.main->mat.first; ma; ma=ma->id.next) { + if(ma->group) { + for(go= ma->group->gobject.first; go; go= go->next) { + for(gol= R.lights.first; gol; gol= gol->next) { + if(gol->ob==go->ob) { + go->lampren= gol->lampren; + break; + } + } + } + } + } +} extern int slurph_opt; /* key.c */ extern ListBase duplilist; @@ -2598,13 +2613,12 @@ void RE_rotateBlenderScene(void) unsigned int lay; float mat[4][4]; - if(G.scene->camera==0) return; + if(G.scene->camera==NULL) return; R.memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); - - slurph_opt= 0; - R.totvlak=R.totvert=R.totlamp=R.tothalo= 0; + + slurph_opt= 0; /* in localview, lamps are using normal layers, objects only local bits */ if(G.scene->lay & 0xFF000000) lay= G.scene->lay & 0xFF000000; @@ -2785,7 +2799,9 @@ void RE_rotateBlenderScene(void) } sort_halos(); - + + set_material_lightgroups(); + if(R.wrld.mode & WO_STARS) RE_make_stars(NULL, NULL, NULL); slurph_opt= 1; diff --git a/source/blender/src/SConscript b/source/blender/src/SConscript index e2deaa47544..992c4f55902 100644 --- a/source/blender/src/SConscript +++ b/source/blender/src/SConscript @@ -105,6 +105,7 @@ source_files = ['B.blend.c', 'oops.c', 'outliner.c', 'splash.jpg.c', + 'parametrizer.c', 'playanim.c', 'poseobject.c', 'previewrender.c', diff --git a/source/blender/src/butspace.c b/source/blender/src/butspace.c index bb6dc671e14..752e831c2b4 100644 --- a/source/blender/src/butspace.c +++ b/source/blender/src/butspace.c @@ -107,7 +107,7 @@ void test_scriptpoin_but(char *name, ID **idpp) } id= id->next; } - *idpp= 0; + *idpp= NULL; } void test_actionpoin_but(char *name, ID **idpp) @@ -122,7 +122,7 @@ void test_actionpoin_but(char *name, ID **idpp) } id= id->next; } - *idpp= 0; + *idpp= NULL; } @@ -144,7 +144,7 @@ void test_obpoin_but(char *name, ID **idpp) } id= id->next; } - *idpp= 0; + *idpp= NULL; } void test_meshpoin_but(char *name, ID **idpp) @@ -162,7 +162,7 @@ void test_meshpoin_but(char *name, ID **idpp) } id= id->next; } - *idpp= 0; + *idpp= NULL; } void test_matpoin_but(char *name, ID **idpp) @@ -180,7 +180,7 @@ void test_matpoin_but(char *name, ID **idpp) } id= id->next; } - *idpp= 0; + *idpp= NULL; } void test_scenepoin_but(char *name, ID **idpp) @@ -198,7 +198,25 @@ void test_scenepoin_but(char *name, ID **idpp) } id= id->next; } - *idpp= 0; + *idpp= NULL; +} + +void test_grouppoin_but(char *name, ID **idpp) +{ + ID *id; + + if( *idpp ) (*idpp)->us--; + + id= G.main->group.first; + while(id) { + if( strcmp(name, id->name+2)==0 ) { + *idpp= id; + id_us_plus(id); + return; + } + id= id->next; + } + *idpp= NULL; } diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 815282720ea..8292357698b 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -3265,6 +3265,7 @@ static void editing_panel_mesh_tools1(Object *ob, Mesh *me) uiDefButBitI(block, TOG, G_DRAW_FACEAREA, REDRAWVIEW3D, "Face Area", 1125,44,150,19, &G.f, 0, 0, 0, 0, "Displays the area of selected faces"); uiBlockEndAlign(block); + uiDefButBitS(block, TOG, B_MESH_X_MIRROR, B_DIFF, "X-axis mirror",1125,0,150,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "While using transforms, mirrors the transformation"); } char *get_vertexgroup_menustr(Object *ob) diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 8281ce7bc8f..2ac7b28cd53 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -119,6 +119,7 @@ #include "BKE_displist.h" #include "BKE_effect.h" #include "BKE_font.h" +#include "BKE_group.h" #include "BKE_image.h" #include "BKE_ipo.h" #include "BKE_lattice.h" @@ -1133,118 +1134,6 @@ void do_constraintbuts(unsigned short event) allqueue (REDRAWBUTSOBJECT, 0); } -void object_panel_constraint(char *context) -{ - uiBlock *block; - Object *ob= OBACT; - ListBase *conlist; - bConstraint *curcon; - short xco, yco; - char str[64]; - - block= uiNewBlock(&curarea->uiblocks, "object_panel_constraint", UI_EMBOSS, UI_HELV, curarea->win); - if(uiNewPanel(curarea, block, "Constraints", context, 640, 0, 318, 204)==0) return; - - /* this is a variable height panel, newpanel doesnt force new size on existing panels */ - /* so first we make it default height */ - uiNewPanelHeight(block, 204); - - if(G.obedit==OBACT) return; // ?? - - conlist = get_active_constraints(OBACT); - - if (conlist) { - - uiDefBlockBut(block, add_constraintmenu, NULL, "Add Constraint", 0, 190, 130, 20, "Add a new constraint"); - - /* print active object or bone */ - str[0]= 0; - if (ob->flag & OB_POSEMODE){ - bPoseChannel *pchan= get_active_posechannel(ob); - if(pchan) sprintf(str, "To Bone: %s", pchan->name); - } - else { - sprintf(str, "To Object: %s", ob->id.name+2); - } - uiDefBut(block, LABEL, 1, str, 150, 190, 150, 20, NULL, 0.0, 0.0, 0, 0, "Displays Active Object or Bone name"); - - /* Go through the list of constraints and draw them */ - xco = 10; - yco = 160; - - for (curcon = conlist->first; curcon; curcon=curcon->next) { - /* hrms, the temporal constraint should not draw! */ - if(curcon->type==CONSTRAINT_TYPE_KINEMATIC) { - bKinematicConstraint *data= curcon->data; - if(data->flag & CONSTRAINT_IK_TEMP) - continue; - } - /* Draw default constraint header */ - draw_constraint(block, conlist, curcon, &xco, &yco); - } - - if(yco < 0) uiNewPanelHeight(block, 204-yco); - - } -} - -static void object_panel_draw(Object *ob) -{ - uiBlock *block; - int xco, a, dx, dy; - - block= uiNewBlock(&curarea->uiblocks, "object_panel_draw", UI_EMBOSS, UI_HELV, curarea->win); - if(uiNewPanel(curarea, block, "Draw", "Object", 320, 0, 318, 204)==0) return; - - /* LAYERS */ - xco= 120; - dx= 35; - dy= 30; - - uiDefBut(block, LABEL, 0, "Layers", 10,170,100,20, NULL, 0, 0, 0, 0, ""); - - uiBlockBeginAlign(block); - for(a=0; a<5; a++) - uiDefButBitI(block, TOG, 1<<a, B_OBLAY+a, "", (short)(xco+a*(dx/2)), 180, (short)(dx/2), (short)(dy/2), &(BASACT->lay), 0, 0, 0, 0, ""); - for(a=0; a<5; a++) - uiDefButBitI(block, TOG, 1<<(a+10), B_OBLAY+a+10, "", (short)(xco+a*(dx/2)), 165, (short)(dx/2), (short)(dy/2), &(BASACT->lay), 0, 0, 0, 0, ""); - - xco+= 7; - uiBlockBeginAlign(block); - for(a=5; a<10; a++) - uiDefButBitI(block, TOG, 1<<a, B_OBLAY+a, "", (short)(xco+a*(dx/2)), 180, (short)(dx/2), (short)(dy/2), &(BASACT->lay), 0, 0, 0, 0, ""); - for(a=5; a<10; a++) - uiDefButBitI(block, TOG, 1<<(a+10), B_OBLAY+a+10, "", (short)(xco+a*(dx/2)), 165, (short)(dx/2), (short)(dy/2), &(BASACT->lay), 0, 0, 0, 0, ""); - - uiBlockEndAlign(block); - - uiDefBut(block, LABEL, 0, "Drawtype", 10,120,100,20, NULL, 0, 0, 0, 0, ""); - - uiBlockBeginAlign(block); - uiDefButC(block, ROW, REDRAWVIEW3D, "Shaded", 10,100,100, 20, &ob->dt, 0, OB_SHADED, 0, 0, "Draw active object shaded or textured"); - uiDefButC(block, ROW, REDRAWVIEW3D, "Solid", 10,80,100, 20, &ob->dt, 0, OB_SOLID, 0, 0, "Draw active object in solid"); - uiDefButC(block, ROW, REDRAWVIEW3D, "Wire", 10,60, 100, 20, &ob->dt, 0, OB_WIRE, 0, 0, "Draw active object in wireframe"); - uiDefButC(block, ROW, REDRAWVIEW3D, "Bounds", 10,40, 100, 20, &ob->dt, 0, OB_BOUNDBOX, 0, 0, "Only draw object with bounding box"); - uiBlockEndAlign(block); - - uiDefBut(block, LABEL, 0, "Draw Extra", 120,120,90,20, NULL, 0, 0, 0, 0, ""); - - uiBlockBeginAlign(block); - uiDefButBitC(block, TOG, OB_BOUNDBOX, REDRAWVIEW3D, "Bounds", 120, 100, 90, 20, &ob->dtx, 0, 0, 0, 0, "Displays the active object's bounds"); - uiDefButBitC(block, TOG, OB_DRAWNAME, REDRAWVIEW3D, "Name", 210, 100, 90, 20, &ob->dtx, 0, 0, 0, 0, "Displays the active object's name"); - - uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Polyheder%x4", - 120, 80, 90, 20, &ob->boundtype, 0, 0, 0, 0, "Selects the boundary display type"); - uiDefButBitC(block, TOG, OB_AXIS, REDRAWVIEW3D, "Axis", 210, 80, 90, 20, &ob->dtx, 0, 0, 0, 0, "Displays the active object's centre and axis"); - - uiDefButBitC(block, TOG, OB_TEXSPACE, REDRAWVIEW3D, "TexSpace", 120, 60, 90, 20, &ob->dtx, 0, 0, 0, 0, "Displays the active object's texture space"); - uiDefButBitC(block, TOG, OB_DRAWWIRE, REDRAWVIEW3D, "Wire", 210, 60, 90, 20, &ob->dtx, 0, 0, 0, 0, "Adds the active object's wireframe over solid drawing"); - - uiDefButBitC(block, TOG, OB_DRAWTRANSP, REDRAWVIEW3D, "Transp", 120, 40, 90, 20, &ob->dtx, 0, 0, 0, 0, "Enables transparent materials for the active object (Mesh only)"); - uiDefButBitC(block, TOG, OB_DRAWXRAY, REDRAWVIEW3D, "X-ray", 210, 40, 90, 20, &ob->dtx, 0, 0, 0, 0, "Makes the active object draw in front of others"); - -} - static void softbody_bake(Object *ob) { SoftBody *sb= ob->soft; @@ -1473,56 +1362,263 @@ void do_object_panels(unsigned short event) } +static void do_add_groupmenu(void *arg, int event) +{ + Object *ob= OBACT; + + if(ob) { + + if(event== -1) { + Group *group= add_group(); + add_to_group(group, ob); + } + else + add_to_group(BLI_findlink(&G.main->group, event), ob); + + ob->flag |= OB_FROMGROUP; + BASACT->flag |= OB_FROMGROUP; + allqueue(REDRAWBUTSOBJECT, 0); + allqueue(REDRAWVIEW3D, 0); + } +} + +static uiBlock *add_groupmenu(void *arg_unused) +{ + uiBlock *block; + Group *group; + short yco= 0; + + block= uiNewBlock(&curarea->uiblocks, "add_constraintmenu", UI_EMBOSSP, UI_HELV, curarea->win); + uiBlockSetButmFunc(block, do_add_groupmenu, NULL); + + uiDefBut(block, BUTM, B_NOP, "ADD NEW", 0, 20, 160, 19, NULL, 0.0, 0.0, 1, -1, ""); + for(group= G.main->group.first; group; group= group->id.next, yco++) { + uiDefBut(block, BUTM, B_NOP, group->id.name+2, 0, -20*yco, 160, 19, NULL, 0.0, 0.0, 1, yco, ""); + } + + uiTextBoundsBlock(block, 50); + uiBlockSetDirection(block, UI_DOWN); + + return block; +} + +static void group_ob_rem(void *gr_v, void *ob_v) +{ + Object *ob= OBACT; + + rem_from_group(gr_v, ob); + if(find_group(ob)==NULL) { + ob->flag &= ~OB_FROMGROUP; + BASACT->flag &= ~OB_FROMGROUP; + } + allqueue(REDRAWBUTSOBJECT, 0); + allqueue(REDRAWVIEW3D, 0); + +} + +static void object_panel_object(Object *ob) +{ + uiBlock *block; + uiBut *but; + Group *group; + int a=0, xco; + + block= uiNewBlock(&curarea->uiblocks, "object_panel_object", UI_EMBOSS, UI_HELV, curarea->win); + if(uiNewPanel(curarea, block, "Object and Links", "Object", 0, 0, 318, 204)==0) return; + + /* object name */ + uiBlockSetCol(block, TH_BUT_SETTING2); + xco= std_libbuttons(block, 10, 180, 0, NULL, 0, &ob->id, NULL, &(G.buts->menunr), B_OBALONE, B_OBLOCAL, 0, 0, B_KEEPDATA); + uiBlockSetCol(block, TH_AUTO); + + /* parent */ + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_OBJECTPANELPARENT, "Par:", xco+5, 180, 305-xco, 20, &ob->parent, "Parent Object"); + + uiDefBlockBut(block, add_groupmenu, NULL, "Add to Group", 10,150,150,20, "Add Object to a new Group"); + + /* all groups */ + uiBlockBeginAlign(block); + for(group= G.main->group.first; group; group= group->id.next) { + if(object_in_group(ob, group)) { + but = uiDefBut(block, TEX, B_IDNAME, "GR:", 10, 120-a, 150, 20, group->id.name+2, 0.0, 19.0, 0, 0, "Displays Group name. Click to change."); + uiButSetFunc(but, test_idbutton_cb, group->id.name, NULL); + + but = uiDefIconBut(block, BUT, B_NOP, VICON_X, 160, 120-a, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Remove Group membership"); + uiButSetFunc(but, group_ob_rem, group, ob); + + a+= 20; + } + } +} + static void object_panel_anim(Object *ob) { uiBlock *block; char str[32]; block= uiNewBlock(&curarea->uiblocks, "object_panel_anim", UI_EMBOSS, UI_HELV, curarea->win); - if(uiNewPanel(curarea, block, "Anim settings", "Object", 0, 0, 318, 204)==0) return; + if(uiNewPanel(curarea, block, "Anim settings", "Object", 320, 0, 318, 204)==0) return; uiBlockBeginAlign(block); - uiDefButS(block, ROW,B_TRACKBUTS,"TrackX", 24,190,59,19, &ob->trackflag, 12.0, 0.0, 0, 0, "Specify the axis that points to another object"); - uiDefButS(block, ROW,B_TRACKBUTS,"Y", 85,190,19,19, &ob->trackflag, 12.0, 1.0, 0, 0, "Specify the axis that points to another object"); - uiDefButS(block, ROW,B_TRACKBUTS,"Z", 104,190,19,19, &ob->trackflag, 12.0, 2.0, 0, 0, "Specify the axis that points to another object"); - uiDefButS(block, ROW,B_TRACKBUTS,"-X", 124,190,24,19, &ob->trackflag, 12.0, 3.0, 0, 0, "Specify the axis that points to another object"); - uiDefButS(block, ROW,B_TRACKBUTS,"-Y", 150,190,24,19, &ob->trackflag, 12.0, 4.0, 0, 0, "Specify the axis that points to another object"); - uiDefButS(block, ROW,B_TRACKBUTS,"-Z", 178,190,24,19, &ob->trackflag, 12.0, 5.0, 0, 0, "Specify the axis that points to another object"); + uiDefButS(block, ROW,B_TRACKBUTS,"TrackX", 24,180,59,19, &ob->trackflag, 12.0, 0.0, 0, 0, "Specify the axis that points to another object"); + uiDefButS(block, ROW,B_TRACKBUTS,"Y", 85,180,19,19, &ob->trackflag, 12.0, 1.0, 0, 0, "Specify the axis that points to another object"); + uiDefButS(block, ROW,B_TRACKBUTS,"Z", 104,180,19,19, &ob->trackflag, 12.0, 2.0, 0, 0, "Specify the axis that points to another object"); + uiDefButS(block, ROW,B_TRACKBUTS,"-X", 124,180,24,19, &ob->trackflag, 12.0, 3.0, 0, 0, "Specify the axis that points to another object"); + uiDefButS(block, ROW,B_TRACKBUTS,"-Y", 150,180,24,19, &ob->trackflag, 12.0, 4.0, 0, 0, "Specify the axis that points to another object"); + uiDefButS(block, ROW,B_TRACKBUTS,"-Z", 178,180,24,19, &ob->trackflag, 12.0, 5.0, 0, 0, "Specify the axis that points to another object"); uiBlockBeginAlign(block); - uiDefButS(block, ROW,REDRAWVIEW3D,"UpX", 226,190,45,19, &ob->upflag, 13.0, 0.0, 0, 0, "Specify the axis that points up"); - uiDefButS(block, ROW,REDRAWVIEW3D,"Y", 274,190,20,19, &ob->upflag, 13.0, 1.0, 0, 0, "Specify the axis that points up"); - uiDefButS(block, ROW,REDRAWVIEW3D,"Z", 298,190,19,19, &ob->upflag, 13.0, 2.0, 0, 0, "Specify the axis that points up"); + uiDefButS(block, ROW,REDRAWVIEW3D,"UpX", 226,180,45,19, &ob->upflag, 13.0, 0.0, 0, 0, "Specify the axis that points up"); + uiDefButS(block, ROW,REDRAWVIEW3D,"Y", 274,180,20,19, &ob->upflag, 13.0, 1.0, 0, 0, "Specify the axis that points up"); + uiDefButS(block, ROW,REDRAWVIEW3D,"Z", 298,180,19,19, &ob->upflag, 13.0, 2.0, 0, 0, "Specify the axis that points up"); + uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, OB_DRAWKEY, REDRAWVIEW3D, "Draw Key", 24,160,71,19, &ob->ipoflag, 0, 0, 0, 0, "Draw object as key position"); - uiDefButBitS(block, TOG, OB_DRAWKEYSEL, REDRAWVIEW3D, "Draw Key Sel", 97,160,81,19, &ob->ipoflag, 0, 0, 0, 0, "Limit the drawing of object keys"); - uiDefButBitS(block, TOG, OB_POWERTRACK, REDRAWVIEW3D, "Powertrack", 180,160,78,19, &ob->transflag, 0, 0, 0, 0, "Switch objects rotation off"); - uiDefButBitS(block, TOG, PARSLOW, 0, "SlowPar", 260,160,56,19, &ob->partype, 0, 0, 0, 0, "Create a delay in the parent relationship"); + uiDefButBitS(block, TOG, OB_DRAWKEY, REDRAWVIEW3D, "Draw Key", 24,155,71,19, &ob->ipoflag, 0, 0, 0, 0, "Draw object as key position"); + uiDefButBitS(block, TOG, OB_DRAWKEYSEL, REDRAWVIEW3D, "Draw Key Sel", 97,155,81,19, &ob->ipoflag, 0, 0, 0, 0, "Limit the drawing of object keys"); + uiDefButBitS(block, TOG, OB_POWERTRACK, REDRAWVIEW3D, "Powertrack", 180,155,78,19, &ob->transflag, 0, 0, 0, 0, "Switch objects rotation off"); + uiDefButBitS(block, TOG, PARSLOW, 0, "SlowPar", 260,155,56,19, &ob->partype, 0, 0, 0, 0, "Create a delay in the parent relationship"); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, OB_DUPLIFRAMES, REDRAWVIEW3D, "DupliFrames", 24,128,89,19, &ob->transflag, 0, 0, 0, 0, "Make copy of object for every frame"); - uiDefButBitS(block, TOG, OB_DUPLIVERTS, REDRAWVIEW3D, "DupliVerts", 114,128,82,19, &ob->transflag, 0, 0, 0, 0, "Duplicate child objects on all vertices"); - uiDefButBitS(block, TOG, OB_DUPLIROT, REDRAWVIEW3D, "Rot", 200,128,31,19, &ob->transflag, 0, 0, 0, 0, "Rotate dupli according to facenormal"); - uiDefButBitS(block, TOG, OB_DUPLINOSPEED, REDRAWVIEW3D, "No Speed", 234,128,82,19, &ob->transflag, 0, 0, 0, 0, "Set dupliframes to still, regardless of frame"); + + uiDefButBitS(block, TOG, OB_DUPLIFRAMES, REDRAWVIEW3D, "DupliFrames", 24,130,89,20, &ob->transflag, 0, 0, 0, 0, "Make copy of object for every frame"); + uiDefButBitS(block, TOG, OB_DUPLIVERTS, REDRAWVIEW3D, "DupliVerts", 114,130,82,20, &ob->transflag, 0, 0, 0, 0, "Duplicate child objects on all vertices"); + uiDefButBitS(block, TOG, OB_DUPLIROT, REDRAWVIEW3D, "Rot", 200,130,31,20, &ob->transflag, 0, 0, 0, 0, "Rotate dupli according to facenormal"); + uiDefButBitS(block, TOG, OB_DUPLINOSPEED, REDRAWVIEW3D, "No Speed", 234,130,82,20, &ob->transflag, 0, 0, 0, 0, "Set dupliframes to still, regardless of frame"); + + uiDefButBitS(block, TOG, OB_DUPLIGROUP, REDRAWVIEW3D, "DupliGroup", 24,110,150,20, &ob->transflag, 0, 0, 0, 0, "Make copy of object for every frame"); + uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, REDRAWVIEW3D, "GR:", 174,110,142,20, &ob->dup_group, "Duplicate this entire Group"); + uiBlockBeginAlign(block); - uiDefButS(block, NUM, REDRAWVIEW3D, "DupSta:", 24,105,141,19, &ob->dupsta, 1.0, (MAXFRAMEF - 1.0f), 0, 0, "Specify startframe for Dupliframes"); - uiDefButS(block, NUM, REDRAWVIEW3D, "DupOn:", 170,105,146,19, &ob->dupon, 1.0, 1500.0, 0, 0, ""); - uiDefButS(block, NUM, REDRAWVIEW3D, "DupEnd", 24,82,140,19, &ob->dupend, 1.0, MAXFRAMEF, 0, 0, "Specify endframe for Dupliframes"); - uiDefButS(block, NUM, REDRAWVIEW3D, "DupOff", 171,82,145,19, &ob->dupoff, 0.0, 1500.0, 0, 0, ""); + uiDefButS(block, NUM, REDRAWVIEW3D, "DupSta:", 24,85,141,19, &ob->dupsta, 1.0, (MAXFRAMEF - 1.0f), 0, 0, "Specify startframe for Dupliframes"); + uiDefButS(block, NUM, REDRAWVIEW3D, "DupOn:", 170,85,146,19, &ob->dupon, 1.0, 1500.0, 0, 0, ""); + uiDefButS(block, NUM, REDRAWVIEW3D, "DupEnd", 24,65,140,19, &ob->dupend, 1.0, MAXFRAMEF, 0, 0, "Specify endframe for Dupliframes"); + uiDefButS(block, NUM, REDRAWVIEW3D, "DupOff", 171,65,145,19, &ob->dupoff, 0.0, 1500.0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, OB_OFFS_OB, REDRAWALL, "Offs Ob", 24,51,56,20, &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on its own objectipo"); - uiDefButBitS(block, TOG, OB_OFFS_PARENT, REDRAWALL, "Offs Par", 82,51,56,20 , &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on the parent"); - uiDefButBitS(block, TOG, OB_OFFS_PARTICLE, REDRAWALL, "Offs Particle", 140,51,103,20, &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on the particle effect"); + uiDefButBitS(block, TOG, OB_OFFS_OB, REDRAWALL, "Offs Ob", 24,35,56,20, &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on its own objectipo"); + uiDefButBitS(block, TOG, OB_OFFS_PARENT, REDRAWALL, "Offs Par", 82,35,56,20 , &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on the parent"); + uiDefButBitS(block, TOG, OB_OFFS_PARTICLE, REDRAWALL, "Offs Particle", 140,35,103,20, &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on the particle effect"); uiBlockBeginAlign(block); - uiDefButF(block, NUM, REDRAWALL, "TimeOffset:", 24,17,115,30, &ob->sf, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify an offset in frames"); - uiDefBut(block, BUT, B_AUTOTIMEOFS, "Automatic Time", 139,17,104,31, 0, 0, 0, 0, 0, "Generate automatic timeoffset values for all selected frames"); - uiDefBut(block, BUT, B_PRINTSPEED, "PrSpeed", 248,17,67,31, 0, 0, 0, 0, 0, "Print objectspeed"); + uiDefButF(block, NUM, REDRAWALL, "TimeOffset:", 24,10,115,20, &ob->sf, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify an offset in frames"); + uiDefBut(block, BUT, B_AUTOTIMEOFS, "Automatic Time", 139,10,104,20, 0, 0, 0, 0, 0, "Generate automatic timeoffset values for all selected frames"); + uiDefBut(block, BUT, B_PRINTSPEED, "PrSpeed", 248,10,67,20, 0, 0, 0, 0, 0, "Print objectspeed"); uiBlockEndAlign(block); sprintf(str, "%.4f", prspeed); - uiDefBut(block, LABEL, 0, str, 247,40,63,31, NULL, 1.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, str, 247,35,63,31, NULL, 1.0, 0, 0, 0, ""); + +} + +static void object_panel_draw(Object *ob) +{ + uiBlock *block; + int xco, a, dx, dy; + + block= uiNewBlock(&curarea->uiblocks, "object_panel_draw", UI_EMBOSS, UI_HELV, curarea->win); + if(uiNewPanel(curarea, block, "Draw", "Object", 640, 0, 318, 204)==0) return; + + /* LAYERS */ + xco= 120; + dx= 35; + dy= 30; + + uiDefBut(block, LABEL, 0, "Layers", 10,170,100,20, NULL, 0, 0, 0, 0, ""); + + uiBlockBeginAlign(block); + for(a=0; a<5; a++) + uiDefButBitI(block, TOG, 1<<a, B_OBLAY+a, "", (short)(xco+a*(dx/2)), 180, (short)(dx/2), (short)(dy/2), &(BASACT->lay), 0, 0, 0, 0, ""); + for(a=0; a<5; a++) + uiDefButBitI(block, TOG, 1<<(a+10), B_OBLAY+a+10, "", (short)(xco+a*(dx/2)), 165, (short)(dx/2), (short)(dy/2), &(BASACT->lay), 0, 0, 0, 0, ""); + + xco+= 7; + uiBlockBeginAlign(block); + for(a=5; a<10; a++) + uiDefButBitI(block, TOG, 1<<a, B_OBLAY+a, "", (short)(xco+a*(dx/2)), 180, (short)(dx/2), (short)(dy/2), &(BASACT->lay), 0, 0, 0, 0, ""); + for(a=5; a<10; a++) + uiDefButBitI(block, TOG, 1<<(a+10), B_OBLAY+a+10, "", (short)(xco+a*(dx/2)), 165, (short)(dx/2), (short)(dy/2), &(BASACT->lay), 0, 0, 0, 0, ""); + + uiBlockEndAlign(block); + + uiDefBut(block, LABEL, 0, "Drawtype", 10,120,100,20, NULL, 0, 0, 0, 0, ""); + + uiBlockBeginAlign(block); + uiDefButC(block, ROW, REDRAWVIEW3D, "Shaded", 10,100,100, 20, &ob->dt, 0, OB_SHADED, 0, 0, "Draw active object shaded or textured"); + uiDefButC(block, ROW, REDRAWVIEW3D, "Solid", 10,80,100, 20, &ob->dt, 0, OB_SOLID, 0, 0, "Draw active object in solid"); + uiDefButC(block, ROW, REDRAWVIEW3D, "Wire", 10,60, 100, 20, &ob->dt, 0, OB_WIRE, 0, 0, "Draw active object in wireframe"); + uiDefButC(block, ROW, REDRAWVIEW3D, "Bounds", 10,40, 100, 20, &ob->dt, 0, OB_BOUNDBOX, 0, 0, "Only draw object with bounding box"); + uiBlockEndAlign(block); + + uiDefBut(block, LABEL, 0, "Draw Extra", 120,120,90,20, NULL, 0, 0, 0, 0, ""); + + uiBlockBeginAlign(block); + uiDefButBitC(block, TOG, OB_BOUNDBOX, REDRAWVIEW3D, "Bounds", 120, 100, 90, 20, &ob->dtx, 0, 0, 0, 0, "Displays the active object's bounds"); + uiDefButBitC(block, TOG, OB_DRAWNAME, REDRAWVIEW3D, "Name", 210, 100, 90, 20, &ob->dtx, 0, 0, 0, 0, "Displays the active object's name"); + + uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Polyheder%x4", + 120, 80, 90, 20, &ob->boundtype, 0, 0, 0, 0, "Selects the boundary display type"); + uiDefButBitC(block, TOG, OB_AXIS, REDRAWVIEW3D, "Axis", 210, 80, 90, 20, &ob->dtx, 0, 0, 0, 0, "Displays the active object's centre and axis"); + + uiDefButBitC(block, TOG, OB_TEXSPACE, REDRAWVIEW3D, "TexSpace", 120, 60, 90, 20, &ob->dtx, 0, 0, 0, 0, "Displays the active object's texture space"); + uiDefButBitC(block, TOG, OB_DRAWWIRE, REDRAWVIEW3D, "Wire", 210, 60, 90, 20, &ob->dtx, 0, 0, 0, 0, "Adds the active object's wireframe over solid drawing"); + + uiDefButBitC(block, TOG, OB_DRAWTRANSP, REDRAWVIEW3D, "Transp", 120, 40, 90, 20, &ob->dtx, 0, 0, 0, 0, "Enables transparent materials for the active object (Mesh only)"); + uiDefButBitC(block, TOG, OB_DRAWXRAY, REDRAWVIEW3D, "X-ray", 210, 40, 90, 20, &ob->dtx, 0, 0, 0, 0, "Makes the active object draw in front of others"); } +void object_panel_constraint(char *context) +{ + uiBlock *block; + Object *ob= OBACT; + ListBase *conlist; + bConstraint *curcon; + short xco, yco; + char str[64]; + + block= uiNewBlock(&curarea->uiblocks, "object_panel_constraint", UI_EMBOSS, UI_HELV, curarea->win); + if(uiNewPanel(curarea, block, "Constraints", context, 960, 0, 318, 204)==0) return; + + /* this is a variable height panel, newpanel doesnt force new size on existing panels */ + /* so first we make it default height */ + uiNewPanelHeight(block, 204); + + if(G.obedit==OBACT) return; // ?? + + conlist = get_active_constraints(OBACT); + + if (conlist) { + + uiDefBlockBut(block, add_constraintmenu, NULL, "Add Constraint", 0, 190, 130, 20, "Add a new constraint"); + + /* print active object or bone */ + str[0]= 0; + if (ob->flag & OB_POSEMODE){ + bPoseChannel *pchan= get_active_posechannel(ob); + if(pchan) sprintf(str, "To Bone: %s", pchan->name); + } + else { + sprintf(str, "To Object: %s", ob->id.name+2); + } + uiDefBut(block, LABEL, 1, str, 150, 190, 150, 20, NULL, 0.0, 0.0, 0, 0, "Displays Active Object or Bone name"); + + /* Go through the list of constraints and draw them */ + xco = 10; + yco = 160; + + for (curcon = conlist->first; curcon; curcon=curcon->next) { + /* hrms, the temporal constraint should not draw! */ + if(curcon->type==CONSTRAINT_TYPE_KINEMATIC) { + bKinematicConstraint *data= curcon->data; + if(data->flag & CONSTRAINT_IK_TEMP) + continue; + } + /* Draw default constraint header */ + draw_constraint(block, conlist, curcon, &xco, &yco); + } + + if(yco < 0) uiNewPanelHeight(block, 204-yco); + + } +} + void do_effects_panels(unsigned short event) { Object *ob; @@ -1961,6 +2057,8 @@ static void object_panel_particles_motion(Object *ob) uiDefButS(block, NUM, B_CALCEFFECT, "Tex:", 75,10,75,20, &paf->timetex, 1.0, 10.0, 0, 0, "Specify texture used for the texture emission"); /* right collumn */ + uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_CALCEFFECT, "GR:", 160, 155, 150, 20, &paf->group, "Limit Force Fields to this Group"); + uiBlockBeginAlign(block); uiDefBut(block, LABEL, 0, "Force:", 160,130,75,20, NULL, 0.0, 0, 0, 0, ""); uiDefButF(block, NUM, B_CALCEFFECT, "X:", 235,130,75,20, paf->force, -1.0, 1.0, 1, 2, "Specify the X axis of a continues force"); @@ -2235,6 +2333,7 @@ void object_panels() if(ob) { if(ob->id.lib) uiSetButLock(1, "Can't edit library data"); + object_panel_object(ob); object_panel_anim(ob); object_panel_draw(ob); object_panel_constraint("Object"); diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 98d4d5d537f..d8121fd458f 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -111,12 +111,9 @@ int vergcband(const void *, const void *); void save_env(char *); void drawcolorband(ColorBand *, float , float , float , float ); - -static MTex mtexcopybuf; static MTex emptytex; static int packdummy = 0; - static char *mapto_blendtype_pup(void) { static char string[1024]; @@ -379,17 +376,20 @@ static void drawcolorband_cb(void) { ID *id, *idfrom; - buttons_active_id(&id, &idfrom); + buttons_active_id(&id, &idfrom); /* base material, not the matlayer! */ if( GS(id->name)==ID_TE) { Tex *tex= (Tex *)id; drawcolorband(tex->coba, 10,145,300,30); } else if( GS(id->name)==ID_MA) { Material *ma= (Material *)id; - if(ma->ramp_show==0) - drawcolorband(ma->ramp_col, 10,110,300,30); - else - drawcolorband(ma->ramp_spec, 10,110,300,30); + ma= get_active_matlayer(ma); + if(ma) { + if(ma->ramp_show==0) + drawcolorband(ma->ramp_col, 10,110,300,30); + else + drawcolorband(ma->ramp_spec, 10,110,300,30); + } } } @@ -759,7 +759,7 @@ void do_texbuts(unsigned short event) do_colorbandbuts(tex->coba, event); } else { - ma= (Material *)id; + ma= get_active_matlayer((Material *)id); if(ma->ramp_show==0) do_colorbandbuts(ma->ramp_col, event); else do_colorbandbuts(ma->ramp_spec, event); } @@ -1416,7 +1416,7 @@ static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *l { MTex *mt=NULL; uiBlock *block; - ID *id, *idfrom; + ID *id=NULL, *idfrom; int a, yco, loos; char str[32]; @@ -1425,7 +1425,12 @@ static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *l if(uiNewPanel(curarea, block, "Texture", "Texture", 320, 0, 318, 204)==0) return; /* first do the browse but */ - buttons_active_id(&id, &idfrom); + if(mtex) + id= (ID *)mtex->tex; + + if(ma) idfrom= &ma->id; + else if(wrld) idfrom= &wrld->id; + else idfrom= &la->id; uiBlockSetCol(block, TH_BUT_SETTING2); if(ma) { @@ -1726,6 +1731,8 @@ static void radio_panel_render(Radio *rad) void do_worldbuts(unsigned short event) { + static short mtexcopied=0; + static MTex mtexcopybuf; World *wrld; MTex *mtex; @@ -1743,6 +1750,35 @@ void do_worldbuts(unsigned short event) BIF_preview_changed(G.buts); } break; + case B_WMTEXCOPY: + wrld= G.buts->lockpoin; + if(wrld && wrld->mtex[(int)wrld->texact] ) { + mtex= wrld->mtex[(int)wrld->texact]; + if(mtex->tex==0) { + error("No texture available"); + } + else { + memcpy(&mtexcopybuf, wrld->mtex[(int)wrld->texact], sizeof(MTex)); + mtexcopied= 1; + } + } + break; + case B_WMTEXPASTE: + wrld= G.buts->lockpoin; + if(wrld && mtexcopied && mtexcopybuf.tex) { + if(wrld->mtex[(int)wrld->texact]==0 ) + wrld->mtex[(int)wrld->texact]= MEM_mallocN(sizeof(MTex), "mtex"); + else if(wrld->mtex[(int)wrld->texact]->tex) + wrld->mtex[(int)wrld->texact]->tex->id.us--; + + memcpy(wrld->mtex[(int)wrld->texact], &mtexcopybuf, sizeof(MTex)); + + id_us_plus((ID *)mtexcopybuf.tex); + BIF_undo_push("Paste mapping settings"); + BIF_preview_changed(G.buts); + scrarea_queue_winredraw(curarea); + } + break; } } @@ -1781,10 +1817,10 @@ static void world_panel_mapto(World *wrld) /* MAP TO */ uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, WOMAP_BLEND, B_MATPRV, "Blend", 10,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the colour progression of the background"); + uiDefButBitS(block, TOG, WOMAP_BLEND, B_MATPRV, "Blend", 10,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the colour progression of the background"); uiDefButBitS(block, TOG, WOMAP_HORIZ, B_MATPRV, "Hori", 85,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the colour of the horizon"); - uiDefButBitS(block, TOG, WOMAP_ZENUP, B_MATPRV, "ZenUp", 160,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the colour of the zenith above"); - uiDefButBitS(block, TOG, WOMAP_ZENDOWN, B_MATPRV, "ZenDo", 235,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the colour of the zenith below"); + uiDefButBitS(block, TOG, WOMAP_ZENUP, B_MATPRV, "ZenUp", 160,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the colour of the zenith above"); + uiDefButBitS(block, TOG, WOMAP_ZENDOWN, B_MATPRV, "ZenDo", 235,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the colour of the zenith below"); uiBlockEndAlign(block); uiBlockBeginAlign(block); @@ -1841,7 +1877,7 @@ static void world_panel_texture(World *wrld) uiDefBut(block, TEX, B_IDNAME, "TE:", 100,160,200,19, id->name+2, 0.0, 18.0, 0, 0, "Displays name of the texture block: click to change"); sprintf(str, "%d", id->us); uiDefBut(block, BUT, 0, str, 196,140,21,19, 0, 0, 0, 0, 0, "Displays number of users of texture: click to make single user"); - uiDefIconBut(block, BUT, B_AUTOTEXNAME, ICON_AUTO, 279,140,21,19, 0, 0, 0, 0, 0, "Auto-assigns name to texture"); + uiDefIconBut(block, BUT, B_AUTOTEXNAME, ICON_AUTO, 220,140,21,19, 0, 0, 0, 0, 0, "Auto-assigns name to texture"); if(id->lib) { if(wrld->id.lib) uiDefIconBut(block, BUT, 0, ICON_DATALIB, 219,140,21,19, 0, 0, 0, 0, 0, ""); else uiDefIconBut(block, BUT, 0, ICON_PARLIB, 219,140,21,19, 0, 0, 0, 0, 0, ""); @@ -1854,24 +1890,31 @@ static void world_panel_texture(World *wrld) uiBlockSetCol(block, TH_AUTO); - + /* copy/paste */ + uiBlockBeginAlign(block); + uiDefIconBut(block, BUT, B_WMTEXCOPY, ICON_COPYUP, 250,140,25,19, 0, 0, 0, 0, 0, "Copies the mapping settings to the buffer"); + uiDefIconBut(block, BUT, B_WMTEXPASTE, ICON_PASTEUP,275,140,25,19, 0, 0, 0, 0, 0, "Pastes the mapping settings from the buffer"); + /* TEXCO */ uiBlockBeginAlign(block); - uiDefButS(block, ROW, B_MATPRV, "View", 100,110,45,20, &(mtex->texco), 4.0, (float)TEXCO_VIEW, 0, 0, "Uses global coordinates for the texture coordinates"); - uiDefButS(block, ROW, B_MATPRV, "AngMap", 145,110,55,20, &(mtex->texco), 4.0, (float)TEXCO_ANGMAP, 0, 0, "Uses 360 degree angular coordinates, e.g. for spherical light probes"); - uiDefButS(block, ROW, B_MATPRV, "Sphere", 200,110,55,20, &(mtex->texco), 4.0, (float)TEXCO_H_SPHEREMAP, 0, 0, "For 360 degree panorama sky, spherical mapped, only top half"); - uiDefButS(block, ROW, B_MATPRV, "Tube", 255,110,45,20, &(mtex->texco), 4.0, (float)TEXCO_H_TUBEMAP, 0, 0, "For 360 degree panorama sky, cylindrical mapped, only top half"); - uiDefButS(block, ROW, B_MATPRV, "Object", 100,90,70,20, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Uses linked object's coordinates for texture coordinates"); - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MATPRV, "", 170,90,130,20, &(mtex->object), ""); + uiDefButS(block, ROW, B_MATPRV, "View", 100,110,100,20, &(mtex->texco), 4.0, (float)TEXCO_VIEW, 0, 0, "Uses view vector for the texture coordinates"); + uiDefButS(block, ROW, B_MATPRV, "Global", 200,110,100,20, &(mtex->texco), 4.0, (float)TEXCO_GLOB, 0, 0, "Uses global coordinates for the texture coordinates (interior mist)"); + + uiDefButS(block, ROW, B_MATPRV, "AngMap", 100,90,70,20, &(mtex->texco), 4.0, (float)TEXCO_ANGMAP, 0, 0, "Uses 360 degree angular coordinates, e.g. for spherical light probes"); + uiDefButS(block, ROW, B_MATPRV, "Sphere", 170,90,65,20, &(mtex->texco), 4.0, (float)TEXCO_H_SPHEREMAP, 0, 0, "For 360 degree panorama sky, spherical mapped, only top half"); + uiDefButS(block, ROW, B_MATPRV, "Tube", 235,90,65,20, &(mtex->texco), 4.0, (float)TEXCO_H_TUBEMAP, 0, 0, "For 360 degree panorama sky, cylindrical mapped, only top half"); + + uiDefButS(block, ROW, B_MATPRV, "Object", 100,70,70,20, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Uses linked object's coordinates for texture coordinates"); + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MATPRV, "", 170,70,130,20, &(mtex->object), ""); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_MATPRV, "dX", 100,50,100,19, mtex->ofs, -20.0, 20.0, 10, 0, "Fine tunes texture mapping X coordinate"); - uiDefButF(block, NUM, B_MATPRV, "dY", 100,30,100,19, mtex->ofs+1, -20.0, 20.0, 10, 0, "Fine tunes texture mapping Y coordinate"); - uiDefButF(block, NUM, B_MATPRV, "dZ", 100,10,100,19, mtex->ofs+2, -20.0, 20.0, 10, 0, "Fine tunes texture mapping Z coordinate"); + uiDefButF(block, NUM, B_MATPRV, "dX", 100,40,100,19, mtex->ofs, -20.0, 20.0, 10, 0, "Fine tunes texture mapping X coordinate"); + uiDefButF(block, NUM, B_MATPRV, "dY", 100,20,100,19, mtex->ofs+1, -20.0, 20.0, 10, 0, "Fine tunes texture mapping Y coordinate"); + uiDefButF(block, NUM, B_MATPRV, "dZ", 100, 0,100,19, mtex->ofs+2, -20.0, 20.0, 10, 0, "Fine tunes texture mapping Z coordinate"); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_MATPRV, "sizeX", 200,50,100,19, mtex->size, -10.0, 10.0, 10, 0, "Sets scaling for the texture's X size"); - uiDefButF(block, NUM, B_MATPRV, "sizeY", 200,30,100,19, mtex->size+1, -10.0, 10.0, 10, 0, "Sets scaling for the texture's Y size"); - uiDefButF(block, NUM, B_MATPRV, "sizeZ", 200,10,100,19, mtex->size+2, -10.0, 10.0, 10, 0, "Sets scaling for the texture's Z size"); + uiDefButF(block, NUM, B_MATPRV, "sizeX", 200,40,100,19, mtex->size, -10.0, 10.0, 10, 0, "Sets scaling for the texture's X size"); + uiDefButF(block, NUM, B_MATPRV, "sizeY", 200,20,100,19, mtex->size+1, -10.0, 10.0, 10, 0, "Sets scaling for the texture's Y size"); + uiDefButF(block, NUM, B_MATPRV, "sizeZ", 200, 0,100,19, mtex->size+2, -10.0, 10.0, 10, 0, "Sets scaling for the texture's Z size"); } @@ -1977,16 +2020,12 @@ static void world_panel_amb_occ(World *wrld) static void world_panel_world(World *wrld) { uiBlock *block; - ID *id, *idfrom; block= uiNewBlock(&curarea->uiblocks, "world_panel_world", UI_EMBOSS, UI_HELV, curarea->win); if(uiNewPanel(curarea, block, "World", "World", 320, 0, 318, 204)==0) return; - /* first do the browse but */ - buttons_active_id(&id, &idfrom); - uiBlockSetCol(block, TH_BUT_SETTING2); - std_libbuttons(block, 10, 180, 0, NULL, B_WORLDBROWSE, id, idfrom, &(G.buts->menunr), B_WORLDALONE, B_WORLDLOCAL, B_WORLDDELETE, 0, B_KEEPDATA); + std_libbuttons(block, 10, 180, 0, NULL, B_WORLDBROWSE, (ID *)wrld, (ID *)G.scene, &(G.buts->menunr), B_WORLDALONE, B_WORLDLOCAL, B_WORLDDELETE, 0, B_KEEPDATA); if(wrld==NULL) return; @@ -2048,6 +2087,8 @@ static void world_panel_preview(World *wrld) void do_lampbuts(unsigned short event) { + static short mtexcopied=0; + static MTex mtexcopybuf; Lamp *la; MTex *mtex; @@ -2091,6 +2132,36 @@ void do_lampbuts(unsigned short event) allqueue(REDRAWBUTSSHADING, 0); allqueue(REDRAWVIEW3D, 0); break; + case B_LMTEXCOPY: + la= G.buts->lockpoin; + if(la && la->mtex[(int)la->texact] ) { + mtex= la->mtex[(int)la->texact]; + if(mtex->tex==0) { + error("No texture available"); + } + else { + memcpy(&mtexcopybuf, la->mtex[(int)la->texact], sizeof(MTex)); + mtexcopied= 1; + } + } + break; + case B_LMTEXPASTE: + la= G.buts->lockpoin; + if(la && mtexcopied && mtexcopybuf.tex) { + if(la->mtex[(int)la->texact]==0 ) + la->mtex[(int)la->texact]= MEM_mallocN(sizeof(MTex), "mtex"); + else if(la->mtex[(int)la->texact]->tex) + la->mtex[(int)la->texact]->tex->id.us--; + + memcpy(la->mtex[(int)la->texact], &mtexcopybuf, sizeof(MTex)); + + id_us_plus((ID *)mtexcopybuf.tex); + BIF_undo_push("Paste mapping settings"); + BIF_preview_changed(G.buts); + scrarea_queue_winredraw(curarea); + } + break; + } if(event) freefastshade(); @@ -2187,7 +2258,7 @@ static void lamp_panel_texture(Object *ob, Lamp *la) uiDefBut(block, TEX, B_IDNAME, "TE:", 100,160,200,19, id->name+2, 0.0, 18.0, 0, 0, "Displays name of the texture block: click to change"); sprintf(str, "%d", id->us); uiDefBut(block, BUT, 0, str, 196,140,21,19, 0, 0, 0, 0, 0, "Displays number of users of texture: click to make single user"); - uiDefIconBut(block, BUT, B_AUTOTEXNAME, ICON_AUTO, 241,140,21,19, 0, 0, 0, 0, 0, "Auto-assigns name to texture"); + uiDefIconBut(block, BUT, B_AUTOTEXNAME, ICON_AUTO, 221,140,21,19, 0, 0, 0, 0, 0, "Auto-assigns name to texture"); if(id->lib) { if(la->id.lib) uiDefIconBut(block, BUT, 0, ICON_DATALIB, 219,140,21,19, 0, 0, 0, 0, 0, ""); else uiDefIconBut(block, BUT, 0, ICON_PARLIB, 219,140,21,19, 0, 0, 0, 0, 0, ""); @@ -2198,6 +2269,11 @@ static void lamp_panel_texture(Object *ob, Lamp *la) else uiDefButS(block, TOG, B_LTEXBROWSE, "Add New" ,100, 160, 200, 19, &(G.buts->texnr), -1.0, 32767.0, 0, 0, "Adds a new texture datablock"); + /* copy/paste */ + uiBlockBeginAlign(block); + uiDefIconBut(block, BUT, B_LMTEXCOPY, ICON_COPYUP, 250,140,25,19, 0, 0, 0, 0, 0, "Copies the mapping settings to the buffer"); + uiDefIconBut(block, BUT, B_LMTEXPASTE, ICON_PASTEUP, 275,140,25,19, 0, 0, 0, 0, 0, "Pastes the mapping settings from the buffer"); + /* TEXCO */ uiBlockSetCol(block, TH_AUTO); uiBlockBeginAlign(block); @@ -2383,7 +2459,6 @@ static void lamp_panel_yafray(Object *ob, Lamp *la) static void lamp_panel_lamp(Object *ob, Lamp *la) { uiBlock *block; - ID *id, *idfrom; float grid= 0.0; short xco; @@ -2395,11 +2470,8 @@ static void lamp_panel_lamp(Object *ob, Lamp *la) uiSetButLock(la->id.lib!=0, "Can't edit library data"); - /* first do the browse but */ - buttons_active_id(&id, &idfrom); - uiBlockSetCol(block, TH_BUT_SETTING2); - xco= std_libbuttons(block, 8, 180, 0, NULL, B_LAMPBROWSE, id, (ID *)ob, &(G.buts->menunr), B_LAMPALONE, B_LAMPLOCAL, 0, 0, 0); + xco= std_libbuttons(block, 8, 180, 0, NULL, B_LAMPBROWSE, (ID *)la, (ID *)ob, &(G.buts->menunr), B_LAMPALONE, B_LAMPLOCAL, 0, 0, 0); uiBlockSetCol(block, TH_AUTO); uiDefButF(block, NUM,B_LAMPREDRAW,"Dist:", xco,180,300-xco,20,&la->dist, 0.01, 5000.0*grid, 100, 0, "Sets the distance value at which light intensity is half"); @@ -2487,12 +2559,20 @@ static void lamp_panel_preview(Object *ob, Lamp *la) void do_matbuts(unsigned short event) { static short mtexcopied=0; + static MTex mtexcopybuf; Material *ma; MTex *mtex; + /* all operations default on active material layer here */ + /* but this also gets called for lamp and world... */ + ma= G.buts->lockpoin; + if(ma && GS(ma->id.name)==ID_MA) + ma = get_active_matlayer(ma); + else + ma= NULL; + switch(event) { case B_MAT_YF_PRESET: { - ma = G.buts->lockpoin; switch (ma->YF_preset) { case 0: /* normal mode, no reflection/refraction */ @@ -2572,7 +2652,6 @@ void do_matbuts(unsigned short event) case B_MATHALO: /* when halo is disabled, clear star flag, this is the same as MA_FACETEXTURE <blush> */ /* same for 'xtreme alpha' which is 'only shadow' */ - ma= G.buts->lockpoin; if((ma->mode & MA_HALO)==0) { ma->mode &= ~(MA_STAR|MA_HALO_XALPHA|MA_ZINV); } @@ -2581,7 +2660,6 @@ void do_matbuts(unsigned short event) shade_buttons_change_3d(); break; case B_TEXCLEAR: - ma= G.buts->lockpoin; mtex= ma->mtex[(int) ma->texact ]; if(mtex) { if(mtex->tex) mtex->tex->id.us--; @@ -2594,7 +2672,6 @@ void do_matbuts(unsigned short event) } break; case B_MTEXCOPY: - ma= G.buts->lockpoin; if(ma && ma->mtex[(int)ma->texact] ) { mtex= ma->mtex[(int)ma->texact]; if(mtex->tex==0) { @@ -2607,9 +2684,12 @@ void do_matbuts(unsigned short event) } break; case B_MTEXPASTE: - ma= G.buts->lockpoin; if(ma && mtexcopied && mtexcopybuf.tex) { - if(ma->mtex[(int)ma->texact]==0 ) ma->mtex[(int)ma->texact]= MEM_mallocN(sizeof(MTex), "mtex"); + if(ma->mtex[(int)ma->texact]==0 ) + ma->mtex[(int)ma->texact]= MEM_mallocN(sizeof(MTex), "mtex"); + else if(ma->mtex[(int)ma->texact]->tex) + ma->mtex[(int)ma->texact]->tex->id.us--; + memcpy(ma->mtex[(int)ma->texact], &mtexcopybuf, sizeof(MTex)); id_us_plus((ID *)mtexcopybuf.tex); @@ -2619,14 +2699,12 @@ void do_matbuts(unsigned short event) } break; case B_MATLAY: - ma= G.buts->lockpoin; if(ma && ma->lay==0) { ma->lay= 1; scrarea_queue_winredraw(curarea); } break; case B_MATZTRANSP: - ma= G.buts->lockpoin; if(ma) { ma->mode &= ~MA_RAYTRANSP; allqueue(REDRAWBUTSSHADING, 0); @@ -2634,7 +2712,6 @@ void do_matbuts(unsigned short event) } break; case B_MATRAYTRANSP: - ma= G.buts->lockpoin; if(ma) { ma->mode &= ~MA_ZTRA; allqueue(REDRAWBUTSSHADING, 0); @@ -2642,7 +2719,6 @@ void do_matbuts(unsigned short event) } break; case B_MATCOLORBAND: - ma= G.buts->lockpoin; if(ma) { if(ma->mode & MA_RAMP_COL) if(ma->ramp_col==NULL) ma->ramp_col= add_colorband(); @@ -2654,7 +2730,33 @@ void do_matbuts(unsigned short event) shade_buttons_change_3d(); } break; - + case B_MAT_LAYERBROWSE: + ma= G.buts->lockpoin; /* use base material instead */ + if(ma) { + MaterialLayer *ml; + + /* the one with a menu set is the browser */ + for(ml= ma->layers.first; ml; ml= ml->next) { + if(ml->menunr) { + if(ml->menunr==32767) { + if(ml->mat) { + ml->mat->id.us--; + ml->mat= copy_material(ml->mat); + } + else ml->mat= add_material("Layer"); + } + else { + ml->mat= BLI_findlink(&G.main->mat, ml->menunr-1); + ml->mat->id.us++; + } + allqueue(REDRAWBUTSSHADING, 0); + BIF_all_preview_changed(); + + break; + } + } + } + break; } } @@ -2715,7 +2817,7 @@ static void material_panel_map_to(Material *ma) uiDefButBitS(block, TOG3, MAP_RAYMIRR, B_MATPRV, "RayMir", 60,160,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the ray-mirror value"); uiDefButBitS(block, TOG3, MAP_ALPHA, B_MATPRV, "Alpha", 110,160,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the alpha value"); uiDefButBitS(block, TOG3, MAP_EMIT, B_MATPRV, "Emit", 160,160,45,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the emit value"); - uiDefButBitS(block, TOG3, MAP_TRANSLU, B_MATPRV, "Translu", 205,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the translucency value"); + uiDefButBitS(block, TOG3, MAP_LAYER, B_MATPRV, "Layer", 205,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the layer blending value"); uiDefButBitS(block, TOG3, MAP_DISPLACE, B_MATPRV, "Disp", 265,160,45,19, &(mtex->mapto), 0, 0, 0, 0, "Let the texture displace the surface"); uiBlockEndAlign(block); @@ -3023,7 +3125,7 @@ static void material_panel_shading(Material *ma) uiBlockEndAlign(block); } else { - char *str1= "Diffuse Shader%t|Lambert %x0|Oren-Nayar %x1|Toon %x2|Minnaert %x3"; + char *str1= "Diffuse Shader%t|Lambert %x0|Oren-Nayar %x1|Toon %x2|Minnaert %x3|Fresnel %x4"; char *str2= "Specular Shader%t|CookTorr %x0|Phong %x1|Blinn %x2|Toon %x3|WardIso %x4"; /* diff shader buttons */ @@ -3039,6 +3141,10 @@ static void material_panel_shading(Material *ma) } else if(ma->diff_shader==MA_DIFF_MINNAERT) uiDefButF(block, NUMSLI, B_MATPRV, "Dark:",90,160, 150,19, &(ma->darkness), 0.0, 2.0, 0, 0, "Sets Minnaert darkness"); + else if(ma->diff_shader==MA_DIFF_FRESNEL) { + uiDefButF(block, NUMSLI, B_MATPRV, "Fresnel:", 90, 160,150,19, &(ma->param[1]), 0.0, 5.0, 0, 0, "Power of Fresnel"); + uiDefButF(block, NUMSLI, B_MATPRV, "Fac:",90,140,150,19, &(ma->param[0]), 1.0, 5.0, 0, 0, "Blending factor"); + } uiBlockEndAlign(block); /* spec shader buttons */ @@ -3075,12 +3181,216 @@ static void material_panel_shading(Material *ma) uiDefButBitI(block, TOG, MA_RAYBIAS, 0, "Bias", 245,80,65,19, &(ma->mode), 0, 0, 0, 0, "Prevents ray traced shadow errors with phong interpolated normals (terminator problem)"); uiBlockEndAlign(block); + uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_NOP, "GR:", 9, 55, 150, 19, &ma->group, "Limit Lighting to Lamps in this Group"); + uiDefButBitI(block, TOG, MA_RADIO, 0, "Radio", 245,55,65,19, &(ma->mode), 0, 0, 0, 0, "Enables material for radiosity rendering"); } +} + +static void matlayer_add(void *ma_v, void *ml_v) +{ + Material *ma= ma_v; + MaterialLayer *ml= ml_v, *mlnew; + + mlnew= MEM_callocN(sizeof(MaterialLayer), "mat layer"); + + if(ml==NULL) + BLI_addhead(&ma->layers, mlnew); + else + BLI_insertlink(&ma->layers, ml, mlnew); + + mlnew->blendfac= 0.5f; + mlnew->flag= ML_RENDER|ML_DIFFUSE|ML_SPECULAR; + + BIF_undo_push("Add Material Layer"); + allqueue(REDRAWBUTSSHADING, 0); +} + +static void matlayer_moveUp(void *ma_v, void *ml_v) +{ + Material *ma= ma_v; + MaterialLayer *ml= ml_v; + + if (ml->prev) { + BLI_remlink(&ma->layers, ml); + BLI_insertlink(&ma->layers, ml->prev->prev, ml); + } + + BIF_undo_push("Move Material Layer"); +} + +static void matlayer_moveDown(void *ma_v, void *ml_v) +{ + Material *ma= ma_v; + MaterialLayer *ml= ml_v; + + if (ml->next) { + BLI_remlink(&ma->layers, ml); + BLI_insertlink(&ma->layers, ml->next, ml); + } + + BIF_undo_push("Move Material Layer"); +} +static void matlayer_del(void *ma_v, void *ml_v) +{ + Material *ma= ma_v; + MaterialLayer *ml= ml_v; + + BLI_remlink(&ma->layers, ml); + if(ml->mat) ml->mat->id.us--; + MEM_freeN(ml); + + BIF_undo_push("Delete Material Layer"); } +static void matlayer_active(void *ma_v, void *ml_v) +{ + Material *ma= ma_v; + MaterialLayer *ml; + + for(ml= ma->layers.first; ml; ml= ml->next) { + if(ml==ml_v) + ml->flag |= ML_ACTIVE; + else + ml->flag &= ~ML_ACTIVE; + } + BIF_undo_push("Activate Material Layer"); +} + +static void matlayer_alone(void *ml_v, void *unused) +{ + MaterialLayer *ml= ml_v; + + ml->mat= copy_material(ml->mat); + + BIF_undo_push("Single user material"); + allqueue(REDRAWBUTSSHADING, 0); + allqueue(REDRAWOOPS, 0); +} + + +static void material_panel_layers(Material *ma) +{ + uiBlock *block; + uiBut *but; + MaterialLayer *ml; + int yco= 155, rb_col; + char *strp; + + block= uiNewBlock(&curarea->uiblocks, "material_panel_layers", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed("Preview", "Material"); + if(uiNewPanel(curarea, block, "Layers", "Material", 0, 0, 318, 204)==0) return; + + uiNewPanelHeight(block, 204); + + /* Active button for current material */ + uiBlockBeginAlign(block); + for(ml= ma->layers.first; ml; ml= ml->next) + if(ml->flag & ML_ACTIVE) break; + + if(ml==NULL) + but=uiDefIconBut(block, BUT, B_MATPRV_DRAW, ICON_MATERIAL, 10, 180, 20, 20, NULL, 0.0, 0.0, 0, 0, "Activate base Material"); + else but=uiDefBut(block, BUT, B_MATPRV_DRAW, " ", 10, 180, 20, 20, NULL, 0.0, 0.0, 0, 0, "Activate base Material"); + uiButSetFunc(but, matlayer_active, ma, NULL); + + /* Enable/disable for current material */ + if(ma->ml_flag & ML_RENDER) + uiDefIconButBitS(block, TOG, ML_RENDER, B_MATPRV_DRAW, ICON_CHECKBOX_HLT, 30, 180, 20, 20, &ma->ml_flag, 0.0, 0.0, 0, 0, "Enable or disable base Material"); + else uiDefButBitS(block, TOG, ML_RENDER, B_MATPRV, " ", 30, 180, 20, 20, &ma->ml_flag, 0.0, 0.0, 0, 0, "Enable or disable base Material"); + + uiBlockEndAlign(block); + /* label */ + uiDefBut(block, LABEL, B_NOP, ma->id.name+2, 60, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, ""); + /* add layer */ + but= uiDefBut(block, BUT, B_NOP, "Add Layer", 200, 180,110,20, NULL, 0, 0, 0, 0, "Add a new Material Layer"); + uiButSetFunc(but, matlayer_add, ma, NULL); + + + for(ml= ma->layers.first; ml; ml= ml->next) { + + /* rounded header */ + rb_col= (ml->flag & ML_ACTIVE)?40:20; + uiDefBut(block, ROUNDBOX, B_DIFF, "", 8, yco-48, 304, 71, NULL, 5.0, 0.0, 3 , rb_col-20, ""); + + /* Active button */ + uiBlockBeginAlign(block); + if(ml->flag & ML_ACTIVE) + but=uiDefIconBut(block, BUT, B_MATPRV_DRAW, ICON_MATERIAL, 10, yco, 20, 20, NULL, 0.0, 0.0, 0, 0, "Activate this layer"); + else but=uiDefBut(block, BUT, B_MATPRV_DRAW, " ", 10, yco, 20, 20, NULL, 0.0, 0.0, 0, 0, "Activate this layer"); + uiButSetFunc(but, matlayer_active, ma, ml); + + /* enable/disable button */ + if(ml->flag & ML_RENDER) + uiDefIconButBitS(block, TOG, ML_RENDER, B_MATPRV_DRAW, ICON_CHECKBOX_HLT, 30, yco, 20, 20, &ml->flag, 0.0, 0.0, 0, 0, "Enable or disable this layer"); + else uiDefButBitS(block, TOG, ML_RENDER, B_MATPRV, " ", 30, yco, 20, 20, &ml->flag, 0.0, 0.0, 0, 0, "Enable or disable this layer"); + + uiBlockBeginAlign(block); + + /* browse button */ + IDnames_to_pupstring(&strp, NULL, "ADD NEW %x32767", &(G.main->mat), (ID *)ma, NULL); + ml->menunr= 0; + uiDefButS(block, MENU, B_MAT_LAYERBROWSE, strp, 60,yco,20,20, &ml->menunr, 0, 0, 0, 0, "Browses existing choices or adds NEW"); + if(strp) MEM_freeN(strp); + + /* name and users */ + if(ml->mat) { + int width; + + if(ml->mat->id.us>1) width= 120; + else width= 140; + but= uiDefBut(block, TEX, B_IDNAME, "MA:",80, yco, width, 20, ml->mat->id.name+2, 0.0, 19.0, 0, 0, "Rename Material"); + uiButSetFunc(but, test_idbutton_cb, ml->mat->id.name, NULL); + + if(ml->mat->id.us>1) { + char str1[32]; + sprintf(str1, "%d", ml->mat->id.us); + but= uiDefBut(block, BUT, B_NOP, str1, 200,yco,20,20, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy."); + uiButSetFunc(but, matlayer_alone, ml, NULL); + } + } + else + uiDefBut(block, LABEL, B_NOP, "No Material",80, yco, 140, 20, NULL, 0.0, 0.0, 0, 0, ""); + + /* add new */ + but= uiDefBut(block, BUT, B_NOP, "Add", 220, yco,30,20, NULL, 0, 0, 0, 0, "Add a new Material Layer"); + uiButSetFunc(but, matlayer_add, ma, ml); + + /* move up/down/delete */ + but = uiDefIconBut(block, BUT, B_MATPRV_DRAW, VICON_MOVE_UP, 250, yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Move layer up"); + uiButSetFunc(but, matlayer_moveUp, ma, ml); + + but = uiDefIconBut(block, BUT, B_MATPRV_DRAW, VICON_MOVE_DOWN, 270, yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Move layer down"); + uiButSetFunc(but, matlayer_moveDown, ma, ml); + + but = uiDefIconBut(block, BUT, B_MATPRV_DRAW, VICON_X, 290, yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Delete material layer"); + uiButSetFunc(but, matlayer_del, ma, ml); + + /* blend slider and operation */ + uiBlockBeginAlign(block); + yco-= 25; + uiDefButS(block, MENU, B_MATPRV, "Mix %x0|Add %x1|Subtract %x3|Multiply %x2|Screen %x4|Divide %x5|Difference %x6|Darken %x7|Lighten %x8", + 35,yco,100,20, &ml->blendmethod, 0, 0, 0, 0, "Blending method for Ramp (uses alpha in Colorband)"); + uiDefButF(block, NUMSLI, B_MATPRV, "Blend:",135,yco,175,20, &ml->blendfac, 0.0, 1.0, 100, 0, "Blending factor"); + + /* output */ + yco-=20; + uiDefButBitS(block, TOG, ML_DIFFUSE, B_MATPRV, "Diff", 35,yco,50,20, &ml->flag, 0, 0, 0, 0, "This Layer affects Diffuse"); + uiDefButBitS(block, TOG, ML_SPECULAR, B_MATPRV, "Spec", 85,yco,50,20, &ml->flag, 0, 0, 0, 0, "This Layer affects Specular"); + uiDefButBitS(block, TOG, ML_ALPHA, B_MATPRV, "Alpha", 135,yco,50,20, &ml->flag, 0, 0, 0, 0, "This Layer affects Alpha"); + uiDefButBitS(block, TOG, ML_NEG_NORMAL, B_MATPRV, "Negate Normal", 185,yco,125,20, &ml->flag, 0, 0, 0, 0, "Negate normal for this layer"); + + yco-= 30; + + uiBlockEndAlign(block); + } + + if(yco < 0) uiNewPanelHeight(block, 204-yco); + +} + + static void material_panel_ramps(Material *ma) { uiBlock *block; @@ -3163,7 +3473,7 @@ static void material_panel_material(Object *ob, Material *ma) if(uiNewPanel(curarea, block, "Material", "Material", 320, 0, 318, 204)==0) return; /* first do the browse but */ - buttons_active_id(&id, &idfrom); + buttons_active_id(&id, &idfrom); /* base material, not the matlayer! */ uiBlockSetCol(block, TH_BUT_SETTING2); std_libbuttons(block, 8, 200, 0, NULL, B_MATBROWSE, id, idfrom, &(G.buts->menunr), B_MATALONE, B_MATLOCAL, B_MATDELETE, B_AUTOMATNAME, B_KEEPDATA); @@ -3204,8 +3514,8 @@ static void material_panel_material(Object *ob, Material *ma) if(ob->totcol==0) return; uiSetButLock(id->lib!=0, "Can't edit library data"); - ma= give_current_material(ob, ob->actcol); - if(ma==0) return; + ma= get_active_matlayer(ma); + if(ma==NULL) return; if(ma->dynamode & MA_DRAW_DYNABUTS) { uiBlockBeginAlign(block); @@ -3324,23 +3634,30 @@ void material_panels() material_panel_material(ob, ma); if(ma) { - material_panel_ramps(ma); - material_panel_shading(ma); - if (G.scene->r.renderer==R_INTERN) - material_panel_tramir(ma); - else { - if (ma->YF_ar==0.f) { - ma->YF_ar = ma->YF_ag = ma->YF_ab = 1; - ma->YF_dscale = 1; - } - material_panel_tramir_yafray(ma); - } - material_panel_texture(ma); + material_panel_layers(ma); - mtex= ma->mtex[ ma->texact ]; - if(mtex && mtex->tex) { - material_panel_map_input(ob, ma); - material_panel_map_to(ma); + ma= get_active_matlayer(ma); + if(ma) { + material_panel_ramps(ma); + material_panel_shading(ma); + + if (G.scene->r.renderer==R_INTERN) + material_panel_tramir(ma); + else { + if(ma->YF_ar==0.f) { + ma->YF_ar = ma->YF_ag = ma->YF_ab = 1; + ma->YF_dscale = 1; + } + material_panel_tramir_yafray(ma); + } + + material_panel_texture(ma); + + mtex= ma->mtex[ ma->texact ]; + if(mtex && mtex->tex) { + material_panel_map_input(ob, ma); + material_panel_map_to(ma); + } } } } @@ -3401,6 +3718,7 @@ void texture_panels() if(G.buts->texfrom==0) { if(ob) { ma= give_current_material(ob, ob->actcol); + ma= get_active_matlayer(ma); if(ma) mtex= ma->mtex[ ma->texact ]; } } @@ -3524,8 +3842,8 @@ void clever_numbuts_buts() break; case TAB_SHADING_MAT: - ma= G.buts->lockpoin; - + ma= get_active_matlayer(G.buts->lockpoin); + /* Build a hex value */ if (ma){ sprintf(hexrgb, "%02X%02X%02X", (int)(ma->r*255), (int)(ma->g*255), (int)(ma->b*255)); diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 3261c884ca6..92154d83348 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -222,7 +222,7 @@ static unsigned int colortab[24]= {0x0, 0xFF88FF, 0xFFBBFF, 0x403000, 0xFFFF88, 0xFFFFBB, 0x104040, 0x66CCCC, 0x77CCCC, - 0x101040, 0x5588FF, 0x88BBFF, + 0x104010, 0x55BB55, 0x66FF66, 0xFFFFFF }; @@ -3604,9 +3604,19 @@ void draw_object(Base *base, int flag) else colindex = 3; } else if(warning_recursive==1) { - if(base->flag & (SELECT+BA_WAS_SEL)) colindex = 7; + if(base->flag & (SELECT+BA_WAS_SEL)) { + if(G.scene->basact==base) colindex = 8; + else colindex= 7; + } else colindex = 6; } + else if(ob->flag & OB_FROMGROUP) { + if(base->flag & (SELECT+BA_WAS_SEL)) { + if(G.scene->basact==base) colindex = 11; + else colindex= 10; + } + else colindex = 9; + } } diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index b470d2ab6af..04439c48f88 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -343,7 +343,6 @@ static void draw_bgpic(void) init_render_texture(bgpic->tex); free_unused_animimages(); ima= bgpic->tex->ima; - end_render_texture(bgpic->tex); } else { ima= bgpic->ima; @@ -1703,6 +1702,7 @@ void do_viewbuts(unsigned short event) DAG_scene_sort(G.scene); DAG_object_flush_update(G.scene, ob, OB_RECALC_OB); allqueue(REDRAWVIEW3D, 1); + allqueue(REDRAWBUTSOBJECT, 0); } } break; diff --git a/source/blender/src/editgroup.c b/source/blender/src/editgroup.c index f55f07986a4..07b3258b776 100644 --- a/source/blender/src/editgroup.c +++ b/source/blender/src/editgroup.c @@ -58,61 +58,16 @@ #include <config.h> #endif -void set_active_group(void) +void add_selected_to_group(Group *group) { - /* with active object, find active group */ - Group *group; - GroupObject *go; - - G.scene->group= NULL; + Base *base; - if(BASACT) { - group= G.main->group.first; - while(group) { - go= group->gobject.first; - while(go) { - if(go->ob == OBACT) { - G.scene->group= group; - return; - } - go= go->next; - } - group= group->id.next; - } - } -} - - -void add_selected_to_group(void) -{ - Base *base= FIRSTBASE; - Group *group; - - if(BASACT==NULL) { - error("No active object"); - return; - } - - if(okee("Add selected to group")==0) return; - - if(G.scene->group==NULL) G.scene->group= add_group(); - - while(base) { + for(base=FIRSTBASE; base; base= base->next) { if TESTBASE(base) { - - /* each object only in one group */ - group= find_group(base->object); - if(group==G.scene->group); - else { - if(group) { - rem_from_group(group, base->object); - } - add_to_group(G.scene->group, base->object); - base->object->flag |= OB_FROMGROUP; - base->flag |= OB_FROMGROUP; - } + add_to_group(group, base->object); + base->object->flag |= OB_FROMGROUP; + base->flag |= OB_FROMGROUP; } - base= base->next; } allqueue(REDRAWVIEW3D, 0); @@ -121,52 +76,46 @@ void add_selected_to_group(void) void rem_selected_from_group(void) { - Base *base=FIRSTBASE; + Base *base; Group *group; - if(okee("Remove selected from group")==0) return; - - while(base) { + for(base=FIRSTBASE; base; base= base->next) { if TESTBASE(base) { - group= find_group(base->object); - if(group) { + while( (group = find_group(base->object)) ) { rem_from_group(group, base->object); - - base->object->flag &= ~OB_FROMGROUP; - base->flag &= ~OB_FROMGROUP; } + base->object->flag &= ~OB_FROMGROUP; + base->flag &= ~OB_FROMGROUP; } - base= base->next; } allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSOBJECT, 0); } -void prev_group_key(Group *group) +void group_operation_with_menu(void) { - GroupKey *gk= group->active; - - if(gk) gk= gk->prev; - - if(gk==NULL) group->active= group->gkey.last; - else group->active= gk; - - set_group_key(group); -} - -void next_group_key(Group *group) -{ - GroupKey *gk= group->active; - - if(gk) gk= gk->next; + Base *base; + Group *group= NULL; + int mode; - if(gk==NULL) group->active= group->gkey.first; - else group->active= gk; + for(base=FIRSTBASE; base; base= base->next) { + if TESTBASE(base) { + group= find_group(base->object); + if(group) break; + } + } - set_group_key(group); + if(base) + mode= pupmenu("Groups %t|Add to current Group %x3|Add to New Group %x1|Remove from all Groups %x2"); + else + mode= pupmenu("Groups %t|Add to New Group %x1|Remove from all Groups %x2"); -} - - + if(mode>0) { + if(group==NULL) group= add_group(); + + if(mode==1 || mode==3) add_selected_to_group(group); + else if(mode==2) rem_selected_from_group(); + } +}
\ No newline at end of file diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index 34a6e2cfc69..c50597605d7 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -2352,7 +2352,6 @@ void common_insertkey(void) else if(ob->type==OB_LATTICE) strcat(menustr, "| %x6|Lattice%x7"); else if(ob->type==OB_CURVE) strcat(menustr, "| %x6|Curve%x7"); else if(ob->type==OB_SURF) strcat(menustr, "| %x6|Surface%x7"); - if(ob->flag & OB_FROMGROUP) strcat(menustr, "| %x6|Entire Group%x10"); } event= pupmenu(menustr); @@ -2363,14 +2362,6 @@ void common_insertkey(void) return; } - if(event==10) { - Group *group= find_group(ob); - if(group) { - add_group_key(group); - allqueue(REDRAWBUTSOBJECT, 0); - } - } - if (ob && (ob->flag & OB_POSEMODE)){ bPoseChannel *pchan; diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index 2eb59c146f2..eb77356ecdc 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -78,6 +78,7 @@ #include "BIF_editmesh.h" #include "BIF_editmode_undo.h" #include "BIF_interface.h" +#include "BIF_meshtools.h" #include "BIF_mywindow.h" #include "BIF_space.h" #include "BIF_screen.h" @@ -537,6 +538,8 @@ void free_editMesh(EditMesh *em) em->alledges= em->curedge= NULL; em->allfaces= em->curface= NULL; + mesh_octree_table(NULL, NULL, 'e'); + G.totvert= G.totface= 0; } diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index 2d1d20c6b8e..3c568266c05 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -103,16 +103,6 @@ editmesh_mods.c, UI level access, no geometry changes /* ****************************** MIRROR **************** */ -static EditVert *get_x_mirror_vert(EditVert *eve) -{ - int index; - - index= mesh_get_x_mirror_vert(G.obedit, POINTER_TO_INT(eve)); - if(index != -1) - return INT_TO_POINTER(index); - return NULL; -} - void EM_select_mirrored(void) { if(G.scene->selectmode & SCE_SELECT_VERTEX) { @@ -121,7 +111,7 @@ void EM_select_mirrored(void) for(eve= em->verts.first; eve; eve= eve->next) { if(eve->f & SELECT) { - v1= get_x_mirror_vert(eve); + v1= editmesh_get_x_mirror_vert(G.obedit, eve->co); if(v1) { eve->f &= ~SELECT; v1->f |= SELECT; diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 811dbd79f23..894f787a2d2 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -62,6 +62,7 @@ #include "DNA_constraint_types.h" #include "DNA_curve_types.h" #include "DNA_effect_types.h" +#include "DNA_group_types.h" #include "DNA_image_types.h" #include "DNA_ipo_types.h" #include "DNA_key_types.h" @@ -71,6 +72,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_meta_types.h" +#include "DNA_nla_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_scene_types.h" @@ -101,6 +103,7 @@ #include "BKE_effect.h" #include "BKE_font.h" #include "BKE_global.h" +#include "BKE_group.h" #include "BKE_ipo.h" #include "BKE_key.h" #include "BKE_lattice.h" @@ -3994,11 +3997,46 @@ void single_user(void) /* ************************************************************* */ +/* helper for below, ma was checked to be not NULL */ +static void make_local_makelocalmaterial(Material *ma) +{ + MaterialLayer *ml; + ID *id; + int b; + + make_local_material(ma); + + for(b=0; b<MAX_MTEX; b++) { + if(ma->mtex[b] && ma->mtex[b]->tex) { + make_local_texture(ma->mtex[b]->tex); + } + } + + id= (ID *)ma->ipo; + if(id && id->lib) make_local_ipo(ma->ipo); + + for(ml=ma->layers.first; ml; ml= ml->next) { + if(ml->mat) { + make_local_material(ml->mat); + + for(b=0; b<MAX_MTEX; b++) { + if(ml->mat->mtex[b] && ml->mat->mtex[b]->tex) { + make_local_texture(ml->mat->mtex[b]->tex); + } + } + + id= (ID *)ml->mat->ipo; + if(id && id->lib) make_local_ipo(ml->mat->ipo); + } + + } +} void make_local(void) { Base *base; Object *ob; + bActionStrip *strip; Material *ma, ***matarar; Lamp *la; Curve *cu; @@ -4009,14 +4047,14 @@ void make_local(void) if(G.scene->id.lib) return; - mode= pupmenu("Make Local%t|Selected %x1|All %x2"); + mode= pupmenu("Make Local%t|Selected Objects %x1|Selected Objects and Data %x2|All %x3"); - if(mode==2) { + if(mode==3) { all_local(NULL); // NULL is all libs allqueue(REDRAWALL, 0); return; } - else if(mode!=1) return; + else if(mode<1) return; clear_id_newpoins(); @@ -4051,7 +4089,7 @@ void make_local(void) id= ob->data; - if(id) { + if(id && mode>1) { switch(ob->type) { case OB_LAMP: @@ -4095,62 +4133,51 @@ void make_local(void) id= (ID *)ob->action; if(id && id->lib) make_local_action(ob->action); + + for (strip=ob->nlastrips.first; strip; strip=strip->next) { + if(strip->act && strip->act->id.lib) + make_local_action(strip->act); + } + } base= base->next; } - base= FIRSTBASE; - while(base) { - ob= base->object; - if(base->flag & SELECT ) { - - if(ob->type==OB_LAMP) { - la= ob->data; - for(b=0; b<MAX_MTEX; b++) { - if(la->mtex[b] && la->mtex[b]->tex) { - make_local_texture(la->mtex[b]->tex); - } - } - } - else { + if(mode>1) { + base= FIRSTBASE; + while(base) { + ob= base->object; + if(base->flag & SELECT ) { - for(a=0; a<ob->totcol; a++) { - ma= ob->mat[a]; - if(ma) { - make_local_material(ma); - - for(b=0; b<MAX_MTEX; b++) { - if(ma->mtex[b] && ma->mtex[b]->tex) { - make_local_texture(ma->mtex[b]->tex); - } + if(ob->type==OB_LAMP) { + la= ob->data; + for(b=0; b<MAX_MTEX; b++) { + if(la->mtex[b] && la->mtex[b]->tex) { + make_local_texture(la->mtex[b]->tex); } - id= (ID *)ma->ipo; - if(id && id->lib) make_local_ipo(ma->ipo); } } - - matarar= (Material ***)give_matarar(ob); - - for(a=0; a<ob->totcol; a++) { - ma= (*matarar)[a]; - if(ma) { - make_local_material(ma); + else { - for(b=0; b<MAX_MTEX; b++) { - if(ma->mtex[b] && ma->mtex[b]->tex) { - make_local_texture(ma->mtex[b]->tex); - } - } - id= (ID *)ma->ipo; - if(id && id->lib) make_local_ipo(ma->ipo); + for(a=0; a<ob->totcol; a++) { + ma= ob->mat[a]; + if(ma) + make_local_makelocalmaterial(ma); + } + + matarar= (Material ***)give_matarar(ob); + + for(a=0; a<ob->totcol; a++) { + ma= (*matarar)[a]; + if(ma) + make_local_makelocalmaterial(ma); } } } + base= base->next; } - base= base->next; } - allqueue(REDRAWALL, 0); BIF_undo_push("Make local"); } @@ -4159,6 +4186,7 @@ static void adduplicate__forwardModifierLinks(void *userData, Object *ob, Object { ID_NEW(*obpoin); } + void adduplicate(int noTrans) /* dtrans is 3 x 3xfloat dloc, drot en dsize */ { @@ -4194,7 +4222,14 @@ void adduplicate(int noTrans) BLI_addhead(&G.scene->base, basen); /* addhead: prevent eternal loop */ basen->object= obn; base->flag &= ~SELECT; - basen->flag &= ~OB_FROMGROUP; + + if(basen->flag & OB_FROMGROUP) { + Group *group; + for(group= G.main->group.first; group; group= group->id.next) { + if(object_in_group(ob, group)) + add_to_group(group, obn); + } + } if(BASACT==base) BASACT= basen; diff --git a/source/blender/src/editscreen.c b/source/blender/src/editscreen.c index b665c64e0e3..b95fc9f11bd 100644 --- a/source/blender/src/editscreen.c +++ b/source/blender/src/editscreen.c @@ -110,6 +110,8 @@ always reset to zero. */ +/* comment added to test orange branch */ + static void testareas(void); static void area_autoplayscreen(void); static void wait_for_event(void); diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c index 2376fe93619..458be9a0897 100644 --- a/source/blender/src/editview.c +++ b/source/blender/src/editview.c @@ -46,10 +46,11 @@ #include "DNA_action_types.h" #include "DNA_armature_types.h" -#include "DNA_meta_types.h" -#include "DNA_mesh_types.h" #include "DNA_curve_types.h" +#include "DNA_group_types.h" #include "DNA_lattice_types.h" +#include "DNA_meta_types.h" +#include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -63,7 +64,9 @@ #include "BKE_armature.h" #include "BKE_depsgraph.h" #include "BKE_global.h" +#include "BKE_group.h" #include "BKE_lattice.h" +#include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_utildefines.h" @@ -1034,8 +1037,6 @@ void set_active_base(Base *base) if(base) { /* signals to buttons */ redraw_test_buttons(base->object); - - set_active_group(); /* signal to ipo */ allqueue(REDRAWIPO, base->object->ipowin); @@ -1069,6 +1070,29 @@ void set_active_object(Object *ob) } } +static void select_all_from_groups(Base *basact) +{ + Group *group; + GroupObject *go; + int deselect= basact->flag & SELECT; + + for(group= G.main->group.first; group; group= group->id.next) { + if(object_in_group(basact->object, group)) { + for(go= group->gobject.first; go; go= go->next) { + if(deselect) go->ob->flag &= ~SELECT; + else go->ob->flag |= SELECT; + } + } + } + /* sync bases */ + for(basact= G.scene->base.first; basact; basact= basact->next) { + if(basact->object->flag & SELECT) + basact->flag |= SELECT; + else + basact->flag &= ~SELECT; + } +} + /* The max number of menu items in an object select menu */ #define SEL_MENU_SIZE 22 @@ -1342,6 +1366,9 @@ void mouse_select(void) deselectall_except(basact); basact->flag |= SELECT; } + else if(G.qual==(LR_SHIFTKEY|LR_ALTKEY)) { + select_all_from_groups(basact); + } else { if(basact->flag & SELECT) { if(basact==oldbasact) diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index 3b17f0c2c26..db4c981eba2 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -2534,7 +2534,7 @@ void main_to_filelist(SpaceFile *sfile) if( sfile->dir[0]==0) { /* make directories */ - sfile->totfile= 21; + sfile->totfile= 22; sfile->filelist= (struct direntry *)malloc(sfile->totfile * sizeof(struct direntry)); for(a=0; a<sfile->totfile; a++) { @@ -2545,24 +2545,25 @@ void main_to_filelist(SpaceFile *sfile) sfile->filelist[0].relname= BLI_strdup(".."); sfile->filelist[1].relname= BLI_strdup("."); sfile->filelist[2].relname= BLI_strdup("Scene"); - sfile->filelist[3].relname= BLI_strdup("Object"); - sfile->filelist[4].relname= BLI_strdup("Mesh"); - sfile->filelist[5].relname= BLI_strdup("Curve"); - sfile->filelist[6].relname= BLI_strdup("Metaball"); - sfile->filelist[7].relname= BLI_strdup("Material"); - sfile->filelist[8].relname= BLI_strdup("Texture"); - sfile->filelist[9].relname= BLI_strdup("Image"); - sfile->filelist[10].relname= BLI_strdup("Wave"); - sfile->filelist[11].relname= BLI_strdup("Lattice"); - sfile->filelist[12].relname= BLI_strdup("Lamp"); - sfile->filelist[13].relname= BLI_strdup("Camera"); - sfile->filelist[14].relname= BLI_strdup("Ipo"); - sfile->filelist[15].relname= BLI_strdup("World"); - sfile->filelist[16].relname= BLI_strdup("Screen"); - sfile->filelist[17].relname= BLI_strdup("VFont"); - sfile->filelist[18].relname= BLI_strdup("Text"); - sfile->filelist[19].relname= BLI_strdup("Armature"); - sfile->filelist[20].relname= BLI_strdup("Action"); + sfile->filelist[3].relname= BLI_strdup("Group"); + sfile->filelist[4].relname= BLI_strdup("Object"); + sfile->filelist[5].relname= BLI_strdup("Mesh"); + sfile->filelist[6].relname= BLI_strdup("Curve"); + sfile->filelist[7].relname= BLI_strdup("Metaball"); + sfile->filelist[8].relname= BLI_strdup("Material"); + sfile->filelist[9].relname= BLI_strdup("Texture"); + sfile->filelist[10].relname= BLI_strdup("Image"); + sfile->filelist[11].relname= BLI_strdup("Wave"); + sfile->filelist[12].relname= BLI_strdup("Lattice"); + sfile->filelist[13].relname= BLI_strdup("Lamp"); + sfile->filelist[14].relname= BLI_strdup("Camera"); + sfile->filelist[15].relname= BLI_strdup("Ipo"); + sfile->filelist[16].relname= BLI_strdup("World"); + sfile->filelist[17].relname= BLI_strdup("Screen"); + sfile->filelist[18].relname= BLI_strdup("VFont"); + sfile->filelist[19].relname= BLI_strdup("Text"); + sfile->filelist[20].relname= BLI_strdup("Armature"); + sfile->filelist[21].relname= BLI_strdup("Action"); qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name); } else { diff --git a/source/blender/src/header_buttonswin.c b/source/blender/src/header_buttonswin.c index 7b992263bb7..02c79f43b8f 100644 --- a/source/blender/src/header_buttonswin.c +++ b/source/blender/src/header_buttonswin.c @@ -62,6 +62,7 @@ #include "BIF_butspace.h" #include "BKE_armature.h" +#include "BKE_blender.h" #include "BKE_global.h" #include "BKE_library.h" #include "BKE_main.h" @@ -72,6 +73,7 @@ #include "BSE_headerbuttons.h" #include "MEM_guardedalloc.h" +#include "BLI_blenlib.h" #include "blendef.h" #include "mydevice.h" @@ -98,9 +100,12 @@ void free_matcopybuf(void) if(matcopybuf.ramp_col) MEM_freeN(matcopybuf.ramp_col); if(matcopybuf.ramp_spec) MEM_freeN(matcopybuf.ramp_spec); + matcopybuf.ramp_col= NULL; matcopybuf.ramp_spec= NULL; + BLI_freelistN(&matcopybuf.layers); + default_mtex(&mtexcopybuf); } @@ -109,6 +114,7 @@ void do_buts_buttons(short event) static short matcopied=0; MTex *mtex; Material *ma; + MaterialLayer *ml; ID id; int a; float dx, dy; @@ -143,9 +149,10 @@ void do_buts_buttons(short event) break; case B_MATCOPY: if(G.buts->lockpoin) { + ma= G.buts->lockpoin; if(matcopied) free_matcopybuf(); - memcpy(&matcopybuf, G.buts->lockpoin, sizeof(Material)); + memcpy(&matcopybuf, ma, sizeof(Material)); if(matcopybuf.ramp_col) matcopybuf.ramp_col= MEM_dupallocN(matcopybuf.ramp_col); if(matcopybuf.ramp_spec) matcopybuf.ramp_spec= MEM_dupallocN(matcopybuf.ramp_spec); @@ -155,12 +162,15 @@ void do_buts_buttons(short event) matcopybuf.mtex[a]= MEM_dupallocN(mtex); } } + duplicatelist(&matcopybuf.layers, &ma->layers); + matcopied= 1; } break; case B_MATPASTE: if(matcopied && G.buts->lockpoin) { ma= G.buts->lockpoin; + /* free current mat */ if(ma->ramp_col) MEM_freeN(ma->ramp_col); if(ma->ramp_spec) MEM_freeN(ma->ramp_spec); @@ -169,6 +179,10 @@ void do_buts_buttons(short event) if(mtex && mtex->tex) mtex->tex->id.us--; if(mtex) MEM_freeN(mtex); } + for(ml= ma->layers.first; ml; ml= ml->next) + if(ml->mat) ml->mat->id.us--; + + BLI_freelistN(&ma->layers); id= (ma->id); memcpy(G.buts->lockpoin, &matcopybuf, sizeof(Material)); @@ -184,6 +198,11 @@ void do_buts_buttons(short event) if(mtex->tex) id_us_plus((ID *)mtex->tex); } } + duplicatelist(&ma->layers, &matcopybuf.layers); + + for(ml= ma->layers.first; ml; ml= ml->next) + if(ml->mat) ml->mat->id.us++; + BIF_preview_changed(G.buts); BIF_undo_push("Paste material settings"); scrarea_queue_winredraw(curarea); @@ -262,6 +281,7 @@ void buttons_active_id(ID **id, ID **idfrom) if(G.buts->texfrom==0) { if(ob && ob->type<OB_LAMP && ob->type) { ma= give_current_material(ob, ob->actcol); + ma= get_active_matlayer(ma); *idfrom= (ID *)ma; if(ma) { mtex= ma->mtex[ ma->texact ]; diff --git a/source/blender/src/header_image.c b/source/blender/src/header_image.c index e0571e94e45..35e7c8e577f 100644 --- a/source/blender/src/header_image.c +++ b/source/blender/src/header_image.c @@ -1013,6 +1013,9 @@ static void do_image_uvsmenu(void *arg, int event) if(G.sima->flag & SI_LSCM_LIVE) G.sima->flag &= ~SI_LSCM_LIVE; else G.sima->flag |= SI_LSCM_LIVE; break; + case 12: + minimize_stretch_tface_uv(); + break; } } @@ -1047,6 +1050,7 @@ static uiBlock *image_uvsmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Minimize Stretch|Ctrl V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Limit Stitch...|Shift V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Stitch|V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, ""); uiDefIconTextBlockBut(block, image_uvs_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, ""); @@ -1099,6 +1103,7 @@ void image_buttons(void) char naam[256]; /* This should not be a static var */ static int headerbuttons_packdummy; + extern short CurrentUnwrapper; headerbuttons_packdummy = 0; @@ -1176,6 +1181,9 @@ void image_buttons(void) /* draw LOCK */ uiDefIconButS(block, ICONTOG, 0, ICON_UNLOCKED, xco,0,XIC,YIC, &(G.sima->lock), 0, 0, 0, 0, "Updates other affected window spaces automatically to reflect changes in real time"); + + xco += 2*XIC; + uiDefButS(block, MENU, B_NOP, "Unwrapper%t|Old LSCM%x0|New LSCM%x1",xco,0,85,YIC, &CurrentUnwrapper, 0, 0, 0, 0, "Unwrapper"); /* Always do this last */ curarea->headbutlen= xco+2*XIC; diff --git a/source/blender/src/header_oops.c b/source/blender/src/header_oops.c index 1da5dc6100f..a8f90b95ed8 100644 --- a/source/blender/src/header_oops.c +++ b/source/blender/src/header_oops.c @@ -1,20 +1,12 @@ /** - * header_oops.c oct-2003 - * - * Functions to draw the "OOPS Schematic" window header - * and handle user events sent to it. - * * $Id$ * - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -28,11 +20,11 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * - * The Original Code is: all of this file. + * The Original Code is: not all of this file anymore. * - * Contributor(s): none yet. + * Contributor(s): Blender Foundation. * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * ***** END GPL LICENSE BLOCK ***** */ #include <stdlib.h> @@ -440,7 +432,7 @@ void oops_buttons(void) } #endif else { - uiDefButS(block, MENU, B_REDR, "Outliner Display%t|All Scenes %x0|Current Scene %x1|Visible Layers %x2|Same Types %x5|Selected %x3|Active %x4", xco, 0, 100, 20, &soops->outlinevis, 0, 0, 0, 0, ""); + uiDefButS(block, MENU, B_REDR, "Outliner Display%t|All Scenes %x0|Current Scene %x1|Visible Layers %x2|Groups %x6|Same Types %x5|Selected %x3|Active %x4", xco, 0, 100, 20, &soops->outlinevis, 0, 0, 0, 0, ""); } /* always do as last */ diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 2b448348034..fbea7637dd1 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -742,7 +742,7 @@ void do_view3d_select_object_groupedmenu(void *arg, int event) case 2: /* Immediate Children */ case 3: /* Parent */ case 4: /* Objects on Shared Layers */ - select_group((short)event); + select_grouped((short)event); break; } allqueue(REDRAWVIEW3D, 0); diff --git a/source/blender/src/headerbuttons.c b/source/blender/src/headerbuttons.c index c9383d2dded..d05904c74a8 100644 --- a/source/blender/src/headerbuttons.c +++ b/source/blender/src/headerbuttons.c @@ -809,6 +809,7 @@ void do_global_buttons(unsigned short event) else { if(G.buts->texfrom==0) { /* from mat */ ma= give_current_material(ob, ob->actcol); + ma= get_active_matlayer(ma); if(ma) { mtex= ma->mtex[ ma->texact ]; if(mtex) { @@ -861,6 +862,7 @@ void do_global_buttons(unsigned short event) if(event==B_EXTEXBROWSE) { id= NULL; ma= give_current_material(ob, ob->actcol); + ma= get_active_matlayer(ma); if(ma) { mtex= ma->mtex[ ma->texact ]; if(mtex) id= (ID *)mtex->tex; @@ -879,6 +881,7 @@ void do_global_buttons(unsigned short event) id= NULL; ma= give_current_material(ob, ob->actcol); + ma= get_active_matlayer(ma); if(ma) { mtex= ma->mtex[ ma->texact ]; if(mtex) id= (ID *)mtex->tex; @@ -1717,7 +1720,13 @@ void do_global_buttons2(short event) ma= give_current_material(ob, ob->actcol); if(ma && ma->id.lib) { if(okee("Make local")) { + MaterialLayer *ml; + make_local_material(ma); + for(ml= ma->layers.first; ml; ml= ml->next) { + if(ml->mat) + make_local_material(ml->mat); + } } } } @@ -1790,6 +1799,7 @@ void do_global_buttons2(short event) if(G.buts->texfrom==0) { /* from mat */ if(ob==0) return; ma= give_current_material(ob, ob->actcol); + ma= get_active_matlayer(ma); if(ma && ma->id.lib==0) { mtex= ma->mtex[ ma->texact ]; if(mtex->tex && mtex->tex->id.us>1) { @@ -1830,6 +1840,7 @@ void do_global_buttons2(short event) if(G.buts->texfrom==0) { /* from mat */ if(ob==0) return; ma= give_current_material(ob, ob->actcol); + ma= get_active_matlayer(ma); if(ma && ma->id.lib==0) { mtex= ma->mtex[ ma->texact ]; if(mtex->tex && mtex->tex->id.lib) { diff --git a/source/blender/src/interface_panel.c b/source/blender/src/interface_panel.c index 54bab5703a3..c9892ed7f1e 100644 --- a/source/blender/src/interface_panel.c +++ b/source/blender/src/interface_panel.c @@ -652,7 +652,7 @@ void uiSetPanel_view2d(ScrArea *sa) pa= sa->panels.first; while(pa) { - if(pa->active) { + if(pa->active && pa->paneltab==NULL) { done= 1; if(pa->ofsx < minx) minx= pa->ofsx; if(pa->ofsx+pa->sizex > maxx) maxx= pa->ofsx+pa->sizex; @@ -696,7 +696,7 @@ void uiMatchPanel_view2d(ScrArea *sa) pa= sa->panels.first; while(pa) { - if(pa->active) { + if(pa->active && pa->paneltab==NULL) { done= 1; if(pa->ofsx < G.v2d->tot.xmin) G.v2d->tot.xmin= pa->ofsx; if(pa->ofsx+pa->sizex > G.v2d->tot.xmax) diff --git a/source/blender/src/meshtools.c b/source/blender/src/meshtools.c index 1ef7320763c..2b96bbc20b6 100644 --- a/source/blender/src/meshtools.c +++ b/source/blender/src/meshtools.c @@ -602,7 +602,7 @@ void sort_faces(void) typedef struct MocNode { struct MocNode *next; - int index[MOC_NODE_RES]; + long index[MOC_NODE_RES]; } MocNode; static int mesh_octree_get_base_offs(float *co, float *offs, float *div) @@ -620,7 +620,7 @@ static int mesh_octree_get_base_offs(float *co, float *offs, float *div) return (vx*MOC_RES*MOC_RES) + vy*MOC_RES + vz; } -static void mesh_octree_add_node(MocNode **bt, int index) +static void mesh_octree_add_node(MocNode **bt, long index) { if(*bt==NULL) { *bt= MEM_callocN(sizeof(MocNode), "MocNode"); @@ -652,7 +652,7 @@ static void mesh_octree_free_node(MocNode **bt) /* temporal define, just to make nicer code below */ #define MOC_ADDNODE(vx, vy, vz) mesh_octree_add_node(basetable + ((vx)*MOC_RES*MOC_RES) + (vy)*MOC_RES + (vz), index) -static void mesh_octree_add_nodes(MocNode **basetable, float *co, float *offs, float *div, int index) +static void mesh_octree_add_nodes(MocNode **basetable, float *co, float *offs, float *div, long index) { float fx, fy, fz; int vx, vy, vz; @@ -693,7 +693,7 @@ static void mesh_octree_add_nodes(MocNode **basetable, float *co, float *offs, f } -static int mesh_octree_find_index(MocNode **bt, MVert *mvert, float *co) +static long mesh_octree_find_index(MocNode **bt, MVert *mvert, float *co) { float *vec; int a; @@ -706,15 +706,13 @@ static int mesh_octree_find_index(MocNode **bt, MVert *mvert, float *co) /* does mesh verts and editmode, code looks potential dangerous, octree should really be filled OK! */ if(mvert) { vec= (mvert+(*bt)->index[a]-1)->co; - if(FloatCompare(vec, co, MOC_THRESH)) return (*bt)->index[a]-1; } else { - EditVert *eve= (EditVert *)INT_TO_POINTER((*bt)->index[a]); - + EditVert *eve= (EditVert *)((*bt)->index[a]); if(FloatCompare(eve->co, co, MOC_THRESH)) - return (int)eve; + return (*bt)->index[a]; } } else return -1; @@ -728,7 +726,7 @@ static int mesh_octree_find_index(MocNode **bt, MVert *mvert, float *co) /* mode is 's' start, or 'e' end, or 'u' use */ /* if end, ob can be NULL */ -int mesh_octree_table(Object *ob, float *co, char mode) +long mesh_octree_table(Object *ob, float *co, char mode) { MocNode **bt; static MocNode **basetable= NULL; @@ -754,21 +752,23 @@ int mesh_octree_table(Object *ob, float *co, char mode) /* for quick unit coordinate calculus */ VECCOPY(offs, bb->vec[0]); - offs[0]+= MOC_THRESH; /* we offset it 1 threshold unit extra */ - offs[1]+= MOC_THRESH; - offs[2]+= MOC_THRESH; + offs[0]-= MOC_THRESH; /* we offset it 1 threshold unit extra */ + offs[1]-= MOC_THRESH; + offs[2]-= MOC_THRESH; - VecSubf(div, bb->vec[6], offs); - div[0]+= MOC_THRESH; /* and divide with 1 threshold unit more extra (try 8x8 unit grid on paint) */ - div[1]+= MOC_THRESH; - div[2]+= MOC_THRESH; + VecSubf(div, bb->vec[6], bb->vec[0]); + div[0]+= 2*MOC_THRESH; /* and divide with 2 threshold unit more extra (try 8x8 unit grid on paint) */ + div[1]+= 2*MOC_THRESH; + div[2]+= 2*MOC_THRESH; VecMulf(div, 1.0f/MOC_RES); if(div[0]==0.0f) div[0]= 1.0f; if(div[1]==0.0f) div[1]= 1.0f; if(div[2]==0.0f) div[2]= 1.0f; - - if(basetable) /* happens when entering wpaint without closing it */ + printvecf("ofs", offs); + printvecf("div", div); + + if(basetable) /* happens when entering this call without ending it */ mesh_octree_table(ob, co, 'e'); basetable= MEM_callocN(MOC_RES*MOC_RES*MOC_RES*sizeof(void *), "sym table"); @@ -777,12 +777,12 @@ int mesh_octree_table(Object *ob, float *co, char mode) EditVert *eve; for(eve= G.editMesh->verts.first; eve; eve= eve->next) { - mesh_octree_add_nodes(basetable, eve->co, offs, div, POINTER_TO_INT(eve)); + mesh_octree_add_nodes(basetable, eve->co, offs, div, (long)(eve)); } } else { MVert *mvert; - int a; + long a; for(a=1, mvert= me->mvert; a<=me->totvert; a++, mvert++) { mesh_octree_add_nodes(basetable, mvert->co, offs, div, a); @@ -815,3 +815,18 @@ int mesh_get_x_mirror_vert(Object *ob, int index) return mesh_octree_table(ob, vec, 'u'); } + +EditVert *editmesh_get_x_mirror_vert(Object *ob, float *co) +{ + float vec[3]; + long poinval; + + vec[0]= -co[0]; + vec[1]= co[1]; + vec[2]= co[2]; + + poinval= mesh_octree_table(ob, vec, 'u'); + if(poinval != -1) + return (EditVert *)(poinval); + return NULL; +}
\ No newline at end of file diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c index 76ab56fb574..c4c11a4c294 100644 --- a/source/blender/src/outliner.c +++ b/source/blender/src/outliner.c @@ -39,6 +39,7 @@ #include "DNA_camera_types.h" #include "DNA_image_types.h" #include "DNA_ipo_types.h" +#include "DNA_group_types.h" #include "DNA_key_types.h" #include "DNA_lamp_types.h" #include "DNA_material_types.h" @@ -65,6 +66,7 @@ #include "BKE_material.h" #include "BKE_modifier.h" #include "BKE_screen.h" +#include "BKE_scene.h" #include "BKE_utildefines.h" #include "BIF_butspace.h" @@ -768,6 +770,23 @@ static void outliner_build_tree(SpaceOops *soops) } outliner_make_hierarchy(soops, &soops->tree); } + else if(soops->outlinevis == SO_GROUPS) { + Group *group; + GroupObject *go; + + for(group= G.main->group.first; group; group= group->id.next) { + te= outliner_add_element(soops, &soops->tree, group, NULL, 0, 0); + tselem= TREESTORE(te); + + for(go= group->gobject.first; go; go= go->next) { + ten= outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0); + ten->directdata= NULL; + } + outliner_make_hierarchy(soops, &te->subtree); + /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */ + for(go= group->gobject.first; go; go= go->next) go->ob->id.newid= NULL; + } + } else if(soops->outlinevis == SO_SAME_TYPE) { Object *ob= OBACT; if(ob) { @@ -1794,22 +1813,29 @@ static void object_select_cb(TreeElement *te, TreeStoreElem *tselem) { Base *base= (Base *)te->directdata; - base->flag |= SELECT; - base->object->flag |= SELECT; + if(base==NULL) base= object_in_scene((Object *)tselem->id, G.scene); + if(base) { + base->flag |= SELECT; + base->object->flag |= SELECT; + } } static void object_deselect_cb(TreeElement *te, TreeStoreElem *tselem) { Base *base= (Base *)te->directdata; - base->flag &= ~SELECT; - base->object->flag &= ~SELECT; + if(base==NULL) base= object_in_scene((Object *)tselem->id, G.scene); + if(base) { + base->flag &= ~SELECT; + base->object->flag &= ~SELECT; + } } static void object_delete_cb(TreeElement *te, TreeStoreElem *tselem) { Base *base= (Base *)te->directdata; + if(base==NULL) base= object_in_scene((Object *)tselem->id, G.scene); if(base) { // check also library later if(G.obedit==base->object) exit_editmode(2); @@ -2121,6 +2147,8 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen BIF_draw_icon(x, y, ICON_NLA); break; case ID_TXT: BIF_draw_icon(x, y, ICON_SCRIPT); break; + case ID_GR: + BIF_draw_icon(x, y, ICON_CIRCLE_DEHLT); break; } } } diff --git a/source/blender/src/parametrizer.c b/source/blender/src/parametrizer.c new file mode 100644 index 00000000000..9ee7d3f5daf --- /dev/null +++ b/source/blender/src/parametrizer.c @@ -0,0 +1,1877 @@ + +#include "MEM_guardedalloc.h" + +#include "BLI_memarena.h" +#include "BLI_arithb.h" +#include "BLI_rand.h" + +#include "BKE_utildefines.h" + +#include "BIF_editsima.h" +#include "BIF_toolbox.h" + +#include "ONL_opennl.h" + +#include "parametrizer.h" +#include "parametrizer_intern.h" + +#include <math.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#if defined(_WIN32) +#define M_PI 3.14159265358979323846 +#endif + +/* Hash */ + +static int PHashSizes[] = { + 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, + 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, + 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459 +}; + +#define PHASH_hash(ph, item) (((unsigned long) (item))%((unsigned int) (ph)->cursize)) + +PHash *phash_new(int sizehint) +{ + PHash *ph = (PHash*)MEM_callocN(sizeof(PHash), "PHash"); + ph->size = 0; + ph->cursize_id = 0; + ph->first = NULL; + + while (PHashSizes[ph->cursize_id] < sizehint) + ph->cursize_id++; + + ph->cursize = PHashSizes[ph->cursize_id]; + ph->buckets = (PHashLink**)MEM_callocN(ph->cursize*sizeof(*ph->buckets), "PHashBuckets"); + + return ph; +} + +void phash_delete(PHash *ph) +{ + MEM_freeN(ph->buckets); + MEM_freeN(ph); +} + +void phash_delete_with_links(PHash *ph) +{ + PHashLink *link, *next=NULL; + + for (link = ph->first; link; link = next) { + next = link->next; + MEM_freeN(link); + } + + phash_delete(ph); +} + +int phash_size(PHash *ph) +{ + return ph->size; +} + +void phash_insert(PHash *ph, PHashLink *link) +{ + int size = ph->cursize; + int hash = PHASH_hash(ph, link->key); + PHashLink *lookup = ph->buckets[hash]; + + if (lookup == NULL) { + /* insert in front of the list */ + ph->buckets[hash] = link; + link->next = ph->first; + ph->first = link; + } + else { + /* insert after existing element */ + link->next = lookup->next; + lookup->next = link; + } + + ph->size++; + + if (ph->size > (size*3)) { + PHashLink *next = NULL, *first = ph->first; + + ph->cursize = PHashSizes[++ph->cursize_id]; + MEM_freeN(ph->buckets); + ph->buckets = (PHashLink**)MEM_callocN(ph->cursize*sizeof(*ph->buckets), "PHashBuckets"); + ph->size = 0; + ph->first = NULL; + + for (link = first; link; link = next) { + next = link->next; + phash_insert(ph, link); + } + } +} + +PHashLink *phash_lookup(PHash *ph, PHashKey key) +{ + PHashLink *link; + int hash = PHASH_hash(ph, key); + + for (link = ph->buckets[hash]; link; link = link->next) + if (link->key == key) + return link; + else if (PHASH_hash(ph, link->key) != hash) + return NULL; + + return link; +} + +PHashLink *phash_next(PHash *ph, PHashKey key, PHashLink *link) +{ + int hash = PHASH_hash(ph, key); + + for (link = link->next; link; link = link->next) + if (link->key == key) + return link; + else if (PHASH_hash(ph, link->key) != hash) + return NULL; + + return link; +} + +/* Heap */ + +#define PHEAP_PARENT(i) ((i-1)>>1) +#define PHEAP_LEFT(i) ((i<<1)+1) +#define PHEAP_RIGHT(i) ((i<<1)+2) +#define PHEAP_COMPARE(a, b) (a->value < b->value) +#define PHEAP_EQUALS(a, b) (a->value == b->value) +#define PHEAP_SWAP(heap, i, j) \ + { SWAP(int, heap->tree[i]->index, heap->tree[j]->index); \ + SWAP(PHeapLink*, heap->tree[i], heap->tree[j]); } + +static void pheap_down(PHeap *heap, int i) +{ + while (P_TRUE) { + int size = heap->size, smallest; + int l = PHEAP_LEFT(i); + int r = PHEAP_RIGHT(i); + + smallest = ((l < size) && PHEAP_COMPARE(heap->tree[l], heap->tree[i]))? l: i; + + if ((r < size) && PHEAP_COMPARE(heap->tree[r], heap->tree[smallest])) + smallest = r; + + if (smallest == i) + break; + + PHEAP_SWAP(heap, i, smallest); + i = smallest; + } +} + +static void pheap_up(PHeap *heap, int i) +{ + while (i > 0) { + int p = PHEAP_PARENT(i); + + if (PHEAP_COMPARE(heap->tree[p], heap->tree[i])) + break; + + PHEAP_SWAP(heap, p, i); + i = p; + } +} + +PHeap *pheap_new() +{ + /* TODO: replace mallocN with something faster */ + + PHeap *heap = (PHeap*)MEM_callocN(sizeof(PHeap), "PHeap"); + heap->bufsize = 1; + heap->tree = (PHeapLink**)MEM_mallocN(sizeof(PHeapLink*), "PHeapTree"); + + return heap; +} + +void pheap_delete(PHeap *heap) +{ + MEM_freeN(heap->tree); + MEM_freeN(heap); +} + +PHeapLink *pheap_insert(PHeap *heap, float value, void *ptr) +{ + PHeapLink *link; + + if ((heap->size + 1) > heap->bufsize) { + int newsize = heap->bufsize*2; + + PHeapLink **ntree = (PHeapLink**)MEM_mallocN(newsize*sizeof(PHeapLink*), "PHeapTree"); + memcpy(ntree, heap->tree, sizeof(PHeapLink*)*heap->size); + MEM_freeN(heap->tree); + + heap->tree = ntree; + heap->bufsize = newsize; + } + + param_assert(heap->size < heap->bufsize); + + link = MEM_mallocN(sizeof *link, "PHeapLink"); + link->value = value; + link->ptr = ptr; + link->index = heap->size; + + heap->tree[link->index] = link; + + heap->size++; + + pheap_up(heap, heap->size-1); + + return link; +} + +int pheap_empty(PHeap *heap) +{ + return (heap->size == 0); +} + +int pheap_size(PHeap *heap) +{ + return heap->size; +} + +void *pheap_min(PHeap *heap) +{ + return heap->tree[0]->ptr; +} + +void *pheap_popmin(PHeap *heap) +{ + void *ptr = heap->tree[0]->ptr; + + MEM_freeN(heap->tree[0]); + + if (heap->size == 1) + heap->size--; + else { + PHEAP_SWAP(heap, 0, heap->size-1); + heap->size--; + + pheap_down(heap, 0); + } + + return ptr; +} + +static void pheap_remove(PHeap *heap, PHeapLink *link) +{ + int i = link->index; + + while (i > 0) { + int p = PHEAP_PARENT(i); + + PHEAP_SWAP(heap, p, i); + i = p; + } + + pheap_popmin(heap); +} + +/* Construction */ + +PEdge *p_wheel_edge_next(PEdge *e) +{ + return e->next->next->pair; +} + +PEdge *p_wheel_edge_prev(PEdge *e) +{ + return (e->pair)? e->pair->next: NULL; +} + +static PVert *p_vert_add(PChart *chart, PHashKey key, float *co, PEdge *e) +{ + PVert *v = (PVert*)BLI_memarena_alloc(chart->handle->arena, sizeof *v); + v->co = co; + v->link.key = key; + v->edge = e; + + phash_insert(chart->verts, (PHashLink*)v); + + return v; +} + +static PVert *p_vert_lookup(PChart *chart, PHashKey key, float *co, PEdge *e) +{ + PVert *v = (PVert*)phash_lookup(chart->verts, key); + + if (v) + return v; + else + return p_vert_add(chart, key, co, e); +} + +static PVert *p_vert_copy(PChart *chart, PVert *v) +{ + PVert *nv = (PVert*)BLI_memarena_alloc(chart->handle->arena, sizeof *nv); + nv->co = v->co; + nv->uv[0] = v->uv[0]; + nv->uv[1] = v->uv[1]; + nv->link.key = v->link.key; + nv->edge = v->edge; + + phash_insert(chart->verts, (PHashLink*)nv); + + return nv; +} + +static PEdge *p_edge_lookup(PChart *chart, PHashKey *vkeys) +{ + PHashKey key = vkeys[0]^vkeys[1]; + PEdge *e = (PEdge*)phash_lookup(chart->edges, key); + + while (e) { + if ((e->vert->link.key == vkeys[0]) && (e->next->vert->link.key == vkeys[1])) + return e; + else if ((e->vert->link.key == vkeys[1]) && (e->next->vert->link.key == vkeys[0])) + return e; + + e = (PEdge*)phash_next(chart->edges, key, (PHashLink*)e); + } + + return NULL; +} + +static void p_face_flip(PFace *f) +{ + PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next; + PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert; + int f1 = e1->flag, f2 = e2->flag, f3 = e3->flag; + + e1->vert = v2; + e1->next = e3; + e1->flag = (f1 & ~PEDGE_VERTEX_FLAGS) | (f2 & PEDGE_VERTEX_FLAGS); + + e2->vert = v3; + e2->next = e1; + e2->flag = (f2 & ~PEDGE_VERTEX_FLAGS) | (f3 & PEDGE_VERTEX_FLAGS); + + e3->vert = v1; + e3->next = e2; + e3->flag = (f3 & ~PEDGE_VERTEX_FLAGS) | (f1 & PEDGE_VERTEX_FLAGS); +} + +static void p_vert_load_pin_select_uvs(PVert *v) +{ + PEdge *e; + int nedges = 0; + + v->uv[0] = v->uv[1] = 0.0f; + nedges = 0; + e = v->edge; + do { + if (e->orig_uv && (e->flag & PEDGE_PIN)) { + if (e->flag & PEDGE_SELECT) + v->flag |= PVERT_SELECT; + + v->flag |= PVERT_PIN; + v->uv[0] += e->orig_uv[0]; + v->uv[1] += e->orig_uv[1]; + nedges++; + } + + e = p_wheel_edge_next(e); + } while (e && e != (v->edge)); + + if (nedges > 0) { + v->uv[0] /= nedges; + v->uv[1] /= nedges; + } +} + +static void p_vert_load_select_uvs(PVert *v) +{ + PEdge *e; + int nedges = 0; + + v->uv[0] = v->uv[1] = 0.0f; + nedges = 0; + e = v->edge; + do { + if (e->orig_uv && (e->flag & PEDGE_SELECT)) + v->flag |= PVERT_SELECT; + + v->uv[0] += e->orig_uv[0]; + v->uv[1] += e->orig_uv[1]; + nedges++; + + e = p_wheel_edge_next(e); + } while (e && e != (v->edge)); + + if (nedges > 0) { + v->uv[0] /= nedges; + v->uv[1] /= nedges; + } +} + +static void p_extrema_verts(PChart *chart, PVert **v1, PVert **v2) +{ + float minv[3], maxv[3], dirlen; + PVert *v, *minvert[3], *maxvert[3]; + int i, dir; + + /* find minimum and maximum verts over x/y/z axes */ + minv[0] = minv[1] = minv[2] = 1e20; + maxv[0] = maxv[1] = maxv[2] = -1e20; + + minvert[0] = minvert[1] = minvert[2] = NULL; + maxvert[0] = maxvert[1] = maxvert[2] = NULL; + + for (v = (PVert*)chart->verts->first; v; v=v->link.next) { + for (i = 0; i < 3; i++) { + if (v->co[i] < minv[i]) { + minv[i] = v->co[i]; + minvert[i] = v; + } + if (v->co[i] > maxv[i]) { + maxv[i] = v->co[i]; + maxvert[i] = v; + } + } + } + + /* find axes with longest distance */ + dir = 0; + dirlen = -1.0; + + for (i = 0; i < 3; i++) { + if (maxv[i] - minv[i] > dirlen) { + dir = i; + dirlen = maxv[i] - minv[i]; + } + } + + if (minvert[dir] == maxvert[dir]) { + /* degenerate case */ + PFace *f = (PFace*)chart->faces->first; + *v1 = f->edge->vert; + *v2 = f->edge->next->vert; + + (*v1)->uv[0] = 0.0f; + (*v1)->uv[1] = 0.5f; + (*v2)->uv[0] = 1.0f; + (*v2)->uv[1] = 0.5f; + } + else { + *v1 = minvert[dir]; + *v2 = maxvert[dir]; + + (*v1)->uv[0] = (*v1)->co[dir]; + (*v1)->uv[1] = (*v1)->co[(dir+1)%3]; + (*v2)->uv[0] = (*v2)->co[dir]; + (*v2)->uv[1] = (*v2)->co[(dir+1)%3]; + } +} + +static float p_vec_normalise(float *v) +{ + float d; + + d = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); + + if(d != 0.0f) { + d = 1.0f/d; + + v[0] *= d; + v[1] *= d; + v[2] *= d; + } + + return d; +} + +static float p_vec_angle_cos(float *v1, float *v2, float *v3) +{ + float d1[3], d2[3]; + + d1[0] = v1[0] - v2[0]; + d1[1] = v1[1] - v2[1]; + d1[2] = v1[2] - v2[2]; + + d2[0] = v3[0] - v2[0]; + d2[1] = v3[1] - v2[1]; + d2[2] = v3[2] - v2[2]; + + p_vec_normalise(d1); + p_vec_normalise(d2); + + return d1[0]*d2[0] + d1[1]*d2[1] + d1[2]*d2[2]; +} + +static float p_vec_angle(float *v1, float *v2, float *v3) +{ + float dot = p_vec_angle_cos(v1, v2, v3); + + if (dot <= -1.0f) + return (float)M_PI; + else if (dot >= 1.0f) + return 0.0f; + else + return (float)acos(dot); +} + +static void p_face_angles(PFace *f, float *a1, float *a2, float *a3) +{ + PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next; + PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert; + + *a1 = p_vec_angle(v3->co, v1->co, v2->co); + *a2 = p_vec_angle(v1->co, v2->co, v3->co); + *a3 = M_PI - *a2 - *a1; +} + +static float p_face_area(PFace *f) +{ + PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next; + PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert; + + return AreaT3Dfl(v1->co, v2->co, v3->co); +} + +static float p_face_uv_area_signed(PFace *f) +{ + PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next; + PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert; + + return 0.5f*(((v2->uv[0]-v1->uv[0]) * (v3->uv[1]-v1->uv[1])) - + ((v3->uv[0]-v1->uv[0]) * (v2->uv[1]-v1->uv[1]))); +} + +static float p_face_uv_area(PFace *f) +{ + return fabs(p_face_uv_area_signed(f)); +} + +static void p_chart_area(PChart *chart, float *uv_area, float *area) +{ + PFace *f; + + *uv_area = *area = 0.0f; + + for (f=(PFace*)chart->faces->first; f; f=f->link.next) { + *uv_area += p_face_uv_area(f); + *area += p_face_area(f); + } +} + +static PChart *p_chart_new(PHandle *handle) +{ + PChart *chart = (PChart*)MEM_callocN(sizeof*chart, "PChart"); + chart->verts = phash_new(1); + chart->edges = phash_new(1); + chart->faces = phash_new(1); + chart->handle = handle; + + return chart; +} + +static void p_chart_delete(PChart *chart) +{ + /* the actual links are free by memarena */ + phash_delete(chart->verts); + phash_delete(chart->edges); + phash_delete(chart->faces); + + MEM_freeN(chart); +} + +static PBool p_edge_implicit_seam(PEdge *e, PEdge *ep) +{ + float *uv1, *uv2, *uvp1, *uvp2; + float limit[2]; + + uv1 = e->orig_uv; + uv2 = e->next->orig_uv; + + if (e->vert->link.key == ep->vert->link.key) { + uvp1 = ep->orig_uv; + uvp2 = ep->next->orig_uv; + } + else { + uvp1 = ep->next->orig_uv; + uvp2 = ep->orig_uv; + } + + get_connected_limit_tface_uv(limit); + + if((fabs(uv1[0]-uvp1[0]) > limit[0]) && (fabs(uv1[1]-uvp1[1]) > limit[1])) { + e->flag |= PEDGE_SEAM; + ep->flag |= PEDGE_SEAM; + return P_TRUE; + } + if((fabs(uv2[0]-uvp2[0]) > limit[0]) && (fabs(uv2[1]-uvp2[1]) > limit[1])) { + e->flag |= PEDGE_SEAM; + ep->flag |= PEDGE_SEAM; + return P_TRUE; + } + + return P_FALSE; +} + +static PBool p_edge_has_pair(PChart *chart, PEdge *e, PEdge **pair, PBool impl) +{ + PHashKey key; + PEdge *pe; + PVert *v1, *v2; + PHashKey key1 = e->vert->link.key; + PHashKey key2 = e->next->vert->link.key; + + if (e->flag & PEDGE_SEAM) + return P_FALSE; + + key = key1 ^ key2; + pe = (PEdge*)phash_lookup(chart->edges, key); + *pair = NULL; + + while (pe) { + if (pe != e) { + v1 = pe->vert; + v2 = pe->next->vert; + + if (((v1->link.key == key1) && (v2->link.key == key2)) || + ((v1->link.key == key2) && (v2->link.key == key1))) { + + /* don't connect seams and t-junctions */ + if ((pe->flag & PEDGE_SEAM) || *pair || + (impl && p_edge_implicit_seam(e, pe))) { + *pair = NULL; + return P_FALSE; + } + + *pair = pe; + } + } + + pe = (PEdge*)phash_next(chart->edges, key, (PHashLink*)pe); + } + + if (*pair && (e->vert == (*pair)->vert)) { + if ((*pair)->next->pair || (*pair)->next->next->pair) { + /* non unfoldable, maybe mobius ring or klein bottle */ + *pair = NULL; + return P_FALSE; + } + } + + return (*pair != NULL); +} + +static PBool p_edge_connect_pair(PChart *chart, PEdge *e, PEdge ***stack, PBool impl) +{ + PEdge *pair; + + if(!e->pair && p_edge_has_pair(chart, e, &pair, impl)) { + if (e->vert == pair->vert) + p_face_flip(pair->face); + + e->pair = pair; + pair->pair = e; + + if (!(pair->face->flag & PFACE_CONNECTED)) { + **stack = pair; + (*stack)++; + } + } + + return (e->pair != NULL); +} + +static int p_connect_pairs(PChart *chart, PBool impl) +{ + PEdge **stackbase = MEM_mallocN(sizeof*stackbase * phash_size(chart->faces), "Pstackbase"); + PEdge **stack = stackbase; + PFace *f, *first; + PEdge *e, *e1, *e2; + int ncharts = 0; + + /* connect pairs, count edges, set vertex-edge pointer to a pairless edge */ + for (first=(PFace*)chart->faces->first; first; first=first->link.next) { + if (first->flag & PFACE_CONNECTED) + continue; + + *stack = first->edge; + stack++; + + while (stack != stackbase) { + stack--; + e = *stack; + e1 = e->next; + e2 = e1->next; + + f = e->face; + f->flag |= PFACE_CONNECTED; + + /* assign verts to charts so we can sort them later */ + f->u.chart = ncharts; + + if (!p_edge_connect_pair(chart, e, &stack, impl)) + e->vert->edge = e; + if (!p_edge_connect_pair(chart, e1, &stack, impl)) + e1->vert->edge = e1; + if (!p_edge_connect_pair(chart, e2, &stack, impl)) + e2->vert->edge = e2; + } + + ncharts++; + } + + MEM_freeN(stackbase); + + return ncharts; +} + +static void p_split_vert(PChart *chart, PEdge *e) +{ + PEdge *we, *lastwe = NULL; + PVert *v = e->vert; + PBool copy = P_TRUE; + + if (e->flag & PEDGE_VERTEX_SPLIT) + return; + + /* rewind to start */ + lastwe = e; + for (we = p_wheel_edge_prev(e); we && (we != e); we = p_wheel_edge_prev(we)) + lastwe = we; + + /* go over all edges in wheel */ + for (we = lastwe; we; we = p_wheel_edge_next(we)) { + if (we->flag & PEDGE_VERTEX_SPLIT) + break; + + we->flag |= PEDGE_VERTEX_SPLIT; + + if (we == v->edge) { + /* found it, no need to copy */ + copy = P_FALSE; + phash_insert(chart->verts, (PHashLink*)v); + } + } + + if (copy) { + /* not found, copying */ + v = p_vert_copy(chart, v); + v->edge = lastwe; + + we = lastwe; + do { + we->vert = v; + we = p_wheel_edge_next(we); + } while (we && (we != lastwe)); + } +} + +static PChart **p_split_charts(PHandle *handle, PChart *chart, int ncharts) +{ + PChart **charts = MEM_mallocN(sizeof*charts * ncharts, "PCharts"), *nchart; + PFace *f, *nextf; + int i; + + for (i = 0; i < ncharts; i++) + charts[i] = p_chart_new(handle); + + f = (PFace*)chart->faces->first; + while (f) { + PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next; + nextf = f->link.next; + + nchart = charts[f->u.chart]; + + phash_insert(nchart->faces, (PHashLink*)f); + phash_insert(nchart->edges, (PHashLink*)e1); + phash_insert(nchart->edges, (PHashLink*)e2); + phash_insert(nchart->edges, (PHashLink*)e3); + + p_split_vert(nchart, e1); + p_split_vert(nchart, e2); + p_split_vert(nchart, e3); + + f = nextf; + } + + return charts; +} + +static void p_face_backup_uvs(PFace *f) +{ + PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next; + + e1->old_uv[0] = e1->orig_uv[0]; + e1->old_uv[1] = e1->orig_uv[1]; + e2->old_uv[0] = e2->orig_uv[0]; + e2->old_uv[1] = e2->orig_uv[1]; + e3->old_uv[0] = e3->orig_uv[0]; + e3->old_uv[1] = e3->orig_uv[1]; +} + +static void p_face_restore_uvs(PFace *f) +{ + PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next; + + e1->orig_uv[0] = e1->old_uv[0]; + e1->orig_uv[1] = e1->old_uv[1]; + e2->orig_uv[0] = e2->old_uv[0]; + e2->orig_uv[1] = e2->old_uv[1]; + e3->orig_uv[0] = e3->old_uv[0]; + e3->orig_uv[1] = e3->old_uv[1]; +} + +static PFace *p_face_add(PChart *chart, ParamKey key, ParamKey *vkeys, + float *co[3], float *uv[3], int i1, int i2, int i3, + ParamBool *pin, ParamBool *select) +{ + PFace *f; + PEdge *e1, *e2, *e3; + + /* allocate */ + f = (PFace*)BLI_memarena_alloc(chart->handle->arena, sizeof *f); + + e1 = (PEdge*)BLI_memarena_alloc(chart->handle->arena, sizeof *e1); + e2 = (PEdge*)BLI_memarena_alloc(chart->handle->arena, sizeof *e2); + e3 = (PEdge*)BLI_memarena_alloc(chart->handle->arena, sizeof *e3); + + /* set up edges */ + f->edge = e1; + e1->face = e2->face = e3->face = f; + + e1->next = e2; + e2->next = e3; + e3->next = e1; + + if (co && uv) { + e1->vert = p_vert_lookup(chart, vkeys[i1], co[i1], e1); + e2->vert = p_vert_lookup(chart, vkeys[i2], co[i2], e2); + e3->vert = p_vert_lookup(chart, vkeys[i3], co[i3], e3); + + e1->orig_uv = uv[i1]; + e2->orig_uv = uv[i2]; + e3->orig_uv = uv[i3]; + } + else { + /* internal call to add face */ + e1->vert = e2->vert = e3->vert = NULL; + e1->orig_uv = e2->orig_uv = e3->orig_uv = NULL; + } + + if (pin) { + if (pin[i1]) e1->flag |= PEDGE_PIN; + if (pin[i2]) e2->flag |= PEDGE_PIN; + if (pin[i3]) e3->flag |= PEDGE_PIN; + } + + if (select) { + if (select[i1]) e1->flag |= PEDGE_SELECT; + if (select[i2]) e2->flag |= PEDGE_SELECT; + if (select[i3]) e3->flag |= PEDGE_SELECT; + } + + /* insert into hash */ + f->link.key = key; + phash_insert(chart->faces, (PHashLink*)f); + + e1->link.key = vkeys[i1]^vkeys[i2]; + e2->link.key = vkeys[i2]^vkeys[i3]; + e3->link.key = vkeys[i3]^vkeys[i1]; + + phash_insert(chart->edges, (PHashLink*)e1); + phash_insert(chart->edges, (PHashLink*)e2); + phash_insert(chart->edges, (PHashLink*)e3); + + return f; +} + +static PBool p_quad_split_direction(float **co) +{ + float a1, a2; + + a1 = p_vec_angle_cos(co[0], co[1], co[2]); + a1 += p_vec_angle_cos(co[1], co[0], co[2]); + a1 += p_vec_angle_cos(co[2], co[0], co[1]); + + a2 = p_vec_angle_cos(co[0], co[1], co[3]); + a2 += p_vec_angle_cos(co[1], co[0], co[3]); + a2 += p_vec_angle_cos(co[3], co[0], co[1]); + + return (a1 > a2); +} + +static float p_edge_length(PEdge *e) +{ + PVert *v1 = e->vert, *v2 = e->next->vert; + float d[3]; + + d[0] = v2->co[0] - v1->co[0]; + d[1] = v2->co[1] - v1->co[1]; + d[2] = v2->co[2] - v1->co[2]; + + return sqrt(d[0]*d[0] + d[1]*d[1] + d[2]*d[2]); +} + +static float p_edge_uv_length(PEdge *e) +{ + PVert *v1 = e->vert, *v2 = e->next->vert; + float d[3]; + + d[0] = v2->uv[0] - v1->uv[0]; + d[1] = v2->uv[1] - v1->uv[1]; + + return sqrt(d[0]*d[0] + d[1]*d[1]); +} + +void p_chart_uv_bbox(PChart *chart, float *minv, float *maxv) +{ + PVert *v; + + INIT_MINMAX2(minv, maxv); + + for (v=(PVert*)chart->verts->first; v; v=v->link.next) { + DO_MINMAX2(v->uv, minv, maxv); + } +} + +static void p_chart_uv_scale(PChart *chart, float scale) +{ + PVert *v; + + for (v=(PVert*)chart->verts->first; v; v=v->link.next) { + v->uv[0] *= scale; + v->uv[1] *= scale; + } +} + +static void p_chart_uv_translate(PChart *chart, float trans[2]) +{ + PVert *v; + + for (v=(PVert*)chart->verts->first; v; v=v->link.next) { + v->uv[0] += trans[0]; + v->uv[1] += trans[1]; + } +} + +static void p_chart_boundaries(PChart *chart, int *nboundaries, PEdge **outer) +{ + PEdge *e, *be; + float len, maxlen = -1.0; + + *nboundaries = 0; + *outer = NULL; + + for (e=(PEdge*)chart->edges->first; e; e=e->link.next) { + if (e->pair || (e->flag & PEDGE_DONE)) + continue; + + (*nboundaries)++; + len = 0.0f; + + be = e; + do { + be->flag |= PEDGE_DONE; + len += p_edge_length(be); + be = be->next->vert->edge; + } while(be != e); + + if (len > maxlen) { + *outer = e; + maxlen = len; + } + } + + for (e=(PEdge*)chart->edges->first; e; e=e->link.next) + e->flag &= ~PEDGE_DONE; +} + +static float p_edge_boundary_angle(PEdge *e) +{ + PEdge *we; + PVert *v, *v1, *v2; + float angle; + int n = 0; + + v = e->vert; + + /* concave angle check -- could be better */ + angle = M_PI; + + we = v->edge; + do { + v1 = we->next->vert; + v2 = we->next->next->vert; + angle -= p_vec_angle(v1->co, v->co, v2->co); + + we = we->next->next->pair; + n++; + } while (we && (we != v->edge)); + + return angle; +} + +static PEdge *p_boundary_edge_next(PEdge *e) +{ + return e->next->vert->edge; +} + +static PEdge *p_boundary_edge_prev(PEdge *e) +{ + PEdge *we = e, *last; + + do { + last = we; + we = p_wheel_edge_next(we); + } while (we && (we != e)); + + return last->next->next; +} + +static void p_chart_fill_boundary(PChart *chart, PEdge *be, int nedges) +{ + PEdge *e, *e1, *e2; + PHashKey vkeys[3]; + PFace *f; + struct PHeap *heap = pheap_new(nedges); + float angle; + + e = be; + do { + angle = p_edge_boundary_angle(e); + e->u.heaplink = pheap_insert(heap, angle, e); + + e = e->next->vert->edge; + } while(e != be); + + if (nedges == 2) { + /* no real boundary, but an isolated seam */ + e = be->next->vert->edge; + e->pair = be; + be->pair = e; + + pheap_remove(heap, e->u.heaplink); + pheap_remove(heap, be->u.heaplink); + } + else { + while (nedges > 2) { + PEdge *ne, *ne1, *ne2; + + e = pheap_popmin(heap); + + e1 = p_boundary_edge_prev(e); + e2 = p_boundary_edge_next(e); + + pheap_remove(heap, e1->u.heaplink); + pheap_remove(heap, e2->u.heaplink); + e->u.heaplink = e1->u.heaplink = e2->u.heaplink = NULL; + + e->flag |= PEDGE_FILLED; + e1->flag |= PEDGE_FILLED; + + vkeys[0] = e->vert->link.key; + vkeys[1] = e1->vert->link.key; + vkeys[2] = e2->vert->link.key; + + f = p_face_add(chart, -1, vkeys, NULL, NULL, 0, 1, 2, NULL, NULL); + f->flag |= PFACE_FILLED; + + ne = f->edge->next->next; + ne1 = f->edge; + ne2 = f->edge->next; + + ne->flag = ne1->flag = ne2->flag = PEDGE_FILLED; + + e->pair = ne; + ne->pair = e; + e1->pair = ne1; + ne1->pair = e1; + + ne->vert = e2->vert; + ne1->vert = e->vert; + ne2->vert = e1->vert; + + if (nedges == 3) { + e2->pair = ne2; + ne2->pair = e2; + } + else { + ne2->vert->edge = ne2; + + ne2->u.heaplink = pheap_insert(heap, p_edge_boundary_angle(ne2), ne2); + e2->u.heaplink = pheap_insert(heap, p_edge_boundary_angle(e2), e2); + } + + nedges--; + } + } + + pheap_delete(heap); +} + +static void p_chart_fill_boundaries(PChart *chart, PEdge *outer) +{ + PEdge *e, *enext, *be; + int nedges; + + for (e=(PEdge*)chart->edges->first; e; e=e->link.next) { + enext = e->link.next; + + if (e->pair || (e->flag & PEDGE_FILLED)) + continue; + + nedges = 0; + be = e; + do { + be->flag |= PEDGE_FILLED; + be = be->next->vert->edge; + nedges++; + } while(be != e); + + if (e != outer) + p_chart_fill_boundary(chart, e, nedges); + } +} + +static void p_flush_uvs(PChart *chart) +{ + PEdge *e; + + for (e=(PEdge*)chart->edges->first; e; e=e->link.next) { + if (e->orig_uv) { + e->orig_uv[0] = e->vert->uv[0]; + e->orig_uv[1] = e->vert->uv[1]; + } + } +} + +static void p_flush_uvs_blend(PChart *chart, float blend) +{ + PEdge *e; + float invblend = 1.0f - blend; + + for (e=(PEdge*)chart->edges->first; e; e=e->link.next) { + if (e->orig_uv) { + e->orig_uv[0] = blend*e->old_uv[0] + invblend*e->vert->uv[0]; + e->orig_uv[1] = blend*e->old_uv[1] + invblend*e->vert->uv[1]; + } + } +} + +/* Exported */ + +ParamHandle *param_construct_begin() +{ + PHandle *handle = MEM_callocN(sizeof*handle, "PHandle"); + handle->construction_chart = p_chart_new(handle); + handle->state = PHANDLE_STATE_ALLOCATED; + handle->arena = BLI_memarena_new((1<<16)); + + return (ParamHandle*)handle; +} + +void param_delete(ParamHandle *handle) +{ + PHandle *phandle = (PHandle*)handle; + int i; + + param_assert((phandle->state == PHANDLE_STATE_ALLOCATED) || + (phandle->state == PHANDLE_STATE_CONSTRUCTED)); + + for (i = 0; i < phandle->ncharts; i++) + p_chart_delete(phandle->charts[i]); + + if (phandle->charts) + MEM_freeN(phandle->charts); + + if (phandle->construction_chart) + p_chart_delete(phandle->construction_chart); + + BLI_memarena_free(phandle->arena); + MEM_freeN(phandle); +} + +void param_face_add(ParamHandle *handle, ParamKey key, int nverts, + ParamKey *vkeys, float **co, float **uv, + ParamBool *pin, ParamBool *select) +{ + PHandle *phandle = (PHandle*)handle; + PChart *chart = phandle->construction_chart; + + param_assert(phash_lookup(chart->faces, key) == NULL); + param_assert(phandle->state == PHANDLE_STATE_ALLOCATED); + param_assert((nverts == 3) || (nverts == 4)); + + if (nverts == 4) { + if (!p_quad_split_direction(co)) { + p_face_add(chart, key, vkeys, co, uv, 0, 1, 2, pin, select); + p_face_add(chart, key, vkeys, co, uv, 0, 2, 3, pin, select); + } + else { + p_face_add(chart, key, vkeys, co, uv, 0, 1, 3, pin, select); + p_face_add(chart, key, vkeys, co, uv, 1, 2, 3, pin, select); + } + } + else + p_face_add(chart, key, vkeys, co, uv, 0, 1, 2, pin, select); +} + +void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys) +{ + PHandle *phandle = (PHandle*)handle; + PChart *chart = phandle->construction_chart; + PEdge *e; + + param_assert(phandle->state == PHANDLE_STATE_ALLOCATED); + + e = p_edge_lookup(chart, vkeys); + if (e) + e->flag |= PEDGE_SEAM; +} + +void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool impl) +{ + PHandle *phandle = (PHandle*)handle; + PChart *chart = phandle->construction_chart; + int i, j, nboundaries = 0; + PEdge *outer; + + param_assert(phandle->state == PHANDLE_STATE_ALLOCATED); + + phandle->ncharts = p_connect_pairs(chart, impl); + phandle->charts = p_split_charts(phandle, chart, phandle->ncharts); + + p_chart_delete(chart); + phandle->construction_chart = NULL; + + for (i = j = 0; i < phandle->ncharts; i++) { + p_chart_boundaries(phandle->charts[i], &nboundaries, &outer); + + if (nboundaries == 0) { + p_chart_delete(phandle->charts[i]); + continue; + } + + phandle->charts[j] = phandle->charts[i]; + j++; + +#if 0 + if (fill && (nboundaries > 1)) + p_chart_fill_boundaries(phandle->charts[i], outer); +#endif + } + + phandle->ncharts = j; + + phandle->state = PHANDLE_STATE_CONSTRUCTED; +} + +/* Least Squares Conformal Maps */ + +static void p_chart_lscm_load_solution(PChart *chart) +{ + PVert *v; + + for (v=(PVert*)chart->verts->first; v; v=v->link.next) { + v->uv[0] = nlGetVariable(2*v->u.index); + v->uv[1] = nlGetVariable(2*v->u.index + 1); + } +} + +static void p_chart_lscm_begin(PChart *chart, PBool live) +{ + PVert *v, *pin1, *pin2; + PBool select = P_FALSE; + int npins = 0, id = 0; + + /* give vertices matrix indices and count pins */ + for (v=(PVert*)chart->verts->first; v; v=v->link.next) { + p_vert_load_pin_select_uvs(v); + + if (v->flag & PVERT_PIN) + npins++; + + if (v->flag & PVERT_SELECT) + select = P_TRUE; + + v->u.index = id++; + } + + if ((live && !select) || (npins == 1)) { + chart->u.lscm.context = NULL; + } + else { + if (npins <= 1) { + /* not enough pins, lets find some ourself */ + p_extrema_verts(chart, &pin1, &pin2); + + chart->u.lscm.pin1 = pin1; + chart->u.lscm.pin2 = pin2; + } + else { + chart->flag |= PCHART_NOPACK; + } + + nlNewContext(); + nlSolverParameteri(NL_NB_VARIABLES, 2*phash_size(chart->verts)); + nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); + + chart->u.lscm.context = nlGetCurrent(); + } +} + +static PBool p_chart_lscm_solve(PChart *chart) +{ + PVert *v, *pin1 = chart->u.lscm.pin1, *pin2 = chart->u.lscm.pin2; + PFace *f; + + nlMakeCurrent(chart->u.lscm.context); + + nlBegin(NL_SYSTEM); + + for (v=(PVert*)chart->verts->first; v; v=v->link.next) + if (v->flag & PVERT_PIN) + p_vert_load_pin_select_uvs(v); + + if (chart->u.lscm.pin1) { + nlLockVariable(2*pin1->u.index); + nlLockVariable(2*pin1->u.index + 1); + nlLockVariable(2*pin2->u.index); + nlLockVariable(2*pin2->u.index + 1); + + nlSetVariable(2*pin1->u.index, pin1->uv[0]); + nlSetVariable(2*pin1->u.index + 1, pin1->uv[1]); + nlSetVariable(2*pin2->u.index, pin2->uv[0]); + nlSetVariable(2*pin2->u.index + 1, pin2->uv[1]); + } + else { + /* set and lock the pins */ + for (v=(PVert*)chart->verts->first; v; v=v->link.next) { + if (v->flag & PVERT_PIN) { + nlLockVariable(2*v->u.index); + nlLockVariable(2*v->u.index + 1); + + nlSetVariable(2*v->u.index, v->uv[0]); + nlSetVariable(2*v->u.index + 1, v->uv[1]); + } + } + } + + /* construct matrix */ + + nlBegin(NL_MATRIX); + + for (f=(PFace*)chart->faces->first; f; f=f->link.next) { + PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next; + PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert; + float a1, a2, a3, ratio, cosine, sine; + float sina1, sina2, sina3, sinmax; + + if (chart->u.lscm.abf_alpha) { + /* use abf angles if passed on */ + a1 = *(chart->u.lscm.abf_alpha++); + a2 = *(chart->u.lscm.abf_alpha++); + a3 = *(chart->u.lscm.abf_alpha++); + } + else + p_face_angles(f, &a1, &a2, &a3); + + sina1 = sin(a1); + sina2 = sin(a2); + sina3 = sin(a3); + + sinmax = MAX3(sina1, sina2, sina3); + + /* shift vertices to find most stable order */ + #define SHIFT3(type, a, b, c) \ + { type tmp; tmp = a; a = c; c = b; b = tmp; } + + if (sina3 != sinmax) { + SHIFT3(PVert*, v1, v2, v3); + SHIFT3(float, a1, a2, a3); + SHIFT3(float, sina1, sina2, sina3); + + if (sina2 == sinmax) { + SHIFT3(PVert*, v1, v2, v3); + SHIFT3(float, a1, a2, a3); + SHIFT3(float, sina1, sina2, sina3); + } + } + + /* angle based lscm formulation */ + ratio = (sina3 == 0.0f)? 0.0f: sina2/sina3; + cosine = cos(a1)*ratio; + sine = sina1*ratio; + + nlBegin(NL_ROW); + nlCoefficient(2*v1->u.index, cosine - 1.0); + nlCoefficient(2*v1->u.index+1, -sine); + nlCoefficient(2*v2->u.index, -cosine); + nlCoefficient(2*v2->u.index+1, sine); + nlCoefficient(2*v3->u.index, 1.0); + nlEnd(NL_ROW); + + nlBegin(NL_ROW); + nlCoefficient(2*v1->u.index, sine); + nlCoefficient(2*v1->u.index+1, cosine - 1.0); + nlCoefficient(2*v2->u.index, -sine); + nlCoefficient(2*v2->u.index+1, -cosine); + nlCoefficient(2*v3->u.index+1, 1.0); + nlEnd(NL_ROW); + } + + nlEnd(NL_MATRIX); + + nlEnd(NL_SYSTEM); + + if (nlSolveAdvanced(NULL, NL_TRUE)) { + p_chart_lscm_load_solution(chart); + return P_TRUE; + } + + return P_FALSE; +} + +static void p_chart_lscm_end(PChart *chart) +{ + if (chart->u.lscm.context) + nlDeleteContext(chart->u.lscm.context); + + chart->u.lscm.context = NULL; + chart->u.lscm.pin1 = NULL; + chart->u.lscm.pin2 = NULL; +} + +void param_lscm_begin(ParamHandle *handle, ParamBool live) +{ + PHandle *phandle = (PHandle*)handle; + int i; + + param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED); + phandle->state = PHANDLE_STATE_LSCM; + + for (i = 0; i < phandle->ncharts; i++) + p_chart_lscm_begin(phandle->charts[i], live); +} + +void param_lscm_solve(ParamHandle *handle) +{ + PHandle *phandle = (PHandle*)handle; + PChart *chart; + int i; + PBool result; + + param_assert(phandle->state == PHANDLE_STATE_LSCM); + + for (i = 0; i < phandle->ncharts; i++) { + chart = phandle->charts[i]; + + if (chart->u.lscm.context) { + result = p_chart_lscm_solve(chart); + + if (!result || (chart->u.lscm.pin1)) + p_chart_lscm_end(chart); + } + } +} + +void param_lscm_end(ParamHandle *handle) +{ + PHandle *phandle = (PHandle*)handle; + int i; + + param_assert(phandle->state == PHANDLE_STATE_LSCM); + + for (i = 0; i < phandle->ncharts; i++) + p_chart_lscm_end(phandle->charts[i]); + + phandle->state = PHANDLE_STATE_CONSTRUCTED; +} + +/* Stretch */ + +#define P_STRETCH_ITER 20 + +static void p_stretch_pin_boundary(PChart *chart) +{ + PVert *v; + + for(v=(PVert*)chart->verts->first; v; v=v->link.next) + if (v->edge->pair == NULL) + v->flag |= PVERT_PIN; + else + v->flag &= ~PVERT_PIN; +} + +static float p_face_stretch(PFace *f) +{ + float T, w, tmp[3]; + float Ps[3], Pt[3]; + float a, c, area; + PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next; + PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert; + + area = p_face_uv_area_signed(f); + + if (area <= 0.0f) /* flipped face -> infinite stretch */ + return 1e10f; + + if (f->flag & PFACE_FILLED) + return 0.0f; + + w= 1.0f/(2.0f*area); + + /* compute derivatives */ + VecCopyf(Ps, v1->co); + VecMulf(Ps, (v2->uv[1] - v3->uv[1])); + + VecCopyf(tmp, v2->co); + VecMulf(tmp, (v3->uv[1] - v1->uv[1])); + VecAddf(Ps, Ps, tmp); + + VecCopyf(tmp, v3->co); + VecMulf(tmp, (v1->uv[1] - v2->uv[1])); + VecAddf(Ps, Ps, tmp); + + VecMulf(Ps, w); + + VecCopyf(Pt, v1->co); + VecMulf(Pt, (v3->uv[0] - v2->uv[0])); + + VecCopyf(tmp, v2->co); + VecMulf(tmp, (v1->uv[0] - v3->uv[0])); + VecAddf(Pt, Pt, tmp); + + VecCopyf(tmp, v3->co); + VecMulf(tmp, (v2->uv[0] - v1->uv[0])); + VecAddf(Pt, Pt, tmp); + + VecMulf(Pt, w); + + /* Sander Tensor */ + a= Inpf(Ps, Ps); + c= Inpf(Pt, Pt); + + T = sqrt(0.5f*(a + c)*f->u.area3d); + + return T; +} + +static float p_stretch_compute_vertex(PVert *v) +{ + PEdge *e = v->edge; + float sum = 0.0f; + + do { + sum += p_face_stretch(e->face); + e = p_wheel_edge_next(e); + } while (e && e != (v->edge)); + + return sum; +} + +static void p_chart_stretch_minimize(PChart *chart, RNG *rng) +{ + PVert *v; + PEdge *e; + int j, nedges; + float orig_stretch, low, stretch_low, high, stretch_high, mid, stretch; + float orig_uv[2], dir[2], random_angle, trusted_radius; + + for(v=(PVert*)chart->verts->first; v; v=v->link.next) { + if((v->flag & PVERT_PIN) || !(v->flag & PVERT_SELECT)) + continue; + + orig_stretch = p_stretch_compute_vertex(v); + orig_uv[0] = v->uv[0]; + orig_uv[1] = v->uv[1]; + + /* move vertex in a random direction */ + trusted_radius = 0.0f; + nedges = 0; + e = v->edge; + + do { + trusted_radius += p_edge_uv_length(e); + nedges++; + + e = p_wheel_edge_next(e); + } while (e && e != (v->edge)); + + trusted_radius /= 2 * nedges; + + random_angle = rng_getFloat(rng) * 2.0 * M_PI; + dir[0] = trusted_radius * cos(random_angle); + dir[1] = trusted_radius * sin(random_angle); + + /* calculate old and new stretch */ + low = 0; + stretch_low = orig_stretch; + + Vec2Addf(v->uv, orig_uv, dir); + high = 1; + stretch = stretch_high = p_stretch_compute_vertex(v); + + /* binary search for lowest stretch position */ + for (j = 0; j < P_STRETCH_ITER; j++) { + mid = 0.5 * (low + high); + v->uv[0]= orig_uv[0] + mid*dir[0]; + v->uv[1]= orig_uv[1] + mid*dir[1]; + stretch = p_stretch_compute_vertex(v); + + if (stretch_low < stretch_high) { + high = mid; + stretch_high = stretch; + } + else { + low = mid; + stretch_low = stretch; + } + } + + /* no luck, stretch has increased, reset to old values */ + if(stretch >= orig_stretch) + Vec2Copyf(v->uv, orig_uv); + } +} + +void param_stretch_begin(ParamHandle *handle) +{ + PHandle *phandle = (PHandle*)handle; + PChart *chart; + PVert *v; + PFace *f; + int i; + + param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED); + phandle->state = PHANDLE_STATE_STRETCH; + + phandle->rng = rng_new(31415926); + phandle->blend = 0.0f; + + for (i = 0; i < phandle->ncharts; i++) { + chart = phandle->charts[i]; + + for (v=(PVert*)chart->verts->first; v; v=v->link.next) + p_vert_load_select_uvs(v); + + p_stretch_pin_boundary(chart); + + for (f=(PFace*)chart->faces->first; f; f=f->link.next) { + p_face_backup_uvs(f); + f->u.area3d = p_face_area(f); + } + } +} + +void param_stretch_blend(ParamHandle *handle, float blend) +{ + PHandle *phandle = (PHandle*)handle; + + param_assert(phandle->state == PHANDLE_STATE_STRETCH); + phandle->blend = blend; +} + +void param_stretch_iter(ParamHandle *handle) +{ + PHandle *phandle = (PHandle*)handle; + PChart *chart; + int i; + + param_assert(phandle->state == PHANDLE_STATE_STRETCH); + + for (i = 0; i < phandle->ncharts; i++) { + chart = phandle->charts[i]; + p_chart_stretch_minimize(chart, phandle->rng); + } +} + +void param_stretch_end(ParamHandle *handle) +{ + PHandle *phandle = (PHandle*)handle; + + param_assert(phandle->state == PHANDLE_STATE_STRETCH); + phandle->state = PHANDLE_STATE_CONSTRUCTED; + + rng_free(phandle->rng); + phandle->rng = NULL; +} + +/* Flushing */ + +void param_flush(ParamHandle *handle) +{ + PHandle *phandle = (PHandle*)handle; + PChart *chart; + int i; + + for (i = 0; i < phandle->ncharts; i++) { + chart = phandle->charts[i]; + + if ((phandle->state == PHANDLE_STATE_LSCM) && !chart->u.lscm.context) + continue; + + if (phandle->blend == 0.0f) + p_flush_uvs(chart); + else + p_flush_uvs_blend(chart, phandle->blend); + } +} + +void param_flush_restore(ParamHandle *handle) +{ + PHandle *phandle = (PHandle*)handle; + PChart *chart; + PFace *f; + int i; + + for (i = 0; i < phandle->ncharts; i++) { + chart = phandle->charts[i]; + + for (f=(PFace*)chart->faces->first; f; f=f->link.next) + p_face_restore_uvs(f); + } +} + +/* Packing */ + +static int compare_chart_area(const void *a, const void *b) +{ + PChart *ca = *((PChart**)a); + PChart *cb = *((PChart**)b); + + if (ca->u.pack.area > cb->u.pack.area) + return -1; + else if (ca->u.pack.area == cb->u.pack.area) + return 0; + else + return 1; +} + +static PBool p_pack_try(PHandle *handle, float side) +{ + PChart *chart; + float packx, packy, rowh, groupw, w, h; + int i; + + packx= packy= 0.0; + rowh= 0.0; + groupw= 1.0/sqrt(handle->ncharts); + + for (i = 0; i < handle->ncharts; i++) { + chart = handle->charts[i]; + + if (chart->flag & PCHART_NOPACK) + continue; + + w = chart->u.pack.size[0]; + h = chart->u.pack.size[1]; + + if(w <= (side-packx)) { + chart->u.pack.trans[0] = packx; + chart->u.pack.trans[1] = packy; + + packx += w; + rowh= MAX2(rowh, h); + } + else { + packy += rowh; + packx = w; + rowh = h; + + chart->u.pack.trans[0] = 0.0; + chart->u.pack.trans[1] = packy; + } + + if (packy+rowh > side) + return P_FALSE; + } + + return P_TRUE; +} + +#define PACK_SEARCH_DEPTH 15 + +void param_pack(ParamHandle *handle) +{ + PHandle *phandle = (PHandle*)handle; + PChart *chart; + float uv_area, area, trans[2], minside, maxside, totarea, side; + int i; + + /* very simple rectangle packing */ + + if (phandle->ncharts == 0) + return; + + totarea = 0.0f; + maxside = 0.0f; + + for (i = 0; i < phandle->ncharts; i++) { + chart = phandle->charts[i]; + + if (chart->flag & PCHART_NOPACK) { + chart->u.pack.area = 0.0f; + continue; + } + + p_chart_area(chart, &uv_area, &area); + p_chart_uv_bbox(chart, trans, chart->u.pack.size); + + /* translate to origin and make area equal to 3d area */ + chart->u.pack.rescale = (uv_area > 0.0f)? sqrt(area)/sqrt(uv_area): 0.0f; + chart->u.pack.area = area; + totarea += area; + + trans[0] = -trans[0]; + trans[1] = -trans[1]; + p_chart_uv_translate(chart, trans); + p_chart_uv_scale(chart, chart->u.pack.rescale); + + /* compute new dimensions for packing */ + chart->u.pack.size[0] += trans[0]; + chart->u.pack.size[1] += trans[1]; + chart->u.pack.size[0] *= chart->u.pack.rescale; + chart->u.pack.size[1] *= chart->u.pack.rescale; + + maxside = MAX3(maxside, chart->u.pack.size[0], chart->u.pack.size[1]); + } + + /* sort by chart area, largest first */ + qsort(phandle->charts, phandle->ncharts, sizeof(PChart*), compare_chart_area); + + /* binary search over pack region size */ + minside = MAX2(sqrt(totarea), maxside); + maxside = (((int)sqrt(phandle->ncharts-1))+1)*maxside; + + if (minside < maxside) { /* should always be true */ + + for (i = 0; i < PACK_SEARCH_DEPTH; i++) { + if (p_pack_try(phandle, (minside+maxside)*0.5f + 1e-5)) + maxside = (minside+maxside)*0.5f; + else + minside = (minside+maxside)*0.5f; + } + } + + /* do the actual packing */ + side = maxside + 1e-5; + if (!p_pack_try(phandle, side)) + param_warning("packing failed.\n"); + + for (i = 0; i < phandle->ncharts; i++) { + chart = phandle->charts[i]; + + if (chart->flag & PCHART_NOPACK) + continue; + + p_chart_uv_scale(chart, 1.0f/side); + trans[0] = chart->u.pack.trans[0]/side; + trans[1] = chart->u.pack.trans[1]/side; + p_chart_uv_translate(chart, trans); + } +} + diff --git a/source/blender/src/parametrizer.h b/source/blender/src/parametrizer.h new file mode 100644 index 00000000000..38bad0e6092 --- /dev/null +++ b/source/blender/src/parametrizer.h @@ -0,0 +1,80 @@ + +#ifndef __PARAMETRIZER_H__ +#define __PARAMETRIZER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void ParamHandle; /* handle to a set of charts */ +typedef long ParamKey; /* (hash) key for identifying verts and faces */ +typedef enum ParamBool { + PARAM_TRUE = 1, + PARAM_FALSE = 0 +} ParamBool; + +/* Chart construction: + ------------------- + - faces and seams may only be added between construct_{begin|end} + - the pointers to co and uv are stored, rather than being copied + - vertices are implicitly created + - in construct_end the mesh will be split up according to the seams + - the resulting charts must be: + - manifold, connected, open (at least one boundary loop) + - output will be written to the uv pointers +*/ + +ParamHandle *param_construct_begin(); + +void param_face_add(ParamHandle *handle, + ParamKey key, + int nverts, + ParamKey *vkeys, + float **co, + float **uv, + ParamBool *pin, + ParamBool *select); + +void param_edge_set_seam(ParamHandle *handle, + ParamKey *vkeys); + +void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool impl); +void param_delete(ParamHandle *chart); + +/* Least Squares Conformal Maps: + ----------------------------- + - charts with less than two pinned vertices are assigned 2 pins + - lscm is divided in three steps: + - begin: compute matrix and it's factorization (expensive) + - solve using pinned coordinates (cheap) + - end: clean up + - uv coordinates are allowed to change within begin/end, for + quick re-solving +*/ + +void param_lscm_begin(ParamHandle *handle, ParamBool live); +void param_lscm_solve(ParamHandle *handle); +void param_lscm_end(ParamHandle *handle); + +/* Stretch */ + +void param_stretch_begin(ParamHandle *handle); +void param_stretch_blend(ParamHandle *handle, float blend); +void param_stretch_iter(ParamHandle *handle); +void param_stretch_end(ParamHandle *handle); + +/* Packing */ + +void param_pack(ParamHandle *handle); + +/* Flushing */ + +void param_flush(ParamHandle *handle); +void param_flush_restore(ParamHandle *handle); + +#ifdef __cplusplus +} +#endif + +#endif /*__PARAMETRIZER_H__*/ + diff --git a/source/blender/src/parametrizer_intern.h b/source/blender/src/parametrizer_intern.h new file mode 100644 index 00000000000..f22a7e4ab66 --- /dev/null +++ b/source/blender/src/parametrizer_intern.h @@ -0,0 +1,191 @@ + +#ifndef __PARAMETRIZER_INTERN_H__ +#define __PARAMETRIZER_INTERN_H__ + +/* Hash: + ----- + - insert only + - elements are all stored in a flat linked list +*/ + +typedef long PHashKey; + +typedef struct PHashLink { + struct PHashLink *next; + PHashKey key; +} PHashLink; + +typedef struct PHash { + PHashLink *first; + PHashLink **buckets; + int size, cursize, cursize_id; +} PHash; + +PHash *phash_new(int sizehint); +void phash_delete_with_links(PHash *ph); +void phash_delete(PHash *ph); + +int phash_size(PHash *ph); + +void phash_insert(PHash *ph, PHashLink *link); +PHashLink *phash_lookup(PHash *ph, PHashKey key); +PHashLink *phash_next(PHash *ph, PHashKey key, PHashLink *link); + +#if 0 + #define param_assert(condition) + #define param_warning(message); +#else + #define param_assert(condition) \ + if (!(condition)) \ + { printf("Assertion %s:%d\n", __FILE__, __LINE__); abort(); } + #define param_warning(message) \ + { printf("Warning %s:%d: %s\n", __FILE__, __LINE__, message); } +#endif + +typedef enum PBool { + P_TRUE = 1, + P_FALSE = 0 +} PBool; + +struct PVert; +struct PEdge; +struct PFace; +struct PChart; +struct PHandle; + +/* Heap */ + +typedef struct PHeapLink { + void *ptr; + float value; + int index; +} PHeapLink; + +typedef struct PHeap { + unsigned int size; + unsigned int bufsize; + PHeapLink *links; + PHeapLink **tree; +} PHeap; + +/* Simplices */ + +typedef struct PVert { + struct PVertLink { + struct PVert *next; + PHashKey key; + } link; + + struct PEdge *edge; + float *co; + float uv[2]; + int flag; + + union PVertUnion { + int index; /* lscm matrix index */ + float distortion; /* area smoothing */ + } u; +} PVert; + +typedef struct PEdge { + struct PEdgeLink { + struct PEdge *next; + PHashKey key; + } link; + + struct PVert *vert; + struct PEdge *pair; + struct PEdge *next; + struct PFace *face; + float *orig_uv, old_uv[2]; + int flag; + + union PEdgeUnion { + PHeapLink *heaplink; + } u; +} PEdge; + +typedef struct PFace { + struct PFaceLink { + struct PFace *next; + PHashKey key; + } link; + + struct PEdge *edge; + int flag; + + union PFaceUnion { + int chart; /* chart construction */ + float area3d; /* stretch */ + } u; +} PFace; + +enum PVertFlag { + PVERT_PIN = 1, + PVERT_SELECT = 2 +}; + +enum PEdgeFlag { + PEDGE_SEAM = 1, + PEDGE_VERTEX_SPLIT = 2, + PEDGE_PIN = 4, + PEDGE_SELECT = 8, + PEDGE_DONE = 16, + PEDGE_FILLED = 32 +}; + +/* for flipping faces */ +#define PEDGE_VERTEX_FLAGS (PEDGE_PIN) + +enum PFaceFlag { + PFACE_CONNECTED = 1, + PFACE_FILLED = 2 +}; + +/* Chart */ + +typedef struct PChart { + PHash *verts; + PHash *edges; + PHash *faces; + + union PChartUnion { + struct PChartLscm { + NLContext context; + float *abf_alpha; + PVert *pin1, *pin2; + } lscm; + struct PChartPack { + float rescale, area; + float size[2], trans[2]; + } pack; + } u; + + int flag; + struct PHandle *handle; +} PChart; + +enum PChartFlag { + PCHART_NOPACK = 1 +}; + +enum PHandleState { + PHANDLE_STATE_ALLOCATED, + PHANDLE_STATE_CONSTRUCTED, + PHANDLE_STATE_LSCM, + PHANDLE_STATE_STRETCH, +}; + +typedef struct PHandle { + PChart *construction_chart; + PChart **charts; + int ncharts; + enum PHandleState state; + MemArena *arena; + PBool implicit; + RNG *rng; + float blend; +} PHandle; + +#endif /*__PARAMETRIZER_INTERN_H__*/ + diff --git a/source/blender/src/previewrender.c b/source/blender/src/previewrender.c index 5761d0af36c..3667b170270 100644 --- a/source/blender/src/previewrender.c +++ b/source/blender/src/previewrender.c @@ -1,7 +1,4 @@ -/* previewrender.c GRAPHICS - * - * maart 95 - * +/* * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** @@ -57,6 +54,7 @@ #include "render.h" #include "mydevice.h" +#include "DNA_group_types.h" #include "DNA_texture_types.h" #include "DNA_world_types.h" #include "DNA_camera_types.h" @@ -130,26 +128,26 @@ static short snijpunt(float *v1, float *v2, float *v3, float *rtlabda, float x2= t10*t21-t11*t20; deeldet= t00*x0+t01*x1+t02*x2; - if(deeldet!=0.0) { + if(deeldet!=0.0f) { m0= ray1[0]-v3[0]; m1= ray1[1]-v3[1]; m2= ray1[2]-v3[2]; det1= m0*x0+m1*x1+m2*x2; rtu= det1/deeldet; - if(rtu<=0.0) { + if(rtu<=0.0f) { det2= t00*(m1*t22-m2*t21); det2+= t01*(m2*t20-m0*t22); det2+= t02*(m0*t21-m1*t20); rtv= det2/deeldet; - if(rtv<=0.0) { - if(rtu+rtv>= -1.0) { + if(rtv<=0.0f) { + if(rtu+rtv>= -1.0f) { det3= m0*(t12*t01-t11*t02); det3+= m1*(t10*t02-t12*t00); det3+= m2*(t11*t00-t10*t01); *rtlabda= det3/deeldet; - if(*rtlabda>=0.0 && *rtlabda<=1.0) { + if(*rtlabda>=0.0f && *rtlabda<=1.0f) { return 1; } } @@ -176,7 +174,7 @@ static int rcubi[3][4]= { static int ray_previewrender(int x, int y, float *vec, float *vn) { - float scalef= 10.0/100.0; + float scalef= 10.0f/100.0f; float ray1[3], ray2[3]; float minlabda, labda; int totface= 3, hitface= -1; @@ -184,10 +182,10 @@ static int ray_previewrender(int x, int y, float *vec, float *vn) ray1[0]= ray2[0]= x*scalef; ray1[1]= ray2[1]= y*scalef; - ray1[2]= -10.0; - ray2[2]= 10.0; + ray1[2]= -10.0f; + ray2[2]= 10.0f; - minlabda= 1.0; + minlabda= 1.0f; for(a=0; a<totface; a++) { if(snijpunt( rcubev[rcubi[a][0]], rcubev[rcubi[a][1]], rcubev[rcubi[a][2]], &labda, ray1, ray2)) { if( labda < minlabda) { @@ -252,8 +250,8 @@ static void set_previewrect(int win, int xmin, int ymin, int xmax, int ymax) pr_sizex= (prerect.xmax-prerect.xmin); pr_sizey= (prerect.ymax-prerect.ymin); - pr_facx= ( pr_sizex-1.0)/PR_RECTX; - pr_facy= ( pr_sizey-1.0)/PR_RECTY; + pr_facx= ( pr_sizex-1.0f)/PR_RECTX; + pr_facy= ( pr_sizey-1.0f)/PR_RECTY; /* correction for gla draw */ prerect.xmin-= curarea->winrct.xmin; @@ -277,7 +275,7 @@ static void end_previewrect(void) glMatrixMode(GL_MODELVIEW); glPopMatrix(); - glPixelZoom(1.0, 1.0); + glPixelZoom(1.0f, 1.0f); // restore viewport / scissor which was set by glaDefine2DArea glViewport(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winx, curarea->winy); @@ -309,10 +307,10 @@ static void draw_tex_crop(Tex *tex) if(tex==0) return; if(tex->type==TEX_IMAGE) { - if(tex->cropxmin==0.0) ret++; - if(tex->cropymin==0.0) ret++; - if(tex->cropxmax==1.0) ret++; - if(tex->cropymax==1.0) ret++; + if(tex->cropxmin==0.0f) ret++; + if(tex->cropymin==0.0f) ret++; + if(tex->cropxmax==1.0f) ret++; + if(tex->cropymax==1.0f) ret++; if(ret==4) return; rct.xmin= PR_XMIN+2+tex->cropxmin*(PR_XMAX-PR_XMIN-4); @@ -405,7 +403,7 @@ static void sky_preview_pixel(float lens, int x, int y, char *rect) if(R.wrld.skytype & WO_SKYPAPER) { view[0]= (2*x)/(float)PR_RECTX; view[1]= (2*y)/(float)PR_RECTY; - view[2]= 0.0; + view[2]= 0.0f; } else { view[0]= x; @@ -425,9 +423,9 @@ static void lamp_preview_pixel(ShadeInput *shi, LampRen *la, int x, int y, char shi->co[1]= (float)y/(PR_RECTX/4); shi->co[2]= 0; - vec[0]= 0.02*x; - vec[1]= 0.02*y; - vec[2]= 0.005*PR_RECTX; + vec[0]= 0.02f*x; + vec[1]= 0.02f*y; + vec[2]= 0.005f*PR_RECTX; VECCOPY(shi->view, vec); dist= Normalise(shi->view); @@ -438,16 +436,16 @@ static void lamp_preview_pixel(ShadeInput *shi, LampRen *la, int x, int y, char if(la->mode & LA_TEXTURE) do_lamp_tex(la, vec, shi, lacol); if(la->type==LA_SUN || la->type==LA_HEMI) { - dist= 1.0; + dist= 1.0f; } else { if(la->mode & LA_QUAD) { - t= 1.0; - if(la->ld1>0.0) + t= 1.0f; + if(la->ld1>0.0f) t= la->dist/(la->dist+la->ld1*dist); - if(la->ld2>0.0) { + if(la->ld2>0.0f) { distkw= la->dist*la->dist; t= t*distkw/(t*distkw+la->ld2*dist*dist); } @@ -471,10 +469,10 @@ static void lamp_preview_pixel(ShadeInput *shi, LampRen *la, int x, int y, char } t= la->spotsi; - if(inpr<t) dist= 0.0; + if(inpr<t) dist= 0.0f; else { t= inpr-t; - if(t<la->spotbl && la->spotbl!=0.0) { + if(t<la->spotbl && la->spotbl!=0.0f) { /* soft area */ i= t/la->spotbl; t= i*i; @@ -577,9 +575,9 @@ static void previewflare(SpaceButs *sbuts, HaloRen *har, unsigned int *rect) afmy= R.afmy; rectot= R.rectot; - R.r.postmul= R.r.postgamma= R.r.postsat= 1.0; - R.r.posthue= R.r.postadd= 0.0; - R.ycor= 1.0; + R.r.postmul= R.r.postgamma= R.r.postsat= 1.0f; + R.r.posthue= R.r.postadd= 0.0f; + R.ycor= 1.0f; R.rectx= PR_RECTX; R.recty= PR_RECTY; R.afmx= PR_RECTX/2; @@ -609,11 +607,11 @@ static void previewflare(SpaceButs *sbuts, HaloRen *har, unsigned int *rect) static void texture_preview_pixel(Tex *tex, int x, int y, char *rect) { float i, v1, xsq, ysq, texvec[3]; - float tin=1.0, tr, tg, tb, ta; + float tin=1.0f, tr, tg, tb, ta; int rgbnor, tracol, skip=0; if(tex->type==TEX_IMAGE) { - v1= 1.0/PR_RECTX; + v1= 1.0f/PR_RECTX; texvec[0]= 0.5+v1*x; texvec[1]= 0.5+v1*y; @@ -622,11 +620,11 @@ static void texture_preview_pixel(Tex *tex, int x, int y, char *rect) if(tex->extend==TEX_REPEAT) { if(tex->xrepeat>1) { texvec[0] *= tex->xrepeat; - if(texvec[0]>1.0) texvec[0] -= (int)(texvec[0]); + if(texvec[0]>1.0f) texvec[0] -= (int)(texvec[0]); } if(tex->yrepeat>1) { texvec[1] *= tex->yrepeat; - if(texvec[1]>1.0) texvec[1] -= (int)(texvec[1]); + if(texvec[1]>1.0f) texvec[1] -= (int)(texvec[1]); } } else if(tex->extend==TEX_CHECKER) { @@ -647,17 +645,17 @@ static void texture_preview_pixel(Tex *tex, int x, int y, char *rect) i= 2.0*(texvec[2]); texvec[0]= (i*texvec[0]); texvec[1]= (i*texvec[1]); - texvec[2]= (-1.0+i*texvec[2]); + texvec[2]= (-1.0f+i*texvec[2]); } else { skip= 1; - tr= tg= tb= ta= 0.0; + tr= tg= tb= ta= 0.0f; } } else { skip= 1; - tr= tg= tb= ta= 0.0; + tr= tg= tb= ta= 0.0f; } } else { @@ -665,7 +663,7 @@ static void texture_preview_pixel(Tex *tex, int x, int y, char *rect) texvec[0]= v1*x; texvec[1]= v1*y; - texvec[2]= 0.0; + texvec[2]= 0.0f; } if(skip==0) rgbnor= multitex_ext(tex, texvec, &tin, &tr, &tg, &tb, &ta); @@ -680,9 +678,9 @@ static void texture_preview_pixel(Tex *tex, int x, int y, char *rect) v1= 255.0*tb; rect[2]= CLAMPIS(v1, 0, 255); - if(ta!=1.0) { + if(ta!=1.0f) { tracol= 64+100*(abs(x)>abs(y)); - tracol= (1.0-ta)*tracol; + tracol= (1.0f-ta)*tracol; rect[0]= tracol+ (rect[0]*ta) ; rect[1]= tracol+ (rect[1]*ta) ; @@ -706,24 +704,24 @@ static void refraction_prv(int *x, int *y, float *n, float index) { float dot, fac, view[3], len; - index= 1.0/index; + index= 1.0f/index; view[0]= index*(float)*x; view[1]= ((float)*y)/index; - view[2]= 20.0; + view[2]= 20.0f; len= Normalise(view); dot= view[0]*n[0] + view[1]*n[1] + view[2]*n[2]; - if(dot>0.0) { - fac= 1.0 - (1.0 - dot*dot)*index*index; - if(fac<= 0.0) return; + if(dot>0.0f) { + fac= 1.0f - (1.0f - dot*dot)*index*index; + if(fac<= 0.0f) return; fac= -dot*index + sqrt(fac); } else { - index = 1.0/index; - fac= 1.0 - (1.0 - dot*dot)*index*index; - if(fac<= 0.0) return; + index = 1.0f/index; + fac= 1.0f - (1.0f - dot*dot)*index*index; + if(fac<= 0.0f) return; fac= -dot*index - sqrt(fac); } @@ -731,157 +729,62 @@ static void refraction_prv(int *x, int *y, float *n, float index) *y= (int)(len*(index*view[1] + fac*n[1])); } - -static void shade_preview_pixel(ShadeInput *shi, float *vec, int x, int y,char *rect, int smooth) +static void shade_lamp_loop_preview(ShadeInput *shi, ShadeResult *shr, int pr_lamp) { extern float fresnel_fac(float *view, float *vn, float ior, float fac); - Material *mat; - float v1,inp, is, inprspec=0, isr=0.0, isb=0.0, isg=0.0; - float diff[3]={0.0, 0.0, 0.0}; - float lv[3], *la, alpha; - float eul[3], tmat[3][3], imat[3][3]; - int temp, a; - char tracol; - - mat= shi->mat; - + Material *mat= shi->mat; + float inp, is, inprspec=0; + float lv[3], *la; + int a; + // copy all relevant material vars, note, keep this synced with render_types.h memcpy(&shi->r, &mat->r, 23*sizeof(float)); // set special cases: shi->har= mat->har; - if((mat->mode & MA_RAYMIRROR)==0) shi->ray_mirror= 0.0; - v1= 1.0/PR_RECTX; - shi->view[0]= v1*x; - shi->view[1]= v1*y; - shi->view[2]= 1.0; - Normalise(shi->view); + if((mat->mode & MA_RAYMIRROR)==0) shi->ray_mirror= 0.0f; + memset(shr, 0, sizeof(ShadeResult)); - shi->xs= (float)x; - shi->ys= (float)y; + /* normals flipped in render for smooth... */ + if( (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0f); - shi->refcol[0]= shi->refcol[1]= shi->refcol[2]= shi->refcol[3]= 0.0; - - /* texture handling */ - if(mat->texco) { - - VECCOPY(shi->lo, vec); - - if(mat->pr_type==MA_CUBE) { - - eul[0]= (297)*M_PI/180.0; - eul[1]= 0.0; - eul[2]= (45)*M_PI/180.0; - EulToMat3(eul, tmat); - - MTC_Mat3MulVecfl(tmat, shi->lo); - MTC_Mat3MulVecfl(tmat, shi->vn); - /* hack for cubemap, why!!! */ - SWAP(float, shi->vn[0], shi->vn[1]); - } - /* textures otherwise upside down */ - if(mat->pr_type==MA_CUBE || mat->pr_type==MA_SPHERE) - shi->lo[2]= -shi->lo[2]; - - if(mat->texco & TEXCO_GLOB) { - VECCOPY(shi->gl, shi->lo); - } - if(mat->texco & TEXCO_WINDOW) { - VECCOPY(shi->winco, shi->lo); - } - if(mat->texco & TEXCO_STICKY) { - VECCOPY(shi->sticky, shi->lo); - } - if(mat->texco & TEXCO_UV) { - VECCOPY(shi->uv, shi->lo); - } - if(mat->texco & TEXCO_STRAND) { - shi->strand= shi->lo[0]; - } - if(mat->texco & TEXCO_OBJECT) { - VECCOPY(shi->co, shi->lo); - } - if(mat->texco & (TEXCO_NORM)) { - shi->orn[0]= shi->vn[0]; - shi->orn[1]= shi->vn[1]; - shi->orn[2]= shi->vn[2]; - } - if(mat->texco & TEXCO_REFL) { - - inp= -2.0*(shi->vn[0]*shi->view[0]+shi->vn[1]*shi->view[1]+shi->vn[2]*shi->view[2]); - shi->ref[0]= (shi->view[0]+inp*shi->vn[0]); - shi->ref[1]= (shi->view[1]+inp*shi->vn[1]); - shi->ref[2]= (shi->view[2]+inp*shi->vn[2]); - } - - /* Clear displase vec for preview */ - shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0; - - /* normals flipped in render for smooth... */ - if( (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0); - - do_material_tex(shi); - - /* normals flipped in render... */ - if( (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0); + do_material_tex(shi); + + /* normals flipped in render... */ + if( (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0f); + + shr->alpha= shi->alpha; - if(mat->texco & TEXCO_REFL) { - /* normals in render are pointing different... rhm */ - if(smooth) shi->ref[1]= -shi->ref[1]; - } - - if(mat->pr_type==MA_CUBE) { - /* rotate normal back for normals texture */ - SWAP(float, shi->vn[0], shi->vn[1]); - MTC_Mat3Inv(imat, tmat); - MTC_Mat3MulVecfl(imat, shi->vn); - } - - } - /* set it here, because ray_mirror will affect it */ - alpha= shi->alpha; - - if(mat->mapto & MAP_DISPLACE) { /* Quick hack of fake displacement preview */ - shi->vn[0]-=2.0*shi->displace[2]; - shi->vn[1]-=2.0*shi->displace[0]; - shi->vn[2]+=2.0*shi->displace[1]; - Normalise(shi->vn); - } - if(mat->mode & (MA_ZTRA|MA_RAYTRANSP)) - if(mat->fresnel_tra!=0.0) - alpha*= fresnel_fac(shi->view, shi->vn, mat->fresnel_tra_i, mat->fresnel_tra); - + if(mat->fresnel_tra!=0.0f) + shr->alpha*= fresnel_fac(shi->view, shi->vn, mat->fresnel_tra_i, mat->fresnel_tra); + if(mat->mode & MA_SHLESS) { - temp= 255.0*(shi->r); - if(temp>255) rect[0]= 255; else if(temp<0) rect[0]= 0; else rect[0]= temp; - - temp= 255.0*(shi->g); - if(temp>255) rect[1]= 255; else if(temp<0) rect[1]= 0; else rect[1]= temp; - - temp= 255.0*(shi->b); - if(temp>255) rect[2]= 255; else if(temp<0) rect[2]= 0; else rect[2]= temp; + shr->diff[0]= shi->r; + shr->diff[1]= shi->g; + shr->diff[2]= shi->b; + } else { for(a=0; a<2; a++) { - if((mat->pr_lamp & (1<<a))==0) continue; + if((pr_lamp & (1<<a))==0) continue; if(a==0) la= pr1_lamp; else la= pr2_lamp; - lv[0]= vec[0]-la[0]; - lv[1]= vec[1]-la[1]; - lv[2]= vec[2]-la[2]; + lv[0]= shi->co[0]-la[0]; + lv[1]= shi->co[1]-la[1]; + lv[2]= shi->co[2]-la[2]; Normalise(lv); is= shi->vn[0]*lv[0]+shi->vn[1]*lv[1]+shi->vn[2]*lv[2]; - if(is<0.0) is= 0.0; + if(is<0.0f) is= 0.0f; - if(shi->spec>0.0) { + if(shi->spec>0.0f) { - if(is>0.0) { + if(is>0.0f) { /* specular shaders */ float specfac; @@ -895,20 +798,20 @@ static void shade_preview_pixel(ShadeInput *shi, float *vec, int x, int y,char * specfac= WardIso_Spec(shi->vn, lv, shi->view, mat->rms, 0); else specfac= Toon_Spec(shi->vn, lv, shi->view, mat->param[2], mat->param[3], 0); - + inprspec= specfac*shi->spec; if(mat->mode & MA_RAMP_SPEC) { float spec[3]; do_specular_ramp(shi, specfac, inprspec, spec); - isr+= inprspec*spec[0]; - isg+= inprspec*spec[1]; - isb+= inprspec*spec[2]; + shr->spec[0]+= inprspec*spec[0]; + shr->spec[1]+= inprspec*spec[1]; + shr->spec[2]+= inprspec*spec[2]; } else { - isr+= inprspec*shi->specr; - isg+= inprspec*shi->specg; - isb+= inprspec*shi->specb; + shr->spec[0]+= inprspec*shi->specr; + shr->spec[1]+= inprspec*shi->specg; + shr->spec[2]+= inprspec*shi->specb; } } } @@ -916,18 +819,17 @@ static void shade_preview_pixel(ShadeInput *shi, float *vec, int x, int y,char * if(mat->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(shi->vn, lv, shi->view, mat->roughness); else if(mat->diff_shader==MA_DIFF_TOON) is= Toon_Diff(shi->vn, lv, shi->view, mat->param[0], mat->param[1]); else if(mat->diff_shader==MA_DIFF_MINNAERT) is= Minnaert_Diff(is, shi->vn, shi->view, mat->darkness); + else if(mat->diff_shader==MA_DIFF_FRESNEL) is= Fresnel_Diff(shi->vn, lv, shi->view, mat->param[0], mat->param[1]); // else Lambert inp= (shi->refl*is + shi->emit); if(a==0) la= pr1_col; else la= pr2_col; - - add_to_diffuse(diff, shi, is, inp*la[0], inp*la[1], inp*la[2]); - //ir+= inp*la[0]; - //ig+= inp*la[1]; - //ib+= inp*la[2]; + + add_to_diffuse(shr->diff, shi, is, inp*la[0], inp*la[1], inp*la[2]); } + /* end lamp loop */ /* drawing checkerboard and sky */ if(mat->mode & MA_RAYMIRROR) { @@ -940,93 +842,240 @@ static void shade_preview_pixel(ShadeInput *shi, float *vec, int x, int y,char * shi->ref[2]= 0.17*y + 0.98*z; /* scale */ - div= (0.85*shi->ref[1]); + div= (0.85f*shi->ref[1]); shi->refcol[0]= shi->ray_mirror*fresnel_fac(shi->view, shi->vn, mat->fresnel_mir_i, mat->fresnel_mir); /* not real 'alpha', but mirror overriding transparency */ if(mat->mode & MA_RAYTRANSP) { float fac= sqrt(shi->refcol[0]); - alpha= alpha*(1.0-fac) + fac; + shr->alpha= shr->alpha*(1.0f-fac) + fac; } - else alpha= alpha*(1.0-shi->refcol[0]) + shi->refcol[0]; + else shr->alpha= shr->alpha*(1.0f-shi->refcol[0]) + shi->refcol[0]; - if(div<0.0) { + if(div<0.0f) { /* minus 0.5 prevents too many small tiles in distance */ - fac= (int)(shi->ref[0]/(div-0.1) ) + (int)(shi->ref[2]/(div-0.1) ); - if(fac & 1) col= 0.8; - else col= 0.3; - + fac= (int)(shi->ref[0]/(div-0.1f) ) + (int)(shi->ref[2]/(div-0.1f) ); + if(fac & 1) col= 0.8f; + else col= 0.3f; + shi->refcol[1]= shi->refcol[0]*col; shi->refcol[2]= shi->refcol[1]; shi->refcol[3]= shi->refcol[2]; } else { - shi->refcol[1]= 0.0; - shi->refcol[2]= shi->refcol[0]*0.3*div; - shi->refcol[3]= shi->refcol[0]*0.8*div; + shi->refcol[1]= 0.0f; + shi->refcol[2]= shi->refcol[0]*0.3f*div; + shi->refcol[3]= shi->refcol[0]*0.8f*div; } } - if(mat->mode & MA_RAMP_COL) ramp_diffuse_result(diff, shi); - if(mat->mode & MA_RAMP_SPEC) ramp_spec_result(&isr, &isg, &isb, shi); + shr->diff[0]+= shi->ambr; + shr->diff[1]+= shi->ambg; + shr->diff[2]+= shi->ambb; - if(shi->refcol[0]==0.0) { - a= 255.0*(diff[0] +shi->ambr +isr); - if(a>255) a=255; else if(a<0) a= 0; - rect[0]= a; - a= 255.0*(diff[1] +shi->ambg +isg); - if(a>255) a=255; else if(a<0) a= 0; - rect[1]= a; - a= 255*(diff[2] +shi->ambb +isb); - if(a>255) a=255; else if(a<0) a= 0; - rect[2]= a; + if(mat->mode & MA_RAMP_COL) ramp_diffuse_result(shr->diff, shi); + if(mat->mode & MA_RAMP_SPEC) ramp_spec_result(shr->spec, shr->spec+1, shr->spec+2, shi); + + /* refcol */ + if(shi->refcol[0]!=0.0f) { + shr->diff[0]= shi->mirr*shi->refcol[1] + (1.0f - shi->mirr*shi->refcol[0])*shr->diff[0]; + shr->diff[1]= shi->mirg*shi->refcol[2] + (1.0f - shi->mirg*shi->refcol[0])*shr->diff[1]; + shr->diff[2]= shi->mirb*shi->refcol[3] + (1.0f - shi->mirb*shi->refcol[0])*shr->diff[2]; } - else { - a= 255.0*( shi->mirr*shi->refcol[1] + (1.0 - shi->mirr*shi->refcol[0])*(diff[0] +shi->ambr) +isr); - if(a>255) a=255; else if(a<0) a= 0; - rect[0]= a; - a= 255.0*( shi->mirg*shi->refcol[2] + (1.0 - shi->mirg*shi->refcol[0])*(diff[1] +shi->ambg) +isg); - if(a>255) a=255; else if(a<0) a= 0; - rect[1]= a; - a= 255.0*( shi->mirb*shi->refcol[3] + (1.0 - shi->mirb*shi->refcol[0])*(diff[2] +shi->ambb) +isb); - if(a>255) a=255; else if(a<0) a= 0; - rect[2]= a; + + /* ztra shade */ + if(shi->spectra!=0.0f) { + inp = MAX3(shr->spec[0], shr->spec[1], shr->spec[2]); + inp *= shi->spectra; + if(inp>1.0f) inp= 1.0f; + shr->alpha= (1.0f-inp)*shr->alpha+inp; } + } +} + +static void shade_preview_pixel(ShadeInput *shi, float *vec, int x, int y, char *rect, int smooth) +{ + Material *mat; + MaterialLayer *ml; + ShadeResult shr; + float v1, inp; + float eul[3], tmat[3][3], imat[3][3], col[3]; + char tracol; + + mat= shi->mat; + + v1= 1.0/PR_RECTX; + shi->view[0]= v1*x; + shi->view[1]= v1*y; + shi->view[2]= 1.0f; + Normalise(shi->view); + + shi->xs= (float)x; + shi->ys= (float)y; + + shi->refcol[0]= shi->refcol[1]= shi->refcol[2]= shi->refcol[3]= 0.0f; + VECCOPY(shi->co, vec); + + /* texture handling */ + if(mat->texco) { + + VECCOPY(shi->lo, vec); + + if(mat->pr_type==MA_CUBE) { + + eul[0]= (297)*M_PI/180.0; + eul[1]= 0.0; + eul[2]= (45)*M_PI/180.0; + EulToMat3(eul, tmat); + + MTC_Mat3MulVecfl(tmat, shi->lo); + MTC_Mat3MulVecfl(tmat, shi->vn); + /* hack for cubemap, why!!! */ + SWAP(float, shi->vn[0], shi->vn[1]); + } + /* textures otherwise upside down */ + if(mat->pr_type==MA_CUBE || mat->pr_type==MA_SPHERE) + shi->lo[2]= -shi->lo[2]; + + if(mat->texco & TEXCO_GLOB) { + VECCOPY(shi->gl, shi->lo); + } + if(mat->texco & TEXCO_WINDOW) { + VECCOPY(shi->winco, shi->lo); + } + if(mat->texco & TEXCO_STICKY) { + VECCOPY(shi->sticky, shi->lo); + } + if(mat->texco & TEXCO_UV) { + VECCOPY(shi->uv, shi->lo); + } + if(mat->texco & TEXCO_STRAND) { + shi->strand= shi->lo[0]; + } + if(mat->texco & TEXCO_OBJECT) { + /* nothing */ + } + if(mat->texco & (TEXCO_NORM)) { + shi->orn[0]= shi->vn[0]; + shi->orn[1]= shi->vn[1]; + shi->orn[2]= shi->vn[2]; + } + if(mat->texco & TEXCO_REFL) { + + inp= -2.0*(shi->vn[0]*shi->view[0]+shi->vn[1]*shi->view[1]+shi->vn[2]*shi->view[2]); + shi->ref[0]= (shi->view[0]+inp*shi->vn[0]); + shi->ref[1]= (shi->view[1]+inp*shi->vn[1]); + shi->ref[2]= (shi->view[2]+inp*shi->vn[2]); + } + + /* Clear displase vec for preview */ + shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0; + + if(mat->texco & TEXCO_REFL) { + /* normals in render are pointing different... rhm */ + if(smooth) shi->ref[1]= -shi->ref[1]; + } + + if(mat->pr_type==MA_CUBE) { + /* rotate normal back for normals texture */ + SWAP(float, shi->vn[0], shi->vn[1]); + MTC_Mat3Inv(imat, tmat); + MTC_Mat3MulVecfl(imat, shi->vn); + } + } - /* ztra shade */ - if(shi->spectra!=0.0) { - inp = MAX3(isr, isg, isb); - inp *= shi->spectra; - if(inp>1.0) inp= 1.0; - alpha= (1.0-inp)*alpha+inp; + if(mat->mapto & MAP_DISPLACE) { /* Quick hack of fake displacement preview */ +// shi->vn[0]-=2.0*shi->displace[2]; +// shi->vn[1]-=2.0*shi->displace[0]; +// shi->vn[2]+=2.0*shi->displace[1]; +// Normalise(shi->vn); + } + + /* ------ main shading loop with material layers */ + VECCOPY(shi->vno, shi->vn); + if(mat->ml_flag & ML_RENDER) + shade_lamp_loop_preview(shi, &shr, mat->pr_lamp); + else { + memset(&shr, 0, sizeof(ShadeResult)); + shr.alpha= 1.0f; + } + + for(ml= mat->layers.first; ml; ml= ml->next) { + if(ml->mat && (ml->flag & ML_RENDER)) { + ShadeResult shrlay; + + shi->mat= ml->mat; + shi->layerfac= ml->blendfac; + VECCOPY(shi->vn, shi->vno); + if(ml->flag & ML_NEG_NORMAL) + VecMulf(shi->vn, -1.0); + + shade_lamp_loop_preview(shi, &shrlay, mat->pr_lamp); + matlayer_blend(ml, shi->layerfac, &shr, &shrlay); + } } - if(alpha!=1.0) { + shi->mat= mat; /* restore, shade input is re-used! */ + + /* after shading and composit layers */ + if(shr.spec[0]<0.0f) shr.spec[0]= 0.0f; + if(shr.spec[1]<0.0f) shr.spec[1]= 0.0f; + if(shr.spec[2]<0.0f) shr.spec[2]= 0.0f; + + if(shr.diff[0]<0.0f) shr.diff[0]= 0.0f; + if(shr.diff[1]<0.0f) shr.diff[1]= 0.0f; + if(shr.diff[2]<0.0f) shr.diff[2]= 0.0f; + + VECADD(col, shr.diff, shr.spec); + if(col[0]<=0.0f) rect[0]= 0; else if(col[0]>=1.0f) rect[0]= 255; else rect[0]= (char)(255.0*col[0]); + if(col[1]<=0.0f) rect[1]= 0; else if(col[1]>=1.0f) rect[1]= 255; else rect[1]= (char)(255.0*col[1]); + if(col[2]<=0.0f) rect[2]= 0; else if(col[2]>=1.0f) rect[2]= 255; else rect[2]= (char)(255.0*col[2]); + + if(shr.alpha!=1.0f) { if(mat->mode & MA_RAYTRANSP) { refraction_prv(&x, &y, shi->vn, shi->ang); } tracol= previewback(mat->pr_back, x, y) & 255; - tracol= (1.0-alpha)*tracol; + tracol= (1.0f-shr.alpha)*tracol; if((mat->mode & MA_RAYTRANSP) && mat->filter!=0.0) { - float fr= 1.0+ mat->filter*(shi->r-1.0); - rect[0]= fr*tracol+ (rect[0]*alpha) ; - fr= 1.0+ mat->filter*(shi->g-1.0); - rect[1]= fr*tracol+ (rect[1]*alpha) ; - fr= 1.0+ mat->filter*(shi->b-1.0); - rect[2]= fr*tracol+ (rect[2]*alpha) ; + float fr= 1.0f+ mat->filter*(shr.diff[0]-1.0f); + rect[0]= fr*tracol+ (rect[0]*shr.alpha) ; + fr= 1.0f+ mat->filter*(shr.diff[0]-1.0f); + rect[1]= fr*tracol+ (rect[1]*shr.alpha) ; + fr= 1.0f+ mat->filter*(shr.diff[0]-1.0f); + rect[2]= fr*tracol+ (rect[2]*shr.alpha) ; } else { - rect[0]= tracol+ (rect[0]*alpha) ; - rect[1]= tracol+ (rect[1]*alpha) ; - rect[2]= tracol+ (rect[2]*alpha) ; + rect[0]= tracol+ (rect[0]*shr.alpha) ; + rect[1]= tracol+ (rect[1]*shr.alpha) ; + rect[2]= tracol+ (rect[2]*shr.alpha) ; } } } +static void preview_init_render_textures(MTex **mtex) +{ + int x; + + for(x=0; x<MAX_MTEX; x++) { + if(mtex[x]) { + if(mtex[x]->tex) { + init_render_texture(mtex[x]->tex); + + if(mtex[x]->tex->env && mtex[x]->tex->env->object) + MTC_Mat4One(mtex[x]->tex->env->object->imat); + + } + if(mtex[x]->object) MTC_Mat4One(mtex[x]->object->imat); + if(mtex[x]->object) MTC_Mat4One(mtex[x]->object->imat); + } + } + +} void BIF_previewrender(SpaceButs *sbuts) { @@ -1100,27 +1149,23 @@ void BIF_previewrender(SpaceButs *sbuts) shi.osatex= 0; if(mat) { + MaterialLayer *ml; + /* rendervars */ init_render_world(); init_render_material(mat); + /* also clears imats */ + preview_init_render_textures(mat->mtex); - /* clear imats, flip normal... (hack because everything is inverted here) */ - for(x=0; x<MAX_MTEX; x++) { - if(mat->mtex[x]) { - if(mat->mtex[x]->tex) { - init_render_texture(mat->mtex[x]->tex); - - if(mat->mtex[x]->tex->env && mat->mtex[x]->tex->env->object) - MTC_Mat4One(mat->mtex[x]->tex->env->object->imat); - - mat->mtex[x]->maptoneg ^= MAP_NORM; - } - if(mat->mtex[x]->object) MTC_Mat4One(mat->mtex[x]->object->imat); - if(mat->mtex[x]->object) MTC_Mat4One(mat->mtex[x]->object->imat); + for(ml= mat->layers.first; ml; ml= ml->next) { + if(ml->mat && (ml->flag & ML_RENDER)) { + init_render_material(ml->mat); + preview_init_render_textures(ml->mat->mtex); + mat->texco |= ml->mat->texco; } } - shi.vlr= 0; + shi.vlr= NULL; shi.mat= mat; if(mat->mode & MA_HALO) init_previewhalo(&har, mat); @@ -1141,15 +1186,15 @@ void BIF_previewrender(SpaceButs *sbuts) else if(la) { init_render_world(); - init_render_textures(); /* do not do it twice!! (brightness) */ - R.totlamp= 0; + preview_init_render_textures(la->mtex); + RE_add_render_lamp(ob, 0); /* 0=no shadbuf or tables */ - lar= R.la[0]; + lar= ((GroupObject *)R.lights.first)->lampren; /* exceptions: */ - lar->spottexfac= 1.0; - lar->spotsi= cos( M_PI/3.0 ); - lar->spotbl= (1.0-lar->spotsi)*la->spotblend; + lar->spottexfac= 1.0f; + lar->spotsi= cos( M_PI/3.0f ); + lar->spotbl= (1.0f-lar->spotsi)*la->spotblend; MTC_Mat3One(lar->imat); } @@ -1165,7 +1210,7 @@ void BIF_previewrender(SpaceButs *sbuts) MTC_Mat4Invert(R.viewmat, R.viewinv); } init_render_world(); - init_render_textures(); /* dont do it twice!! (brightness) */ + preview_init_render_textures(wrld->mtex); } uiPanelPush(block); // sets UImat @@ -1258,12 +1303,12 @@ void BIF_previewrender(SpaceButs *sbuts) } } else { - vec[0]= x*(2.0/PR_RECTX); - vec[1]= y*(2.0/PR_RECTX); + vec[0]= x*(2.0f/PR_RECTX); + vec[1]= y*(2.0f/PR_RECTX); vec[2]= 0.0; - shi.vn[0]= shi.vn[1]= 0.0; - shi.vn[2]= 1.0; + shi.vn[0]= shi.vn[1]= 0.0f; + shi.vn[2]= 1.0f; shade_preview_pixel(&shi, vec, x, y, (char *)rect, 0); } @@ -1317,27 +1362,10 @@ void BIF_previewrender(SpaceButs *sbuts) uiPanelPop(block); - if(mat) { - end_render_material(mat); - for(x=0; x<MAX_MTEX; x++) { - if(mat->mtex[x] && mat->mtex[x]->tex) { - end_render_texture(mat->mtex[x]->tex); - mat->mtex[x]->maptoneg ^= MAP_NORM; - } - } - } - else if(tex) { - end_render_texture(tex); - } - else if(la) { - if(R.totlamp) { - MEM_freeN(R.la[0]); - } - R.totlamp= 0; - end_render_textures(); - } - else if(wrld) { - end_render_textures(); + if(lar) { + MEM_freeN(lar); + MEM_freeN(R.lights.first); + R.lights.first= R.lights.last= NULL; } } diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 5c07f1ba341..9228455371e 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -89,6 +89,7 @@ #include "BIF_editarmature.h" #include "BIF_editconstraint.h" #include "BIF_editfont.h" +#include "BIF_editgroup.h" #include "BIF_editkey.h" #include "BIF_editlattice.h" #include "BIF_editmesh.h" @@ -577,31 +578,10 @@ static void select_parent(void) /* Makes parent active and de-selected OBACT */ } } - -void select_group_menu(void) -{ - char *str; - short nr; - - /* make menu string */ - - str= MEM_mallocN(160, "groupmenu"); - strcpy(str, "Select Grouped%t|Children%x1|" - "Immediate Children%x2|Parent%x3|" - "Objects on Shared Layers%x4"); - - /* here we go */ - - nr= pupmenu(str); - MEM_freeN(str); - - select_group(nr); -} - -void select_group(short nr) +void select_grouped(short nr) { Base *base; - + if(nr==4) { base= FIRSTBASE; while(base) { @@ -623,6 +603,27 @@ void select_group(short nr) allqueue(REDRAWIPO, 0); } +static void select_grouped_menu(void) +{ + char *str; + short nr; + + /* make menu string */ + + str= MEM_mallocN(160, "groupmenu"); + strcpy(str, "Select Grouped%t|Children%x1|" + "Immediate Children%x2|Parent%x3|" + "Objects on Shared Layers%x4"); + + /* here we go */ + + nr= pupmenu(str); + MEM_freeN(str); + + select_grouped(nr); +} + + static unsigned short convert_for_nonumpad(unsigned short event) { if (event>=ZEROKEY && event<=NINEKEY) { @@ -1262,10 +1263,9 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case GKEY: - /* RMGRP if(G.qual & LR_CTRLKEY) add_selected_to_group(); - else if(G.qual & LR_ALTKEY) rem_selected_from_group(); */ - if((G.qual==LR_SHIFTKEY)) - select_group_menu(); + if(G.qual & LR_CTRLKEY) group_operation_with_menu(); + else if((G.qual==LR_SHIFTKEY)) + select_grouped_menu(); else if(G.qual==LR_ALTKEY) { if(okee("Clear location")) { clear_object('g'); @@ -3867,8 +3867,7 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt) sample_vpaint(); break; case AKEY: - if((G.qual==0)) - select_swap_tface_uv(); + select_swap_tface_uv(); break; case BKEY: if(G.qual==LR_SHIFTKEY) @@ -3956,6 +3955,8 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt) stitch_uv_tface(0); else if(G.qual==LR_SHIFTKEY) stitch_uv_tface(1); + else if(G.qual==LR_CTRLKEY) + minimize_stretch_tface_uv(); break; case WKEY: weld_align_menu_tface_uv(); diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 354ab917dd0..9720bdceebe 100755 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -100,6 +100,7 @@ #include "BIF_editsima.h" #include "BIF_gl.h" #include "BIF_poseobject.h" +#include "BIF_meshtools.h" #include "BIF_mywindow.h" #include "BIF_resources.h" #include "BIF_screen.h" @@ -1409,6 +1410,7 @@ static void VertsToTransData(TransData *td, EditVert *eve) td->ext = NULL; td->tdi = NULL; td->val = NULL; + td->tdmir= NULL; } static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s) @@ -1503,7 +1505,8 @@ static void createTransEditVerts(TransInfo *t) float mtx[3][3], smtx[3][3]; int count=0, countsel=0; int propmode = t->flag & T_PROP_EDIT; - + int mirror= (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR); + // transform now requires awareness for select mode, so we tag the f1 flags in verts if(G.scene->selectmode & SCE_SELECT_VERTEX) { for(eve= em->verts.first; eve; eve= eve->next) { @@ -1570,6 +1573,17 @@ static void createTransEditVerts(TransInfo *t) } } + /* find out which half we do */ + if(mirror) { + for (eve=em->verts.first; eve; eve=eve->next) { + if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) { + if(eve->co[0]<0.0f) + mirror = -1; + break; + } + } + } + for (eve=em->verts.first; eve; eve=eve->next) { if(eve->h==0) { if(propmode || eve->f1) { @@ -1604,6 +1618,12 @@ static void createTransEditVerts(TransInfo *t) Mat3CpyMat3(tob->smtx, smtx); Mat3CpyMat3(tob->mtx, mtx); } + + /* Mirror? */ + if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) { + EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc); /* initializes octree on first call */ + if(vmir!=eve) tob->tdmir= vmir; + } tob++; } } @@ -1713,6 +1733,9 @@ static void createTransUVs(TransInfo *t) UVsToTransData(td++, td2d++, tf->uv[3], (tf->flag & TF_SEL4)); } } + + if (G.sima->flag & SI_LSCM_LIVE) + unwrap_lscm_live_begin(); } void flushTransUVs(TransInfo *t) @@ -2025,6 +2048,9 @@ void special_aftertrans_update(TransInfo *t) if(G.obedit) { if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE) allqueue(REDRAWBUTSEDIT, 0); + + /* table needs to be created for each edit command, since vertices can move etc */ + mesh_octree_table(G.obedit, NULL, 'e'); } else if( (t->flag & T_POSE) && t->poseobj) { bArmature *arm; diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index 0003ce71471..d88a128cdb7 100755 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -57,6 +57,7 @@ #include "BIF_editarmature.h" #include "BIF_editmesh.h" #include "BIF_editsima.h" +#include "BIF_meshtools.h" #include "BKE_action.h" #include "BKE_anim.h" @@ -78,6 +79,7 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" +#include "BLI_editVert.h" #include "blendef.h" @@ -174,6 +176,28 @@ static void clipMirrorModifier(TransInfo *t, Object *ob) } } +/* assumes G.obedit set to mesh object */ +static void editmesh_apply_to_mirror(TransInfo *t) +{ + TransData *td = t->data; + EditVert *eve; + int i; + + for(i = 0 ; i < t->total; i++, td++) { + if (td->flag & TD_NOACTION) + break; + if (td->loc==NULL) + break; + + eve= td->tdmir; + if(eve) { + eve->co[0]= -td->loc[0]; + eve->co[1]= td->loc[1]; + eve->co[2]= td->loc[2]; + } + } +} + /* called for updating while transform acts, once per redraw */ void recalcData(TransInfo *t) { @@ -186,6 +210,9 @@ void recalcData(TransInfo *t) if(t->state != TRANS_CANCEL) clipMirrorModifier(t, G.obedit); + if(G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR) + editmesh_apply_to_mirror(t); + DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); /* sets recalc flags */ recalc_editnormals(); @@ -273,7 +300,8 @@ void recalcData(TransInfo *t) } else if(t->spacetype==SPACE_IMAGE) { flushTransUVs(t); - if (G.sima->flag & SI_LSCM_LIVE) unwrap_lscm_live(); + if (G.sima->flag & SI_LSCM_LIVE) + unwrap_lscm_live_re_solve(); } else { for(base= FIRSTBASE; base; base= base->next) { @@ -454,6 +482,11 @@ void postTrans (TransInfo *t) MEM_freeN(t->data2d); t->data2d= NULL; } + + if(t->spacetype==SPACE_IMAGE) { + if (G.sima->flag & SI_LSCM_LIVE) + unwrap_lscm_live_end(); + } } static void apply_grid3(TransInfo *t, float *val, int max_index, float fac1, float fac2, float fac3) diff --git a/source/blender/src/unwrapper.c b/source/blender/src/unwrapper.c index 045eea31625..52f3fcc77f1 100644 --- a/source/blender/src/unwrapper.c +++ b/source/blender/src/unwrapper.c @@ -43,6 +43,8 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" #include "BKE_global.h" #include "BKE_mesh.h" @@ -53,6 +55,7 @@ #include "BIF_editsima.h" #include "BIF_space.h" +#include "BIF_screen.h" #include "blendef.h" #include "mydevice.h" @@ -60,6 +63,12 @@ #include "ONL_opennl.h" #include "BDR_unwrapper.h" +#include "PIL_time.h" + +#include "parametrizer.h" + +short CurrentUnwrapper = 0; + /* Implementation Least Squares Conformal Maps parameterization, based on * chapter 2 of: * Bruno Levy, Sylvain Petitjean, Nicolas Ray, Jerome Maillot. Least Squares @@ -903,9 +912,9 @@ static int unwrap_lscm_face_group(Mesh *me, int *groups, int gid) lscm_build_matrix(me, lscmvert, groups, gid, center, radius); nlEnd(NL_SYSTEM); - + /* LSCM solver magic! */ - nlSolve(); + nlSolve(NULL, NL_FALSE); /* load new uv's: will be projected uv's if solving failed */ lscm_load_solution(me, lscmvert, groups, gid); @@ -1133,6 +1142,11 @@ void unwrap_lscm(void) int res; Mesh *me; int totgroup, *groups=NULL, a; + + if (CurrentUnwrapper == 1) { + unwrap_lscm_new(); + return; + } me= get_mesh(OBACT); if(me==0 || me->tface==0) return; @@ -1336,3 +1350,246 @@ void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index) object_tface_flags_changed(OBACT, 0); } +/* Parametrizer */ + +ParamHandle *construct_param_handle(Mesh *me, short implicit, short fill) +{ + int a; + TFace *tf; + MFace *mf; + MVert *mv; + MEdge *medge; + ParamHandle *handle; + + handle = param_construct_begin(); + + mv= me->mvert; + mf= me->mface; + tf= me->tface; + for (a=0; a<me->totface; a++, mf++, tf++) { + ParamKey key, vkeys[4]; + ParamBool pin[4], select[4]; + float *co[4]; + float *uv[4]; + int nverts; + + if ((tf->flag & TF_HIDE) || !(tf->flag & TF_SELECT)) + continue; + + if (implicit && !(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4))) + continue; + + key = (ParamKey)mf; + vkeys[0] = (ParamKey)mf->v1; + vkeys[1] = (ParamKey)mf->v2; + vkeys[2] = (ParamKey)mf->v3; + + co[0] = (mv+mf->v1)->co; + co[1] = (mv+mf->v2)->co; + co[2] = (mv+mf->v3)->co; + + uv[0] = tf->uv[0]; + uv[1] = tf->uv[1]; + uv[2] = tf->uv[2]; + + pin[0] = ((tf->unwrap & TF_PIN1) != 0); + pin[1] = ((tf->unwrap & TF_PIN2) != 0); + pin[2] = ((tf->unwrap & TF_PIN3) != 0); + + select[0] = ((tf->flag & TF_SEL1) != 0); + select[1] = ((tf->flag & TF_SEL2) != 0); + select[2] = ((tf->flag & TF_SEL3) != 0); + + if (mf->v4) { + vkeys[3] = (ParamKey)mf->v4; + co[3] = (mv+mf->v4)->co; + uv[3] = tf->uv[3]; + pin[3] = ((tf->unwrap & TF_PIN4) != 0); + select[3] = ((tf->flag & TF_SEL4) != 0); + nverts = 4; + } + else + nverts = 3; + + param_face_add(handle, key, nverts, vkeys, co, uv, pin, select); + } + + if (!implicit) { + for(medge=me->medge, a=me->totedge; a>0; a--, medge++) { + if(medge->flag & ME_SEAM) { + ParamKey vkeys[2]; + + vkeys[0] = (ParamKey)medge->v1; + vkeys[1] = (ParamKey)medge->v2; + param_edge_set_seam(handle, vkeys); + } + } + } + + param_construct_end(handle, fill, implicit); + + return handle; +} + +void unwrap_lscm_new(void) +{ + Mesh *me; + ParamHandle *handle; + + me= get_mesh(OBACT); + if(me==0 || me->tface==0) return; + + handle = construct_param_handle(me, 0, 1); + + param_lscm_begin(handle, PARAM_FALSE); + param_lscm_solve(handle); + param_lscm_end(handle); + + param_pack(handle); + param_flush(handle); + + param_delete(handle); + + BIF_undo_push("UV lscm unwrap"); + + object_uvs_changed(OBACT); + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWIMAGE, 0); +} + +void minimize_stretch_tface_uv(void) +{ + Mesh *me; + ParamHandle *handle; + double lasttime; + short doit = 1, escape = 0, val, blend = 0; + unsigned short event = 0; + + me = get_mesh(OBACT); + if(me==0 || me->tface==0) return; + + handle = construct_param_handle(me, 1, 0); + + lasttime = PIL_check_seconds_timer(); + + param_stretch_begin(handle); + + while (doit) { + param_stretch_iter(handle); + + while (qtest()) { + event= extern_qread(&val); + + if (val) { + switch (event) { + case ESCKEY: + escape = 1; + case RETKEY: + case PADENTER: + doit = 0; + break; + case PADPLUSKEY: + case WHEELUPMOUSE: + if (blend < 10) { + blend++; + param_stretch_blend(handle, blend*0.1f); + param_flush(handle); + lasttime = 0.0f; + } + break; + case PADMINUS: + case WHEELDOWNMOUSE: + if (blend > 0) { + blend--; + param_stretch_blend(handle, blend*0.1f); + param_flush(handle); + lasttime = 0.0f; + } + break; + } + } + else if ((event == LEFTMOUSE) || (event == RIGHTMOUSE)) { + escape = (event == RIGHTMOUSE); + doit = 0; + } + } + + if (!doit) + break; + + if (PIL_check_seconds_timer() - lasttime > 0.5) { + char str[100]; + + param_flush(handle); + + sprintf(str, "Stretch minimize. Blend %.2f.", blend*0.1f); + headerprint(str); + + lasttime = PIL_check_seconds_timer(); + if(G.sima->lock) force_draw_plus(SPACE_VIEW3D, 0); + else force_draw(0); + } + } + + if (escape) + param_flush_restore(handle); + else + param_flush(handle); + + param_stretch_end(handle); + + param_delete(handle); + + BIF_undo_push("UV stretch minimize"); + + object_uvs_changed(OBACT); + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWIMAGE, 0); +} + +/* LSCM live mode */ + +static ParamHandle *liveHandle = NULL; + +void unwrap_lscm_live_begin(void) +{ + Mesh *me; + + if (CurrentUnwrapper == 0) + return; + + me= get_mesh(OBACT); + if(me==0 || me->tface==0) return; + + liveHandle = construct_param_handle(me, 0, 0); + + param_lscm_begin(liveHandle, PARAM_TRUE); +} + +void unwrap_lscm_live_re_solve(void) +{ + if (CurrentUnwrapper == 0) { + unwrap_lscm(); + return; + } + + if (liveHandle) { + param_lscm_solve(liveHandle); + param_flush(liveHandle); + } +} + +void unwrap_lscm_live_end(void) +{ + if (CurrentUnwrapper == 0) + return; + + if (liveHandle) { + param_lscm_end(liveHandle); + param_delete(liveHandle); + liveHandle = NULL; + } +} + |