Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_anim.h3
-rw-r--r--source/blender/blenkernel/BKE_bad_level_calls.h2
-rw-r--r--source/blender/blenkernel/BKE_effect.h6
-rw-r--r--source/blender/blenkernel/BKE_group.h12
-rw-r--r--source/blender/blenkernel/BKE_material.h6
-rw-r--r--source/blender/blenkernel/BKE_scene.h2
-rw-r--r--source/blender/blenkernel/BKE_utildefines.h5
-rw-r--r--source/blender/blenkernel/bad_level_call_stubs/stubs.c4
-rw-r--r--source/blender/blenkernel/intern/anim.c47
-rw-r--r--source/blender/blenkernel/intern/displist.c15
-rw-r--r--source/blender/blenkernel/intern/effect.c85
-rw-r--r--source/blender/blenkernel/intern/group.c229
-rw-r--r--source/blender/blenkernel/intern/material.c104
-rw-r--r--source/blender/blenkernel/intern/object.c6
-rw-r--r--source/blender/blenkernel/intern/scene.c6
-rw-r--r--source/blender/blenkernel/intern/softbody.c2
-rw-r--r--source/blender/blenloader/intern/readblenentry.c2
-rw-r--r--source/blender/blenloader/intern/readfile.c90
-rw-r--r--source/blender/blenloader/intern/writefile.c23
-rw-r--r--source/blender/include/BDR_unwrapper.h11
-rw-r--r--source/blender/include/BIF_editgroup.h10
-rw-r--r--source/blender/include/BIF_meshtools.h4
-rw-r--r--source/blender/include/BIF_resources.h4
-rw-r--r--source/blender/include/BIF_space.h3
-rw-r--r--source/blender/include/blendef.h2
-rw-r--r--source/blender/include/butspace.h17
-rwxr-xr-xsource/blender/include/transform.h1
-rw-r--r--source/blender/makesdna/DNA_effect_types.h3
-rw-r--r--source/blender/makesdna/DNA_group_types.h45
-rw-r--r--source/blender/makesdna/DNA_material_types.h41
-rw-r--r--source/blender/makesdna/DNA_object_types.h9
-rw-r--r--source/blender/makesdna/DNA_scene_types.h28
-rw-r--r--source/blender/makesdna/DNA_space_types.h1
-rw-r--r--source/blender/makesdna/DNA_world_types.h3
-rw-r--r--source/blender/render/extern/include/render.h8
-rw-r--r--source/blender/render/extern/include/render_types.h54
-rw-r--r--source/blender/render/intern/include/pixelshading.h7
-rw-r--r--source/blender/render/intern/include/rendercore.h10
-rw-r--r--source/blender/render/intern/include/texture.h2
-rw-r--r--source/blender/render/intern/source/envmap.c7
-rw-r--r--source/blender/render/intern/source/initrender.c30
-rw-r--r--source/blender/render/intern/source/pixelshading.c31
-rw-r--r--source/blender/render/intern/source/ray.c45
-rw-r--r--source/blender/render/intern/source/renderPreAndPost.c9
-rw-r--r--source/blender/render/intern/source/rendercore.c363
-rw-r--r--source/blender/render/intern/source/renderdatabase.c29
-rw-r--r--source/blender/render/intern/source/texture.c52
-rw-r--r--source/blender/render/intern/source/vanillaRenderPipe.c7
-rw-r--r--source/blender/render/intern/source/zbuf.c7
-rw-r--r--source/blender/renderconverter/intern/convertBlenderScene.c80
-rw-r--r--source/blender/src/SConscript1
-rw-r--r--source/blender/src/butspace.c30
-rw-r--r--source/blender/src/buttons_editing.c1
-rw-r--r--source/blender/src/buttons_object.c381
-rw-r--r--source/blender/src/buttons_shading.c464
-rw-r--r--source/blender/src/drawobject.c14
-rw-r--r--source/blender/src/drawview.c2
-rw-r--r--source/blender/src/editgroup.c115
-rw-r--r--source/blender/src/editipo.c9
-rw-r--r--source/blender/src/editmesh.c3
-rw-r--r--source/blender/src/editmesh_mods.c12
-rw-r--r--source/blender/src/editobject.c127
-rw-r--r--source/blender/src/editscreen.c2
-rw-r--r--source/blender/src/editview.c35
-rw-r--r--source/blender/src/filesel.c39
-rw-r--r--source/blender/src/header_buttonswin.c22
-rw-r--r--source/blender/src/header_image.c8
-rw-r--r--source/blender/src/header_oops.c20
-rw-r--r--source/blender/src/header_view3d.c2
-rw-r--r--source/blender/src/headerbuttons.c11
-rw-r--r--source/blender/src/interface_panel.c4
-rw-r--r--source/blender/src/meshtools.c55
-rw-r--r--source/blender/src/outliner.c36
-rw-r--r--source/blender/src/parametrizer.c1877
-rw-r--r--source/blender/src/parametrizer.h80
-rw-r--r--source/blender/src/parametrizer_intern.h191
-rw-r--r--source/blender/src/previewrender.c596
-rw-r--r--source/blender/src/space.c59
-rwxr-xr-xsource/blender/src/transform_conversions.c28
-rwxr-xr-xsource/blender/src/transform_generics.c35
-rw-r--r--source/blender/src/unwrapper.c261
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;
+ }
+}
+