From f3fc5a8b6103f7f8b256fdceee8412e0182a5a8f Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sun, 7 Sep 2008 19:58:37 +0000 Subject: [PATCH 01/32] BGE bug #17574 fixed: GE Text input doesn't register in 2.47. Force registration of keyboard sensor with no link as this is typically the setting for key logging. --- source/gameengine/Converter/KX_ConvertSensors.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index 74819431858..f16855955ff 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -781,6 +781,13 @@ void BL_ConvertSensors(struct Object* blenderobject, "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); } } + // special case: Keyboard sensor with no link + // this combination is usually used for key logging. + if (sens->type == SENS_KEYBOARD && sens->totlinks == 0) { + // Force the registration so that the sensor runs + gamesensor->IncLink(); + } + // done with gamesensor gamesensor->Release(); From 26d8da99cc451c4a60fa0d3f8e467c3dd6ae5e7c Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 7 Sep 2008 20:18:26 +0000 Subject: [PATCH 02/32] Bug [#17454] Wave modifier crash, fix provided by Banlu Kemiyatorn --- source/blender/src/buttons_editing.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index c83d7b2e124..0a792b05428 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1573,6 +1573,18 @@ static void build_uvlayer_menu_vars(CustomData *data, char **menu_string, } } +void set_wave_uvlayer(void *arg1, void *arg2) +{ + WaveModifierData *wmd=arg1; + CustomDataLayer *layer = arg2; + + /*check we have UV layers*/ + if (wmd->uvlayer_tmp < 1) return; + layer = layer + (wmd->uvlayer_tmp-1); + + strcpy(wmd->uvlayer_name, layer->name); +} + void set_displace_uvlayer(void *arg1, void *arg2) { DisplaceModifierData *dmd=arg1; @@ -2193,7 +2205,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco 0.0, 1.0, 0, 0, "Set the UV layer to use"); MEM_freeN(strtmp); i = CustomData_get_layer_index(fdata, CD_MTFACE); - uiButSetFunc(but, set_displace_uvlayer, wmd, + uiButSetFunc(but, set_wave_uvlayer, wmd, &fdata->layers[i]); } if(wmd->texmapping == MOD_DISP_MAP_OBJECT) { From a9d334df67a921dd6c60c4574dbb4eb6443e9c37 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 7 Sep 2008 20:46:54 +0000 Subject: [PATCH 03/32] Bugfix for #17572 Boids Particles Crash --- source/blender/blenkernel/intern/particle_system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 96eb4d5d8e3..71dd2f64c72 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -3875,7 +3875,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, state->vel[2]=0.0; state->co[2]=part->groundz; - if(psys->keyed_ob){ + if(psys->keyed_ob && (psys->keyed_ob->type == OB_MESH)){ Object *zob=psys->keyed_ob; int min_face; float co1[3],co2[3],min_d=2.0,min_w[4],imat[4][4]; From ce7caf203d81168b06f815464c4ae2fa6179a302 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 8 Sep 2008 06:49:19 +0000 Subject: [PATCH 04/32] View 3D - Improvements for Info Drawing: The little info string beside the mini-axis (in bottom left corner) is now more useful when animating fullscreen. ZanQdo feature request. * Info string is drawn in yellow when there is a keyframe on this frame. Hopefully this doesn't introduce any major slowdowns, as it does do a search for keyframes for every redraw. * Name of first marker that occurs on the current frame is now also shown (in angled brackets). No angle brackets are shown if no marker. * Info string is also shown when there is no active object. --- source/blender/src/drawview.c | 221 +++++++++++++++++++++++++++------- 1 file changed, 179 insertions(+), 42 deletions(-) diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index f8d77698489..42576c901d7 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -135,6 +135,7 @@ #include "BIF_verse.h" #endif +#include "BDR_drawaction.h" #include "BDR_drawmesh.h" #include "BDR_drawobject.h" #include "BDR_editobject.h" @@ -1207,60 +1208,196 @@ void drawname(Object *ob) BMF_DrawString(G.font, ob->id.name+2); } +static char *get_cfra_marker_name() +{ + ListBase *markers= &G.scene->markers; + TimeMarker *m1, *m2; + + /* search through markers for match */ + for (m1=markers->first, m2=markers->last; m1 && m2; m1=m1->next, m2=m2->prev) { + if (m1->frame==CFRA) + return m1->name; + if (m2->frame==CFRA) + return m2->name; + + if (m1 == m2) + break; + } + + return NULL; +} +// TODO: move this func into some keyframing API +short ob_cfra_has_keyframe (Object *ob) +{ + // fixme... this is slow! + if (ob) { + ListBase keys = {NULL, NULL}; + ActKeyColumn *ak, *akn; + Key *key= ob_get_key(ob); + int cfra, found= 0; + + /* check active action */ + if (ob->action) { + /* get keyframes of action */ + action_to_keylist(ob->action, &keys, NULL, NULL); + + cfra= frame_to_float(CFRA); + cfra= get_action_frame(ob, cfra); + + /* check if a keyframe occurs on current frame */ + for (ak=keys.first, akn=keys.last; ak && akn; ak=ak->next, akn=akn->prev) { + if (cfra == ak->cfra) { + found= 1; + break; + } + else if (cfra == akn->cfra) { + found= 1; + break; + } + + if (ak == akn) + break; + } + + /* free temp list */ + BLI_freelistN(&keys); + keys.first= keys.last= NULL; + + /* return if found */ + if (found) return 1; + } + + /* accumulate keyframes for available ipo's */ + if (ob->ipo) + ipo_to_keylist(ob->ipo, &keys, NULL, NULL); + if (key) + ipo_to_keylist(key->ipo, &keys, NULL, NULL); + + if (keys.first) { + cfra= frame_to_float(CFRA); + found= 0; + + /* check if a keyframe occurs on current frame */ + for (ak=keys.first, akn=keys.last; ak && akn; ak=ak->next, akn=akn->prev) { + if (IS_EQ(cfra, ak->cfra)) { + found= 1; + break; + } + else if (IS_EQ(cfra, akn->cfra)) { + found= 1; + break; + } + + if (ak == akn) + break; + } + + /* free temp list */ + BLI_freelistN(&keys); + keys.first= keys.last= NULL; + + /* return if found */ + if (found) return 1; + } + } + + /* couldn't find a keyframe */ + return 0; +} + +/* draw info beside axes in bottom left-corner: + * framenum, object name, bone name (if available), marker name (if available) + */ static void draw_selected_name(Object *ob) { - char info[128]; + char info[256], *markern; short offset=30; - - if(ob->type==OB_ARMATURE) { - bArmature *arm= ob->data; - char *name= NULL; - - if(ob==G.obedit) { - EditBone *ebo; - for (ebo=G.edbo.first; ebo; ebo=ebo->next){ - if ((ebo->flag & BONE_ACTIVE) && (ebo->layer & arm->layer)) { - name= ebo->name; - break; + + /* get name of marker on current frame (if available) */ + markern= get_cfra_marker_name(); + + /* check if there is an object */ + if(ob) { + /* name(s) to display depends on type of object */ + if(ob->type==OB_ARMATURE) { + bArmature *arm= ob->data; + char *name= NULL; + + /* show name of active bone too (if possible) */ + if(ob==G.obedit) { + EditBone *ebo; + for (ebo=G.edbo.first; ebo; ebo=ebo->next){ + if ((ebo->flag & BONE_ACTIVE) && (ebo->layer & arm->layer)) { + name= ebo->name; + break; + } } } - } - else if(ob->pose && (ob->flag & OB_POSEMODE)) { - bPoseChannel *pchan; - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if((pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) { - name= pchan->name; - break; + else if(ob->pose && (ob->flag & OB_POSEMODE)) { + bPoseChannel *pchan; + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if((pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) { + name= pchan->name; + break; + } } } + if(name && markern) + sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, name, markern); + else if(name) + sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, name); + else + sprintf(info, "(%d) %s", CFRA, ob->id.name+2); } - if(name) - sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, name); + else if(ELEM3(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) { + Key *key= NULL; + KeyBlock *kb = NULL; + char shapes[75]; + + /* try to display active shapekey too */ + shapes[0] = 0; + key = ob_get_key(ob); + if(key){ + kb = BLI_findlink(&key->block, ob->shapenr-1); + if(kb){ + sprintf(shapes, ": %s ", kb->name); + if(ob->shapeflag == OB_SHAPE_LOCK){ + sprintf(shapes, "%s (Pinned)",shapes); + } + } + } + + if(markern) + sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, shapes, markern); + else + sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, shapes); + } + else { + /* standard object */ + if (markern) + sprintf(info, "(%d) %s <%s>", CFRA, ob->id.name+2, markern); + else + sprintf(info, "(%d) %s", CFRA, ob->id.name+2); + } + + /* colour depends on whether there is a keyframe */ + if (ob_cfra_has_keyframe(ob)) + BIF_ThemeColor(TH_VERTEX_SELECT); else - sprintf(info, "(%d) %s", CFRA, ob->id.name+2); + BIF_ThemeColor(TH_TEXT_HI); } - else if(ob->type==OB_MESH) { - Key *key= NULL; - KeyBlock *kb = NULL; - char shapes[75]; + else { + /* no object */ + if (markern) + sprintf(info, "(%d) <%s>", CFRA, markern); + else + sprintf(info, "(%d)", CFRA); - shapes[0] = 0; - key = ob_get_key(ob); - if(key){ - kb = BLI_findlink(&key->block, ob->shapenr-1); - if(kb){ - sprintf(shapes, ": %s ", kb->name); - if(ob->shapeflag == OB_SHAPE_LOCK){ - sprintf(shapes, "%s (Pinned)",shapes); - } - } - } - sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, shapes); + /* colour is always white */ + BIF_ThemeColor(TH_TEXT_HI); } - else sprintf(info, "(%d) %s", CFRA, ob->id.name+2); - - BIF_ThemeColor(TH_TEXT_HI); + if (U.uiflag & USER_SHOW_ROTVIEWICON) offset = 14 + (U.rvisize * 2); @@ -3257,7 +3394,7 @@ void drawview3dspace(ScrArea *sa, void *spacedata) } ob= OBACT; - if(ob && (U.uiflag & USER_DRAWVIEWINFO)) + if(U.uiflag & USER_DRAWVIEWINFO) draw_selected_name(ob); draw_area_emboss(sa); From 6a83746fb33d3803b212a26ca72882d55127009d Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Mon, 8 Sep 2008 10:31:00 +0000 Subject: [PATCH 05/32] Bugfix #17305 3d window didn't refresh correctly when loading a new background image. Fix by Ken Hughes. :) --- source/blender/src/buttons_shading.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 3f65f686e93..6d5e1a62ad4 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -211,6 +211,7 @@ static void load_image_cb(char *str, void *ima_pp_v, void *iuser_v) /* called fr if(GS(tex->id.name)==ID_TE) { BIF_preview_changed(ID_TE); allqueue(REDRAWBUTSSHADING, 0); + allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWOOPS, 0); } } From da474210de8871ea2a6dfcd2bfa37a71f9f6aed8 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Mon, 8 Sep 2008 11:13:34 +0000 Subject: [PATCH 06/32] Bug #17317 Vertexpaint mode: option "paint mask" (Fkey) missed redraw for buttons --- source/blender/include/blendef.h | 1 + source/blender/src/header_view3d.c | 8 ++++++-- source/blender/src/space.c | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h index 228530db445..a7f7bc2e4b8 100644 --- a/source/blender/include/blendef.h +++ b/source/blender/include/blendef.h @@ -241,6 +241,7 @@ #define B_SEL_END 168 #define B_MAN_MODE 169 #define B_NDOF 170 +#define B_VIEW_BUTSEDIT 171 /* IPO: 200 */ #define B_IPOHOME 201 diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index c8a006a8221..704d4bdea54 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -5387,7 +5387,11 @@ void do_view3d_buttons(short event) case B_MAN_MODE: allqueue(REDRAWVIEW3D, 1); break; - + case B_VIEW_BUTSEDIT: + allqueue(REDRAWVIEW3D, 1); + allqueue(REDRAWBUTSEDIT, 1); + break; + default: if(event>=B_LAY && event Date: Mon, 8 Sep 2008 12:06:40 +0000 Subject: [PATCH 07/32] Bugfix: Grease Pencil panel now updates correctly in Sequencer --- source/blender/src/drawgpencil.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/source/blender/src/drawgpencil.c b/source/blender/src/drawgpencil.c index 6e897052218..fb21d94f39a 100644 --- a/source/blender/src/drawgpencil.c +++ b/source/blender/src/drawgpencil.c @@ -98,6 +98,8 @@ void gp_ui_activelayer_cb (void *gpd, void *gpl) { gpencil_layer_setactive(gpd, gpl); + + scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -109,6 +111,8 @@ void gp_ui_renamelayer_cb (void *gpd_arg, void *gpl_arg) BLI_uniquename(&gpd->layers, gpl, "GP_Layer", offsetof(bGPDlayer, info[0]), 128); gpencil_layer_setactive(gpd, gpl); + + scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -116,6 +120,8 @@ void gp_ui_renamelayer_cb (void *gpd_arg, void *gpl_arg) void gp_ui_addlayer_cb (void *gpd, void *dummy) { gpencil_layer_addnew(gpd); + + scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -123,6 +129,8 @@ void gp_ui_addlayer_cb (void *gpd, void *dummy) void gp_ui_dellayer_cb (void *gpd, void *dummy) { gpencil_layer_delactive(gpd); + + scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -133,6 +141,8 @@ void gp_ui_delstroke_cb (void *gpd, void *gpl) gpencil_layer_setactive(gpd, gpl); gpencil_frame_delete_laststroke(gpf); + + scrarea_queue_winredraw(curarea); } /* delete active frame of active layer */ @@ -143,6 +153,7 @@ void gp_ui_delframe_cb (void *gpd, void *gpl) gpencil_layer_setactive(gpd, gpl); gpencil_layer_delframe(gpl, gpf); + scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -151,6 +162,8 @@ void gp_ui_convertlayer_cb (void *gpd, void *gpl) { gpencil_layer_setactive(gpd, gpl); gpencil_convert_menu(); + + scrarea_queue_winredraw(curarea); } /* ------- Drawing Code ------- */ From 2768ee67bd0d78b7af1ef78537257ccf7bba7491 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 8 Sep 2008 12:36:49 +0000 Subject: [PATCH 08/32] Grease Pencil - Defaults Cleanups: * Made new layers default to having thickness of 3, and opacity of 0.9. These values seem to be used more often. * Newly added Grease Pencil blocks will now be expanded by default in the Action Editor * Added support for Image Editor grease-pencil blocks to the Action Editor * Added version-patching for missing colours used by the info-string for GPencil. --- source/blender/src/drawaction.c | 12 ++++++++++++ source/blender/src/gpencil.c | 7 +++---- source/blender/src/resources.c | 2 ++ source/blender/src/usiblender.c | 9 +++++++++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index 0782ccfc7ee..33eb5262c3d 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -682,6 +682,18 @@ static void draw_channel_names(void) special= ICON_SEQUENCE; } break; + case SPACE_IMAGE: + { + SpaceImage *sima= sa->spacedata.first; + + if (sima->image) + sprintf(name, "Image: %s", sima->image->id.name+2); + else + sprintf(name, "Image: "); + + special= ICON_IMAGE_COL; + } + break; default: { diff --git a/source/blender/src/gpencil.c b/source/blender/src/gpencil.c index fa3ada89a3a..c7540bc4a1f 100644 --- a/source/blender/src/gpencil.c +++ b/source/blender/src/gpencil.c @@ -224,8 +224,8 @@ bGPDlayer *gpencil_layer_addnew (bGPdata *gpd) BLI_addtail(&gpd->layers, gpl); /* set basic settings */ - gpl->color[3]= 1.0f; - gpl->thickness = 1; + gpl->color[3]= 0.9f; + gpl->thickness = 3; /* auto-name */ sprintf(gpl->info, "GP_Layer"); @@ -247,8 +247,7 @@ bGPdata *gpencil_data_addnew (void) gpd= MEM_callocN(sizeof(bGPdata), "GreasePencilData"); /* initial settings */ - /* it is quite useful to be able to see this info, so on by default */ - gpd->flag = GP_DATA_DISPINFO; + gpd->flag = (GP_DATA_DISPINFO|GP_DATA_EXPAND); return gpd; } diff --git a/source/blender/src/resources.c b/source/blender/src/resources.c index acd14aae7a5..1bef10d0415 100644 --- a/source/blender/src/resources.c +++ b/source/blender/src/resources.c @@ -753,6 +753,8 @@ char *BIF_ThemeColorsPup(int spacetype) str += sprintf(str, "Transition Strip %%x%d|", TH_SEQ_TRANSITION); str += sprintf(str, "Meta Strip %%x%d|", TH_SEQ_META); str += sprintf(str, "Current Frame %%x%d", TH_CFRAME); + str += sprintf(str, "Keyframe %%x%d|", TH_VERTEX_SELECT); + str += sprintf(str, "Draw Action %%x%d|", TH_BONE_POSE); break; case SPACE_SOUND: str += sprintf(str, "Grid %%x%d|", TH_GRID); diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index 901daf0ee58..aa49065320b 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -484,11 +484,20 @@ static void init_userdef_file(void) bTheme *btheme; for(btheme= U.themes.first; btheme; btheme= btheme->next) { char *col; + + /* IPO Editor: Handles/Vertices */ col = btheme->tipo.vertex; SETCOL(btheme->tipo.handle_vertex, col[0], col[1], col[2], 255); col = btheme->tipo.vertex_select; SETCOL(btheme->tipo.handle_vertex_select, col[0], col[1], col[2], 255); btheme->tipo.handle_vertex_size= btheme->tipo.vertex_size; + + /* Sequence/Image Editor: colors for GPencil text */ + col = btheme->tv3d.bone_pose; + SETCOL(btheme->tseq.bone_pose, col[0], col[1], col[2], 255); + SETCOL(btheme->tima.bone_pose, col[0], col[1], col[2], 255); + col = btheme->tv3d.vertex_select; + SETCOL(btheme->tseq.vertex_select, col[0], col[1], col[2], 255); } } From f7a6d032fc7f82fb1cf8947ae6914ab2131155c1 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Mon, 8 Sep 2008 13:04:10 +0000 Subject: [PATCH 09/32] Bugfix #17375 Crash on converting object to other type, and replace object. Deleting should trigger a new depsgraph. Oldie bug! --- source/blender/src/editobject.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 2094074e3f3..e8084bd45a9 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -3023,6 +3023,10 @@ void convertmenu(void) basedel = NULL; } + /* delete object should renew depsgraph */ + if(nr==2) + DAG_scene_sort(G.scene); + /* texspace and normals */ if(!basen) BASACT= base; From de4828036857e76141ca336997b99978ee09fb5f Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Mon, 8 Sep 2008 15:15:00 +0000 Subject: [PATCH 10/32] Bugfix #17566 Modifier buttons: now check properly for external lib data, modifiers are on object only. Only "Apply" is locked now. --- source/blender/src/buttons_editing.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 0a792b05428..425ec8956cb 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1855,6 +1855,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco y -= 18; if (!isVirtual && (md->type!=eModifierType_Collision)) { + uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* only here obdata, the rest of modifiers is ob level */ + uiBlockBeginAlign(block); if (md->type==eModifierType_ParticleSystem) { but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Convert", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Convert the current particles to a mesh object"); @@ -1870,6 +1872,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiButSetFunc(but, modifiers_copyModifier, ob, md); } uiBlockEndAlign(block); + + uiSetButLock(ob && ob->id.lib, ERROR_LIBDATA_MESSAGE); } lx = x + 10; @@ -2552,7 +2556,7 @@ static void editing_panel_modifiers(Object *ob) block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win); if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return; - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + uiSetButLock((ob && ob->id.lib), ERROR_LIBDATA_MESSAGE); uiNewPanelHeight(block, 204); uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier"); From 3f87319428ff6b7b6fc0eb6df8c6ecaad49b49cc Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Mon, 8 Sep 2008 23:39:32 +0000 Subject: [PATCH 11/32] Python API ---------- Add access to MTex objects from Lamps and Worlds (first pass). Since the MTex structure is slightly difference between materials, lamps, and worlds, a field is added to the BPy MTex object to distinquish which type it wraps. Attempting to access attributes which are unique to materials for lamp or world MTex objects throw an exception. The next pass will implement MTex attributes which are specific to Lamps and Worlds. A new attribute (textures) is added to each module. It is compatible with the previous Material.getTextures(), which returns a tuple of either MTex objects or None. Surprised we never added an attribute for this before in all the changes and refactoring. --- source/blender/python/api2_2x/Lamp.c | 30 +++ source/blender/python/api2_2x/MTex.c | 217 ++++++++++-------- source/blender/python/api2_2x/MTex.h | 8 +- source/blender/python/api2_2x/Material.c | 108 +++++++-- source/blender/python/api2_2x/World.c | 29 +++ source/blender/python/api2_2x/doc/Lamp.py | 2 + source/blender/python/api2_2x/doc/Material.py | 4 +- source/blender/python/api2_2x/doc/Texture.py | 120 ++++++---- source/blender/python/api2_2x/doc/World.py | 2 + 9 files changed, 361 insertions(+), 159 deletions(-) diff --git a/source/blender/python/api2_2x/Lamp.c b/source/blender/python/api2_2x/Lamp.c index 2e58cb71b90..1b9b1041aee 100644 --- a/source/blender/python/api2_2x/Lamp.c +++ b/source/blender/python/api2_2x/Lamp.c @@ -39,6 +39,7 @@ #include "BSE_editipo.h" #include "mydevice.h" #include "Ipo.h" +#include "MTex.h" #include "constant.h" #include "gen_utils.h" #include "gen_library.h" @@ -206,6 +207,7 @@ static PyObject *Lamp_getQuad2( BPy_Lamp * self ); static PyObject *Lamp_getCol( BPy_Lamp * self ); static PyObject *Lamp_getIpo( BPy_Lamp * self ); static PyObject *Lamp_getComponent( BPy_Lamp * self, void * closure ); +static PyObject *Lamp_getTextures( BPy_Lamp * self ); static PyObject *Lamp_clearIpo( BPy_Lamp * self ); static PyObject *Lamp_insertIpoKey( BPy_Lamp * self, PyObject * args ); static PyObject *Lamp_oldsetIpo( BPy_Lamp * self, PyObject * args ); @@ -500,6 +502,10 @@ static PyGetSetDef BPy_Lamp_getseters[] = { (getter)Lamp_getComponent, (setter)Lamp_setComponent, "Lamp color blue component", (void *)EXPP_LAMP_COMP_B}, + {"textures", + (getter)Lamp_getTextures, (setter)NULL, + "The Lamp's texture list as a tuple", + NULL}, {"Modes", (getter)Lamp_getModesConst, (setter)NULL, "Dictionary of values for 'mode' attribute", @@ -1393,6 +1399,30 @@ static PyObject *Lamp_getTypesConst( void ) "Photon", EXPP_LAMP_TYPE_YF_PHOTON ); } +static PyObject *Lamp_getTextures( BPy_Lamp * self ) +{ + int i; + PyObject *tuple; + + /* build a texture list */ + tuple = PyTuple_New( MAX_MTEX ); + if( !tuple ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, + "couldn't create PyTuple" ); + + for( i = 0; i < MAX_MTEX; ++i ) { + struct MTex *mtex = self->lamp->mtex[i]; + if( mtex ) { + PyTuple_SET_ITEM( tuple, i, MTex_CreatePyObject( mtex, ID_LA ) ); + } else { + Py_INCREF( Py_None ); + PyTuple_SET_ITEM( tuple, i, Py_None ); + } + } + + return tuple; +} + /* #####DEPRECATED###### */ static PyObject *Lamp_oldsetSamples( BPy_Lamp * self, PyObject * args ) diff --git a/source/blender/python/api2_2x/MTex.c b/source/blender/python/api2_2x/MTex.c index a95836f0596..fa7c62ac8d6 100644 --- a/source/blender/python/api2_2x/MTex.c +++ b/source/blender/python/api2_2x/MTex.c @@ -26,6 +26,7 @@ * * ***** END GPL LICENSE BLOCK ***** */ + #include "MTex.h" /*This must come first*/ #include "BKE_utildefines.h" @@ -252,7 +253,7 @@ PyObject *MTex_Init( void ) return submodule; } -PyObject *MTex_CreatePyObject( MTex * mtex ) +PyObject *MTex_CreatePyObject( MTex * mtex, unsigned short type ) { BPy_MTex *pymtex; @@ -262,6 +263,7 @@ PyObject *MTex_CreatePyObject( MTex * mtex ) "couldn't create BPy_MTex PyObject" ); pymtex->mtex = mtex; + pymtex->type = type; return ( PyObject * ) pymtex; } @@ -286,7 +288,12 @@ static int MTex_compare( BPy_MTex * a, BPy_MTex * b ) static PyObject *MTex_repr( BPy_MTex * self ) { - return PyString_FromFormat( "[MTex]" ); + if( self->type == ID_MA ) + return PyString_FromFormat( "[MTex (Material)]" ); + else if( self->type == ID_LA ) + return PyString_FromFormat( "[MTex (Lamp)]" ); + else + return PyString_FromFormat( "[MTex (World)]" ); } @@ -350,6 +357,10 @@ static int MTex_setObject( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getUVLayer( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a Material MTex object" ); + return PyString_FromString(self->mtex->uvname); } @@ -364,6 +375,10 @@ static int MTex_setUVLayer( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getMapTo( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a Material MTex object" ); + return PyInt_FromLong( self->mtex->mapto ); } @@ -371,18 +386,20 @@ static int MTex_setMapTo( BPy_MTex *self, PyObject *value, void *closure) { int mapto; - if( !PyInt_Check( value ) ) { + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + + if( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, - "expected an int" ); - } + "expected an int" ); mapto = PyInt_AsLong( value ); /* This method is deprecated anyway. */ - if ( mapto < 0 || mapto > 16383 ) { + if ( mapto < 0 || mapto > 16383 ) return EXPP_ReturnIntError( PyExc_ValueError, "Value must be a sum of values from Texture.MapTo dictionary" ); - } self->mtex->mapto = (short)mapto; @@ -400,11 +417,9 @@ static int MTex_setCol( BPy_MTex *self, PyObject *value, void *closure) float rgb[3]; int i; - if( !PyArg_ParseTuple( value, "fff", - &rgb[0], &rgb[1], &rgb[2] ) ) - + if( !PyArg_ParseTuple( value, "fff", &rgb[0], &rgb[1], &rgb[2] ) ) return EXPP_ReturnIntError( PyExc_TypeError, - "expected tuple of 3 floats" ); + "expected tuple of 3 floats" ); for( i = 0; i < 3; ++i ) if( rgb[i] < 0 || rgb[i] > 1 ) @@ -478,117 +493,84 @@ static PyObject *MTex_getColFac( BPy_MTex *self, void *closure ) static int MTex_setColFac( BPy_MTex *self, PyObject *value, void *closure) { - float f; - - if ( !PyFloat_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected a float" ); - - f = (float)PyFloat_AsDouble(value); - - if (f < 0 || f > 1) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [0,1]" ); - - self->mtex->colfac = f; - - return 0; + return EXPP_setFloatRange( value, &self->mtex->colfac, 0.0f, 1.0f ); } static PyObject *MTex_getNorFac( BPy_MTex *self, void *closure ) { + if( self->type == ID_LA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material or world MTex object" ); + return PyFloat_FromDouble(self->mtex->norfac); } static int MTex_setNorFac( BPy_MTex *self, PyObject *value, void *closure) { - float f; - - if ( !PyFloat_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected a float" ); - - f = (float)PyFloat_AsDouble(value); - - if (f < 0 || f > 25) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [0,25]" ); - - self->mtex->norfac = f; - - return 0; + switch( self->type ) + { + case ID_WO: + return EXPP_setFloatRange( value, &self->mtex->norfac, 0.0f, 1.0f ); + case ID_MA: + return EXPP_setFloatRange( value, &self->mtex->norfac, 0.0f, 25.0f ); + default: + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material or world MTex object" ); + } } static PyObject *MTex_getVarFac( BPy_MTex *self, void *closure ) { + if( self->type == ID_LA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material or world MTex object" ); + return PyFloat_FromDouble(self->mtex->varfac); } static int MTex_setVarFac( BPy_MTex *self, PyObject *value, void *closure) { - float f; + if( self->type == ID_LA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material or world MTex object" ); - if ( !PyFloat_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected a float" ); - - f = (float)PyFloat_AsDouble(value); - - if (f < 0 || f > 1) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [0,1]" ); - - self->mtex->varfac = f; - - return 0; + return EXPP_setFloatRange( value, &self->mtex->varfac, 0.0f, 1.0f ); } static PyObject *MTex_getDispFac( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyFloat_FromDouble(self->mtex->dispfac); } static int MTex_setDispFac( BPy_MTex *self, PyObject *value, void *closure) { - float f; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); - if ( !PyFloat_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected a float" ); - - f = (float)PyFloat_AsDouble(value); - - if (f < 0 || f > 1) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [0,1]" ); - - self->mtex->dispfac = f; - - return 0; + return EXPP_setFloatRange( value, &self->mtex->dispfac, 0.0f, 1.0f ); } static PyObject *MTex_getWarpFac( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyFloat_FromDouble(self->mtex->warpfac); } static int MTex_setWarpFac( BPy_MTex *self, PyObject *value, void *closure) { - float f; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); - if ( !PyFloat_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected a float" ); - - f = (float)PyFloat_AsDouble(value); - - if (f < 0 || f > 1) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [0,1]" ); - - self->mtex->warpfac = f; - - return 0; + return EXPP_setFloatRange( value, &self->mtex->warpfac, 0.0f, 1.0f ); } static PyObject *MTex_getOfs( BPy_MTex *self, void *closure ) @@ -601,16 +583,24 @@ static int MTex_setOfs( BPy_MTex *self, PyObject *value, void *closure) { float f[3]; int i; + float max; if( !PyArg_ParseTuple( value, "fff", &f[0], &f[1], &f[2] ) ) - return EXPP_ReturnIntError( PyExc_TypeError, "expected tuple of 3 floats" ); + if( self->type == ID_MA ) + max = 10.0f; + else + max = 20.0f; + for( i = 0; i < 3; ++i ) - if( f[i] < -10 || f[i] > 10 ) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [-10,10]" ); + if( f[i] < -max || f[i] > max ) { + char errstr[64]; + sprintf( errstr, "values must be in range [-%6.0f,%6.0f]", + max, max ); + return EXPP_ReturnIntError( PyExc_ValueError, errstr ); + } self->mtex->ofs[0] = f[0]; self->mtex->ofs[1] = f[1]; @@ -649,6 +639,10 @@ static int MTex_setSize( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getMapping( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyInt_FromLong( self->mtex->mapping ); } @@ -656,6 +650,11 @@ static int MTex_setMapping( BPy_MTex *self, PyObject *value, void *closure) { int n; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + + if ( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "Value must be member of Texture.Mappings dictionary" ); @@ -664,8 +663,7 @@ static int MTex_setMapping( BPy_MTex *self, PyObject *value, void *closure) /* if (n != MTEX_FLAT && n != MTEX_TUBE && n != MTEX_CUBE && n != MTEX_SPHERE) */ - if (n < 0 || n > 3) - { + if (n < 0 || n > 3) { return EXPP_ReturnIntError( PyExc_ValueError, "Value must be member of Texture.Mappings dictionary" ); } @@ -696,6 +694,10 @@ static int MTex_setFlag( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getProjX( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyInt_FromLong( self->mtex->projx ); } @@ -703,6 +705,10 @@ static int MTex_setProjX( BPy_MTex *self, PyObject *value, void *closure) { int proj; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + if( !PyInt_Check( value ) ) { return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.Proj dictionary" ); @@ -722,6 +728,10 @@ static int MTex_setProjX( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getProjY( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyInt_FromLong( self->mtex->projy ); } @@ -729,6 +739,10 @@ static int MTex_setProjY( BPy_MTex *self, PyObject *value, void *closure ) { int proj; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + if( !PyInt_Check( value ) ) { return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.Proj dictionary" ); @@ -748,6 +762,10 @@ static int MTex_setProjY( BPy_MTex *self, PyObject *value, void *closure ) static PyObject *MTex_getProjZ( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyInt_FromLong( self->mtex->projz ); } @@ -755,6 +773,10 @@ static int MTex_setProjZ( BPy_MTex *self, PyObject *value, void *closure) { int proj; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + if( !PyInt_Check( value ) ) { return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.Proj dictionary" ); @@ -776,12 +798,14 @@ static PyObject *MTex_getMapToFlag( BPy_MTex *self, void *closure ) { int flag = GET_INT_FROM_POINTER(closure); + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + if ( self->mtex->mapto & flag ) - { return PyInt_FromLong( ( self->mtex->maptoneg & flag ) ? -1 : 1 ); - } else { + else return PyInt_FromLong( 0 ); - } } static int MTex_setMapToFlag( BPy_MTex *self, PyObject *value, void *closure) @@ -789,14 +813,17 @@ static int MTex_setMapToFlag( BPy_MTex *self, PyObject *value, void *closure) int flag = GET_INT_FROM_POINTER(closure); int intVal; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + if ( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "expected an int"); - intVal = PyInt_AsLong( value ); + intVal = PyInt_AsLong( value ) ; - if (flag == MAP_COL || flag == MAP_COLSPEC || flag == MAP_COLMIR || - flag == MAP_WARP) { + if( flag & ( MAP_COL | MAP_COLSPEC | MAP_COLMIR | MAP_WARP ) ) { if (intVal < 0 || intVal > 1) { return EXPP_ReturnIntError( PyExc_ValueError, "value for that mapping must be 0 or 1" ); diff --git a/source/blender/python/api2_2x/MTex.h b/source/blender/python/api2_2x/MTex.h index 5e67ebc47ca..b6c98a40d2e 100644 --- a/source/blender/python/api2_2x/MTex.h +++ b/source/blender/python/api2_2x/MTex.h @@ -38,22 +38,26 @@ /* Python BPy_MTex structure definition */ /*****************************************************************************/ +#define MATERIAL_MTEX_TYPE 1 +#define WORLD_MTEX_TYPE 2 +#define LAMP_MTEX_TYPE 3 + typedef struct { PyObject_HEAD MTex * mtex; + unsigned short type; } BPy_MTex; extern PyTypeObject MTex_Type; #define BPy_MTex_Check(v) ((v)->ob_type == &MTex_Type) - /*****************************************************************************/ /* Module Blender.Texture.MTex - public functions */ /*****************************************************************************/ PyObject *MTex_Init( void ); -PyObject *MTex_CreatePyObject( struct MTex *obj ); +PyObject *MTex_CreatePyObject( struct MTex *obj, unsigned short type ); MTex *MTex_FromPyObject( PyObject * py_obj ); diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c index 54c2d9b20bd..e32b87da240 100644 --- a/source/blender/python/api2_2x/Material.c +++ b/source/blender/python/api2_2x/Material.c @@ -555,6 +555,7 @@ static int Material_setSssFront( BPy_Material * self, PyObject * value ); static int Material_setSssBack( BPy_Material * self, PyObject * value ); static int Material_setSssBack( BPy_Material * self, PyObject * value ); static int Material_setTexChannel( BPy_Material * self, PyObject * value ); +static int Material_setTextures( BPy_Material * self, PyObject * value ); static PyObject *Material_getColorComponent( BPy_Material * self, void * closure ); @@ -1168,6 +1169,10 @@ static PyGetSetDef BPy_Material_getseters[] = { (getter)Material_getColorband, (setter)Material_setColorband, "The specular colorband for this material", (void *) 1}, + {"textures", + (getter)Material_getTextures, (setter)Material_setTextures, + "The Material's texture list as a tuple", + NULL}, /* SSS settings */ {"enableSSS", @@ -1737,27 +1742,23 @@ static PyObject* Material_getSssBack( BPy_Material * self ) static PyObject *Material_getTextures( BPy_Material * self ) { int i; - struct MTex *mtex; - PyObject *t[MAX_MTEX]; PyObject *tuple; /* build a texture list */ - for( i = 0; i < MAX_MTEX; ++i ) { - mtex = self->material->mtex[i]; - - if( mtex ) { - t[i] = MTex_CreatePyObject( mtex ); - } else { - Py_INCREF( Py_None ); - t[i] = Py_None; - } - } - - /* turn the array into a tuple */ - tuple = Py_BuildValue( "NNNNNNNNNNNNNNNNNN", t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], t[9], t[10], t[11], t[12], t[13], t[14], t[15], t[16], t[17] ); + tuple = PyTuple_New( MAX_MTEX ); if( !tuple ) return EXPP_ReturnPyObjError( PyExc_MemoryError, - "Material_getTextures: couldn't create PyTuple" ); + "couldn't create PyTuple" ); + + for( i = 0; i < MAX_MTEX; ++i ) { + struct MTex *mtex = self->material->mtex[i]; + if( mtex ) { + PyTuple_SET_ITEM( tuple, i, MTex_CreatePyObject( mtex, ID_MA ) ); + } else { + Py_INCREF( Py_None ); + PyTuple_SET_ITEM( tuple, i, Py_None ); + } + } return tuple; } @@ -2432,14 +2433,83 @@ static PyObject *Material_setTexture( BPy_Material * self, PyObject * args ) Py_RETURN_NONE; } +static int Material_setTextures( BPy_Material * self, PyObject * value ) +{ + int i; + + if( !PyList_Check( value ) && !PyTuple_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list of integers" ); + + /* don't allow more than MAX_MTEX items */ + if( PySequence_Size(value) > MAX_MTEX ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "size of sequence greater than number of allowed textures" ); + + /* get a fast sequence; in Python 2.5, this just return the original + * list or tuple and INCREFs it, so we must DECREF */ + value = PySequence_Fast( value, "" ); + + /* check the list for valid entries */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + if( item != Py_None && !BPy_MTex_Check( item ) ) { + Py_DECREF(value); + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list containing MTex objects and NONE" ); + } + } + + /* for each MTex object, copy to this structure */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->material->mtex[i]; + if( item != Py_None ) { + BPy_MTex *obj = (BPy_MTex *)item; + + /* if MTex is already at this location, just skip it */ + if( obj->mtex == mtex ) continue; + + /* create a new entry if needed, otherwise update reference count + * for texture that is being replaced */ + if( !mtex ) + mtex = self->material->mtex[i] = add_mtex( ); + else + mtex->tex->id.us--; + + /* copy the data */ + mtex->tex = obj->mtex->tex; + id_us_plus( &mtex->tex->id ); + mtex->texco = obj->mtex->texco; + mtex->mapto = obj->mtex->mapto; + } + } + + /* now go back and free any entries now marked as None */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->material->mtex[i]; + if( item == Py_None && mtex ) { + mtex->tex->id.us--; + MEM_freeN( mtex ); + self->material->mtex[i] = NULL; + } + } + + Py_DECREF(value); + return 0; +} + static PyObject *Material_clearTexture( BPy_Material * self, PyObject * value ) { int texnum = (int)PyInt_AsLong(value); struct MTex *mtex; /* non ints will be -1 */ - if( ( texnum < 0 ) || ( texnum >= MAX_MTEX ) ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected int in [0,9]" ); + if( ( texnum < 0 ) || ( texnum >= MAX_MTEX ) ) { + char errstr[64]; + sprintf( errstr, "expected int in [0,%d]", MAX_MTEX ); + return EXPP_ReturnPyObjError( PyExc_TypeError, errstr ); + } mtex = self->material->mtex[texnum]; if( mtex ) { diff --git a/source/blender/python/api2_2x/World.c b/source/blender/python/api2_2x/World.c index 6021f8552ad..3901e8296fb 100644 --- a/source/blender/python/api2_2x/World.c +++ b/source/blender/python/api2_2x/World.c @@ -52,6 +52,7 @@ #include "BIF_space.h" #include "mydevice.h" #include "Ipo.h" +#include "MTex.h" #include "gen_utils.h" #include "gen_library.h" @@ -99,6 +100,7 @@ static PyObject *World_getScriptLinks( BPy_World * self, PyObject * value ); static PyObject *World_addScriptLink( BPy_World * self, PyObject * args ); static PyObject *World_clearScriptLinks( BPy_World * self, PyObject * args ); static PyObject *World_setCurrent( BPy_World * self ); +static PyObject *World_getTextures( BPy_World * self ); static PyObject *World_copy( BPy_World * self ); @@ -250,6 +252,9 @@ static PyGetSetDef BPy_World_getseters[] = { "world mist settings", NULL}, {"ipo", (getter)World_getIpo, (setter)World_setIpo, "world ipo", NULL}, + {"textures", (getter)World_getTextures, (setter)NULL, + "The World's texture list as a tuple", + NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; @@ -1029,3 +1034,27 @@ static PyObject *World_insertIpoKey( BPy_World * self, PyObject * args ) Py_RETURN_NONE; } + +static PyObject *World_getTextures( BPy_World * self ) +{ + int i; + PyObject *tuple; + + /* build a texture list */ + tuple = PyTuple_New( MAX_MTEX ); + if( !tuple ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, + "couldn't create PyTuple" ); + + for( i = 0; i < MAX_MTEX; ++i ) { + struct MTex *mtex = self->world->mtex[i]; + if( mtex ) { + PyTuple_SET_ITEM( tuple, i, MTex_CreatePyObject( mtex, ID_WO ) ); + } else { + Py_INCREF( Py_None ); + PyTuple_SET_ITEM( tuple, i, Py_None ); + } + } + + return tuple; +} diff --git a/source/blender/python/api2_2x/doc/Lamp.py b/source/blender/python/api2_2x/doc/Lamp.py index a7a1fb94620..162d94ccff3 100644 --- a/source/blender/python/api2_2x/doc/Lamp.py +++ b/source/blender/python/api2_2x/doc/Lamp.py @@ -161,6 +161,8 @@ class Lamp: @type type: int @ivar falloffType: Lamp falloff type. See L{Falloffs} for values. @type falloffType: int + @type textures: a tuple of Blender MTex objects. + @ivar textures: The Lamp's texture list. Empty texture channels contains None. @warning: Most member variables assume values in some [Min, Max] interval. When trying to set them, the given parameter will be clamped to lie in diff --git a/source/blender/python/api2_2x/doc/Material.py b/source/blender/python/api2_2x/doc/Material.py index 02f7edd77f5..05497cf551c 100644 --- a/source/blender/python/api2_2x/doc/Material.py +++ b/source/blender/python/api2_2x/doc/Material.py @@ -338,7 +338,9 @@ class Material: ch.append(4) mat.enabledTextures = ch print mat.enabledTextures # will print: [0, 4, 6] - + + @type textures: a tuple of Blender MTex objects. + @ivar textures: the Material's Texture list. Empty texture channels contains None. @ivar enableSSS: If True, subsurface scattering will be rendered on this material. @type enableSSS: bool @ivar sssScale: If True, subsurface scattering will be rendered on this material. diff --git a/source/blender/python/api2_2x/doc/Texture.py b/source/blender/python/api2_2x/doc/Texture.py index cebb7de7011..223c5e6ebdd 100644 --- a/source/blender/python/api2_2x/doc/Texture.py +++ b/source/blender/python/api2_2x/doc/Texture.py @@ -500,48 +500,84 @@ class MTex: This object links a material to a texture. It allows the same texture to be used in several different ways. - @ivar tex: The Texture this is linked to. - @type tex: Blender Texture - @ivar texco: Texture coordinates ("Map input"). See L{TexCo} - @ivar mapto: "Map to" field of texture. OR'd values of L{MapTo} - @ivar object: Object whose space to use when texco is Object - @type object: Blender Object - @ivar col: Color that the texture blends with - @ivar dvar: Value that the texture blends with when not blending colors - @ivar blendmode: Texture blending mode. L{BlendModes} - @ivar colfac: Factor by which texture affects color - @ivar norfac: Factor by which texture affects normal - @ivar varfac: Factor by which texture affects most variables - @ivar dispfac: Factor by which texture affects displacement - @ivar warpfac: Factor by which texture affects warp - @ivar ofs: Offset to adjust texture space - @ivar size: Size to scale texture space - @ivar mapping: Mapping of texture coordinates (flat, cube, etc.). L{Mappings} - @ivar stencil: Stencil mode - @ivar neg: Negate texture values mode - @ivar noRGB: Convert texture RGB values to intensity values - @ivar correctNor: Correct normal mapping for Texture space and Object space - @ivar fromDupli: Dupli's instanced from verts, faces or particles, inherit texture coordinate from their parent - @ivar fromOrig: Dupli's derive their object coordinates from the original objects transformation - @ivar xproj: Projection of X axis to Texture space. L{Proj} - @ivar yproj: Projection of Y axis to Texture space. L{Proj} - @ivar zproj: Projection of Z axis to Texture space. L{Proj} - @ivar mtCol: How texture maps to color - @ivar mtNor: How texture maps to normals - @ivar mtCsp: How texture maps to specularity color - @ivar mtCmir: How texture maps to mirror color - @ivar mtRef: How texture maps to reflectivity - @ivar mtSpec: How texture maps to specularity - @ivar mtEmit: How texture maps to emit value - @ivar mtAlpha: How texture maps to alpha value - @ivar mtHard: How texture maps to hardness - @ivar mtRayMir: How texture maps to RayMir value - @ivar mtTranslu: How texture maps to translucency - @ivar mtAmb: How texture maps to ambient value - @ivar mtDisp: How texture maps to displacement - @ivar mtWarp: How texture maps to warp - @ivar uvlayer: The name of the UV Layer this texture is mapped to (when left blank uses render layer) - @type uvlayer: string + @type blendmode: int + @ivar blendmode: Texture blending mode. See L{BlendModes} + @type col: tuple + @ivar col: Color that the texture blends with. Range of. + @type colfac: float + @ivar colfac: Factor by which texture affects color. + @ivar correctNor: Correct normal mapping for Texture space and Object space. + @type correctNor: boolean + @type dispfac: float + @ivar dispfac: Factor by which texture affects displacement. + @type dvar: float + @ivar dvar: Value that the texture blends with when not blending colors. + @type fromDupli: boolean + @ivar fromDupli: Duplis instanced from verts, faces or particles, inherit texture coordinate from their parent. + @type fromOrig: boolean + @ivar fromOrig: Duplis derive their object coordinates from the original objects transformation. + @type mapping: int + @ivar mapping: Mapping of texture coordinates (flat, cube, etc.). See L{Mappings}. + @type mapto: int + @ivar mapto: "Map to" field of texture. OR'd values of L{MapTo}. + @ivar mtAlpha: How texture maps to alpha value. + @type mtAlpha: int + @ivar mtAmb: How texture maps to ambient value. + @type mtAmb: int + @ivar mtCmir: How texture maps to mirror color. + @type mtCmir: int + @ivar mtCol: How texture maps to color. + @type mtCol: int + @ivar mtCsp: How texture maps to specularity color + @type mtCsp: int + @ivar mtDisp: How texture maps to displacement + @type mtDisp: int + @ivar mtEmit: How texture maps to emit value + @type mtEmit: int + @ivar mtHard: How texture maps to hardness + @type mtHard: int + @ivar mtNor: How texture maps to normals + @type mtNor: int + @ivar mtRayMir: How texture maps to RayMir value + @type mtRayMir: int + @ivar mtRef: How texture maps to reflectivity + @type mtRef: int + @ivar mtSpec: How texture maps to specularity + @type mtSpec: int + @ivar mtTranslu: How texture maps to translucency + @type mtTranslu: int + @ivar mtWarp: How texture maps to warp + @type mtWarp: int + @ivar neg: Negate texture values mode + @type neg: boolean + @ivar norfac: Factor by which texture affects normal + @type norfac: float + @ivar noRGB: Convert texture RGB values to intensity values + @type noRGB: boolean + @ivar object: Object whose space to use when texco is Object + @type object: Blender Object or None + @type ofs: tuple + @ivar ofs: Offset to adjust texture space + @type size: tuple + @ivar size: Size to scale texture space + @ivar stencil: Stencil mode + @type stencil: boolean + @ivar tex: The Texture this is linked to. + @type tex: Blender Texture + @ivar texco: Texture coordinates ("Map input"). See L{TexCo} + @type texco: int + @ivar uvlayer: The name of the UV Layer this texture is mapped to (when left blank uses render layer) + @type uvlayer: string + @type varfac: float + @ivar varfac: Factor by which texture affects most variables + @type warpfac: float + @ivar warpfac: Factor by which texture affects warp + @type xproj: int + @ivar xproj: Projection of X axis to Texture space. See L{Proj} + @type yproj: int + @ivar yproj: Projection of Y axis to Texture space. See L{Proj} + @type zproj: int + @ivar zproj: Projection of Z axis to Texture space. See L{Proj} """ def getIpo(): diff --git a/source/blender/python/api2_2x/doc/World.py b/source/blender/python/api2_2x/doc/World.py index d9e9bae750d..d8052c609cd 100644 --- a/source/blender/python/api2_2x/doc/World.py +++ b/source/blender/python/api2_2x/doc/World.py @@ -82,6 +82,8 @@ class World: @ivar mist: the mist parameters of a world object. See getMist for the semantics of these parameters. @type ipo: Blender Ipo @ivar ipo: The world type ipo linked to this world object. + @type textures: a tuple of Blender MTex objects. + @ivar textures: The World's texture list. Empty texture channels contains None. """ def getRange(): From 70be839859852f9fcf3ab234093c390d5b2c9c05 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Tue, 9 Sep 2008 10:16:09 +0000 Subject: [PATCH 12/32] Bugfix #13837 Tonemap didn't correctly accept any buffer type. The coder who added this should check this fix! Any node coder maybe... --- source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c b/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c index 5e1803a6774..950ad97a397 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c @@ -130,13 +130,16 @@ static void node_composit_exec_tonemap(void *data, bNode *node, bNodeStack **in, if ((img==NULL) || (out[0]->hasoutput==0)) return; if (img->type != CB_RGBA) - new = typecheck_compbuf(img, CB_RGBA); - else - new = dupalloc_compbuf(img); + img = typecheck_compbuf(img, CB_RGBA); + + new = dupalloc_compbuf(img); tonemap(node->storage, new, img); out[0]->data = new; + + if(img!=in[0]->data) + free_compbuf(img); } static void node_composit_init_tonemap(bNode* node) From 0995466927632a34ac4f8bbbc48709178d796836 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 9 Sep 2008 10:58:58 +0000 Subject: [PATCH 13/32] wasnt using icon buttons correctly --- source/blender/src/buttons_logic.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index df76534f3f5..934ff9e008a 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -3379,7 +3379,8 @@ void logic_buts(void) uiBlockSetEmboss(block, UI_EMBOSSM); uiDefIconButBitS(block, TOG, SENS_DEL, B_DEL_SENS, ICON_X, xco, yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Delete Sensor"); if (pin) - uiDefIconButBitS(block, ICONTOG, SENS_PIN, B_REDR, (sens->flag & SENS_PIN) ? ICON_PIN_DEHLT:ICON_PIN_HLT, (short)(xco+width-44), yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller"); + uiDefIconButBitS(block, ICONTOG, SENS_PIN, B_REDR, ICON_PIN_DEHLT, (short)(xco+width-44), yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller"); + uiDefIconButBitS(block, ICONTOG, SENS_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Sensor settings"); ycoo= yco; @@ -3456,7 +3457,7 @@ void logic_buts(void) uiBlockSetEmboss(block, UI_EMBOSSM); uiDefIconButBitS(block, TOG, ACT_DEL, B_DEL_ACT, ICON_X, xco, yco, 22, 19, &act->flag, 0, 0, 0, 0, "Delete Actuator"); if (pin) - uiDefIconButBitS(block, ICONTOG, ACT_PIN, B_REDR, (act->flag & ACT_PIN) ? ICON_PIN_DEHLT:ICON_PIN_HLT, (short)(xco+width-44), yco, 22, 19, &act->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller"); + uiDefIconButBitS(block, ICONTOG, ACT_PIN, B_REDR, ICON_PIN_DEHLT, (short)(xco+width-44), yco, 22, 19, &act->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller"); uiDefIconButBitS(block, ICONTOG, ACT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &act->flag, 0, 0, 0, 0, "Display the actuator"); if(act->flag & ACT_SHOW) { From ad31f6a4b31183ecdbb7f71ba080e50e3577de4d Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Tue, 9 Sep 2008 11:40:29 +0000 Subject: [PATCH 14/32] Bugfix #13675 Edge render made star render disappear. Wrong Z value comparing... (2 year old bug!) --- source/blender/render/intern/source/rendercore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 5b8cedfce78..bda02bea8d7 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -158,7 +158,7 @@ static int calchalo_z(HaloRen *har, int zz) { if(har->type & HA_ONLYSKY) { - if(zz!=0x7FFFFFFF) zz= - 0x7FFFFF; + if(zz < 0x7FFFFFF0) zz= - 0x7FFFFF; /* edge render messes zvalues */ } else { zz= (zz>>8); From 4db3d6c595d696ebe0a9b4125c6df8b9e10cadf4 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Tue, 9 Sep 2008 12:00:38 +0000 Subject: [PATCH 15/32] Bugfix #13653 Autosave disable didn't work. Note however that a disabled autosave only gets active on saving the user settings, and loading blender again. This is a timer that gets set on startup. I didn't code a kill timer. :) --- source/blender/src/editscreen.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/blender/src/editscreen.c b/source/blender/src/editscreen.c index 1cd8733a7ea..976e58ed102 100644 --- a/source/blender/src/editscreen.c +++ b/source/blender/src/editscreen.c @@ -1023,8 +1023,11 @@ int blender_test_break(void) return (G.afbreek==1); } -void reset_autosave(void) { - window_set_timer(mainwin, U.savetime*60*1000, AUTOSAVE_FILE); +void reset_autosave(void) +{ + if(U.flag & USER_AUTOSAVE) { + window_set_timer(mainwin, U.savetime*60*1000, AUTOSAVE_FILE); + } } /* ************ handlers ************** */ From 7366834443a65e05e3eb160a00ed689da9a866ad Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Tue, 9 Sep 2008 12:51:22 +0000 Subject: [PATCH 16/32] Bugfix #13596 Wrong popup on single-user particles, it said "make local". --- source/blender/src/buttons_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 18384dd90b3..0f968a7c60c 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -3001,7 +3001,7 @@ void do_effects_panels(unsigned short event) if(ob && (psys=psys_get_current(ob))){ if(psys->part) { if(psys->part->id.us>1){ - if(okee("Make local")){ + if(okee("Make Single User")){ part=psys_copy_settings(psys->part); part->id.us=1; psys->part->id.us--; From 68d7f0a3d15b750d0c166114c74f19ee72cea3cb Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Tue, 9 Sep 2008 13:35:38 +0000 Subject: [PATCH 17/32] Bugfix #13592 Sequencer, Time, Sound windows were drawing frame numbers double when too far zoomed in. --- source/blender/src/drawipo.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c index 9b5be04eac1..87e36c4ad24 100644 --- a/source/blender/src/drawipo.c +++ b/source/blender/src/drawipo.c @@ -921,6 +921,13 @@ void drawscroll(int disptype) BIF_ThemeColor(TH_TEXT); val= ipogrid_startx; + + if (ELEM3(curarea->spacetype, SPACE_SEQ, SPACE_SOUND, SPACE_TIME)) { /* prevents printing twice same frame */ + while(ipogrid_dx < 0.9999f) { + ipogrid_dx *= 2.0f; + dfac*= 2.0f; + } + } while(fac < hor.xmax) { if(curarea->spacetype==SPACE_OOPS) { From 160c0de87b7b7d03a4516e2a1e7bd548d6cbcf3d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 9 Sep 2008 14:16:54 +0000 Subject: [PATCH 18/32] Fix for bug #17580: crash rendering instanced objects with halo material attach to the object instead of the mesh. Also for bug #13489: avoid a crash rendering with invalid active vcol layer, most likely caused by a bug that was already fixed. --- .../blender/render/intern/source/convertblender.c | 14 ++++++++------ .../blender/render/intern/source/renderdatabase.c | 14 +++++++------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 9ee6f873f3f..322d2066a6c 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -4578,17 +4578,19 @@ static int allow_render_object(Object *ob, int nolamps, int onlyselected, Object static int allow_render_dupli_instance(Render *re, DupliObject *dob, Object *obd) { ParticleSystem *psys; - Material ***material; + Material *ma; short a, *totmaterial; - /* don't allow objects with halos */ + /* don't allow objects with halos. we need to have + * all halo's to sort them globally in advance */ totmaterial= give_totcolp(obd); - material= give_matarar(obd); - if(totmaterial && material) { - for(a= 0; a<*totmaterial; a++) - if((*material)[a] && (*material)[a]->mode & MA_HALO) + if(totmaterial) { + for(a= 0; a<*totmaterial; a++) { + ma= give_current_material(obd, a); + if(ma && (ma->mode & MA_HALO)) return 0; + } } for(psys=obd->particlesystem.first; psys; psys=psys->next) diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 98b1426e8ff..d44b49cc706 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -483,16 +483,16 @@ void RE_set_customdata_names(ObjectRen *obr, CustomData *data) DerivedMesh which stores the layers is freed */ CustomDataLayer *layer; - int numlayers, i, mtfn, mcn; + int numtf = 0, numcol = 0, i, mtfn, mcn; if (CustomData_has_layer(data, CD_MTFACE)) { - numlayers= CustomData_number_of_layers(data, CD_MTFACE); - obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numlayers, "mtfacenames"); + numtf= CustomData_number_of_layers(data, CD_MTFACE); + obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numtf, "mtfacenames"); } if (CustomData_has_layer(data, CD_MCOL)) { - numlayers= CustomData_number_of_layers(data, CD_MCOL); - obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numlayers, "mcolnames"); + numcol= CustomData_number_of_layers(data, CD_MCOL); + obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numcol, "mcolnames"); } for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) { @@ -500,12 +500,12 @@ void RE_set_customdata_names(ObjectRen *obr, CustomData *data) if (layer->type == CD_MTFACE) { strcpy(obr->mtface[mtfn++], layer->name); - obr->actmtface= layer->active_rnd; + obr->actmtface= CLAMPIS(layer->active_rnd, 0, numtf); obr->bakemtface= layer->active; } else if (layer->type == CD_MCOL) { strcpy(obr->mcol[mcn++], layer->name); - obr->actmcol= layer->active_rnd; + obr->actmcol= CLAMPIS(layer->active_rnd, 0, numcol); } } } From e9b08b64fae2c8c5197f9c1e724f4017244a973c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 9 Sep 2008 15:15:01 +0000 Subject: [PATCH 19/32] Fix for bug #17402: IK influence blending with pole targets didn't give smooth transition. Now it blends the result of IK solving in that case. --- source/blender/blenkernel/intern/armature.c | 21 ++++++++++++++++---- source/blender/blenlib/BLI_arithb.h | 1 + source/blender/blenlib/intern/arithb.c | 22 +++++++++++++++++++++ 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index fb7d59c137a..720ed0513ed 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1690,7 +1690,7 @@ static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip) were executed & assigned. Now as last we do an IK pass */ static void execute_posetree(Object *ob, PoseTree *tree) { - float R_parmat[3][3]; + float R_parmat[3][3], identity[3][3]; float iR_parmat[3][3]; float R_bonemat[3][3]; float goalrot[3][3], goalpos[3]; @@ -1699,7 +1699,8 @@ static void execute_posetree(Object *ob, PoseTree *tree) float irest_basis[3][3], full_basis[3][3]; float end_pose[4][4], world_pose[4][4]; float length, basis[3][3], rest_basis[3][3], start[3], *ikstretch=NULL; - int a, flag, hasstretch=0; + float resultinf=0.0f; + int a, flag, hasstretch=0, resultblend=0; bPoseChannel *pchan; IK_Segment *seg, *parent, **iktree, *iktarget; IK_Solver *solver; @@ -1844,6 +1845,12 @@ static void execute_posetree(Object *ob, PoseTree *tree) Mat4MulMat4(goal, rootmat, goalinv); VECCOPY(polepos, goal[3]); poleconstrain= 1; + + /* for pole targets, we blend the result of the ik solver + * instead of the target position, otherwise we can't get + * a smooth transition */ + resultblend= 1; + resultinf= target->con->enforce; if(data->flag & CONSTRAINT_IK_GETANGLE) { poleangledata= data; @@ -1853,7 +1860,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) } /* do we need blending? */ - if (target->con->enforce!=1.0) { + if (!resultblend && target->con->enforce!=1.0) { float q1[4], q2[4], q[4]; float fac= target->con->enforce; float mfac= 1.0-fac; @@ -1903,7 +1910,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) tree->basis_change= MEM_mallocN(sizeof(float[3][3])*tree->totchannel, "ik basis change"); if(hasstretch) ikstretch= MEM_mallocN(sizeof(float)*tree->totchannel, "ik stretch"); - + for(a=0; atotchannel; a++) { IK_GetBasisChange(iktree[a], tree->basis_change[a]); @@ -1931,6 +1938,12 @@ static void execute_posetree(Object *ob, PoseTree *tree) VecMulf(tree->basis_change[a][1], stretch); VecMulf(tree->basis_change[a][2], stretch); } + + if(resultblend && resultinf!=1.0f) { + Mat3One(identity); + Mat3BlendMat3(tree->basis_change[a], identity, + tree->basis_change[a], resultinf); + } IK_FreeSegment(iktree[a]); } diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 4448231b2b4..6e54fae58d0 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -164,6 +164,7 @@ void Mat3Inv(float m1[][3], float m2[][3]); void Mat3CpyMat4(float m1[][3],float m2[][4]); void Mat4CpyMat3(float m1[][4], float m2[][3]); +void Mat3BlendMat3(float out[][3], float dst[][3], float src[][3], float srcweight); void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight); float Det2x2(float a,float b,float c, float d); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 50f8ba0fcde..f89f90f7045 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -759,6 +759,28 @@ void Mat4MulSerie(float answ[][4], float m1[][4], } } +void Mat3BlendMat3(float out[][3], float dst[][3], float src[][3], float srcweight) +{ + float squat[4], dquat[4], fquat[4]; + float ssize[3], dsize[3], fsize[4]; + float rmat[3][3], smat[3][3]; + + Mat3ToQuat(dst, dquat); + Mat3ToSize(dst, dsize); + + Mat3ToQuat(src, squat); + Mat3ToSize(src, ssize); + + /* do blending */ + QuatInterpol(fquat, dquat, squat, srcweight); + VecLerpf(fsize, dsize, ssize, srcweight); + + /* compose new matrix */ + QuatToMat3(fquat, rmat); + SizeToMat3(fsize, smat); + Mat3MulMat3(out, rmat, smat); +} + void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight) { float squat[4], dquat[4], fquat[4]; From d9404adcd177d3a67bd5d32fbe883d709f91cbae Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 9 Sep 2008 16:38:08 +0000 Subject: [PATCH 20/32] Bugfix #17562: array fit to curve isnt working --- source/blender/blenkernel/intern/modifier.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 4c74fe1cca2..936081ab94f 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -793,12 +793,18 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) { Curve *cu = amd->curve_ob->data; if(cu) { + float tmp_mat[3][3]; + float scale; + + object_to_mat3(amd->curve_ob, tmp_mat); + scale = Mat3ToScalef(tmp_mat); + if(!cu->path) { cu->flag |= CU_PATH; // needed for path & bevlist makeDispListCurveTypes(amd->curve_ob, 0); } if(cu->path) - length = cu->path->totdist; + length = scale*cu->path->totdist; } } From be19db6854bea16284f46b1e0fe92a9c70f72f80 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 9 Sep 2008 17:27:01 +0000 Subject: [PATCH 21/32] Fix for bug #12132: vector blur with fast moving objects does not give a smooth fallof. there's no correct fix possible due to a lack of information, but this manually adds a smoother falloff, overestimating the contribution of foregroud pixels instead of becoming transparent. --- source/blender/render/intern/source/zbuf.c | 90 ++++++++++++++++------ 1 file changed, 66 insertions(+), 24 deletions(-) diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index be555443605..76a47a11338 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -2981,10 +2981,11 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * { ZSpan zspan; DrawBufPixel *rectdraw, *dr; - static float jit[16][2]; + static float jit[256][2]; float v1[3], v2[3], v3[3], v4[3], fx, fy; - float *rectvz, *dvz, *dimg, *dvec1, *dvec2, *dz, *dz1, *dz2, *rectz, *minvecbufrect= NULL; - float maxspeedsq= (float)nbd->maxspeed*nbd->maxspeed; + float *rectvz, *dvz, *dimg, *dvec1, *dvec2, *dz, *dz1, *dz2, *rectz; + float *minvecbufrect= NULL, *rectweight, *rw, *rectmax, *rm, *ro; + float maxspeedsq= (float)nbd->maxspeed*nbd->maxspeed, totfac; int y, x, step, maxspeed=nbd->maxspeed, samples= nbd->samples; int tsktsk= 0; static int firsttime= 1; @@ -3003,6 +3004,9 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * rectmove= MEM_mapallocN(xsize*ysize, "rectmove"); rectdraw= MEM_mapallocN(sizeof(DrawBufPixel)*xsize*ysize, "rect draw"); zspan.rectp= (int *)rectdraw; + + rectweight= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect weight"); + rectmax= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect max"); /* debug... check if PASS_VECTOR_MAX still is in buffers */ dvec1= vecbufrect; @@ -3142,7 +3146,7 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * dm= rectmove; dvec1= vecbufrect; for(x=xsize*ysize; x>0; x--, dm++, dvec1+=4) { - if(dvec1[0]!=0.0f || dvec1[1]!=0.0f || dvec1[2]!=0.0f || dvec1[3]!=0.0f) + if((dvec1[0]!=0.0f || dvec1[1]!=0.0f || dvec1[2]!=0.0f || dvec1[3]!=0.0f)) *dm= 255; } @@ -3151,9 +3155,12 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * /* has to become static, the init-jit calls a random-seed, screwing up texture noise node */ if(firsttime) { firsttime= 0; - BLI_initjit(jit[0], 16); + BLI_initjit(jit[0], 256); } + memset(newrect, 0, sizeof(float)*xsize*ysize*4); + totfac= 0.0f; + /* accumulate */ samples/= 2; for(step= 1; step<=samples; step++) { @@ -3161,7 +3168,7 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * int side; for(side=0; side<2; side++) { - float blendfac= 1.0f/((ABS(step)*2+side)+1), ipodata[4]; + float blendfac, ipodata[4]; /* clear zbuf, if we draw future we fill in not moving pixels */ if(0) @@ -3193,30 +3200,32 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * set_quad_bezier_ipo(0.5f + 0.5f*speedfac, ipodata); - for(fy= -0.5f+jit[step & 15][0], y=0; y1) { + float jfx = fx + 0.5f; + float jfy = fy + 0.5f; DrawBufPixel col; /* make vertices */ if(nbd->curved) { /* curved */ quad_bezier_2d(v1, dz1, dz1+2, ipodata); - v1[0]+= fx; v1[1]+= fy; v1[2]= *dz; + v1[0]+= jfx; v1[1]+= jfy; v1[2]= *dz; quad_bezier_2d(v2, dz1+4, dz1+4+2, ipodata); - v2[0]+= fx+1.0f; v2[1]+= fy; v2[2]= *dz; + v2[0]+= jfx+1.0f; v2[1]+= jfy; v2[2]= *dz; quad_bezier_2d(v3, dz2+4, dz2+4+2, ipodata); - v3[0]+= fx+1.0f; v3[1]+= fy+1.0f; v3[2]= *dz; + v3[0]+= jfx+1.0f; v3[1]+= jfy+1.0f; v3[2]= *dz; quad_bezier_2d(v4, dz2, dz2+2, ipodata); - v4[0]+= fx; v4[1]+= fy+1.0f; v4[2]= *dz; + v4[0]+= jfx; v4[1]+= jfy+1.0f; v4[2]= *dz; } else { - v1[0]= speedfac*dz1[0]+fx; v1[1]= speedfac*dz1[1]+fy; v1[2]= *dz; - v2[0]= speedfac*dz1[4]+fx+1.0f; v2[1]= speedfac*dz1[5]+fy; v2[2]= *dz; - v3[0]= speedfac*dz2[4]+fx+1.0f; v3[1]= speedfac*dz2[5]+fy+1.0f; v3[2]= *dz; - v4[0]= speedfac*dz2[0]+fx; v4[1]= speedfac*dz2[1]+fy+1.0f; v4[2]= *dz; + v1[0]= speedfac*dz1[0]+jfx; v1[1]= speedfac*dz1[1]+jfy; v1[2]= *dz; + v2[0]= speedfac*dz1[4]+jfx+1.0f; v2[1]= speedfac*dz1[5]+jfy; v2[2]= *dz; + v3[0]= speedfac*dz2[4]+jfx+1.0f; v3[1]= speedfac*dz2[5]+jfy+1.0f; v3[2]= *dz; + v4[0]= speedfac*dz2[0]+jfx; v4[1]= speedfac*dz2[1]+jfy+1.0f; v4[2]= *dz; } if(*dm==255) col.alpha= 1.0f; else if(*dm<2) col.alpha= 0.0f; @@ -3229,26 +3238,59 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * dz1+=4; dz2+=4; } - + + /* blend with a falloff. this fixes the ugly effect you get with + * a fast moving object. then it looks like a solid object overlayed + * over a very transparent moving version of itself. in reality, the + * whole object should become transparent if it is moving fast, be + * we don't know what is behind it so we don't do that. this hack + * overestimates the contribution of foreground pixels but looks a + * bit better without a sudden cutoff. */ + blendfac= ((samples - step)/(float)samples); + /* smoothstep to make it look a bit nicer as well */ + blendfac= 3.0f*pow(blendfac, 2.0f) - 2.0f*pow(blendfac, 3.0f); + /* accum */ - for(dr= rectdraw, dz2=newrect, x= xsize*ysize-1; x>=0; x--, dr++, dz2+=4) { + rw= rectweight; + rm= rectmax; + for(dr= rectdraw, dz2=newrect, x= xsize*ysize-1; x>=0; x--, dr++, dz2+=4, rw++, rm++) { if(dr->colpoin) { - float bfac= dr->alpha*blendfac*dr->colpoin[3]; - float mf= 1.0f - bfac; + float bfac= dr->alpha*blendfac; - dz2[0]= mf*dz2[0] + bfac*dr->colpoin[0]; - dz2[1]= mf*dz2[1] + bfac*dr->colpoin[1]; - dz2[2]= mf*dz2[2] + bfac*dr->colpoin[2]; - dz2[3]= mf*dz2[3] + bfac*dr->colpoin[3]; + dz2[0] += bfac*dr->colpoin[0]; + dz2[1] += bfac*dr->colpoin[1]; + dz2[2] += bfac*dr->colpoin[2]; + dz2[3] += bfac*dr->colpoin[3]; + + *rw += bfac; + *rm= MAX2(*rm, bfac); } } } } + /* blend between original images and accumulated image */ + rw= rectweight; + rm= rectmax; + ro= imgrect; + dm= rectmove; + for(dz2=newrect, x= xsize*ysize-1; x>=0; x--, dz2+=4, ro+=4, rw++, rm++, dm++) { + float mfac = *rm; + float fac = (*rw == 0.0f)? 0.0f: mfac/(*rw); + float nfac = 1.0f - mfac; + + dz2[0]= fac*dz2[0] + nfac*ro[0]; + dz2[1]= fac*dz2[1] + nfac*ro[1]; + dz2[2]= fac*dz2[2] + nfac*ro[2]; + dz2[3]= fac*dz2[3] + nfac*ro[3]; + } + MEM_freeN(rectz); MEM_freeN(rectmove); MEM_freeN(rectdraw); MEM_freeN(rectvz); + MEM_freeN(rectweight); + MEM_freeN(rectmax); if(minvecbufrect) MEM_freeN(vecbufrect); /* rects were swapped! */ zbuf_free_span(&zspan); } From 568ba1572655a42728145eda67790652008c8b2b Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 9 Sep 2008 18:44:10 +0000 Subject: [PATCH 22/32] Bugfix for [#17329] Bevel Weights are lost after Subsurf --- source/blender/blenkernel/intern/subsurf_ccg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index f334fc39daa..d7e9fd556b6 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -700,6 +700,7 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, for(index = 0; index < totedge; index++) { CCGEdge *e = edgeMap2[index]; unsigned int flags = 0; + char bweight = 0; int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(ss, e)); if(!ccgSubSurf_getEdgeNumFaces(ss, e)) flags |= ME_LOOSEEDGE; @@ -710,12 +711,14 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, dm->getEdge(dm, edgeIdx, &origMed); flags |= origMed.flag; + bweight = origMed.bweight; } for(x = 0; x < edgeSize - 1; x++) { med->v1 = getEdgeIndex(ss, e, x, edgeSize); med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize); med->flag = flags; + med->bweight = bweight; *origIndex = ccgDM_getEdgeMapIndex(NULL, ss, e); ++med; ++origIndex; From 84d7e2ea9cb514b5cdcdb6dea185ab292d3810f3 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 9 Sep 2008 20:00:57 +0000 Subject: [PATCH 23/32] Fix for bug #17443: make bone heat weighting solve a bit less sensitive to poorly shaped geometry, should succeed solving in more cases now. --- source/blender/include/BIF_meshlaplacian.h | 2 +- source/blender/src/meshlaplacian.c | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/source/blender/include/BIF_meshlaplacian.h b/source/blender/include/BIF_meshlaplacian.h index 9fb8aad0eb6..71db8d0bba2 100644 --- a/source/blender/include/BIF_meshlaplacian.h +++ b/source/blender/include/BIF_meshlaplacian.h @@ -47,7 +47,7 @@ struct EditMesh; struct LaplacianSystem; typedef struct LaplacianSystem LaplacianSystem; -LaplacianSystem *laplacian_construct_begin(int totvert, int totface); +LaplacianSystem *laplacian_construct_begin(int totvert, int totface, int lsq); void laplacian_add_vertex(LaplacianSystem *sys, float *co, int pinned); void laplacian_add_triangle(LaplacianSystem *sys, int v1, int v2, int v3); diff --git a/source/blender/src/meshlaplacian.c b/source/blender/src/meshlaplacian.c index 2de6367c9ad..c2ad60ea842 100644 --- a/source/blender/src/meshlaplacian.c +++ b/source/blender/src/meshlaplacian.c @@ -178,6 +178,7 @@ static void laplacian_triangle_area(LaplacianSystem *sys, int i1, int i2, int i3 varea[i1] += (obtuse == 1)? area: area*0.5; varea[i2] += (obtuse == 2)? area: area*0.5; varea[i3] += (obtuse == 3)? area: area*0.5; + //printf("area %f\n", area); } else { len1= VecLenf(v2, v3); @@ -191,7 +192,10 @@ static void laplacian_triangle_area(LaplacianSystem *sys, int i1, int i2, int i3 varea[i1] += (t2 + t3)*0.25f; varea[i2] += (t1 + t3)*0.25f; varea[i3] += (t1 + t2)*0.25f; + //printf("varea %f %f %f\n", t1, t2, t3); } + + //printf("triangle area %f %f %f\n", t1, t2, t3); } static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int i2, int i3) @@ -204,7 +208,7 @@ static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int v3= sys->verts[i3]; /* instead of *0.5 we divided by the number of faces of the edge, it still - needs to be varified that this is indeed the correct thing to do! */ + needs to be verified that this is indeed the correct thing to do! */ t1= cotan_weight(v1, v2, v3)/laplacian_edge_count(sys->edgehash, i2, i3); t2= cotan_weight(v2, v3, v1)/laplacian_edge_count(sys->edgehash, i3, i1); t3= cotan_weight(v3, v1, v2)/laplacian_edge_count(sys->edgehash, i1, i2); @@ -229,7 +233,7 @@ static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int } } -LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface) +LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface, int lsq) { LaplacianSystem *sys; @@ -248,6 +252,8 @@ LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface) /* create opennl context */ nlNewContext(); nlSolverParameteri(NL_NB_VARIABLES, totvert); + if(lsq) + nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); sys->context= nlGetCurrent(); @@ -292,7 +298,7 @@ void laplacian_system_construct_end(LaplacianSystem *sys) for(a=0; aareaweights) { if(sys->varea[a] != 0.0f) - sys->varea[a]= 0.5f/sys->varea[a]; + sys->varea[a]= 0.5f/sys->varea[a]; //MAX2(sys->varea[a], 0.001f); } else sys->varea[a]= 1.0f; @@ -631,7 +637,7 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numbones, } /* create laplacian */ - sys = laplacian_system_construct_begin(me->totvert, totface); + sys = laplacian_system_construct_begin(me->totvert, totface, 1); sys->heat.mesh= me; sys->heat.verts= verts; @@ -933,7 +939,7 @@ void rigid_deform_begin(EditMesh *em) } /* create laplacian */ - sys = laplacian_system_construct_begin(totvert, totface); + sys = laplacian_system_construct_begin(totvert, totface, 0); sys->rigid.mesh= em; sys->rigid.R = MEM_callocN(sizeof(float)*3*3*totvert, "RigidDeformR"); From df1d59805ff74ee5ab36d5cc6d400f8a4eb12eff Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 9 Sep 2008 20:09:54 +0000 Subject: [PATCH 24/32] Fix for bug #17588: crash with ctrl+a and no active object. --- source/blender/src/editobject.c | 1 + source/blender/src/meshlaplacian.c | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index e8084bd45a9..e05d1c519d5 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -4138,6 +4138,7 @@ void apply_object( void ) } else { ob= OBACT; + if(ob==0) return; if ((ob->pose) && (ob->flag & OB_POSEMODE)) evt = pupmenu("Apply Object%t|Current Pose as RestPose%x3"); diff --git a/source/blender/src/meshlaplacian.c b/source/blender/src/meshlaplacian.c index c2ad60ea842..96349e8fb98 100644 --- a/source/blender/src/meshlaplacian.c +++ b/source/blender/src/meshlaplacian.c @@ -178,7 +178,6 @@ static void laplacian_triangle_area(LaplacianSystem *sys, int i1, int i2, int i3 varea[i1] += (obtuse == 1)? area: area*0.5; varea[i2] += (obtuse == 2)? area: area*0.5; varea[i3] += (obtuse == 3)? area: area*0.5; - //printf("area %f\n", area); } else { len1= VecLenf(v2, v3); @@ -192,10 +191,7 @@ static void laplacian_triangle_area(LaplacianSystem *sys, int i1, int i2, int i3 varea[i1] += (t2 + t3)*0.25f; varea[i2] += (t1 + t3)*0.25f; varea[i3] += (t1 + t2)*0.25f; - //printf("varea %f %f %f\n", t1, t2, t3); } - - //printf("triangle area %f %f %f\n", t1, t2, t3); } static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int i2, int i3) @@ -298,7 +294,7 @@ void laplacian_system_construct_end(LaplacianSystem *sys) for(a=0; aareaweights) { if(sys->varea[a] != 0.0f) - sys->varea[a]= 0.5f/sys->varea[a]; //MAX2(sys->varea[a], 0.001f); + sys->varea[a]= 0.5f/sys->varea[a]; } else sys->varea[a]= 1.0f; From f198acd5dd6867401e5517f8a919aaf53af85e84 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 9 Sep 2008 20:19:00 +0000 Subject: [PATCH 25/32] Fix for bug #14775: memorblock end corrupt print, needed to allocate one byte more for the align menu string 0 terminator. --- source/blender/src/transform_orientations.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/src/transform_orientations.c b/source/blender/src/transform_orientations.c index 9c7a2f67b89..fc9dfbb902e 100644 --- a/source/blender/src/transform_orientations.c +++ b/source/blender/src/transform_orientations.c @@ -352,7 +352,7 @@ char * BIF_menustringTransformOrientation(char *title) { char *str_menu, *p; - str_menu = MEM_callocN(strlen(menu) + strlen(title) + 40 * BIF_countTransformOrientation(), "UserTransSpace from matrix"); + str_menu = MEM_callocN(strlen(menu) + strlen(title) + 1 + 40 * BIF_countTransformOrientation(), "UserTransSpace from matrix"); p = str_menu; p += sprintf(str_menu, "%s", title); From fede495c073a7369a61e668dae95cf8c7b99a068 Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Tue, 9 Sep 2008 20:52:18 +0000 Subject: [PATCH 26/32] Python API ---------- Bugfix #14425. Particle.Get() could return a list of invalid items. The API still needs more work, but for now throw an NotImplemented exception. --- source/blender/python/api2_2x/Particle.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/source/blender/python/api2_2x/Particle.c b/source/blender/python/api2_2x/Particle.c index bc65426e16c..893ee077d67 100644 --- a/source/blender/python/api2_2x/Particle.c +++ b/source/blender/python/api2_2x/Particle.c @@ -526,15 +526,18 @@ throws NameError if name not found PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) { +#if 1 + return EXPP_ReturnPyObjError( PyExc_NotImplementedError, + "Particle.Get() not implemented" ); +#else ParticleSettings *psys_iter; char *name = NULL; -#if 0 ParticleSystem *blparticlesys = 0; Object *ob; PyObject *partsyslist,*current; -#endif + if( !PyArg_ParseTuple( args, "|s", &name ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected string argument" ); @@ -577,7 +580,6 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) } while( psys_iter ){ -#if 0 pyobj = ParticleSystem_CreatePyObject( psys_iter); if( !pyobj){ Py_DECREF( pylist ); @@ -586,7 +588,6 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) "could not create ParticleSystem PyObject"); } PyList_SET_ITEM( pylist, index, pyobj); -#endif printf("name is %s\n", psys_iter->id.name+2); psys_iter = psys_iter->id.next; index++; @@ -596,10 +597,6 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) } - - -#if 0 - for( ob = G.main->particlesystem.first; ob; ob = ob->id.next ) if( !strcmp( name, ob->id.name + 2 ) ) break; @@ -626,7 +623,6 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) } return partsyslist; - #endif } From f305bb22b7e5f809063539cdb76a24727f41a11a Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Tue, 9 Sep 2008 21:15:30 +0000 Subject: [PATCH 27/32] Patch 17508: Blender Web Plugin - XEmbed. Enable XEmbed integration of blenderplayer, using -i as input parameter to pass embedder window id. create a minimal web plugin to embed blenderplayer on web pages (using gecko/mozilla as browser). Only for *nix. --- CMakeLists.txt | 8 +++ intern/ghost/GHOST_ISystem.h | 4 +- intern/ghost/GHOST_Types.h | 10 +++ intern/ghost/intern/GHOST_SystemCarbon.cpp | 3 +- intern/ghost/intern/GHOST_SystemCarbon.h | 4 +- intern/ghost/intern/GHOST_SystemWin32.cpp | 2 +- intern/ghost/intern/GHOST_SystemWin32.h | 3 +- intern/ghost/intern/GHOST_SystemX11.cpp | 13 +++- intern/ghost/intern/GHOST_SystemX11.h | 6 +- intern/ghost/intern/GHOST_WindowX11.cpp | 67 ++++++++++++++----- intern/ghost/intern/GHOST_WindowX11.h | 2 + source/gameengine/GamePlayer/CMakeLists.txt | 4 ++ .../GamePlayer/ghost/GPG_Application.cpp | 25 ++++++- .../GamePlayer/ghost/GPG_Application.h | 3 + .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 21 +++++- 15 files changed, 147 insertions(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 97113c22f98..4c1b863178f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,6 +64,7 @@ OPTION(WITH_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ON) OPTION(WITH_FFMPEG "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)" OFF) OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON) OPTION(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" OFF) +OPTION(WITH_WEBPLUGIN "Enable Web Plugin (Mozilla-Unix only)" OFF) IF(NOT WITH_GAMEENGINE AND WITH_PLAYER) MESSAGE("WARNING: WITH_PLAYER needs WITH_GAMEENGINE") @@ -456,6 +457,13 @@ SUBDIRS( # Blender Application SUBDIRS(source/creator) +#----------------------------------------------------------------------------- +# Blender WebPlugin +IF(WITH_WEBPLUGIN) + SET(MOZILLA_DIR "${CMAKE_SOURCE_DIR}/../gecko-sdk/" CACHE PATH "Gecko SDK path") + SET(WITH_PLAYER ON) +ENDIF(WITH_WEBPLUGIN) + #----------------------------------------------------------------------------- # Blender Player IF(WITH_PLAYER) diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 2ad2e9ddce7..baf0cb813f8 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -224,13 +224,15 @@ public: * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. * @param stereoVisual Create a stereo visual for quad buffered stereo. + * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ virtual GHOST_IWindow* createWindow( const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual) = 0; + const bool stereoVisual, + const GHOST_TEmbedderWindowID parentWindow = 0) = 0; /** * Dispose a window. diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index f81192f1887..6b1295f649b 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -100,6 +100,7 @@ typedef enum { GHOST_kWindowStateMaximized, GHOST_kWindowStateMinimized, GHOST_kWindowStateFullScreen, + GHOST_kWindowStateEmbedded, GHOST_kWindowState8Normal = 8, GHOST_kWindowState8Maximized, GHOST_kWindowState8Minimized, @@ -392,6 +393,15 @@ typedef struct { } GHOST_DisplaySetting; +#ifdef _WIN32 +typedef long GHOST_TEmbedderWindowID; +#endif // _WIN32 + +#ifndef _WIN32 +// I can't use "Window" from "" because it conflits with Window defined in winlay.h +typedef int GHOST_TEmbedderWindowID; +#endif // _WIN32 + /** * A timer task callback routine. * @param task The timer task object. diff --git a/intern/ghost/intern/GHOST_SystemCarbon.cpp b/intern/ghost/intern/GHOST_SystemCarbon.cpp index 78c25997806..067c8deee32 100644 --- a/intern/ghost/intern/GHOST_SystemCarbon.cpp +++ b/intern/ghost/intern/GHOST_SystemCarbon.cpp @@ -402,7 +402,8 @@ GHOST_IWindow* GHOST_SystemCarbon::createWindow( GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - bool stereoVisual + bool stereoVisual, + const GHOST_TEmbedderWindowID parentWindow ) { GHOST_IWindow* window = 0; diff --git a/intern/ghost/intern/GHOST_SystemCarbon.h b/intern/ghost/intern/GHOST_SystemCarbon.h index 2afc8e0885a..2a1d6325784 100644 --- a/intern/ghost/intern/GHOST_SystemCarbon.h +++ b/intern/ghost/intern/GHOST_SystemCarbon.h @@ -103,6 +103,7 @@ public: * @param height The height the window. * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. + * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ virtual GHOST_IWindow* createWindow( @@ -113,7 +114,8 @@ public: GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual + const bool stereoVisual, + const GHOST_TEmbedderWindowID parentWindow = 0 ); /*************************************************************************************** diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 7bc20d38739..feb0fe39040 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -169,7 +169,7 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow( const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - bool stereoVisual) + bool stereoVisual, const GHOST_TEmbedderWindowID parentWindow ) { GHOST_Window* window = 0; window = new GHOST_WindowWin32 (title, left, top, width, height, state, type, stereoVisual); diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index c26ef25e366..00f7af00162 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -109,13 +109,14 @@ public: * @param height The height the window. * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. + * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ virtual GHOST_IWindow* createWindow( const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual); + const bool stereoVisual, const GHOST_TEmbedderWindowID parentWindow = 0 ); /*************************************************************************************** ** Event management functionality diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 3003e0b8b14..1b90831986d 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -191,6 +191,7 @@ getMainDisplayDimensions( * @param height The height the window. * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. + * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ GHOST_IWindow* @@ -203,14 +204,18 @@ createWindow( GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - bool stereoVisual + bool stereoVisual, + const GHOST_TEmbedderWindowID parentWindow ){ GHOST_WindowX11 * window = 0; if (!m_display) return 0; + + + window = new GHOST_WindowX11 ( - this,m_display,title, left, top, width, height, state, type, stereoVisual + this,m_display,title, left, top, width, height, state, parentWindow, type, stereoVisual ); if (window) { @@ -511,7 +516,9 @@ GHOST_SystemX11::processEvent(XEvent *xe) } break; } - + + case DestroyNotify: + ::exit(-1); // We're not interested in the following things.(yet...) case NoExpose : case GraphicsExpose : diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index 726cdfb2fff..c67f7d81e60 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -108,6 +108,7 @@ public: * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. * @param stereoVisual Create a stereo visual for quad buffered stereo. + * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ GHOST_IWindow* @@ -119,9 +120,10 @@ public: GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual + const bool stereoVisual, + const GHOST_TEmbedderWindowID parentWindow = 0 ); - + /** * @section Interface Inherited from GHOST_ISystem */ diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index a98a59377c7..7b0606c40b7 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -138,6 +138,7 @@ GHOST_WindowX11( GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, + const GHOST_TEmbedderWindowID parentWindow, GHOST_TDrawingContextType type, const bool stereoVisual ) : @@ -205,21 +206,57 @@ GHOST_WindowX11( // create the window! - m_window = - XCreateWindow( - m_display, - RootWindow(m_display, m_visual->screen), - left, - top, - width, - height, - 0, // no border. - m_visual->depth, - InputOutput, - m_visual->visual, - CWBorderPixel|CWColormap|CWEventMask, - &xattributes - ); + ; + if (parentWindow == 0) { + m_window = + XCreateWindow( + m_display, + RootWindow(m_display, m_visual->screen), + left, + top, + width, + height, + 0, // no border. + m_visual->depth, + InputOutput, + m_visual->visual, + CWBorderPixel|CWColormap|CWEventMask, + &xattributes + ); + } else { + + Window root_return; + int x_return,y_return; + unsigned int w_return,h_return,border_w_return,depth_return; + GHOST_TInt32 screen_x, screen_y; + + XGetGeometry(m_display, parentWindow, &root_return, &x_return, &y_return, + &w_return, &h_return, &border_w_return, &depth_return ); + + left = 0; + top = 0; + width = w_return; + height = h_return; + + + m_window = XCreateWindow( + m_display, + parentWindow, // reparent against embedder + left, + top, + width, + height, + 0, // no border. + m_visual->depth, + InputOutput, + m_visual->visual, + CWBorderPixel|CWColormap|CWEventMask, + &xattributes + ); + + XSelectInput(m_display , parentWindow, SubstructureNotifyMask); + + } // Are we in fullscreen mode - then include diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 1203dbde80d..abb5c131cb7 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -64,6 +64,7 @@ public: * @param width The width the window. * @param height The height the window. * @param state The state the window is initially opened with. + * @param parentWindow Parent (embedder) window * @param type The type of drawing context installed in this window. * @param stereoVisual Stereo visual for quad buffered stereo. */ @@ -76,6 +77,7 @@ public: GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, + const GHOST_TEmbedderWindowID parentWindow, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, const bool stereoVisual = false ); diff --git a/source/gameengine/GamePlayer/CMakeLists.txt b/source/gameengine/GamePlayer/CMakeLists.txt index ff1040bfb40..fc5912155cf 100644 --- a/source/gameengine/GamePlayer/CMakeLists.txt +++ b/source/gameengine/GamePlayer/CMakeLists.txt @@ -25,3 +25,7 @@ # ***** END GPL LICENSE BLOCK ***** SUBDIRS(common ghost) + +IF(WITH_WEBPLUGIN) + SUBDIRS(xembed) +ENDIF(WITH_WEBPLUGIN) diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 806216e05bb..3d9ae66c9ea 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -129,7 +129,8 @@ GPG_Application::GPG_Application(GHOST_ISystem* system) m_blendermat(0), m_blenderglslmat(0), m_pyGlobalDictString(0), - m_pyGlobalDictString_Length(0) + m_pyGlobalDictString_Length(0), + m_isEmbedded(false) { fSystem = system; } @@ -325,6 +326,26 @@ bool GPG_Application::startWindow(STR_String& title, return success; } +bool GPG_Application::startEmbeddedWindow(STR_String& title, + const GHOST_TEmbedderWindowID parentWindow, + const bool stereoVisual, + const int stereoMode) { + + m_mainWindow = fSystem->createWindow(title, 0, 0, 0, 0, GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL, stereoVisual, parentWindow); + + if (!m_mainWindow) { + printf("error: could not create main window\n"); + exit(-1); + } + m_isEmbedded = true; + + bool success = initEngine(m_mainWindow, stereoMode); + if (success) { + success = startEngine(); + } + return success; +} bool GPG_Application::startFullScreen( @@ -887,7 +908,7 @@ bool GPG_Application::handleKey(GHOST_IEvent* event, bool isDown) GHOST_TEventKeyData* keyData = static_cast(eventData); //no need for this test //if (fSystem->getFullScreen()) { - if (keyData->key == GHOST_kKeyEsc && !m_keyboard->m_hookesc) { + if (keyData->key == GHOST_kKeyEsc && !m_keyboard->m_hookesc && !m_isEmbedded) { m_exitRequested = KX_EXIT_REQUEST_OUTSIDE; } //} diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.h b/source/gameengine/GamePlayer/ghost/GPG_Application.h index 5242a419808..7fc369fc0fd 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.h +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.h @@ -62,6 +62,7 @@ public: bool startWindow(STR_String& title, int windowLeft, int windowTop, int windowWidth, int windowHeight, const bool stereoVisual, const int stereoMode); bool startFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode); + bool startEmbeddedWindow(STR_String& title, const GHOST_TEmbedderWindowID parent_window, const bool stereoVisual, const int stereoMode); #ifdef WIN32 bool startScreenSaverFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode); bool startScreenSaverPreview(HWND parentWindow, const bool stereoVisual, const int stereoMode); @@ -143,6 +144,8 @@ protected: bool m_engineInitialized; /** Engine state. */ bool m_engineRunning; + /** Running on embedded window */ + bool m_isEmbedded; /** the gameengine itself */ KX_KetsjiEngine* m_ketsjiengine; diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index cc781a38bbb..d44e983af89 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -178,6 +178,9 @@ void usage(char* program) printf(" anaglyph (Red-Blue glasses)\n"); printf(" vinterlace (Vertical interlace for autostereo display)\n"); printf(" depending on the type of stereo you want\n"); +#ifndef _WIN32 + printf(" -i: parent windows ID \n"); +#endif #ifdef _WIN32 printf(" -c: keep console window open\n"); #endif @@ -297,6 +300,9 @@ int main(int argc, char** argv) int fullScreenFrequency = 60; char* pyGlobalDictString = NULL; /* store python dict data between blend file loading */ int pyGlobalDictString_Length = 0; + GHOST_TEmbedderWindowID parentWindow = 0; + + #ifdef __linux__ #ifdef __alpha__ @@ -457,6 +463,16 @@ int main(int argc, char** argv) usage(argv[0]); return 0; break; +#ifndef _WIN32 + case 'i': + i++; + if ( (i + 1) < argc ) + parentWindow = atoi(argv[i++]); +#ifndef NDEBUG + printf("XWindows ID = %d\n", parentWindow); +#endif //NDEBUG + +#endif // _WIN32 case 'c': i++; closeConsole = false; @@ -729,7 +745,10 @@ int main(int argc, char** argv) else #endif { - app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight, + if (parentWindow != 0) + app.startEmbeddedWindow(title, parentWindow, stereoWindow, stereomode); + else + app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight, stereoWindow, stereomode); } } From aa10e1b11eca50503b0b52f0723f698f0527822f Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 9 Sep 2008 21:46:19 +0000 Subject: [PATCH 28/32] Bugfix for [#17363] Edge selection mode + knife twice = latter cut doesn't do anything --- source/blender/src/editmesh_loop.c | 6 +++--- source/blender/src/editmesh_tools.c | 17 +++++++++++------ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/source/blender/src/editmesh_loop.c b/source/blender/src/editmesh_loop.c index 4ac5072b212..2c5386b86b6 100644 --- a/source/blender/src/editmesh_loop.c +++ b/source/blender/src/editmesh_loop.c @@ -745,9 +745,9 @@ void KnifeSubdivide(char mode) eed= eed->next; } - if (mode==KNIFE_EXACT) esubdivideflag(1, 0, B_KNIFE|B_PERCENTSUBD,1,SUBDIV_SELECT_ORIG); - else if (mode==KNIFE_MIDPOINT) esubdivideflag(1, 0, B_KNIFE,1,SUBDIV_SELECT_ORIG); - else if (mode==KNIFE_MULTICUT) esubdivideflag(1, 0, B_KNIFE,numcuts,SUBDIV_SELECT_ORIG); + if(mode==KNIFE_EXACT) esubdivideflag(SELECT, 0, B_KNIFE|B_PERCENTSUBD,1,SUBDIV_SELECT_ORIG); + else if (mode==KNIFE_MIDPOINT) esubdivideflag(SELECT, 0, B_KNIFE,1,SUBDIV_SELECT_ORIG); + else if (mode==KNIFE_MULTICUT) esubdivideflag(SELECT, 0, B_KNIFE,numcuts,SUBDIV_SELECT_ORIG); eed=em->edges.first; while(eed){ diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c index c2fccb0e50f..fe4c98aa4de 100644 --- a/source/blender/src/editmesh_tools.c +++ b/source/blender/src/editmesh_tools.c @@ -2698,16 +2698,21 @@ void esubdivideflag(int flag, float rad, int beauty, int numcuts, int seltype) free_tagged_edges_faces(em->edges.first, em->faces.first); if(seltype == SUBDIV_SELECT_ORIG && G.qual != LR_CTRLKEY) { + /* bugfix: vertex could get flagged as "not-selected" + // solution: clear flags before, not at the same time as setting SELECT flag -dg + */ for(eed = em->edges.first;eed;eed = eed->next) { - if(eed->f2 & EDGENEW || eed->f2 & EDGEOLD) { - eed->f |= flag; - EM_select_edge(eed,1); - - }else{ + if(!(eed->f2 & EDGENEW || eed->f2 & EDGEOLD)) { eed->f &= !flag; EM_select_edge(eed,0); } - } + } + for(eed = em->edges.first;eed;eed = eed->next) { + if(eed->f2 & EDGENEW || eed->f2 & EDGEOLD) { + eed->f |= flag; + EM_select_edge(eed,1); + } + } } else if ((seltype == SUBDIV_SELECT_INNER || seltype == SUBDIV_SELECT_INNER_SEL)|| G.qual == LR_CTRLKEY) { for(eed = em->edges.first;eed;eed = eed->next) { if(eed->f2 & EDGEINNER) { From 74ab278d46bd3784da769d3e3460750ad279cf02 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Tue, 9 Sep 2008 22:40:10 +0000 Subject: [PATCH 29/32] BGE bug #17549: fix crash on removeParent() with static mesh. Fix scaling bug on setParent(). Add python setWorldPosition() to allow setting object position in world coordinate regardless if it is a root or a child object. --- source/gameengine/Ketsji/KX_GameObject.cpp | 23 +++++++++++++++---- source/gameengine/Ketsji/KX_GameObject.h | 1 + .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 5 ++-- source/gameengine/PyDoc/KX_GameObject.py | 11 ++++++++- 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 27a955b3105..0e5956d4fdb 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -235,11 +235,12 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) m_pPhysicsController1->SuspendDynamics(true); } // Set us to our new scale, position, and orientation - scale1[0] = scale1[0]/scale2[0]; - scale1[1] = scale1[1]/scale2[1]; - scale1[2] = scale1[2]/scale2[2]; + scale2[0] = 1.0/scale2[0]; + scale2[1] = 1.0/scale2[1]; + scale2[2] = 1.0/scale2[2]; + scale1 = scale1 * scale2; MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse(); - MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale1; + MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale2; NodeSetLocalScale(scale1); NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2])); @@ -914,6 +915,7 @@ void KX_GameObject::Suspend() PyMethodDef KX_GameObject::Methods[] = { {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS}, {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O}, + {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O}, {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS}, {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS}, {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS}, @@ -1576,6 +1578,19 @@ PyObject* KX_GameObject::PySetPosition(PyObject* self, PyObject* value) return NULL; } +PyObject* KX_GameObject::PySetWorldPosition(PyObject* self, PyObject* value) +{ + MT_Point3 pos; + if (PyVecTo(value, pos)) + { + NodeSetWorldPosition(pos); + NodeUpdateGS(0.f,true); + Py_RETURN_NONE; + } + + return NULL; +} + PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self) { KX_IPhysicsController* ctrl = GetPhysicsController(); diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 98b3f3b4c3f..2da0be4df25 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -754,6 +754,7 @@ public: KX_PYMETHOD_NOARGS(KX_GameObject,GetPosition); KX_PYMETHOD_O(KX_GameObject,SetPosition); + KX_PYMETHOD_O(KX_GameObject,SetWorldPosition); KX_PYMETHOD_VARARGS(KX_GameObject,GetLinearVelocity); KX_PYMETHOD_VARARGS(KX_GameObject,SetLinearVelocity); KX_PYMETHOD_VARARGS(KX_GameObject,GetAngularVelocity); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index d14ddf8f65c..d3b83a74439 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -452,11 +452,12 @@ void CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctr // this function is used when the collisionning group of a controller is changed // remove and add the collistioning object btRigidBody* body = ctrl->GetRigidBody(); - btVector3 inertia; + btVector3 inertia(0.0,0.0,0.0); m_dynamicsWorld->removeCollisionObject(body); body->setCollisionFlags(newCollisionFlags); - body->getCollisionShape()->calculateLocalInertia(newMass, inertia); + if (newMass) + body->getCollisionShape()->calculateLocalInertia(newMass, inertia); body->setMassProps(newMass, inertia); m_dynamicsWorld->addCollisionObject(body, newCollisionGroup, newCollisionMask); // to avoid nasty interaction, we must update the property of the controller as well diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py index 9729b14a43f..ff9b4ffc95b 100644 --- a/source/gameengine/PyDoc/KX_GameObject.py +++ b/source/gameengine/PyDoc/KX_GameObject.py @@ -58,7 +58,16 @@ class KX_GameObject: """ def setPosition(pos): """ - Sets the game object's position. + Sets the game object's position. + Global coordinates for root object, local for child objects. + + + @type pos: [x, y, z] + @param pos: the new position, in local coordinates. + """ + def setWorldPosition(pos): + """ + Sets the game object's position in world coordinates regardless if the object is root or child. @type pos: [x, y, z] @param pos: the new position, in world coordinates. From eaf84d2c25c0b70b0a71fe042c8b559a3a504418 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 10 Sep 2008 01:17:03 +0000 Subject: [PATCH 30/32] BPY merge from apricot branch. work around non unix line endings using pythons execfile() function rather then loading the binary data and manually stripping the line endings. --- source/blender/python/BPY_interface.c | 57 ++++----------------------- 1 file changed, 8 insertions(+), 49 deletions(-) diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c index 05254bca8c0..c91aabc4a02 100644 --- a/source/blender/python/BPY_interface.c +++ b/source/blender/python/BPY_interface.c @@ -778,9 +778,6 @@ int BPY_run_script(Script *script) PyObject *py_dict, *py_res, *pyarg; Text *text = NULL; BPy_constant *info; - int len; - - FILE *fp = NULL; PyGILState_STATE gilstate = PyGILState_Ensure(); @@ -825,12 +822,8 @@ int BPY_run_script(Script *script) Py_INCREF( Py_None ); pyarg = Py_None; } else { - if (BLI_exists(script->scriptname)) { - fp = fopen( script->scriptname, "rb" ); - } - - if( !fp ) { - printf( "Error loading script: couldn't open file %s\n", script->scriptname ); + if (!BLI_exists(script->scriptname)) { + printf( "Script does not exit %s\n", script->scriptname ); free_libblock( &G.main->script, script ); PyGILState_Release(gilstate); return 0; @@ -875,51 +868,17 @@ int BPY_run_script(Script *script) if (text) { py_res = RunPython( text, py_dict ); } else { + char pystring[sizeof(script->scriptname) + 15]; + sprintf(pystring, "execfile(r'%s')", script->scriptname); + py_res = PyRun_String( pystring, Py_file_input, py_dict, py_dict ); + } + + if( !py_res ) { /* Failed execution of the script */ /* Previously we used PyRun_File to run directly the code on a FILE * object, but as written in the Python/C API Ref Manual, chapter 2, * 'FILE structs for different C libraries can be different and * incompatible'. * So now we load the script file data to a buffer */ - char *buffer=NULL, *buffer_ofs=NULL, *b_to, *b_from; - - fseek( fp, 0L, SEEK_END ); - len = ftell( fp ); - fseek( fp, 0L, SEEK_SET ); - - buffer = buffer_ofs = MEM_mallocN( len + 2, "pyfilebuf" ); /* len+2 to add '\n\0' */ - len = fread( buffer, 1, len, fp ); - - buffer[len] = '\n'; /* fix syntax error in files w/o eol */ - buffer[len + 1] = '\0'; - - - /* fast clean-up of dos cr/lf line endings, remove convert '\r\n's to '\n' */ - if (*buffer_ofs == '\r' && *(buffer_ofs+1) == '\n') { - buffer_ofs++; - } - b_from = b_to = buffer_ofs; - - while(*b_from != '\0') { - if (*b_from == '\r' && *( b_from+1 ) == '\n') { - b_from++; - } - if (b_from != b_to) { - *b_to = *b_from; - } - b_to++; - b_from++; - } - *b_to = '\0'; - /* done cleaning the string */ - - fclose( fp ); - - py_res = PyRun_String( buffer_ofs, Py_file_input, py_dict, py_dict ); - MEM_freeN( buffer ); - } - - if( !py_res ) { /* Failed execution of the script */ - BPY_Err_Handle( script->id.name + 2 ); ReleaseGlobalDictionary( py_dict ); script->py_globaldict = NULL; From ecc5bdb8d72aca5199de6a69b4b6c493f0191d51 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 10 Sep 2008 03:34:08 +0000 Subject: [PATCH 31/32] 2 gamelogic templates, one with example functions and comments, another minimal template for those who know the api. --- release/scripts/scripttemplate_gamelogic.py | 93 +++++++++++++++++++ .../scripts/scripttemplate_gamelogic_basic.py | 33 +++++++ 2 files changed, 126 insertions(+) create mode 100644 release/scripts/scripttemplate_gamelogic.py create mode 100644 release/scripts/scripttemplate_gamelogic_basic.py diff --git a/release/scripts/scripttemplate_gamelogic.py b/release/scripts/scripttemplate_gamelogic.py new file mode 100644 index 00000000000..17095251155 --- /dev/null +++ b/release/scripts/scripttemplate_gamelogic.py @@ -0,0 +1,93 @@ +#!BPY +""" +Name: 'GameLogic Example' +Blender: 245 +Group: 'ScriptTemplate' +Tooltip: 'Script template with examples of how to use game logic' +""" + +from Blender import Window +import bpy + +script_data = \ +''' +# GameLogic has been added to the global namespace no need to import + +# for keyboard event comparison +# import GameKeys + +# support for Vector(), Matrix() types and advanced functions like AngleBetweenVecs(v1,v2) and RotationMatrix(...) +# import Mathutils + +# for functions like getWindowWidth(), getWindowHeight() +# import Rasterizer + +def main(): + cont = GameLogic.getCurrentController() + + # The KX_GameObject that owns this controller. + own = cont.getOwner() + + # for scripts that deal with spacial logic + own_pos = own.getPosition() + + + # Some example functions, remove to write your own script. + # check for a positive sensor, will run on any object without errors. + print 'Logic info for KX_GameObject', own.getName() + input = False + + for sens in cont.getSensors(): + # The sensor can be on another object, we may want to use it + own_sens = sens.getOwner() + print ' sensor:', sens.getName(), + if sens.isPositive(): + print '(true)' + input = True + else: + print '(false)' + + for actu in cont.getActuators(): + # The actuator can be on another object, we may want to use it + own_actu = actu.getOwner() + print ' actuator:', sens.getName() + + # This runs the actuator or turns it off + # note that actuators will continue to run unless explicitly turned off. + if input: + GameLogic.addActiveActuator(actu, True) + else: + GameLogic.addActiveActuator(actu, False) + + # Its also good practice to get sensors and actuators by names + # so any changes to their order wont break the script. + + # sens_key = cont.getSensor('key_sensor') + # actu_motion = cont.getActuator('motion') + + + # Loop through all other objects in the scene + sce = GameLogic.getCurrentScene() + print 'Scene Objects:', sce.getName() + for ob in sce.getObjectList(): + print ' ', ob.getName(), ob.getPosition() + + + # Example where collision objects are checked for their properties + # adding to our objects "life" property + """ + actu_collide = cont.getSensor('collision_sens') + for ob in actu_collide.getHitObjectList(): + # Check to see the object has this property + if hasattr(ob, 'life'): + own.life += ob.life + ob.life = 0 + print own.life + """ +main() +''' + +new_text = bpy.data.texts.new('gamelogic_example.py') +new_text.write(script_data) +bpy.data.texts.active = new_text +Window.RedrawAll() diff --git a/release/scripts/scripttemplate_gamelogic_basic.py b/release/scripts/scripttemplate_gamelogic_basic.py new file mode 100644 index 00000000000..dfd52a9f749 --- /dev/null +++ b/release/scripts/scripttemplate_gamelogic_basic.py @@ -0,0 +1,33 @@ +#!BPY +""" +Name: 'GameLogic Template' +Blender: 245 +Group: 'ScriptTemplate' +Tooltip: 'Basic template for new game logic scripts' +""" + +from Blender import Window +import bpy + +script_data = \ +''' +def main(): + + cont = GameLogic.getCurrentController() + own = cont.getOwner() + + sens = cont.getSensor('mySensor') + actu = cont.getActuator('myActuator') + + if sens.isPositive(): + GameLogic.addActiveActuator(actu, True) + else: + GameLogic.addActiveActuator(actu, False) + +main() +''' + +new_text = bpy.data.texts.new('gamelogic_example.py') +new_text.write(script_data) +bpy.data.texts.active = new_text +Window.RedrawAll() From 75078d62df5ee8186369b5f1273b61b0736346ec Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 10 Sep 2008 09:51:06 +0000 Subject: [PATCH 32/32] Fix for bug #17589: removing a lamp in the game engine with glsl materials did not work correct. --- source/gameengine/Ketsji/KX_Light.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 979015532e3..e0f171e78e0 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -65,6 +65,13 @@ KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, KX_LightObject::~KX_LightObject() { + GPULamp *lamp; + + if((lamp = GetGPULamp())) { + float obmat[4][4] = {{0}}; + GPU_lamp_update(lamp, 0, obmat); + } + m_rendertools->RemoveLight(&m_lightobj); }