From 37a79f47272ddd0cf5702ae0a73c2c39ef192ad4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 16 Apr 2012 13:49:04 +0000 Subject: [PATCH 01/12] fix [#30972] Editmesh split by materials not working. --- release/scripts/startup/bl_ui/space_view3d.py | 2 +- source/blender/editors/mesh/editmesh_tools.c | 51 +++++++++++++------ 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 20f5b471784..6c152c7cd43 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1680,7 +1680,7 @@ class VIEW3D_MT_edit_mesh_vertices(Menu): layout.operator("mesh.merge") layout.operator("mesh.rip_move") layout.operator("mesh.split") - layout.operator("mesh.separate") + layout.operator_menu_enum("mesh.separate", "type") layout.operator("mesh.vert_connect") layout.operator("mesh.vert_slide") diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 5b6811fcc5c..b8ab538b60e 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3131,7 +3131,7 @@ static int mesh_separate_selected(Main *bmain, Scene *scene, Base *editbase, wmO BMesh *bm_new; if (!em) - return OPERATOR_CANCELLED; + return FALSE; bm_new = BM_mesh_create(&bm_mesh_allocsize_default); CustomData_copy(&em->bm->vdata, &bm_new->vdata, CD_MASK_BMESH, CD_CALLOC, 0); @@ -3182,13 +3182,41 @@ static int mesh_separate_selected(Main *bmain, Scene *scene, Base *editbase, wmO BM_mesh_free(bm_new); ((Mesh *)basenew->object->data)->edit_btmesh = NULL; - return 1; + return TRUE; } -//BMESH_TODO -static int mesh_separate_material(Main *UNUSED(bmain), Scene *UNUSED(scene), Base *UNUSED(editbase), wmOperator *UNUSED(wmop)) +static int mesh_separate_material(Main *bmain, Scene *scene, Base *editbase, wmOperator *wmop) { - return 0; + BMFace *f_cmp, *f; + BMIter iter; + int result = FALSE; + Object *obedit = editbase->object; + BMEditMesh *em = BMEdit_FromObject(obedit); + BMesh *bm = em->bm; + + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + + while ((f_cmp = BM_iter_at_index(bm, BM_FACES_OF_MESH, NULL, 0))) { + const short mat_nr = f_cmp->mat_nr; + int tot = 0; + + BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) { + if (f->mat_nr == mat_nr) { + BM_face_select_set(bm, f, TRUE); + tot++; + } + } + + /* leave the current object with some materials */ + if (tot == bm->totface) { + break; + } + + /* Move selection into a separate object */ + result |= mesh_separate_selected(bmain, scene, editbase, wmop); + } + + return result; } static int mesh_separate_loose(Main *bmain, Scene *scene, Base *editbase, wmOperator *wmop) @@ -3199,21 +3227,14 @@ static int mesh_separate_loose(Main *bmain, Scene *scene, Base *editbase, wmOper BMVert *v_seed; BMWalker walker; BMIter iter; - int result = 0; + int result = FALSE; Object *obedit = editbase->object; - Mesh *me = obedit->data; - BMEditMesh *em = me->edit_btmesh; + BMEditMesh *em = BMEdit_FromObject(obedit); BMesh *bm = em->bm; int max_iter = bm->totvert; /* Clear all selected vertices */ - BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) { - BM_elem_select_set(bm, v, FALSE); - } - - /* Flush the selection to clear edge/face selections to match - * selected vertices */ - EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX); + EDBM_flag_disable_all(em, BM_ELEM_SELECT); /* A "while (true)" loop should work here as each iteration should * select and remove at least one vertex and when all vertices From f4498e62a78e80e0db0a6d398f8b956827dddca5 Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Mon, 16 Apr 2012 13:49:33 +0000 Subject: [PATCH 02/12] Dynamic output sockets for the image input node. This is needed to enable the node to read arbitrary multilayer exr files. Output sockets of this node are now generated dynamically when the image is updated. The image buffer has to be loaded to detect multilayer files on update. --- source/blender/blenkernel/intern/node.c | 2 + source/blender/makesrna/intern/rna_nodetree.c | 6 +- .../nodes/composite/node_composite_tree.c | 24 +- .../composite/nodes/node_composite_image.c | 338 +++++++++++++----- 4 files changed, 263 insertions(+), 107 deletions(-) diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index b50969d0107..2fb3f81b147 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1616,6 +1616,7 @@ int nodeUpdateID(bNodeTree *ntree, ID *id) for (node= ntree->nodes.first; node; node= node->next) { if (node->id==id) { change = TRUE; + node->update |= NODE_UPDATE_ID; ntreetype->update_node(ntree, node); /* clear update flag */ node->update = 0; @@ -1626,6 +1627,7 @@ int nodeUpdateID(bNodeTree *ntree, ID *id) for (node= ntree->nodes.first; node; node= node->next) { if (node->id==id) { change = TRUE; + node->update |= NODE_UPDATE_ID; if (node->typeinfo->updatefunc) node->typeinfo->updatefunc(ntree, node); /* clear update flag */ diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 9d5a6049144..f5bded42a1c 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -357,7 +357,7 @@ static void rna_Node_update(Main *bmain, Scene *scene, PointerRNA *ptr) node_update(bmain, scene, ntree, node); } -static void rna_Node_image_update(Main *bmain, Scene *scene, PointerRNA *ptr) +static void rna_Node_tex_image_update(Main *bmain, Scene *scene, PointerRNA *ptr) { bNodeTree *ntree = (bNodeTree*)ptr->id.data; bNode *node = (bNode*)ptr->data; @@ -1299,7 +1299,7 @@ static void def_sh_tex_environment(StructRNA *srna) RNA_def_property_struct_type(prop, "Image"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Image", ""); - RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_image_update"); + RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_tex_image_update"); RNA_def_struct_sdna_from(srna, "NodeTexEnvironment", "storage"); def_sh_tex(srna); @@ -1333,7 +1333,7 @@ static void def_sh_tex_image(StructRNA *srna) RNA_def_property_struct_type(prop, "Image"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Image", ""); - RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_image_update"); + RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_tex_image_update"); RNA_def_struct_sdna_from(srna, "NodeTexImage", "storage"); def_sh_tex(srna); diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 7bd0d03322d..049b5dd8178 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -757,26 +757,14 @@ void ntreeCompositForceHidden(bNodeTree *ntree, Scene *curscene) if (srl) force_hidden_passes(node, srl->passflag); } + /* XXX this stuff is called all the time, don't want that. + * Updates should only happen when actually necessary. + */ + #if 0 else if ( node->type==CMP_NODE_IMAGE) { - Image *ima= (Image *)node->id; - if (ima) { - if (ima->rr) { - ImageUser *iuser= node->storage; - RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); - if (rl) - force_hidden_passes(node, rl->passflag); - else - force_hidden_passes(node, RRES_OUT_IMAGE|RRES_OUT_ALPHA); - } - else if (ima->type!=IMA_TYPE_MULTILAYER) { /* if ->rr not yet read we keep inputs */ - force_hidden_passes(node, RRES_OUT_IMAGE|RRES_OUT_ALPHA|RRES_OUT_Z); - } - else - force_hidden_passes(node, RRES_OUT_IMAGE|RRES_OUT_ALPHA); - } - else - force_hidden_passes(node, RRES_OUT_IMAGE|RRES_OUT_ALPHA); + nodeUpdate(ntree, node); } + #endif } } diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 44efbc6f9db..323767b64b1 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -32,7 +32,6 @@ #include "node_composite_util.h" - /* **************** IMAGE (and RenderResult, multilayer image) ******************** */ static bNodeSocketTemplate cmp_node_rlayers_out[]= { @@ -67,6 +66,212 @@ static bNodeSocketTemplate cmp_node_rlayers_out[]= { { -1, 0, "" } }; +static bNodeSocket *cmp_node_image_add_render_pass_output(bNodeTree *ntree, bNode *node, int UNUSED(pass), int rres_index) +{ + bNodeSocket *sock; + + sock = node_add_output_from_template(ntree, node, &cmp_node_rlayers_out[rres_index]); + /* for render pass outputs store the pass type index as a lookup key */ + sock->storage = SET_INT_IN_POINTER(rres_index); + + return sock; +} + +static void cmp_node_image_add_render_pass_outputs(bNodeTree *ntree, bNode *node, int passflag) +{ + if (passflag & SCE_PASS_COMBINED) { + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_IMAGE); + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_ALPHA); + } + + if (passflag & SCE_PASS_Z) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_Z, RRES_OUT_Z); + if (passflag & SCE_PASS_NORMAL) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_NORMAL, RRES_OUT_NORMAL); + if (passflag & SCE_PASS_VECTOR) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_VECTOR, RRES_OUT_VEC); + if (passflag & SCE_PASS_UV) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_UV, RRES_OUT_UV); + if (passflag & SCE_PASS_RGBA) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_RGBA, RRES_OUT_RGBA); + if (passflag & SCE_PASS_DIFFUSE) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE, RRES_OUT_DIFF); + if (passflag & SCE_PASS_SPEC) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SPEC, RRES_OUT_SPEC); + if (passflag & SCE_PASS_SHADOW) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SHADOW, RRES_OUT_SHADOW); + if (passflag & SCE_PASS_AO) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_AO, RRES_OUT_AO); + if (passflag & SCE_PASS_REFLECT) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFLECT, RRES_OUT_REFLECT); + if (passflag & SCE_PASS_REFRACT) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFRACT, RRES_OUT_REFRACT); + if (passflag & SCE_PASS_INDIRECT) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDIRECT, RRES_OUT_INDIRECT); + if (passflag & SCE_PASS_INDEXOB) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXOB, RRES_OUT_INDEXOB); + if (passflag & SCE_PASS_INDEXMA) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXMA, RRES_OUT_INDEXMA); + if (passflag & SCE_PASS_MIST) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_MIST, RRES_OUT_MIST); + if (passflag & SCE_PASS_EMIT) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_EMIT, RRES_OUT_EMIT); + if (passflag & SCE_PASS_ENVIRONMENT) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_ENVIRONMENT, RRES_OUT_ENV); + + if (passflag & SCE_PASS_DIFFUSE_DIRECT) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_DIRECT, RRES_OUT_DIFF_DIRECT); + if (passflag & SCE_PASS_DIFFUSE_INDIRECT) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_INDIRECT, RRES_OUT_DIFF_INDIRECT); + if (passflag & SCE_PASS_DIFFUSE_COLOR) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_COLOR, RRES_OUT_DIFF_COLOR); + + if (passflag & SCE_PASS_GLOSSY_DIRECT) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_DIRECT, RRES_OUT_GLOSSY_DIRECT); + if (passflag & SCE_PASS_GLOSSY_INDIRECT) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_INDIRECT, RRES_OUT_GLOSSY_INDIRECT); + if (passflag & SCE_PASS_GLOSSY_COLOR) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_COLOR, RRES_OUT_GLOSSY_COLOR); + + if (passflag & SCE_PASS_TRANSM_DIRECT) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_DIRECT, RRES_OUT_TRANSM_DIRECT); + if (passflag & SCE_PASS_TRANSM_INDIRECT) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_INDIRECT, RRES_OUT_TRANSM_INDIRECT); + if (passflag & SCE_PASS_TRANSM_COLOR) + cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_COLOR, RRES_OUT_TRANSM_COLOR); +} + +static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, RenderLayer *rl) +{ + bNodeSocket *sock; + RenderPass *rpass; + int index; + for (rpass=rl->passes.first, index=0; rpass; rpass=rpass->next, ++index) { + int type; + if (rpass->channels == 1) + type = SOCK_FLOAT; + else + type = SOCK_RGBA; + + sock = nodeAddSocket(ntree, node, SOCK_OUT, rpass->name, type); + /* for multilayer image use pass index directly as key */ + sock->storage = SET_INT_IN_POINTER(index); + } +} + +static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node) +{ + Image *ima= (Image *)node->id; + if (ima) { + ImageUser *iuser= node->storage; + + /* make sure ima->type is correct */ + BKE_image_get_ibuf(ima, iuser); + + if (ima->rr) { + RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); + + if (rl) { + if (ima->type!=IMA_TYPE_MULTILAYER) + cmp_node_image_add_render_pass_outputs(ntree, node, rl->passflag); + else + cmp_node_image_add_multilayer_outputs(ntree, node, rl); + } + else + cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA); + } + else + cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA|RRES_OUT_Z); + } + else + cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA); +} + +static bNodeSocket *cmp_node_image_output_find_match(bNode *UNUSED(node), bNodeSocket *newsock, ListBase *oldsocklist) +{ + bNodeSocket *sock; + + for (sock=oldsocklist->first; sock; sock=sock->next) + if (strcmp(sock->name, newsock->name)==0) + return sock; + return NULL; +} + +static bNodeSocket *cmp_node_image_output_relink(bNode *node, bNodeSocket *oldsock, int oldindex) +{ + bNodeSocket *sock; + + /* first try to find matching socket name */ + for (sock=node->outputs.first; sock; sock=sock->next) + if (strcmp(sock->name, oldsock->name)==0) + return sock; + + /* no matching name, simply link to same index */ + return BLI_findlink(&node->outputs, oldindex); +} + +static void cmp_node_image_sync_output(bNode *UNUSED(node), bNodeSocket *UNUSED(newsock), bNodeSocket *UNUSED(oldsock)) +{ + /* pass */ +} + +/* XXX make this into a generic socket verification function for dynamic socket replacement (multilayer, groups, static templates) */ +static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node) +{ + bNodeSocket *newsock, *oldsock, *oldsock_next; + ListBase oldsocklist; + int oldindex; + bNodeLink *link; + + /* store current nodes in oldsocklist, then clear socket list */ + oldsocklist = node->outputs; + node->outputs.first = node->outputs.last = NULL; + + /* XXX make callback */ + cmp_node_image_create_outputs(ntree, node); + /* flag all new sockets as dynamic, to prevent removal by socket verification function */ + for (newsock=node->outputs.first; newsock; newsock=newsock->next) + newsock->flag |= SOCK_DYNAMIC; + + for (newsock=node->outputs.first; newsock; newsock=newsock->next) { + /* XXX make callback */ + oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist); + if (oldsock) { + /* XXX make callback */ + cmp_node_image_sync_output(node, newsock, oldsock); + } + } + + /* move links to new socket */ + for (oldsock=oldsocklist.first, oldindex=0; oldsock; oldsock=oldsock->next, ++oldindex) { + newsock = cmp_node_image_output_relink(node, oldsock, oldindex); + + if (newsock) { + for (link=ntree->links.first; link; link=link->next) { + if (link->fromsock == oldsock) + link->fromsock = newsock; + } + } + } + + /* delete old sockets + * XXX oldsock is not actually in the node->outputs list any more, + * but the nodeRemoveSocket function works anyway. In future this + * should become part of the core code, so can take care of this behavior. + */ + for (oldsock=oldsocklist.first; oldsock; oldsock=oldsock_next) { + oldsock_next = oldsock->next; + nodeRemoveSocket(ntree, node, oldsock); + } +} + +static void cmp_node_image_update(bNodeTree *ntree, bNode *node) +{ + /* avoid unnecessary updates, only changes to the image/image user data are of interest */ + if (node->update & NODE_UPDATE_ID) + cmp_node_image_verify_outputs(ntree, node); +} + /* float buffer from the image with matching color management */ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc) { @@ -189,85 +394,21 @@ static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd) } /* check if layer is available, returns pass buffer */ -static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passtype) +static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passindex) { - RenderPass *rpass; - short index; - - for (index=0, rpass= rl->passes.first; rpass; rpass= rpass->next, index++) - if (rpass->passtype==passtype) - break; - + RenderPass *rpass = BLI_findlink(&rl->passes, passindex); if (rpass) { CompBuf *cbuf; - iuser->pass= index; + iuser->pass = passindex; BKE_image_multilayer_index(ima->rr, iuser); - cbuf= node_composit_get_image(rd, ima, iuser); + cbuf = node_composit_get_image(rd, ima, iuser); return cbuf; } return NULL; } -static void outputs_multilayer_get(RenderData *rd, RenderLayer *rl, bNodeStack **out, Image *ima, ImageUser *iuser) -{ - if (out[RRES_OUT_Z]->hasoutput) - out[RRES_OUT_Z]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_Z); - if (out[RRES_OUT_VEC]->hasoutput) - out[RRES_OUT_VEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_VECTOR); - if (out[RRES_OUT_NORMAL]->hasoutput) - out[RRES_OUT_NORMAL]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_NORMAL); - if (out[RRES_OUT_UV]->hasoutput) - out[RRES_OUT_UV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_UV); - - if (out[RRES_OUT_RGBA]->hasoutput) - out[RRES_OUT_RGBA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RGBA); - if (out[RRES_OUT_DIFF]->hasoutput) - out[RRES_OUT_DIFF]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE); - if (out[RRES_OUT_SPEC]->hasoutput) - out[RRES_OUT_SPEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SPEC); - if (out[RRES_OUT_SHADOW]->hasoutput) - out[RRES_OUT_SHADOW]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SHADOW); - if (out[RRES_OUT_AO]->hasoutput) - out[RRES_OUT_AO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_AO); - if (out[RRES_OUT_REFLECT]->hasoutput) - out[RRES_OUT_REFLECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFLECT); - if (out[RRES_OUT_REFRACT]->hasoutput) - out[RRES_OUT_REFRACT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFRACT); - if (out[RRES_OUT_INDIRECT]->hasoutput) - out[RRES_OUT_INDIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDIRECT); - if (out[RRES_OUT_INDEXOB]->hasoutput) - out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB); - if (out[RRES_OUT_INDEXMA]->hasoutput) - out[RRES_OUT_INDEXMA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXMA); - if (out[RRES_OUT_MIST]->hasoutput) - out[RRES_OUT_MIST]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_MIST); - if (out[RRES_OUT_EMIT]->hasoutput) - out[RRES_OUT_EMIT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_EMIT); - if (out[RRES_OUT_ENV]->hasoutput) - out[RRES_OUT_ENV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_ENVIRONMENT); - if (out[RRES_OUT_DIFF_DIRECT]->hasoutput) - out[RRES_OUT_DIFF_DIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE_DIRECT); - if (out[RRES_OUT_DIFF_INDIRECT]->hasoutput) - out[RRES_OUT_DIFF_INDIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE_INDIRECT); - if (out[RRES_OUT_DIFF_COLOR]->hasoutput) - out[RRES_OUT_DIFF_COLOR]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE_COLOR); - if (out[RRES_OUT_GLOSSY_DIRECT]->hasoutput) - out[RRES_OUT_GLOSSY_DIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_GLOSSY_DIRECT); - if (out[RRES_OUT_GLOSSY_INDIRECT]->hasoutput) - out[RRES_OUT_GLOSSY_INDIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_GLOSSY_INDIRECT); - if (out[RRES_OUT_GLOSSY_COLOR]->hasoutput) - out[RRES_OUT_GLOSSY_COLOR]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_GLOSSY_COLOR); - if (out[RRES_OUT_TRANSM_DIRECT]->hasoutput) - out[RRES_OUT_TRANSM_DIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_TRANSM_DIRECT); - if (out[RRES_OUT_TRANSM_INDIRECT]->hasoutput) - out[RRES_OUT_TRANSM_INDIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_TRANSM_INDIRECT); - if (out[RRES_OUT_TRANSM_COLOR]->hasoutput) - out[RRES_OUT_TRANSM_COLOR]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_TRANSM_COLOR); -} - - static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) { @@ -277,7 +418,6 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSE RenderData *rd= data; Image *ima= (Image *)node->id; ImageUser *iuser= (ImageUser *)node->storage; - CompBuf *stackbuf= NULL; /* first set the right frame number in iuser */ BKE_image_user_calc_frame(iuser, rd->cfra, 0); @@ -290,15 +430,36 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSE RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); if (rl) { - out[0]->data= stackbuf= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_COMBINED); + bNodeSocket *sock; + int out_index; + CompBuf *combinedbuf= NULL, *firstbuf= NULL; - /* go over all layers */ - outputs_multilayer_get(rd, rl, out, ima, iuser); + for (sock=node->outputs.first, out_index=0; sock; sock=sock->next, ++out_index) { + int passindex = GET_INT_FROM_POINTER(sock->storage); + if (out[out_index]->hasoutput) { + CompBuf *stackbuf = out[out_index]->data = compbuf_multilayer_get(rd, rl, ima, iuser, passindex); + if (stackbuf) { + /* preview policy: take first 'Combined' pass if available, + * otherwise just use the first layer. + */ + if (!firstbuf) + firstbuf = stackbuf; + if (!combinedbuf && + (strcmp(sock->name, "Combined")==0 || strcmp(sock->name, "Image")==0)) + combinedbuf = stackbuf; + } + } + } + + /* preview */ + if (combinedbuf) + generate_preview(data, node, combinedbuf); + else if (firstbuf) + generate_preview(data, node, firstbuf); } } else { - stackbuf= node_composit_get_image(rd, ima, iuser); - + CompBuf *stackbuf = node_composit_get_image(rd, ima, iuser); if (stackbuf) { /*respect image premul option*/ if (stackbuf->type==CB_RGBA && ima->flag & IMA_DO_PREMUL) { @@ -324,23 +485,23 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSE /* put image on stack */ out[0]->data= stackbuf; - + + /* alpha output */ + if (out[1]->hasoutput) + out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A); + + /* Z output */ if (out[2]->hasoutput) out[2]->data= node_composit_get_zimage(node, rd); + + /* preview */ + generate_preview(data, node, stackbuf); } } - - /* alpha and preview for both types */ - if (stackbuf) { - if (out[1]->hasoutput) - out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A); - - generate_preview(data, node, stackbuf); - } } } -static void node_composit_init_image(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) +static void node_composit_init_image(bNodeTree *ntree, bNode* node, bNodeTemplate *UNUSED(ntemp)) { ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user"); node->storage= iuser; @@ -348,6 +509,9 @@ static void node_composit_init_image(bNodeTree *UNUSED(ntree), bNode* node, bNod iuser->sfra= 1; iuser->fie_ima= 2; iuser->ok= 1; + + /* setup initial outputs */ + cmp_node_image_verify_outputs(ntree, node); } void register_node_type_cmp_image(bNodeTreeType *ttype) @@ -355,10 +519,10 @@ void register_node_type_cmp_image(bNodeTreeType *ttype) static bNodeType ntype; node_type_base(ttype, &ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS); - node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out); node_type_size(&ntype, 120, 80, 300); node_type_init(&ntype, node_composit_init_image); node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage); + node_type_update(&ntype, cmp_node_image_update, NULL); node_type_exec(&ntype, node_composit_exec_image); nodeRegisterType(ttype, &ntype); @@ -449,6 +613,8 @@ static void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStac out[RRES_OUT_TRANSM_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_COLOR); } + + static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) { Scene *sce= (Scene *)node->id; From caafc8184bb63f38eeac13f9acf7f7410cddc440 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 16 Apr 2012 13:53:30 +0000 Subject: [PATCH 03/12] Fix #30720: Creating Navmesh crashes blender In fact there were several issues fixed (all of them regressions since bmesh merge): - Creating navmesh crashed because creating new faces for mesh was trying to set default values for all customdata layers in this face. This requires memory pool created for this datablock. Usually this pool is creating on creating datablock if there're some elements to be stored in this block. In cases of regular primitive creating it wasn't an issue because they doesn't create customdata layers, they only creates geometry. Navigation mesh creates geometry and customdata layers (CD_RECAST layer) which used to confuse a bit custom data functions. Solved by ensuring there's memory pool created for polygons datablock after adding new custom data layer. Most probably it's better to be resolved on CD level (like smarter track on changed amount of stored data and so) but prefer not to make such global changes so close to the release. - Toggling edit mode lead to loosing recast datalayer. Solved by adding recast layer to bmesh mask so it'll be copied to/from edit mesh. - Some part of code assumed raycast layer is in face datablock, some that it's in polygon datablock. Made it to be in polygons datablock. Kind of temporary solution to make navmesh working, probably it'll fail if one will want to edit navmesh by hand after it was generated. Proper way would be to ensure the whole navmesh things are using ngons. --- .../blender/blenkernel/intern/DerivedMesh.c | 34 +++++++++---------- source/blender/blenkernel/intern/customdata.c | 2 +- .../blenkernel/intern/navmesh_conversion.c | 2 +- source/blender/editors/mesh/mesh_navmesh.c | 1 + source/gameengine/Ketsji/KX_NavMeshObject.cpp | 3 +- 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index e6fb506620c..3330a6596a7 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1753,18 +1753,6 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos add_orco_dm(ob, NULL, *deform_r, NULL, CD_ORCO); } -#ifdef WITH_GAMEENGINE - /* NavMesh - this is a hack but saves having a NavMesh modifier */ - if ((ob->gameflag & OB_NAVMESH) && (finaldm->type == DM_TYPE_CDDM)) { - DerivedMesh *tdm; - tdm= navmesh_dm_createNavMeshForVisualization(finaldm); - if (finaldm != tdm) { - finaldm->release(finaldm); - finaldm= tdm; - } - } -#endif /* WITH_GAMEENGINE */ - { /* calculating normals can re-calculate tessfaces in some cases */ #if 0 @@ -1820,6 +1808,18 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos } } +#ifdef WITH_GAMEENGINE + /* NavMesh - this is a hack but saves having a NavMesh modifier */ + if ((ob->gameflag & OB_NAVMESH) && (finaldm->type == DM_TYPE_CDDM)) { + DerivedMesh *tdm; + tdm= navmesh_dm_createNavMeshForVisualization(finaldm); + if (finaldm != tdm) { + finaldm->release(finaldm); + finaldm= tdm; + } + } +#endif /* WITH_GAMEENGINE */ + *final_r = finaldm; if (orcodm) @@ -2898,7 +2898,7 @@ static void navmesh_drawColored(DerivedMesh *dm) int a, glmode; MVert *mvert = (MVert *)CustomData_get_layer(&dm->vertData, CD_MVERT); MFace *mface = (MFace *)CustomData_get_layer(&dm->faceData, CD_MFACE); - int *polygonIdx = (int *)CustomData_get_layer(&dm->faceData, CD_RECAST); + int *polygonIdx = (int *)CustomData_get_layer(&dm->polyData, CD_RECAST); float col[3]; if (!polygonIdx) @@ -2980,14 +2980,14 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm) int res; result = CDDM_copy(dm); - if (!CustomData_has_layer(&result->faceData, CD_RECAST)) { - int *sourceRecastData = (int*)CustomData_get_layer(&dm->faceData, CD_RECAST); + if (!CustomData_has_layer(&result->polyData, CD_RECAST)) { + int *sourceRecastData = (int*)CustomData_get_layer(&dm->polyData, CD_RECAST); if (sourceRecastData) { - CustomData_add_layer_named(&result->faceData, CD_RECAST, CD_DUPLICATE, + CustomData_add_layer_named(&result->polyData, CD_RECAST, CD_DUPLICATE, sourceRecastData, maxFaces, "recastData"); } } - recastData = (int*)CustomData_get_layer(&result->faceData, CD_RECAST); + recastData = (int*)CustomData_get_layer(&result->polyData, CD_RECAST); /* note: This is not good design! - really should not be doing this */ result->drawFacesTex = navmesh_DM_drawFacesTex; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index f0bda57466d..2450f3ca83e 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -1099,7 +1099,7 @@ const CustomDataMask CD_MASK_DERIVEDMESH = CD_MASK_ORIGINDEX | CD_MASK_POLYINDEX; const CustomDataMask CD_MASK_BMESH = CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | - CD_MASK_PROP_STR | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_MDISPS | CD_MASK_CREASE | CD_MASK_BWEIGHT; + CD_MASK_PROP_STR | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_MDISPS | CD_MASK_CREASE | CD_MASK_BWEIGHT | CD_MASK_RECAST; const CustomDataMask CD_MASK_FACECORNERS = CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; diff --git a/source/blender/blenkernel/intern/navmesh_conversion.c b/source/blender/blenkernel/intern/navmesh_conversion.c index 27e309e9d20..34e0be1de92 100644 --- a/source/blender/blenkernel/intern/navmesh_conversion.c +++ b/source/blender/blenkernel/intern/navmesh_conversion.c @@ -166,7 +166,7 @@ int buildRawVertIndicesData(DerivedMesh* dm, int *nverts_r, float **verts_r, } //carefully, recast data is just reference to data in derived mesh - *recastData = (int*)CustomData_get_layer(&dm->faceData, CD_RECAST); + *recastData = (int*)CustomData_get_layer(&dm->polyData, CD_RECAST); *nverts_r = nverts; *verts_r = verts; diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c index f1b0a82b654..7d78a527b06 100644 --- a/source/blender/editors/mesh/mesh_navmesh.c +++ b/source/blender/editors/mesh/mesh_navmesh.c @@ -345,6 +345,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, /* create custom data layer to save polygon idx */ CustomData_add_layer_named(&em->bm->pdata, CD_RECAST, CD_CALLOC, NULL, 0, "createRepresentation recastData"); + CustomData_bmesh_init_pool(&em->bm->pdata, 0, BM_FACE); /* create verts and faces for detailed mesh */ meshes = recast_polyMeshDetailGetMeshes(dmesh, &nmeshes); diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.cpp b/source/gameengine/Ketsji/KX_NavMeshObject.cpp index 22f96eb7297..35058e5fe5d 100644 --- a/source/gameengine/Ketsji/KX_NavMeshObject.cpp +++ b/source/gameengine/Ketsji/KX_NavMeshObject.cpp @@ -112,7 +112,8 @@ bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts, { DerivedMesh* dm = mesh_create_derived_no_virtual(KX_GetActiveScene()->GetBlenderScene(), GetBlenderObject(), NULL, CD_MASK_MESH); - int* recastData = (int*) dm->getTessFaceDataArray(dm, CD_RECAST); + CustomData *pdata = dm->getPolyDataLayout(dm); + int* recastData = (int*) CustomData_get_layer(pdata, CD_RECAST); if (recastData) { int *dtrisToPolysMap=NULL, *dtrisToTrisMap=NULL, *trisToFacesMap=NULL; From 6e40088604b744eba4eb1775ac0776998d8a03cc Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 16 Apr 2012 14:27:22 +0000 Subject: [PATCH 04/12] Partial revert of rev45691: allow lightmap undo and add comment why redo was disabled --- .../scripts/startup/bl_operators/uvcalc_lightmap.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py index 3074db17d0f..417ae89218c 100644 --- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py +++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py @@ -550,6 +550,16 @@ class LightMapPack(Operator): bl_idname = "uv.lightmap_pack" bl_label = "Lightmap Pack" + # Disable REGISTER flag for now because this operator might create new + # images. This leads to non-proper operator redo because current undo + # stack is local for edit mode and can not remove images created by this + # oprtator. + # Proper solution would be to make undo stack aware of such things, + # but for now just disable redo. Keep undo here so unwanted changes to uv + # coords might be undone. + # This fixes infinite image creation reported there [#30968] (sergey) + bl_options = {'UNDO'} + PREF_CONTEXT = bpy.props.EnumProperty( name="Selection", items=(('SEL_FACES', "Selected Faces", "Space all UVs evently"), From e0605cca9a09d9d33974f7beea3acbb1741b476e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 16 Apr 2012 14:34:48 +0000 Subject: [PATCH 05/12] fix error when a failed thumb overrides a newer good thumbnail. on saving blend file remove failed thumb. --- source/blender/windowmanager/intern/wm_files.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 0ffd9e00f7e..9ffea0e290b 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -805,6 +805,7 @@ int WM_write_file(bContext *C, const char *target, int fileflags, ReportList *re /* run this function after because the file cant be written before the blend is */ if (ibuf_thumb) { + IMB_thumb_delete(filepath, THB_FAIL); /* without this a failed thumb overrides */ ibuf_thumb = IMB_thumb_create(filepath, THB_NORMAL, THB_SOURCE_BLEND, ibuf_thumb); IMB_freeImBuf(ibuf_thumb); } From 0f7ab89b4ee803aa9cb2182eb6f394d2cf28de56 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 16 Apr 2012 15:13:21 +0000 Subject: [PATCH 06/12] fix for fail thumbs being used when the failed thumbnail image is older then the image/movie/blend. --- source/blender/blenlib/intern/storage.c | 1 + source/blender/imbuf/intern/thumbs.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 9bcbdcce12e..f4070f76519 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -551,6 +551,7 @@ void BLI_file_free_lines(LinkNode *lines) BLI_linklist_free(lines, (void(*)(void*)) MEM_freeN); } +/** is file1 older then file2 */ int BLI_file_older(const char *file1, const char *file2) { #ifdef WIN32 diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 5c54fbab0cf..5d64e1b2aec 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -223,6 +223,8 @@ static void thumbname_from_uri(const char* uri, char* thumb, const int thumb_len to_hex_char(hexdigest, digest, 16); hexdigest[32] = '\0'; BLI_snprintf(thumb, thumb_len, "%s.png", hexdigest); + + // printf("%s: '%s' --> '%s'\n", __func__, uri, thumb); } static int thumbpath_from_uri(const char* uri, char* path, const int path_len, ThumbSize size) @@ -378,7 +380,9 @@ ImBuf* IMB_thumb_create(const char* path, ThumbSize size, ThumbSource source, Im if (IMB_saveiff(img, temp, IB_rect | IB_metadata)) { #ifndef WIN32 chmod(temp, S_IRUSR | S_IWUSR); -#endif +#endif + // printf("%s saving thumb: '%s'\n", __func__, tpath); + BLI_rename(temp, tpath); } @@ -441,7 +445,13 @@ ImBuf* IMB_thumb_manage(const char* path, ThumbSize size, ThumbSource source) if (thumbpath_from_uri(uri, thumb, sizeof(thumb), THB_FAIL)) { /* failure thumb exists, don't try recreating */ if (BLI_exists(thumb)) { - return NULL; + /* clear out of date fail case */ + if (BLI_file_older(thumb, path)) { + BLI_delete(thumb, 0, 0); + } + else { + return NULL; + } } } From e889fa467816950c828f7696be2433c472a7d4ad Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 16 Apr 2012 16:24:55 +0000 Subject: [PATCH 07/12] improve scanfill for uneven ngons, previously scanfill would use the most angular corner, but this made non planer ngons rip frequently (often reported problem). now calculate the normal as with ngons. --- source/blender/blenlib/intern/scanfill.c | 55 +++++++++++------------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 69b8f3f3ee7..a303cadab85 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -786,7 +786,7 @@ int BLI_edgefill(ScanFillContext *sf_ctx, const short do_quad_tri_speedup) ScanFillVert *eve; ScanFillEdge *eed, *nexted; PolyFill *pflist, *pf; - float limit, *min_xy_p, *max_xy_p, *v1, *v2, norm[3], len; + float *min_xy_p, *max_xy_p; short a, c, poly = 0, ok = 0, toggle = 0; int totfaces = 0; /* total faces added */ int co_x, co_y; @@ -813,7 +813,7 @@ int BLI_edgefill(ScanFillContext *sf_ctx, const short do_quad_tri_speedup) eve = sf_ctx->fillvertbase.first; /* no need to check 'eve->next->next->next' is valid, already counted */ - /*use shortest diagonal for quad*/ + /* use shortest diagonal for quad */ sub_v3_v3v3(vec1, eve->co, eve->next->next->co); sub_v3_v3v3(vec2, eve->next->co, eve->next->next->next->co); @@ -848,41 +848,36 @@ int BLI_edgefill(ScanFillContext *sf_ctx, const short do_quad_tri_speedup) eve = eve->next; } - if (ok == 0) return 0; + if (ok == 0) { + return 0; + } + else { + /* define projection: with 'best' normal */ + /* Newell's Method */ + /* Similar code used elsewhere, but this checks for double ups + * which historically this function supports so better not change */ + float *v_prev; + float n[3] = {0.0f}; - /* NEW NEW! define projection: with 'best' normal */ - /* just use the first three different vertices */ - - /* THIS PART STILL IS PRETTY WEAK! (ton) */ + eve = sf_ctx->fillvertbase.last; + v_prev = eve->co; - eve = sf_ctx->fillvertbase.last; - len = 0.0; - v1 = eve->co; - v2 = 0; - eve = sf_ctx->fillvertbase.first; - limit = 1e-8f; - - while (eve) { - if (v2) { - if (!compare_v3v3(v2, eve->co, COMPLIMIT)) { - float inner = angle_v3v3v3(v1, v2, eve->co); - inner = MIN2(fabsf(inner), fabsf(M_PI - inner)); - - if (inner > limit) { - limit = inner; - len = normal_tri_v3(norm, v1, v2, eve->co); - } + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { + if (LIKELY(!compare_v3v3(v_prev, eve->co, COMPLIMIT))) { + n[0] += (v_prev[1] - eve->co[1]) * (v_prev[2] + eve->co[2]); + n[1] += (v_prev[2] - eve->co[2]) * (v_prev[0] + eve->co[0]); + n[2] += (v_prev[0] - eve->co[0]) * (v_prev[1] + eve->co[1]); } + v_prev = eve->co; } - else if (!compare_v3v3(v1, eve->co, COMPLIMIT)) - v2 = eve->co; - eve = eve->next; + if (UNLIKELY(normalize_v3(n) == 0.0f)) { + n[2] = 1.0f; /* other axis set to 0.0 */ + } + + axis_dominant_v3(&co_x, &co_y, n); } - if (len == 0.0f) return 0; /* no fill possible */ - - axis_dominant_v3(&co_x, &co_y, norm); /* STEP 1: COUNT POLYS */ eve = sf_ctx->fillvertbase.first; From 67f8e3a3a7af4146b9bb7ae40f1bdc8dabc2b48f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 16 Apr 2012 16:49:37 +0000 Subject: [PATCH 08/12] inline function for "Newell's Method" used for normal calc. --- source/blender/blenlib/BLI_math_vector.h | 2 ++ source/blender/blenlib/intern/math_base_inline.c | 2 +- .../blender/blenlib/intern/math_vector_inline.c | 15 +++++++++++++-- source/blender/blenlib/intern/scanfill.c | 4 +--- source/blender/bmesh/intern/bmesh_polygon.c | 12 +++--------- 5 files changed, 20 insertions(+), 15 deletions(-) diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 7fba2699fc7..54c06616110 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -124,6 +124,8 @@ MINLINE float dot_v3v3(const float a[3], const float b[3]); MINLINE float cross_v2v2(const float a[2], const float b[2]); MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3]); +MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3]); + MINLINE void star_m3_v3(float rmat[3][3],float a[3]); /*********************************** Length **********************************/ diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index 58c882e894e..b2d5392c596 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -92,7 +92,7 @@ MINLINE float saasinf(float fac) MINLINE float sasqrtf(float fac) { if (fac <= 0.0f) return 0.0f; - return (float)sqrtf(fac); + return sqrtf(fac); } MINLINE float interpf(float target, float origin, float fac) diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index 62e582c89c4..ef8f26e3780 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -480,6 +480,17 @@ MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3]) r[2] = a[0] * b[1] - a[1] * b[0]; } +/* Newell's Method */ +/* excuse this fairly spesific function, + * its used for polygon normals all over the place + * could use a better name */ +MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3]) +{ + n[0] += (v_prev[1] - v_curr[1]) * (v_prev[2] + v_curr[2]); + n[1] += (v_prev[2] - v_curr[2]) * (v_prev[0] + v_curr[0]); + n[2] += (v_prev[0] - v_curr[0]) * (v_prev[1] + v_curr[1]); +} + MINLINE void star_m3_v3(float rmat[][3], float a[3]) { rmat[0][0] = rmat[1][1] = rmat[2][2] = 0.0; @@ -505,7 +516,7 @@ MINLINE float len_squared_v3(const float v[3]) MINLINE float len_v2(const float v[2]) { - return (float)sqrtf(v[0] * v[0] + v[1] * v[1]); + return sqrtf(v[0] * v[0] + v[1] * v[1]); } MINLINE float len_v2v2(const float v1[2], const float v2[2]) @@ -514,7 +525,7 @@ MINLINE float len_v2v2(const float v1[2], const float v2[2]) x = v1[0] - v2[0]; y = v1[1] - v2[1]; - return (float)sqrtf(x * x + y * y); + return sqrtf(x * x + y * y); } MINLINE float len_v3(const float a[3]) diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index a303cadab85..1b60d58b154 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -864,9 +864,7 @@ int BLI_edgefill(ScanFillContext *sf_ctx, const short do_quad_tri_speedup) for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { if (LIKELY(!compare_v3v3(v_prev, eve->co, COMPLIMIT))) { - n[0] += (v_prev[1] - eve->co[1]) * (v_prev[2] + eve->co[2]); - n[1] += (v_prev[2] - eve->co[2]) * (v_prev[0] + eve->co[0]); - n[2] += (v_prev[0] - eve->co[0]) * (v_prev[1] + eve->co[1]); + add_newell_cross_v3_v3v3(n, v_prev, eve->co); } v_prev = eve->co; } diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 67e3d24ade1..77e50b1ea3f 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -84,9 +84,7 @@ static void compute_poly_normal(float normal[3], float verts[][3], int nverts) /* Newell's Method */ for (i = 0; i < nverts; v_prev = v_curr, v_curr = verts[++i]) { - n[0] += (v_prev[1] - v_curr[1]) * (v_prev[2] + v_curr[2]); - n[1] += (v_prev[2] - v_curr[2]) * (v_prev[0] + v_curr[0]); - n[2] += (v_prev[0] - v_curr[0]) * (v_prev[1] + v_curr[1]); + add_newell_cross_v3_v3v3(n, v_prev, v_curr); } if (UNLIKELY(normalize_v3_v3(normal, n) == 0.0f)) { @@ -109,9 +107,7 @@ static void bm_face_compute_poly_normal(BMFace *f) /* Newell's Method */ do { - n[0] += (v_prev[1] - v_curr[1]) * (v_prev[2] + v_curr[2]); - n[1] += (v_prev[2] - v_curr[2]) * (v_prev[0] + v_curr[0]); - n[2] += (v_prev[0] - v_curr[0]) * (v_prev[1] + v_curr[1]); + add_newell_cross_v3_v3v3(n, v_prev, v_curr); l_iter = l_iter->next; v_prev = v_curr; @@ -142,9 +138,7 @@ static void bm_face_compute_poly_normal_vertex_cos(BMFace *f, float n[3], /* Newell's Method */ do { - n[0] += (v_prev[1] - v_curr[1]) * (v_prev[2] + v_curr[2]); - n[1] += (v_prev[2] - v_curr[2]) * (v_prev[0] + v_curr[0]); - n[2] += (v_prev[0] - v_curr[0]) * (v_prev[1] + v_curr[1]); + add_newell_cross_v3_v3v3(n, v_prev, v_curr); l_iter = l_iter->next; v_prev = v_curr; From 195d6c1b1a363bb30b6efaf9c274cc45edaa6f9a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 16 Apr 2012 18:24:49 +0000 Subject: [PATCH 09/12] minor speedup for scanfill, dont calculate the normal if its already known - use for editmode ngon filling. --- .../blenkernel/intern/editderivedmesh.c | 2 +- source/blender/blenlib/BLI_scanfill.h | 2 ++ source/blender/blenlib/intern/scanfill.c | 36 ++++++++++++------- source/blender/bmesh/intern/bmesh_polygon.c | 6 ++-- .../editors/uvedit/uvedit_unwrap_ops.c | 2 +- .../blender/windowmanager/intern/wm_gesture.c | 3 +- 6 files changed, 33 insertions(+), 18 deletions(-) diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 07a43db8560..d9a011d481f 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -218,7 +218,7 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm) /*complete the loop*/ BLI_addfilledge(&sf_ctx, firstv, v); - totfilltri = BLI_edgefill(&sf_ctx, FALSE); + totfilltri = BLI_edgefill_ex(&sf_ctx, FALSE, f->no); BLI_array_growitems(looptris, totfilltri); for (efa = sf_ctx.fillfacebase.first; efa; efa=efa->next) { diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h index 67ff9a88700..5a5e55cc90a 100644 --- a/source/blender/blenlib/BLI_scanfill.h +++ b/source/blender/blenlib/BLI_scanfill.h @@ -100,6 +100,8 @@ struct ScanFillEdge *BLI_addfilledge(ScanFillContext *sf_ctx, struct ScanFillVer int BLI_begin_edgefill(ScanFillContext *sf_ctx); int BLI_edgefill(ScanFillContext *sf_ctx, const short do_quad_tri_speedup); +int BLI_edgefill_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedup, + const float nor_proj[3]); void BLI_end_edgefill(ScanFillContext *sf_ctx); /* These callbacks are needed to make the lib finction properly */ diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 1b60d58b154..4878ad628ef 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -773,6 +773,11 @@ int BLI_begin_edgefill(ScanFillContext *sf_ctx) } int BLI_edgefill(ScanFillContext *sf_ctx, const short do_quad_tri_speedup) +{ + return BLI_edgefill_ex(sf_ctx, do_quad_tri_speedup, NULL); +} + +int BLI_edgefill_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedup, const float nor_proj[3]) { /* * - fill works with its own lists, so create that first (no faces!) @@ -852,21 +857,28 @@ int BLI_edgefill(ScanFillContext *sf_ctx, const short do_quad_tri_speedup) return 0; } else { - /* define projection: with 'best' normal */ - /* Newell's Method */ - /* Similar code used elsewhere, but this checks for double ups - * which historically this function supports so better not change */ - float *v_prev; - float n[3] = {0.0f}; + float n[3]; - eve = sf_ctx->fillvertbase.last; - v_prev = eve->co; + if (nor_proj) { + copy_v3_v3(n, nor_proj); + } + else { + /* define projection: with 'best' normal */ + /* Newell's Method */ + /* Similar code used elsewhere, but this checks for double ups + * which historically this function supports so better not change */ + float *v_prev; - for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { - if (LIKELY(!compare_v3v3(v_prev, eve->co, COMPLIMIT))) { - add_newell_cross_v3_v3v3(n, v_prev, eve->co); - } + zero_v3(n); + eve = sf_ctx->fillvertbase.last; v_prev = eve->co; + + for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { + if (LIKELY(!compare_v3v3(v_prev, eve->co, COMPLIMIT))) { + add_newell_cross_v3_v3v3(n, v_prev, eve->co); + } + v_prev = eve->co; + } } if (UNLIKELY(normalize_v3(n) == 0.0f)) { diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 77e50b1ea3f..1b480ab0315 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -529,8 +529,8 @@ static int linecrossesf(const float v1[2], const float v2[2], const float v3[2], GETMIN2(v1, v2, mv1, mv2); GETMIN2(v3, v4, mv3, mv4); - /* do an interval test on the x and y axe */ - /* first do x axi */ + /* do an interval test on the x and y axes */ + /* first do x axis */ if (ABS(v1[1] - v2[1]) < EPS && ABS(v3[1] - v4[1]) < EPS && ABS(v1[1] - v3[1]) < EPS) @@ -538,7 +538,7 @@ static int linecrossesf(const float v1[2], const float v2[2], const float v3[2], return (mv4[0] >= mv1[0] && mv3[0] <= mv2[0]); } - /* now do y axi */ + /* now do y axis */ if (ABS(v1[0] - v2[0]) < EPS && ABS(v3[0] - v4[0]) < EPS && ABS(v1[0] - v3[0]) < EPS) diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 5b3c4f9cd97..6e1506d4c0f 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -288,7 +288,7 @@ static ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em, BLI_addfilledge(&sf_ctx, firstv, v); - BLI_edgefill(&sf_ctx, TRUE); + BLI_edgefill_ex(&sf_ctx, TRUE, efa->no); for (sefa = sf_ctx.fillfacebase.first; sefa; sefa = sefa->next) { ls[0] = sefa->v1->tmp.p; ls[1] = sefa->v2->tmp.p; diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index 0add9106872..bfa3645bf57 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -253,8 +253,9 @@ static void draw_filled_lasso(wmGesture *gt) /* highly unlikely this will fail, but could crash if (gt->points == 0) */ if (firstv) { + float zvec[3] = {0.0f, 0.0f, 1.0f}; BLI_addfilledge(&sf_ctx, firstv, v); - BLI_edgefill(&sf_ctx, FALSE); + BLI_edgefill_ex(&sf_ctx, FALSE, zvec); glEnable(GL_BLEND); glColor4f(1.0, 1.0, 1.0, 0.05); From 348622360752916f9b776597e846cd2af260cdb9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 17 Apr 2012 05:09:37 +0000 Subject: [PATCH 10/12] code cleanup: remove/comment some unused code. --- source/blender/blenfont/intern/blf_font.c | 4 ++-- source/blender/bmesh/operators/bmo_mirror.c | 6 +++--- source/blender/editors/mesh/editmesh_bvh.c | 13 ------------- source/blender/editors/mesh/editmesh_tools.c | 4 ++-- source/blender/editors/sound/sound_ops.c | 3 +-- 5 files changed, 8 insertions(+), 22 deletions(-) diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 84cefc923a0..7a4e1d4b781 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -279,8 +279,8 @@ void blf_font_buffer(FontBLF *font, const char *str) if (font->b_fbuf) { int yb = yb_start; - for (y = (chy >= 0 ? 0:-chy); y < height_clip; y++) { - for (x = (chx >= 0 ? 0:-chx); x < width_clip; x++) { + for (y = ((chy >= 0) ? 0 : -chy); y < height_clip; y++) { + for (x = ((chx >= 0) ? 0 : -chx); x < width_clip; x++) { a = *(g->bitmap + x + (yb * g->pitch)) / 255.0f; if (a > 0.0f) { diff --git a/source/blender/bmesh/operators/bmo_mirror.c b/source/blender/bmesh/operators/bmo_mirror.c index 1b6d64073c0..17a00f5e095 100644 --- a/source/blender/bmesh/operators/bmo_mirror.c +++ b/source/blender/bmesh/operators/bmo_mirror.c @@ -43,7 +43,7 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) BMOperator dupeop, weldop; BMOIter siter; BMIter iter; - BMVert *v, *v2, **vmap = NULL; + BMVert *v /* , *v2 */ /* UNUSED */, **vmap = NULL; BLI_array_declare(vmap); BMEdge /* *e, */ **emap = NULL; BLI_array_declare(emap); @@ -69,11 +69,11 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) /* create old -> new mappin */ i = 0; - v2 = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); + /* v2 = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); */ /* UNUSED */ BMO_ITER(v, &siter, bm, &dupeop, "newout", BM_VERT) { BLI_array_growone(vmap); vmap[i] = v; - v2 = BM_iter_step(&iter); + /* v2 = BM_iter_step(&iter); */ /* UNUSED */ i++; } bm->elem_index_dirty |= BM_VERT; diff --git a/source/blender/editors/mesh/editmesh_bvh.c b/source/blender/editors/mesh/editmesh_bvh.c index f9c673010f3..c1b694d5e2d 100644 --- a/source/blender/editors/mesh/editmesh_bvh.c +++ b/source/blender/editors/mesh/editmesh_bvh.c @@ -305,19 +305,6 @@ BMVert *BMBVH_FindClosestVert(BMBVHTree *tree, float *co, float maxdist) return NULL; } -typedef struct walklist { - BMVert *v; - int valence; - int depth; - float w, r; - int totwalked; - - /* state data */ - BMVert *lastv; - BMLoop *curl, *firstl; - BMEdge *cure; -} walklist; - /* UNUSED */ #if 0 static short winding(float *v1, float *v2, float *v3) diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index b8ab538b60e..2af931372bb 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -2051,8 +2051,8 @@ void MESH_OT_remove_doubles(wmOperatorType *ot) /************************ Vertex Path Operator *************************/ typedef struct PathNode { - int u; - int visited; + /* int u; */ /* UNUSED */ + /* int visited; */ /* UNUSED */ ListBase edges; } PathNode; diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index f7598045f81..b50c3f11534 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -283,8 +283,7 @@ static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op)) sound_update_animation_flags_exec(C, NULL); - for (cfra = scene->r.sfra > 0 ? scene->r.sfra - 1 : 0; cfra <= scene->r.efra + 1; cfra++) - { + for (cfra = (scene->r.sfra > 0) ? (scene->r.sfra - 1) : 0; cfra <= scene->r.efra + 1; cfra++) { scene->r.cfra = cfra; scene_update_for_newframe(bmain, scene, scene->lay); } From 0de1ed57876edb5324a08e79f4d920919f9f5df9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 17 Apr 2012 05:47:32 +0000 Subject: [PATCH 11/12] add import operator python template. --- ...ator_export.py => operator_file_export.py} | 11 +-- .../scripts/templates/operator_file_import.py | 79 +++++++++++++++++++ 2 files changed, 85 insertions(+), 5 deletions(-) rename release/scripts/templates/{operator_export.py => operator_file_export.py} (86%) create mode 100644 release/scripts/templates/operator_file_import.py diff --git a/release/scripts/templates/operator_export.py b/release/scripts/templates/operator_file_export.py similarity index 86% rename from release/scripts/templates/operator_export.py rename to release/scripts/templates/operator_file_export.py index 3a7040ae2d2..7703d14de67 100644 --- a/release/scripts/templates/operator_export.py +++ b/release/scripts/templates/operator_file_export.py @@ -3,7 +3,7 @@ import bpy def write_some_data(context, filepath, use_some_setting): print("running write_some_data...") - f = open(filepath, 'w') + f = open(filepath, 'w', encoding='utf-8') f.write("Hello World %s" % use_some_setting) f.close() @@ -14,11 +14,12 @@ def write_some_data(context, filepath, use_some_setting): # invoke() function which calls the file selector. from bpy_extras.io_utils import ExportHelper from bpy.props import StringProperty, BoolProperty, EnumProperty +from bpy.types import Operator -class ExportSomeData(bpy.types.Operator, ExportHelper): - '''This appears in the tooltip of the operator and in the generated docs.''' - bl_idname = "export.some_data" # this is important since its how bpy.ops.export.some_data is constructed +class ExportSomeData(Operator, ExportHelper): + '''This appears in the tooltip of the operator and in the generated docs''' + bl_idname = "export_test.some_data" # important since its how bpy.ops.import_test.some_data is constructed bl_label = "Export Some Data" # ExportHelper mixin class uses this @@ -72,4 +73,4 @@ if __name__ == "__main__": register() # test call - bpy.ops.export.some_data('INVOKE_DEFAULT') + bpy.ops.export_test.some_data('INVOKE_DEFAULT') diff --git a/release/scripts/templates/operator_file_import.py b/release/scripts/templates/operator_file_import.py new file mode 100644 index 00000000000..10a054cf1df --- /dev/null +++ b/release/scripts/templates/operator_file_import.py @@ -0,0 +1,79 @@ +import bpy + + +def read_some_data(context, filepath, use_some_setting): + print("running read_some_data...") + f = open(filepath, 'r', encoding='utf-8') + data = f.read() + f.close() + + # would normally load the data hare + print(data) + + return {'FINISHED'} + + +# ImportHelper is a helper class, defines filename and +# invoke() function which calls the file selector. +from bpy_extras.io_utils import ImportHelper +from bpy.props import StringProperty, BoolProperty, EnumProperty +from bpy.types import Operator + + +class ImportSomeData(Operator, ImportHelper): + '''This appears in the tooltip of the operator and in the generated docs''' + bl_idname = "import_test.some_data" # important since its how bpy.ops.import_test.some_data is constructed + bl_label = "Import Some Data" + + # ImportHelper mixin class uses this + filename_ext = ".txt" + + filter_glob = StringProperty( + default="*.txt", + options={'HIDDEN'}, + ) + + # List of operator properties, the attributes will be assigned + # to the class instance from the operator settings before calling. + use_setting = BoolProperty( + name="Example Boolean", + description="Example Tooltip", + default=True, + ) + + type = EnumProperty( + name="Example Enum", + description="Choose between two items", + items=(('OPT_A', "First Option", "Description one"), + ('OPT_B', "Second Option", "Description two")), + default='OPT_A', + ) + + @classmethod + def poll(cls, context): + return context.active_object is not None + + def execute(self, context): + return read_some_data(context, self.filepath, self.use_setting) + + +# Only needed if you want to add into a dynamic menu +def menu_func_import(self, context): + self.layout.operator(ImportSomeData.bl_idname, text="Text Import Operator") + + +def register(): + bpy.utils.register_class(ImportSomeData) + bpy.types.INFO_MT_file_import.append(menu_func_import) + + +def unregister(): + bpy.utils.unregister_class(ImportSomeData) + bpy.types.INFO_MT_file_import.remove(menu_func_import) + + +if __name__ == "__main__": + register() + + # test call + bpy.ops.import_test.some_data('INVOKE_DEFAULT') From 1142a504cbd2085ee0b3bd1a25fbe4443ecf3a3a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 17 Apr 2012 05:49:07 +0000 Subject: [PATCH 12/12] remove the poll function from import/export templates --- release/scripts/templates/operator_file_export.py | 4 ---- release/scripts/templates/operator_file_import.py | 4 ---- 2 files changed, 8 deletions(-) diff --git a/release/scripts/templates/operator_file_export.py b/release/scripts/templates/operator_file_export.py index 7703d14de67..e3e0217e26a 100644 --- a/release/scripts/templates/operator_file_export.py +++ b/release/scripts/templates/operator_file_export.py @@ -46,10 +46,6 @@ class ExportSomeData(Operator, ExportHelper): default='OPT_A', ) - @classmethod - def poll(cls, context): - return context.active_object is not None - def execute(self, context): return write_some_data(context, self.filepath, self.use_setting) diff --git a/release/scripts/templates/operator_file_import.py b/release/scripts/templates/operator_file_import.py index 10a054cf1df..98a3ae96287 100644 --- a/release/scripts/templates/operator_file_import.py +++ b/release/scripts/templates/operator_file_import.py @@ -49,10 +49,6 @@ class ImportSomeData(Operator, ImportHelper): default='OPT_A', ) - @classmethod - def poll(cls, context): - return context.active_object is not None - def execute(self, context): return read_some_data(context, self.filepath, self.use_setting)